Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 8 additions & 30 deletions multiapps-controller-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,19 @@
<artifactId>value</artifactId>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.cloudfoundry/cloudfoundry-client-reactor -->
<dependency>
<groupId>org.cloudfoundry</groupId>
<artifactId>cloudfoundry-client-reactor</artifactId>
</dependency>
<!-- Transitive dependency from cloudfoundry-client. Pin the version, because the one they're using (1.0.3) contains vulnerabilities -->
<!-- reactor-netty backs the Spring WebClient used by the OAuth client (RestUtil). -->
<!-- https://mvnrepository.com/artifact/io.projectreactor.netty/reactor-netty -->
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
</dependency>
<!-- commons-logging: used directly by JsonUtil (previously came transitively via cloudfoundry-client). -->
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commons-logging.version}</version>
</dependency>
<!-- Required dependency due to enabled metrics of reactor-netty client -->
<!-- https://mvnrepository.com/artifact/io.micrometer/micrometer-registry-jmx -->
<dependency>
Expand Down Expand Up @@ -140,30 +142,6 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.cloudfoundry</groupId>
<artifactId>cloudfoundry-client-reactor</artifactId>
<version>${cloudfoundry-client.version}</version>
<exclusions>
<exclusion>
<!-- Excluding the dependency as it will be overridden by commons-logging (see below)
because they expose the same module, but jcl-over-slf4j 2.0.9 which comes as a transitive
dependency does not expose "org.apache.commons.logging.impl" package from "org.apache.commons.logging"
module which is used by org.springframework.core.log.CompositeLog and leads to java.lang.IllegalAccessError
during integration tests. -->
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</exclusion>
<!--
Excluding jackson-databind because the Cloud Foundry client pulls in
an old Jackson 2.13.x version that conflicts with Spring WebFlux 6.2.x
and causes DefaultExchangeStrategiesBuilder to fail initialization. -->
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging-->
<dependency>
<groupId>commons-logging</groupId>
Expand Down
5 changes: 2 additions & 3 deletions multiapps-controller-client/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@
exports org.cloudfoundry.multiapps.controller.client.facade.util;
exports org.cloudfoundry.multiapps.controller.client.facade.dto;

requires transitive org.cloudfoundry.client;
requires spring.security.oauth2.core;
requires transitive spring.web;

requires com.fasterxml.jackson.databind;
requires org.apache.commons.collections4;
requires org.apache.commons.io;
requires org.apache.commons.logging;
requires org.cloudfoundry.client.reactor;
requires org.cloudfoundry.multiapps.common;
requires org.cloudfoundry.util;
requires org.slf4j;
requires java.net.http;
requires spring.core;
Expand All @@ -41,5 +38,7 @@
requires static java.compiler;
requires static jakarta.inject;
requires static org.immutables.value;
requires io.netty.codec;
requires java.desktop;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.cloudfoundry.multiapps.controller;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

public class Constants {

Check warning on line 6 in multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/Constants.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a private constructor to hide the implicit public one.

See more on https://sonarcloud.io/project/issues?id=cloudfoundry_multiapps-controller&issues=AaBnl2TBjZDKeJDbqdcl&open=AaBnl2TBjZDKeJDbqdcl&pullRequest=1907

public static final Duration DEFAULT_CONNECT_TIMEOUT = Duration.ofMinutes(1);
public static final Duration JOB_POLL_MIN_INTERVAL = Duration.ofSeconds(1);
public static final Duration JOB_POLL_MAX_INTERVAL = Duration.ofSeconds(15);
public static final Duration DELETE_JOB_TIMEOUT = Duration.ofMinutes(5);
public static final Duration BINDING_OPERATIONS_TIMEOUT = Duration.ofMinutes(10);
public static final long PACKAGE_UPLOAD_JOB_POLLING_PERIOD = TimeUnit.SECONDS.toMillis(5);

public static final int DEFAULT_CONNECTION_POOL_SIZE = 192;
public static final int UNDEFINED_PORT = -1;
public static final int MAX_CONCURRENT_PAGES = 256;
public static final int DEFAULT_CONCURRENT_TASKS = 256;
public static final int MAX_CHAR_LENGTH_FOR_PARAMS_IN_REQUEST = 4000;

public static final String CONNECTION_POOL_NAME = "cf-controller-client";
public static final String LOOP_RESOURCES_SUFFIX = "-loop-resources";
public static final String CF_API_V3 = "/v3";
public static final String HREF = "href";
public static final String CLOUD_CONTROLLER_CF_ROOT_DOCUMENT_NAME = "cloud_controller_v3";
public static final String LOG_CACHE_CF_ROOT_DOCUMENT_NAME = "log_cache";
public static final String API_HOST_PREFIX = "api.";
public static final String LOG_CACHE_PREFIX = "log-cache.";
public static final String ROOT_DOCUMENT_LINKS_LIST = "links";

public static final String EMPTY_STRING = "";
public static final String COLON = ":";
public static final String PROTOCOL_SEPARATOR = "://";

public static final String PACKAGE_LINK = "package";
public static final String WEB_PROCESS_TYPE = "web";

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,52 @@
public class Messages {

// INFO messages
public static final String WAITING_MS_BEFORE_RETRYING_WITH_TIMEOUT_OF_MS = "Waiting: {} ms before retrying with timeout of: {} ms";
public static final String WAITING_MS_BEFORE_RETRYING_WITH_TIMEOUT_OF_MS = "Waiting: {} ms before retrying with timeout of: {} ms.";
public static final String RATE_LIMITED_BY_CC_WAITING_S = "CC returned 429 with Retry-After: {} s. Waiting {} s (capped) before retrying.";
public static final String RATE_LIMITED_BY_CC_NO_HEADER_WAITING_MS = "CC returned 429 without Retry-After header. Waiting {} ms before retrying.";
public static final String RANDOM_WAIT_BEFORE_RETRY_MS = "Waiting {} ms (randomized) before retrying failed CC operation.";

// Exception messages
public static final String ERROR_OCCURRED_SETTING_UP_DEFAULT_SSL_CONTEXT = "An error occurred while setting up the default SSLContext.";
public static final String ERROR_OCCURRED_SETTING_UP_ALWAYS_APPROVING_SSL_CONTEXT = "An error occurred while setting up the always approving SSLContext.";
public static final String COULD_NOT_DETERMINE_API_ORIGIN_FROM_0 = "Could not determine the API origin from \"{0}\".";
public static final String COULD_NOT_RESOLVE_URL_FROM_0_1 = "Could not resolve URL from \"{0}\" \"{1}\".";
public static final String COULD_NOT_RESOLVE_LOG_CACHE_URL_FROM_0 = "Could not derive the log-cache URL from \"{0}\".";
public static final String CF_ROOT_DOCUMENT_REQUEST_TO_0_RETURNED_1 = "CF root request to \"{0}\" returned \"{1}\".";
public static final String INTERRUPTED_WHILE_CALLING_THE_CF_ROOT_URL_AT_0 = "Interrupted while calling the CF root URL at \"{0}\".";
public static final String FAILED_TO_CALL_THE_CF_ROOT_AT_0_WITH_1 = "Failed to call the CF root at \"{0}\" with: \"{1}\".";
public static final String SERVICE_KEY_0_NOT_FOUND = "Service key \"{0}\" not found.";
public static final String SERVICE_INSTANCE_0_NOT_FOUND = "Service instance \"{0}\" not found.";
public static final String SERVICE_BROKER_0_NOT_FOUND = "Service broker \"{0}\" not found.";
public static final String APPLICATION_0_NOT_FOUND = "Application \"{0}\" not found.";
public static final String DOMAIN_0_NOT_FOUND = "Domain \"{0}\" not found.";
public static final String SERVICE_PLAN_0_NOT_FOUND = "Service plan \"{0}\" not found.";
public static final String STACK_0_NOT_FOUND = "Stack \"{0}\" not found.";
public static final String ORGANISATION_0_NOT_FOUND = "Organization \"{0}\" not found.";
public static final String SPACE_WITH_GUID_0_NOT_FOUND = "Space with GUID \"{0}\" not found.";
public static final String APPLICATION_WITH_GUID_0_DOES_NOT_HAVE_A_DROPLET = "Application with guid \"{0}\" does not have a droplet";
public static final String HOST_0_NOT_FOUND_FOR_DOMAIN_1 = "Host \"{0}\" not found for domain \"{1}\".";
public static final String UNABLE_TO_0_WITHOUT_SPECIFYING_ORGANIZATION_AND_SPACE_TO_USE = "Unable to \"{0}\" without specifying organization and space to use.";
public static final String DOMAIN_0_NOT_FOUND_FOR_URI_1 = "Domain \"{0}\" not found for URI \"{1}\"";
public static final String SERVICE_BINDING_BETWEEN_SERVICE_WITH_GUID_0_AND_APPLICATION_WITH_GUID_1_NOT_FOUND = "Service binding between service with GUID \"{0}\" and application with GUID \"{1}\" not found.";
public static final String SERVICE_PLAN_WITH_GUID_0_NOT_AVAILABLE_FOR_SERVICE_INSTANCE_1 = "Service plan with guid \"{0}\" is not available for service instance \"{1}\".";
public static final String NO_SERVICE_PLAN_FOUND = "Service plan with guid \"{0}\" for service instance with name \"{1}\" was not found.";
public static final String SERVICE_OFFERING_WITH_GUID_0_IS_NOT_AVAILABLE = "Service offering with guid \"{0}\" is not available.";
public static final String SERVICE_OFFERING_WITH_GUID_0_NOT_FOUND = "Service offering with guid \"{0}\" not found.";
public static final String TARGET_SPACE_REQUIRED_TO_CREATE_AN_APPLICATION = "A target space is required to create an application.";
public static final String JOB_0_DID_NOT_COMPLETE_WITHIN_1 = "Job \"{0}\" did not complete within \"{1}\"";
public static final String ORGANIZATION_WITH_GUID_0_NOT_FOUND = "Organization with GUID \"{0}\" not found.";
public static final String SPACE_0_NOT_FOUND_IN_ORGANIZATION_1 = "Space \"{0}\" not found in organization \"{1}\"";
public static final String INTERRUPTED_WHILE_POLLING_ASYNC_JOB_0 = "Interrupted while polling an async job: \"{0}\"";
public static final String UNKNOWN_JOB_STATE_0 = "Unknown job state: \"{0}\"";
public static final String UNKNOWN_SERVICE_INSTANCE_TYPE_0 = "Unknown service instance type: \"{0}\"";
public static final String UNKNOWN_USER_ROLE_0 = "Unknown user role: \"{0}\"";

//Status texts
public static final String NOT_FOUND = "Not Found";
public static final String JOB_TIMEOUT = "Job Timeout";
public static final String JOB_FAILED = "Job Failed";
public static final String BAD_REQUEST = "Bad Request";
public static final String FORBIDDEN = "Forbidden";

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.util.function.Function;
import java.util.function.Supplier;

import org.cloudfoundry.client.v3.Metadata;
import org.cloudfoundry.multiapps.controller.client.facade.ApplicationServicesUpdateCallback;
import org.cloudfoundry.multiapps.controller.client.facade.CloudControllerClient;
import org.cloudfoundry.multiapps.controller.client.facade.CloudControllerClientImpl;
Expand All @@ -35,6 +34,7 @@
import org.cloudfoundry.multiapps.controller.client.facade.domain.DockerInfo;
import org.cloudfoundry.multiapps.controller.client.facade.domain.DropletInfo;
import org.cloudfoundry.multiapps.controller.client.facade.domain.InstancesInfo;
import org.cloudfoundry.multiapps.controller.client.facade.domain.Metadata;
import org.cloudfoundry.multiapps.controller.client.facade.domain.ServicePlanVisibility;
import org.cloudfoundry.multiapps.controller.client.facade.domain.Staging;
import org.cloudfoundry.multiapps.controller.client.facade.domain.Upload;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.cloudfoundry.multiapps.controller.client.facade;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface AllowNulls {
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import java.util.Set;
import java.util.UUID;

import org.cloudfoundry.client.v3.Metadata;
import org.cloudfoundry.multiapps.controller.client.facade.domain.Metadata;
import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudApplication;
import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudAsyncJob;
import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudBuild;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import java.util.UUID;
import java.util.function.Supplier;

import org.cloudfoundry.AbstractCloudFoundryException;
import org.cloudfoundry.client.v3.Metadata;
import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudApplication;
import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudAsyncJob;
import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudBuild;
Expand All @@ -32,6 +30,7 @@
import org.cloudfoundry.multiapps.controller.client.facade.domain.DockerInfo;
import org.cloudfoundry.multiapps.controller.client.facade.domain.DropletInfo;
import org.cloudfoundry.multiapps.controller.client.facade.domain.InstancesInfo;
import org.cloudfoundry.multiapps.controller.client.facade.domain.Metadata;
import org.cloudfoundry.multiapps.controller.client.facade.domain.ServicePlanVisibility;
import org.cloudfoundry.multiapps.controller.client.facade.domain.Staging;
import org.cloudfoundry.multiapps.controller.client.facade.domain.Upload;
Expand All @@ -40,7 +39,6 @@
import org.cloudfoundry.multiapps.controller.client.facade.rest.CloudControllerRestClient;
import org.cloudfoundry.multiapps.controller.client.facade.rest.CloudControllerRestClientFactory;
import org.cloudfoundry.multiapps.controller.client.facade.rest.ImmutableCloudControllerRestClientFactory;
import org.springframework.http.HttpStatus;
import org.springframework.util.Assert;

/**
Expand Down Expand Up @@ -659,16 +657,9 @@ private void handleExceptions(Runnable runnable) {
}

private <T> T handleExceptions(Supplier<T> runnable) {
try {
return runnable.get();
} catch (AbstractCloudFoundryException e) {
throw convertV3ClientException(e);
}
}

private CloudOperationException convertV3ClientException(AbstractCloudFoundryException e) {
HttpStatus httpStatus = HttpStatus.valueOf(e.getStatusCode());
return new CloudOperationException(httpStatus, httpStatus.getReasonPhrase(), e.getMessage(), e);
// The underlying CloudControllerRestClient already surfaces failures as CloudOperationException
// (via CloudControllerResponseErrorHandler), so no exception translation is needed here.
return runnable.get();
}

}
Loading
Loading