Allow CF deployment properties defaults to be provided via configuration.

This commit is contained in:
Scott Frederick
2018-10-08 14:12:28 -05:00
parent 6c0ddfc000
commit 43950e446c
14 changed files with 245 additions and 323 deletions

View File

@@ -51,7 +51,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@AutoConfigureAfter(AppDeployerAutoConfiguration.class)
@AutoConfigureAfter(CloudFoundryAppDeployerAutoConfiguration.class)
@ConditionalOnBean(AppDeployer.class)
public class AppBrokerAutoConfiguration {

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2016-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.appbroker.autoconfigure;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.cloud.appbroker.deployer.AppDeployer;
import org.springframework.cloud.appbroker.deployer.cloudfoundry.CloudFoundryAppDeployer;
import org.springframework.cloud.appbroker.deployer.cloudfoundry.CloudFoundryDeploymentProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
@Configuration
@AutoConfigureAfter(CloudFoundryClientAutoConfiguration.class)
public class AppDeployerAutoConfiguration {
@Bean
@ConditionalOnBean(CloudFoundryOperations.class)
public AppDeployer cloudFoundryAppDeployer(CloudFoundryOperations cloudFoundryOperations,
CloudFoundryProperties cloudFoundryProperties,
ResourceLoader resourceLoader) {
CloudFoundryDeploymentProperties cloudFoundryDeploymentProperties = new CloudFoundryDeploymentProperties();
cloudFoundryDeploymentProperties.setDefaultOrg(cloudFoundryProperties.getDefaultOrg());
cloudFoundryDeploymentProperties.setUsername(cloudFoundryProperties.getUsername());
return new CloudFoundryAppDeployer(cloudFoundryDeploymentProperties, cloudFoundryOperations, resourceLoader);
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright 2016-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.appbroker.autoconfigure;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.doppler.DopplerClient;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.DefaultCloudFoundryOperations;
import org.cloudfoundry.reactor.ConnectionContext;
import org.cloudfoundry.reactor.DefaultConnectionContext;
import org.cloudfoundry.reactor.TokenProvider;
import org.cloudfoundry.reactor.client.ReactorCloudFoundryClient;
import org.cloudfoundry.reactor.doppler.ReactorDopplerClient;
import org.cloudfoundry.reactor.tokenprovider.PasswordGrantTokenProvider;
import org.cloudfoundry.reactor.uaa.ReactorUaaClient;
import org.cloudfoundry.uaa.UaaClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.appbroker.deployer.AppDeployer;
import org.springframework.cloud.appbroker.deployer.cloudfoundry.CloudFoundryAppDeployer;
import org.springframework.cloud.appbroker.deployer.cloudfoundry.CloudFoundryDeploymentProperties;
import org.springframework.cloud.appbroker.deployer.cloudfoundry.CloudFoundryTargetProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import java.util.Optional;
@Configuration
@ConditionalOnProperty(CloudFoundryAppDeployerAutoConfiguration.PROPERTY_PREFIX + ".api-host")
@EnableConfigurationProperties
public class CloudFoundryAppDeployerAutoConfiguration {
static final String PROPERTY_PREFIX = "spring.cloud.appbroker.deployer.cloudfoundry";
@Bean
@ConfigurationProperties(PROPERTY_PREFIX + ".properties")
public CloudFoundryDeploymentProperties cloudFoundryDeploymentProperties() {
return new CloudFoundryDeploymentProperties();
}
@Bean
@ConfigurationProperties(PROPERTY_PREFIX)
CloudFoundryTargetProperties cloudFoundryTargetProperties() {
return new CloudFoundryTargetProperties();
}
@Bean
public AppDeployer cloudFoundryAppDeployer(CloudFoundryOperations cloudFoundryOperations,
CloudFoundryTargetProperties targetProperties,
CloudFoundryDeploymentProperties deploymentProperties,
ResourceLoader resourceLoader) {
return new CloudFoundryAppDeployer(targetProperties, deploymentProperties, cloudFoundryOperations, resourceLoader);
}
@Bean
ReactorCloudFoundryClient cloudFoundryClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
return ReactorCloudFoundryClient.builder()
.connectionContext(connectionContext)
.tokenProvider(tokenProvider)
.build();
}
@Bean
CloudFoundryOperations cloudFoundryOperations(CloudFoundryTargetProperties properties, CloudFoundryClient client,
DopplerClient dopplerClient, UaaClient uaaClient) {
return DefaultCloudFoundryOperations.builder()
.cloudFoundryClient(client)
.dopplerClient(dopplerClient)
.uaaClient(uaaClient)
.organization(properties.getDefaultOrg())
.space(properties.getDefaultSpace())
.build();
}
@Bean
DefaultConnectionContext connectionContext(CloudFoundryTargetProperties properties) {
return DefaultConnectionContext.builder()
.apiHost(properties.getApiHost())
.port(Optional.ofNullable(properties.getApiPort()))
.skipSslValidation(properties.isSkipSslValidation())
.secure(properties.isSecure())
.build();
}
@Bean
ReactorDopplerClient dopplerClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
return ReactorDopplerClient.builder()
.connectionContext(connectionContext)
.tokenProvider(tokenProvider)
.build();
}
@Bean
@ConditionalOnProperty({CloudFoundryAppDeployerAutoConfiguration.PROPERTY_PREFIX + ".username",
CloudFoundryAppDeployerAutoConfiguration.PROPERTY_PREFIX + ".password"})
PasswordGrantTokenProvider tokenProvider(CloudFoundryTargetProperties properties) {
return PasswordGrantTokenProvider.builder()
.password(properties.getPassword())
.username(properties.getUsername())
.build();
}
@Bean
ReactorUaaClient uaaClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
return ReactorUaaClient.builder()
.connectionContext(connectionContext)
.tokenProvider(tokenProvider)
.build();
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright 2016-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.appbroker.autoconfigure;
import java.util.Optional;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.doppler.DopplerClient;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.DefaultCloudFoundryOperations;
import org.cloudfoundry.reactor.ConnectionContext;
import org.cloudfoundry.reactor.DefaultConnectionContext;
import org.cloudfoundry.reactor.TokenProvider;
import org.cloudfoundry.reactor.client.ReactorCloudFoundryClient;
import org.cloudfoundry.reactor.doppler.ReactorDopplerClient;
import org.cloudfoundry.reactor.tokenprovider.PasswordGrantTokenProvider;
import org.cloudfoundry.reactor.uaa.ReactorUaaClient;
import org.cloudfoundry.uaa.UaaClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnProperty(CloudFoundryProperties.PROPERTY_PREFIX + ".api-host")
@EnableConfigurationProperties(CloudFoundryProperties.class)
public class CloudFoundryClientAutoConfiguration {
@Bean
ReactorCloudFoundryClient cloudFoundryClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
return ReactorCloudFoundryClient.builder()
.connectionContext(connectionContext)
.tokenProvider(tokenProvider)
.build();
}
@Bean
CloudFoundryOperations cloudFoundryOperations(CloudFoundryProperties properties, CloudFoundryClient client,
DopplerClient dopplerClient, UaaClient uaaClient) {
return DefaultCloudFoundryOperations.builder()
.cloudFoundryClient(client)
.dopplerClient(dopplerClient)
.uaaClient(uaaClient)
.organization(properties.getDefaultOrg())
.space(properties.getDefaultSpace())
.build();
}
@Bean
DefaultConnectionContext connectionContext(CloudFoundryProperties properties) {
return DefaultConnectionContext.builder()
.apiHost(properties.getApiHost())
.port(Optional.ofNullable(properties.getApiPort()))
.skipSslValidation(properties.isSkipSslValidation())
.secure(properties.isSecure())
.build();
}
@Bean
ReactorDopplerClient dopplerClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
return ReactorDopplerClient.builder()
.connectionContext(connectionContext)
.tokenProvider(tokenProvider)
.build();
}
@Bean
@ConditionalOnProperty({CloudFoundryProperties.PROPERTY_PREFIX + ".username",
CloudFoundryProperties.PROPERTY_PREFIX + ".password"})
PasswordGrantTokenProvider tokenProvider(CloudFoundryProperties properties) {
return PasswordGrantTokenProvider.builder()
.password(properties.getPassword())
.username(properties.getUsername())
.build();
}
@Bean
ReactorUaaClient uaaClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
return ReactorUaaClient.builder()
.connectionContext(connectionContext)
.tokenProvider(tokenProvider)
.build();
}
}

View File

@@ -1,4 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.appbroker.autoconfigure.CloudFoundryClientAutoConfiguration,\
org.springframework.cloud.appbroker.autoconfigure.AppDeployerAutoConfiguration,\
org.springframework.cloud.appbroker.autoconfigure.CloudFoundryAppDeployerAutoConfiguration,\
org.springframework.cloud.appbroker.autoconfigure.AppBrokerAutoConfiguration

View File

@@ -40,10 +40,9 @@ class AppBrokerAutoConfigurationTest {
.withConfiguration(AutoConfigurations.of(AppBrokerAutoConfiguration.class));
@Test
void servicesAreCreatedWithAppDeployerConfigured() {
void servicesAreCreatedWithCloudFoundryConfigured() {
this.contextRunner
.withConfiguration(AutoConfigurations.of(AppDeployerAutoConfiguration.class,
CloudFoundryClientAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(CloudFoundryAppDeployerAutoConfiguration.class))
.withPropertyValues(
"spring.cloud.appbroker.services[0].service-name=service1",
"spring.cloud.appbroker.services[0].plan-name=service1-plan1",

View File

@@ -28,13 +28,16 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.appbroker.deployer.AppDeployer;
import org.springframework.cloud.appbroker.deployer.cloudfoundry.CloudFoundryDeploymentProperties;
import org.springframework.cloud.appbroker.deployer.cloudfoundry.CloudFoundryTargetProperties;
import static org.assertj.core.api.Assertions.assertThat;
class CloudFoundryClientAutoConfigurationTest {
class CloudFoundryAppDeployerAutoConfigurationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CloudFoundryClientAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(CloudFoundryAppDeployerAutoConfiguration.class));
@Test
void clientIsCreatedWithPasswordGrantConfiguration() {
@@ -45,15 +48,28 @@ class CloudFoundryClientAutoConfigurationTest {
"spring.cloud.appbroker.deployer.cloudfoundry.default-org=example-org",
"spring.cloud.appbroker.deployer.cloudfoundry.default-space=example-space",
"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.properties.memory=2G",
"spring.cloud.appbroker.deployer.cloudfoundry.properties.count=3",
"spring.cloud.appbroker.deployer.cloudfoundry.properties.buildpack=example-buildpack",
"spring.cloud.appbroker.deployer.cloudfoundry.properties.domain=example.com"
)
.run((context) -> {
assertThat(context).hasSingleBean(CloudFoundryProperties.class);
CloudFoundryProperties cloudFoundryProperties = context.getBean(CloudFoundryProperties.class);
assertThat(cloudFoundryProperties.getApiHost()).isEqualTo("api.example.com");
assertThat(cloudFoundryProperties.getApiPort()).isEqualTo(443);
assertThat(cloudFoundryProperties.getDefaultOrg()).isEqualTo("example-org");
assertThat(cloudFoundryProperties.getDefaultSpace()).isEqualTo("example-space");
assertThat(context).hasSingleBean(CloudFoundryTargetProperties.class);
CloudFoundryTargetProperties targetProperties = context.getBean(CloudFoundryTargetProperties.class);
assertThat(targetProperties.getApiHost()).isEqualTo("api.example.com");
assertThat(targetProperties.getApiPort()).isEqualTo(443);
assertThat(targetProperties.getDefaultOrg()).isEqualTo("example-org");
assertThat(targetProperties.getDefaultSpace()).isEqualTo("example-space");
assertThat(context).hasSingleBean(CloudFoundryDeploymentProperties.class);
CloudFoundryDeploymentProperties deploymentProperties = context.getBean(CloudFoundryDeploymentProperties.class);
assertThat(deploymentProperties.getMemory()).isEqualTo("2G");
assertThat(deploymentProperties.getCount()).isEqualTo(3);
assertThat(deploymentProperties.getBuildpack()).isEqualTo("example-buildpack");
assertThat(deploymentProperties.getDomain()).isEqualTo("example.com");
assertThat(context).hasSingleBean(AppDeployer.class);
assertThat(context).hasSingleBean(ReactorCloudFoundryClient.class);
assertThat(context).hasSingleBean(ReactorDopplerClient.class);
@@ -68,7 +84,8 @@ class CloudFoundryClientAutoConfigurationTest {
void clientIsNotCreatedWithoutConfiguration() {
this.contextRunner
.run((context) -> {
assertThat(context).doesNotHaveBean(CloudFoundryProperties.class);
assertThat(context).doesNotHaveBean(CloudFoundryTargetProperties.class);
assertThat(context).doesNotHaveBean(CloudFoundryDeploymentProperties.class);
assertThat(context).doesNotHaveBean(ReactorCloudFoundryClient.class);
assertThat(context).doesNotHaveBean(ReactorDopplerClient.class);
assertThat(context).doesNotHaveBean(ReactorUaaClient.class);

View File

@@ -33,8 +33,10 @@ public class SpacePerServiceInstance extends TargetFactory<SpacePerServiceInstan
}
private Mono<BackingApplication> apply(BackingApplication backingApplication, String serviceInstanceId) {
backingApplication.getProperties().put(DeploymentProperties.HOST_KEY, backingApplication.getName() + "-" + serviceInstanceId);
backingApplication.getProperties().put(DeploymentProperties.TARGET_KEY, serviceInstanceId);
backingApplication.addProperty(DeploymentProperties.HOST_PROPERTY_KEY,
backingApplication.getName() + "-" + serviceInstanceId);
backingApplication.addProperty(DeploymentProperties.TARGET_PROPERTY_KEY,
serviceInstanceId);
return Mono.just(backingApplication);
}

View File

@@ -74,15 +74,18 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private final CloudFoundryTargetProperties targetProperties;
private final CloudFoundryDeploymentProperties defaultDeploymentProperties;
private final CloudFoundryOperations operations;
private ResourceLoader resourceLoader;
public CloudFoundryAppDeployer(CloudFoundryDeploymentProperties deploymentProperties,
public CloudFoundryAppDeployer(CloudFoundryTargetProperties targetProperties,
CloudFoundryDeploymentProperties deploymentProperties,
CloudFoundryOperations operations,
ResourceLoader resourceLoader) {
this.targetProperties = targetProperties;
this.defaultDeploymentProperties = deploymentProperties;
this.operations = operations;
this.resourceLoader = resourceLoader;
@@ -133,8 +136,8 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
.build();
Mono<Void> requestPushApplication = requestPushApplication(applicationManifestRequest);
if (deploymentProperties.containsKey(DeploymentProperties.TARGET_KEY)) {
String space = deploymentProperties.get(DeploymentProperties.TARGET_KEY);
if (deploymentProperties.containsKey(DeploymentProperties.TARGET_PROPERTY_KEY)) {
String space = deploymentProperties.get(DeploymentProperties.TARGET_PROPERTY_KEY);
requestPushApplication = requestPushApplicationInSpace(applicationManifestRequest, space);
}
@@ -202,7 +205,7 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
private Mono<String> getOrganizationIdPublisher() {
OrganizationInfoRequest organizationInfoRequest =
OrganizationInfoRequest.builder().name(this.defaultDeploymentProperties.getDefaultOrg()).build();
OrganizationInfoRequest.builder().name(this.targetProperties.getDefaultOrg()).build();
return this.operations.organizations().get(organizationInfoRequest).map(OrganizationDetail::getId);
}
@@ -214,8 +217,8 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
Map<String, String> deploymentProperties = request.getProperties();
Mono<Void> requestDeleteApplication;
if (deploymentProperties.containsKey(DeploymentProperties.TARGET_KEY)) {
String space = deploymentProperties.get(DeploymentProperties.TARGET_KEY);
if (deploymentProperties.containsKey(DeploymentProperties.TARGET_PROPERTY_KEY)) {
String space = deploymentProperties.get(DeploymentProperties.TARGET_PROPERTY_KEY);
requestDeleteApplication = requestDeleteApplicationInSpace(appName, space)
.then(createSpaceOperations().delete(DeleteSpaceRequest.builder().name(space).build()));
} else {
@@ -259,7 +262,7 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
return new DefaultSpaces(
((DefaultCloudFoundryOperations) this.operations).getCloudFoundryClientPublisher() ,
getOrganizationIdPublisher(),
Mono.just(this.defaultDeploymentProperties.getUsername()));
Mono.just(this.targetProperties.getUsername()));
}
private Map<String, String> getEnvironmentVariables(Map<String, String> environment) {
@@ -309,7 +312,7 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
}
private boolean useSpringApplicationJson(Map<String, String> environment) {
return Optional.ofNullable(environment.get(CloudFoundryDeploymentProperties.USE_SPRING_APPLICATION_JSON_KEY))
return Optional.ofNullable(environment.get(DeploymentProperties.USE_SPRING_APPLICATION_JSON_KEY))
.map(Boolean::valueOf)
.orElse(this.defaultDeploymentProperties.isUseSpringApplicationJson());
}
@@ -348,11 +351,11 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
private Integer instances(Map<String, String> properties) {
return Optional.ofNullable(properties.get(DeploymentProperties.COUNT_PROPERTY_KEY))
.map(Integer::parseInt)
.orElse(this.defaultDeploymentProperties.getInstances());
.orElse(this.defaultDeploymentProperties.getCount());
}
private String host(Map<String, String> properties) {
return Optional.ofNullable(properties.get(CloudFoundryDeploymentProperties.HOST_PROPERTY))
return Optional.ofNullable(properties.get(DeploymentProperties.HOST_PROPERTY_KEY))
.orElse(this.defaultDeploymentProperties.getHost());
}

View File

@@ -17,7 +17,7 @@
package org.springframework.cloud.appbroker.deployer.cloudfoundry;
import org.cloudfoundry.operations.applications.ApplicationHealthCheck;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.appbroker.deployer.DeploymentProperties;
import java.time.Duration;
import java.util.HashSet;
@@ -32,7 +32,7 @@ import java.util.Set;
* @author Ilayaperumal Gopinathan
*/
@SuppressWarnings({"unused", "PMD.TooManyFields"})
public class CloudFoundryDeploymentProperties {
public class CloudFoundryDeploymentProperties extends DeploymentProperties {
static final String HEALTHCHECK_PROPERTY_KEY = "health-check";
static final String HEALTHCHECK_HTTP_ENDPOINT_PROPERTY_KEY = "health-check-http-endpoint";
@@ -47,21 +47,12 @@ public class CloudFoundryDeploymentProperties {
static final String NO_ROUTE_PROPERTY = "no-route";
static final String HOST_PROPERTY = "host";
static final String DOMAIN_PROPERTY = "domain";
static final String BUILDPACK_PROPERTY_KEY = "buildpack";
static final String JAVA_OPTS_PROPERTY_KEY = "javaOpts";
static final String USE_SPRING_APPLICATION_JSON_KEY = "use-spring-application-json";
/**
* The host name to use as part of the route. Defaults to hostname derived by Cloud Foundry.
*/
private String host;
/**
* The domain to use when mapping routes for applications.
*/
@@ -78,16 +69,6 @@ public class CloudFoundryDeploymentProperties {
*/
private String buildpack;
/**
* The amount of memory to allocate, if not overridden per-app. Default unit is mebibytes, 'M' and 'G" suffixes supported.
*/
private String memory;
/**
* The amount of disk space to allocate, if not overridden per-app. Default unit is mebibytes, 'M' and 'G" suffixes supported.
*/
private String disk;
/**
* The type of health check to perform on deployed application, if not overridden per-app. Defaults to PORT
*/
@@ -103,11 +84,6 @@ public class CloudFoundryDeploymentProperties {
*/
private Integer healthCheckTimeout;
/**
* The number of instances to run.
*/
private Integer instances;
/**
* Flag to enable prefixing the app name with a random prefix.
*/
@@ -123,11 +99,6 @@ public class CloudFoundryDeploymentProperties {
*/
private long statusTimeout = 5_000L;
/**
* Flag to indicate whether application properties are fed into SPRING_APPLICATION_JSON or ENVIRONMENT VARIABLES.
*/
private boolean useSpringApplicationJson = true;
/**
* If set, override the timeout allocated for staging the app by the client.
*/
@@ -138,12 +109,6 @@ public class CloudFoundryDeploymentProperties {
*/
private Duration startupTimeout = Duration.ofMinutes(5L);
/**
* String to use as prefix for name of deployed app. Defaults to spring.application.name.
*/
@Value("${spring.application.name:}")
private String appNamePrefix;
/**
* Whether to also delete routes when un-deploying an application.
*/
@@ -151,10 +116,6 @@ public class CloudFoundryDeploymentProperties {
private String javaOpts;
private String defaultOrg;
private String username;
public String getBuildpack() {
return buildpack;
}
@@ -163,30 +124,6 @@ public class CloudFoundryDeploymentProperties {
this.buildpack = buildpack;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getDisk() {
return disk;
}
public void setDisk(String disk) {
this.disk = disk;
}
public Integer getInstances() {
return instances;
}
public void setInstances(int instances) {
this.instances = instances;
}
public boolean isEnableRandomAppNamePrefix() {
return enableRandomAppNamePrefix;
}
@@ -195,14 +132,6 @@ public class CloudFoundryDeploymentProperties {
this.enableRandomAppNamePrefix = enableRandomAppNamePrefix;
}
public String getAppNamePrefix() {
return appNamePrefix;
}
public void setAppNamePrefix(String appNamePrefix) {
this.appNamePrefix = appNamePrefix;
}
public long getApiTimeout() {
return apiTimeout;
}
@@ -211,14 +140,6 @@ public class CloudFoundryDeploymentProperties {
this.apiTimeout = apiTimeout;
}
public boolean isUseSpringApplicationJson() {
return useSpringApplicationJson;
}
public void setUseSpringApplicationJson(boolean useSpringApplicationJson) {
this.useSpringApplicationJson = useSpringApplicationJson;
}
public ApplicationHealthCheck getHealthCheck() {
return healthCheck;
}
@@ -251,14 +172,6 @@ public class CloudFoundryDeploymentProperties {
this.domain = domain;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public Set<String> getRoutes() {
return routes;
}
@@ -306,20 +219,4 @@ public class CloudFoundryDeploymentProperties {
public void setJavaOpts(String javaOpts) {
this.javaOpts = javaOpts;
}
public String getDefaultOrg() {
return defaultOrg;
}
public void setDefaultOrg(String defaultOrg) {
this.defaultOrg = defaultOrg;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

View File

@@ -14,18 +14,13 @@
* limitations under the License.
*/
package org.springframework.cloud.appbroker.autoconfigure;
package org.springframework.cloud.appbroker.deployer.cloudfoundry;
import java.net.URI;
import org.cloudfoundry.reactor.ProxyConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(CloudFoundryProperties.PROPERTY_PREFIX)
public class CloudFoundryProperties {
static final String PROPERTY_PREFIX = "spring.cloud.appbroker.deployer.cloudfoundry";
public class CloudFoundryTargetProperties {
private String apiHost;
private Integer apiPort;

View File

@@ -61,7 +61,7 @@ class CloudFoundryAppDeployerTest {
@Mock
private ResourceLoader resourceLoader;
private CloudFoundryDeploymentProperties deploymentProperties;
@BeforeEach
@@ -76,7 +76,7 @@ class CloudFoundryAppDeployerTest {
.thenReturn(new FileSystemResource(APP_PATH));
appDeployer = new CloudFoundryAppDeployer(
deploymentProperties, cloudFoundryOperations, resourceLoader);
new CloudFoundryTargetProperties(), deploymentProperties, cloudFoundryOperations, resourceLoader);
}
@Test
@@ -110,7 +110,7 @@ class CloudFoundryAppDeployerTest {
.property(CloudFoundryDeploymentProperties.HEALTHCHECK_HTTP_ENDPOINT_PROPERTY_KEY, "/healthcheck")
.property(CloudFoundryDeploymentProperties.BUILDPACK_PROPERTY_KEY, "buildpack")
.property(CloudFoundryDeploymentProperties.DOMAIN_PROPERTY, "domain")
.property(CloudFoundryDeploymentProperties.HOST_PROPERTY, "host")
.property(DeploymentProperties.HOST_PROPERTY_KEY, "host")
.property(CloudFoundryDeploymentProperties.NO_ROUTE_PROPERTY, "true")
.build();
@@ -137,7 +137,7 @@ class CloudFoundryAppDeployerTest {
@Test
void deployAppWithDefaultProperties() {
deploymentProperties.setInstances(3);
deploymentProperties.setCount(3);
deploymentProperties.setMemory("2G");
deploymentProperties.setDisk("3G");
deploymentProperties.setBuildpack("buildpack");
@@ -173,7 +173,7 @@ class CloudFoundryAppDeployerTest {
@Test
void deployAppWithRequestOverridingDefaultProperties() {
deploymentProperties.setInstances(3);
deploymentProperties.setCount(3);
deploymentProperties.setMemory("2G");
deploymentProperties.setDisk("3G");
deploymentProperties.setBuildpack("buildpack1");
@@ -192,7 +192,7 @@ class CloudFoundryAppDeployerTest {
.property(CloudFoundryDeploymentProperties.HEALTHCHECK_HTTP_ENDPOINT_PROPERTY_KEY, "/healthcheck2")
.property(CloudFoundryDeploymentProperties.BUILDPACK_PROPERTY_KEY, "buildpack2")
.property(CloudFoundryDeploymentProperties.DOMAIN_PROPERTY, "domain2")
.property(CloudFoundryDeploymentProperties.HOST_PROPERTY, "host2")
.property(DeploymentProperties.HOST_PROPERTY_KEY, "host2")
.property(CloudFoundryDeploymentProperties.NO_ROUTE_PROPERTY, "true")
.build();

View File

@@ -16,8 +16,6 @@
package org.springframework.cloud.appbroker.deployer;
import org.springframework.cloud.appbroker.deployer.util.ByteSizeUtils;
public class DeploymentProperties {
/**
* The deployment property for the count (number of app instances).
@@ -31,23 +29,6 @@ public class DeploymentProperties {
*/
public static final String GROUP_PROPERTY_KEY = "group";
/**
* The deployment property that indicates if each app instance should have an index value
* within a sequence from 0 to N-1, where N is the value of the {@value #COUNT_PROPERTY_KEY}
* property. If not provided, a deployer should assume app instance indexing is not necessary.
*/
public static final String INDEXED_PROPERTY_KEY = "indexed";
/**
* The property to be set at each instance level to specify the sequence number
* amongst 0 to N-1, where N is the value of the {@value #COUNT_PROPERTY_KEY} property.
* Specified as CAPITAL_WITH_UNDERSCORES as this is typically passed as an environment
* variable, but when targeting a Spring app, other variations may apply.
*
* @see #INDEXED_PROPERTY_KEY
*/
public static final String INSTANCE_INDEX_PROPERTY_KEY = "INSTANCE_INDEX";
/**
* The deployment property for the memory setting for the container that will run the app.
* The memory is specified in <a href="https://en.wikipedia.org/wiki/Mebibyte">Mebibytes</a>,
@@ -57,8 +38,6 @@ public class DeploymentProperties {
* 1 MiB = 2^20 bytes = 1024*1024 bytes vs. the decimal based 1MB = 10^6 bytes = 1000*1000 bytes,
* <p>
* Implementations are expected to translate this value to the target platform as faithfully as possible.
*
* @see ByteSizeUtils
*/
public static final String MEMORY_PROPERTY_KEY = "memory";
@@ -71,27 +50,69 @@ public class DeploymentProperties {
* 1 MiB = 2^20 bytes = 1024*1024 bytes vs. the decimal based 1MB = 10^6 bytes = 1000*1000 bytes,
* <p>
* Implementations are expected to translate this value to the target platform as faithfully as possible.
*
* @see ByteSizeUtils
*/
public static final String DISK_PROPERTY_KEY = "disk";
/**
* The deployment property for the cpu setting for the container that will run the app.
* The cpu is specified as whole multiples or decimal fractions of virtual cores. Some platforms will not
* support setting cpu and will ignore this setting. Other platforms may require whole numbers and might
* round up. Exactly how this property affects the deployments will vary between implementations.
*/
public static final String CPU_PROPERTY_KEY = "cpu";
/**
* The deployment property for the host that will be used in the app.
*/
public static final String HOST_KEY = "host";
public static final String HOST_PROPERTY_KEY = "host";
/**
* The deployment property for the location where the app will be deployed.
* The location will vary between implementations.
*/
public static final String TARGET_KEY = "target";
public static final String TARGET_PROPERTY_KEY = "target";
public static final String USE_SPRING_APPLICATION_JSON_KEY = "use-spring-application-json";
private String host;
private String memory;
private String disk;
private Integer count;
private boolean useSpringApplicationJson = true;
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getDisk() {
return disk;
}
public void setDisk(String disk) {
this.disk = disk;
}
public Integer getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public boolean isUseSpringApplicationJson() {
return useSpringApplicationJson;
}
public void setUseSpringApplicationJson(boolean useSpringApplicationJson) {
this.useSpringApplicationJson = useSpringApplicationJson;
}
}

View File

@@ -32,6 +32,10 @@ import static org.hamcrest.Matchers.is;
import static org.springframework.cloud.appbroker.sample.CreateInstanceWithPropertiesComponentTest.APP_NAME;
@TestPropertySource(properties = {
"spring.cloud.appbroker.deployer.cloudfoundry.properties.memory=1G",
"spring.cloud.appbroker.deployer.cloudfoundry.properties.count=1",
"spring.cloud.appbroker.deployer.cloudfoundry.properties.health-check=http",
"spring.cloud.appbroker.deployer.cloudfoundry.properties.health-check-http-endpoint=/myhealth",
"spring.cloud.appbroker.services[0].service-name=example",
"spring.cloud.appbroker.services[0].plan-name=standard",
"spring.cloud.appbroker.services[0].apps[0].path=classpath:demo.jar",
@@ -56,7 +60,9 @@ class CreateInstanceWithPropertiesComponentTest extends WiremockComponentTest {
cloudControllerFixture.stubPushApp(APP_NAME,
matchingJsonPath("$.[?(@.memory == '2048')]"),
matchingJsonPath("$.[?(@.instances == '2')]"),
matchingJsonPath("$.[?(@.health_check_timeout == '180')]"));
matchingJsonPath("$.[?(@.health_check_timeout == '180')]"),
matchingJsonPath("$.[?(@.health_check_type == 'http')]"),
matchingJsonPath("$.[?(@.health_check_http_endpoint == '/myhealth')]"));
// when a service instance is created
given(brokerFixture.serviceInstanceRequest())