diff --git a/spring-cloud-app-broker-autoconfigure/src/test/java/org/springframework/cloud/appbroker/autoconfigure/AppBrokerAutoConfigurationTest.java b/spring-cloud-app-broker-autoconfigure/src/test/java/org/springframework/cloud/appbroker/autoconfigure/AppBrokerAutoConfigurationTest.java index bb387248..84952402 100644 --- a/spring-cloud-app-broker-autoconfigure/src/test/java/org/springframework/cloud/appbroker/autoconfigure/AppBrokerAutoConfigurationTest.java +++ b/spring-cloud-app-broker-autoconfigure/src/test/java/org/springframework/cloud/appbroker/autoconfigure/AppBrokerAutoConfigurationTest.java @@ -30,6 +30,7 @@ import org.springframework.cloud.appbroker.deployer.BrokeredService; import org.springframework.cloud.appbroker.deployer.BrokeredServices; import org.springframework.cloud.appbroker.deployer.DeployerClient; +import org.springframework.cloud.appbroker.deployer.cloudfoundry.CloudFoundryTargetProperties; import org.springframework.cloud.appbroker.extensions.parameters.BackingApplicationsParametersTransformationService; import org.springframework.cloud.appbroker.extensions.parameters.BackingServicesParametersTransformationService; import org.springframework.cloud.appbroker.extensions.parameters.EnvironmentMappingParametersTransformerFactory; @@ -217,7 +218,9 @@ private ApplicationContextRunner configuredContext() { "spring.cloud.appbroker.deployer.cloudfoundry.api-host=https://api.example.local", "spring.cloud.appbroker.deployer.cloudfoundry.username=user", - "spring.cloud.appbroker.deployer.cloudfoundry.password=secret" + "spring.cloud.appbroker.deployer.cloudfoundry.password=secret", + "spring.cloud.appbroker.deployer.cloudfoundry.staging-timeout=3", + "spring.cloud.appbroker.deployer.cloudfoundry.deployment-timeout=4" ); } @@ -255,6 +258,12 @@ private void assertBeansCreated(AssertableApplicationContext context) { } private void assertPropertiesLoaded(AssertableApplicationContext context) { + CloudFoundryTargetProperties cloudFoundryTargetProperties = context.getBean(CloudFoundryTargetProperties.class); + assertThat(cloudFoundryTargetProperties.getUsername()).isEqualTo("user"); + assertThat(cloudFoundryTargetProperties.getPassword()).isEqualTo("secret"); + assertThat(cloudFoundryTargetProperties.getDeploymentTimeout()).isEqualTo(4L); + assertThat(cloudFoundryTargetProperties.getStagingTimeout()).isEqualTo(3L); + BrokeredServices brokeredServices = context.getBean(BrokeredServices.class); assertThat(brokeredServices).hasSize(2); diff --git a/spring-cloud-app-broker-deployer-cloudfoundry/src/main/java/org/springframework/cloud/appbroker/deployer/cloudfoundry/CloudFoundryAppDeployer.java b/spring-cloud-app-broker-deployer-cloudfoundry/src/main/java/org/springframework/cloud/appbroker/deployer/cloudfoundry/CloudFoundryAppDeployer.java index ecdb9b96..063d3634 100644 --- a/spring-cloud-app-broker-deployer-cloudfoundry/src/main/java/org/springframework/cloud/appbroker/deployer/cloudfoundry/CloudFoundryAppDeployer.java +++ b/spring-cloud-app-broker-deployer-cloudfoundry/src/main/java/org/springframework/cloud/appbroker/deployer/cloudfoundry/CloudFoundryAppDeployer.java @@ -137,10 +137,11 @@ import org.springframework.http.HttpStatus; import org.springframework.util.StringUtils; -//TODO: refactor this class @SuppressWarnings({"PMD.GodClass", "PMD.CyclomaticComplexity", "PMD.ExcessiveClassLength"}) public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware { + private static final Duration DEFAULT_PLATFORM_OPERATION_DURATION = Duration.ofMinutes(10); + private static final Logger LOG = LoggerFactory.getLogger(CloudFoundryAppDeployer.class); private static final String REQUEST_LOG_TEMPLATE = "request={}"; @@ -454,7 +455,7 @@ private Mono waitForDeploymentDeployed(String deploymentI .deploymentId(deploymentId) .build()) .filter(this::deploymentFinished) - .repeatWhenEmpty(getExponentialBackOff()) + .repeatWhenEmpty(getExponentialBackOff(getDeploymentTimeout())) .doOnRequest(l -> LOG.debug("Waiting for deployment to complete. deploymentId={}", deploymentId)) .doOnSuccess(response -> { LOG.info("Success waiting for deployment to complete. deploymentId={}", deploymentId); @@ -503,7 +504,7 @@ private Mono waitForBuildStaged(String buildId) { .buildId(buildId) .build()) .filter(p -> p.getState().equals(BuildState.STAGED)) - .repeatWhenEmpty(getExponentialBackOff()) + .repeatWhenEmpty(getExponentialBackOff(getStagingTimeout())) .doOnRequest(l -> LOG.debug("Waiting for build to stage. buildId={}", buildId)) .doOnSuccess(response -> { LOG.info("Success waiting for build to stage. buildId={}", buildId); @@ -535,7 +536,7 @@ private Mono waitForPackageReady(String packageId) { .packages() .get(GetPackageRequest.builder().packageId(packageId).build()) .filter(p -> p.getState().equals(PackageState.READY)) - .repeatWhenEmpty(getExponentialBackOff()) + .repeatWhenEmpty(getExponentialBackOff(DEFAULT_PLATFORM_OPERATION_DURATION)) .doOnRequest(l -> LOG.debug("Waiting for package ready. packageId={}", packageId)) .doOnSuccess(response -> { LOG.info("Success waiting for package ready. packageId={}", packageId); @@ -679,8 +680,22 @@ private Mono createPackageForApplication(String applicati applicationId, e.getMessage()), e)); } - private Function, Publisher> getExponentialBackOff() { - return DelayUtils.exponentialBackOff(Duration.ofSeconds(2), Duration.ofMinutes(5), Duration.ofMinutes(10)); + private Duration getStagingTimeout() { + if (targetProperties.getStagingTimeout() == null) { + return DEFAULT_PLATFORM_OPERATION_DURATION; + } + return Duration.ofMinutes(targetProperties.getStagingTimeout()); + } + + private Duration getDeploymentTimeout() { + if (targetProperties.getDeploymentTimeout() == null) { + return DEFAULT_PLATFORM_OPERATION_DURATION; + } + return Duration.ofMinutes(targetProperties.getDeploymentTimeout()); + } + + private Function, Publisher> getExponentialBackOff(Duration timeout) { + return DelayUtils.exponentialBackOff(Duration.ofSeconds(2), Duration.ofMinutes(5), timeout); } private Mono pushApplication(DeployApplicationRequest request, Map deploymentProperties, diff --git a/spring-cloud-app-broker-deployer-cloudfoundry/src/main/java/org/springframework/cloud/appbroker/deployer/cloudfoundry/CloudFoundryTargetProperties.java b/spring-cloud-app-broker-deployer-cloudfoundry/src/main/java/org/springframework/cloud/appbroker/deployer/cloudfoundry/CloudFoundryTargetProperties.java index 738ed5bd..45205e10 100644 --- a/spring-cloud-app-broker-deployer-cloudfoundry/src/main/java/org/springframework/cloud/appbroker/deployer/cloudfoundry/CloudFoundryTargetProperties.java +++ b/spring-cloud-app-broker-deployer-cloudfoundry/src/main/java/org/springframework/cloud/appbroker/deployer/cloudfoundry/CloudFoundryTargetProperties.java @@ -44,6 +44,10 @@ public class CloudFoundryTargetProperties { private String identityZoneSubdomain; + private Long deploymentTimeout; + + private Long stagingTimeout; + public String getApiHost() { return apiHost; } @@ -136,6 +140,22 @@ public ProxyConfiguration getProxyConfiguration() { return null; } + public Long getDeploymentTimeout() { + return deploymentTimeout; + } + + public void setDeploymentTimeout(Long deploymentTimeout) { + this.deploymentTimeout = deploymentTimeout; + } + + public Long getStagingTimeout() { + return stagingTimeout; + } + + public void setStagingTimeout(Long stagingTimeout) { + this.stagingTimeout = stagingTimeout; + } + private static String parseApiHost(String api) { final URI uri = URI.create(api); return uri.getHost() == null ? api : uri.getHost(); diff --git a/spring-cloud-app-broker-docs/src/docs/asciidoc/deployment-platforms.adoc b/spring-cloud-app-broker-docs/src/docs/asciidoc/deployment-platforms.adoc index 860aea08..cd5d9f34 100644 --- a/spring-cloud-app-broker-docs/src/docs/asciidoc/deployment-platforms.adoc +++ b/spring-cloud-app-broker-docs/src/docs/asciidoc/deployment-platforms.adoc @@ -21,6 +21,8 @@ spring: *client-secret: EXAMPLE_SECRET* *default-org: test* *default-space: development* + *staging-timeout: 15* + *deployment-timeout: 10* ---- ====