diff --git a/pom.xml b/pom.xml
index 906105c..d39a235 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,12 +23,12 @@
- https://github.com/spring-cloud/spring-cloud-consul
+ https://github.com/spring-cloud/spring-cloud-cloudfoundry
- scm:git:git://github.com/spring-cloud/spring-cloud-consul.git
+ scm:git:git://github.com/spring-cloud/spring-cloud-cloudfoundry.git
- scm:git:ssh://git@github.com/spring-cloud/spring-cloud-consul.git
+ scm:git:ssh://git@github.com/spring-cloud/spring-cloud-cloudfoundry.git
HEAD
diff --git a/spring-cloud-cloudfoundry-commons/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryClientAutoConfiguration.java b/spring-cloud-cloudfoundry-commons/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryClientAutoConfiguration.java
index ab03886..4cf5c00 100644
--- a/spring-cloud-cloudfoundry-commons/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryClientAutoConfiguration.java
+++ b/spring-cloud-cloudfoundry-commons/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryClientAutoConfiguration.java
@@ -43,9 +43,10 @@ import org.springframework.context.annotation.Lazy;
*
* @author Josh Long
* @author Ben Hale
+ * @author Scott Frederick
*/
@Configuration
-@ConditionalOnProperty(prefix = "spring.cloud.cloudfoundry", name = {"username", "password", "org", "space"})
+@ConditionalOnProperty(prefix = "spring.cloud.cloudfoundry", name = {"username", "password"})
@ConditionalOnClass(name = {"reactor.core.publisher.Flux", "org.cloudfoundry.operations.DefaultCloudFoundryOperations",
"org.cloudfoundry.reactor.client.ReactorCloudFoundryClient", "org.reactivestreams.Publisher"})
@EnableConfigurationProperties(CloudFoundryProperties.class)
@@ -64,16 +65,6 @@ public class CloudFoundryClientAutoConfiguration {
return new CloudFoundryService(cloudFoundryOperations);
}
- @Bean
- @Lazy
- @ConditionalOnMissingBean
- public ReactorCloudFoundryClient cloudFoundryClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
- return ReactorCloudFoundryClient.builder()
- .connectionContext(connectionContext)
- .tokenProvider(tokenProvider)
- .build();
- }
-
@Bean
@Lazy
@ConditionalOnMissingBean
@@ -93,18 +84,13 @@ public class CloudFoundryClientAutoConfiguration {
.space(space)
.build();
}
-
@Bean
@Lazy
@ConditionalOnMissingBean
- public DefaultConnectionContext connectionContext() {
-
- String apiHost = this.cloudFoundryProperties.getUrl();
- Boolean skipSslValidation = this.cloudFoundryProperties.isSkipSslValidation();
-
- return DefaultConnectionContext.builder()
- .apiHost(apiHost)
- .skipSslValidation(skipSslValidation)
+ public ReactorCloudFoundryClient cloudFoundryClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
+ return ReactorCloudFoundryClient.builder()
+ .connectionContext(connectionContext)
+ .tokenProvider(tokenProvider)
.build();
}
@@ -128,6 +114,29 @@ public class CloudFoundryClientAutoConfiguration {
.build();
}
+ @Bean
+ @Lazy
+ @ConditionalOnMissingBean
+ public ReactorUaaClient uaaClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
+ return ReactorUaaClient.builder()
+ .connectionContext(connectionContext)
+ .tokenProvider(tokenProvider)
+ .build();
+ }
+
+ @Bean
+ @Lazy
+ @ConditionalOnMissingBean
+ public DefaultConnectionContext connectionContext() {
+ String apiHost = this.cloudFoundryProperties.getUrl();
+ Boolean skipSslValidation = this.cloudFoundryProperties.isSkipSslValidation();
+
+ return DefaultConnectionContext.builder()
+ .apiHost(apiHost)
+ .skipSslValidation(skipSslValidation)
+ .build();
+ }
+
@Bean
@Lazy
@ConditionalOnMissingBean
@@ -139,16 +148,6 @@ public class CloudFoundryClientAutoConfiguration {
.username(username)
.build();
}
-
- @Bean
- @Lazy
- @ConditionalOnMissingBean
- public ReactorUaaClient uaaClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
- return ReactorUaaClient.builder()
- .connectionContext(connectionContext)
- .tokenProvider(tokenProvider)
- .build();
- }
}
diff --git a/spring-cloud-cloudfoundry-commons/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryProperties.java b/spring-cloud-cloudfoundry-commons/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryProperties.java
index ad29ff2..d87cb12 100644
--- a/spring-cloud-cloudfoundry-commons/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryProperties.java
+++ b/spring-cloud-cloudfoundry-commons/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryProperties.java
@@ -28,7 +28,10 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
+ * Configuration properties for a connection to a Cloud Foundry platform.
+ *
* @author Josh Long
+ * @author Scott Frederick
*/
@ConfigurationProperties(prefix = "spring.cloud.cloudfoundry")
public class CloudFoundryProperties implements InitializingBean {
@@ -36,7 +39,8 @@ public class CloudFoundryProperties implements InitializingBean {
/**
* URL of Cloud Foundry API (Cloud Controller).
*/
- private String url = "api.run.pivotal.io";
+ @Value("${vcap.application.cf_api:api.run.pivotal.io}")
+ private String url;
/**
* Username to authenticate (usually an email address).
@@ -49,12 +53,12 @@ public class CloudFoundryProperties implements InitializingBean {
private String password;
/**
- * Organization name to authenticate with (default to user's default).
+ * Organization name to initially target.
*/
private String org;
/**
- * Space name to authenticate with (default to user's default).
+ * Space name to initially target.
*/
@Value("${vcap.application.space_name:}")
private String space;
@@ -127,19 +131,21 @@ public class CloudFoundryProperties implements InitializingBean {
}
@Override
- public void afterPropertiesSet() throws Exception {
+ public void afterPropertiesSet() {
this.url = safeUrl(this.url);
this.password = this.password.trim();
this.username = this.username.trim();
- this.org = this.org.trim();
- this.space = this.space.trim();
+ if (this.org != null) {
+ this.org = this.org.trim();
+ }
+ if (this.space != null) {
+ this.space = this.space.trim();
+ }
Map vals = new HashMap<>();
- vals.put("org", getOrg());
vals.put("url", getUrl());
vals.put("username", getUsername());
vals.put("password", getPassword());
- vals.put("space", getSpace());
vals.forEach((key, value) -> Assert.hasText(value, String.format("'%s' must be provided", key)));
}
}
\ No newline at end of file
diff --git a/spring-cloud-cloudfoundry-commons/src/test/java/org/springframework/cloud/cloudfoundry/CloudFoundryClientAutoConfigurationTest.java b/spring-cloud-cloudfoundry-commons/src/test/java/org/springframework/cloud/cloudfoundry/CloudFoundryClientAutoConfigurationTest.java
index 55f849a..adacc83 100644
--- a/spring-cloud-cloudfoundry-commons/src/test/java/org/springframework/cloud/cloudfoundry/CloudFoundryClientAutoConfigurationTest.java
+++ b/spring-cloud-cloudfoundry-commons/src/test/java/org/springframework/cloud/cloudfoundry/CloudFoundryClientAutoConfigurationTest.java
@@ -16,39 +16,40 @@
package org.springframework.cloud.cloudfoundry;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.assertj.core.api.Assertions;
import org.cloudfoundry.doppler.DopplerClient;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.DefaultCloudFoundryOperations;
-import org.cloudfoundry.operations.applications.ApplicationDetail;
-import org.cloudfoundry.operations.applications.GetApplicationRequest;
-import org.cloudfoundry.operations.applications.InstanceDetail;
import org.cloudfoundry.operations.organizations.OrganizationSummary;
import org.cloudfoundry.reactor.DefaultConnectionContext;
import org.cloudfoundry.reactor.client.ReactorCloudFoundryClient;
import org.cloudfoundry.reactor.tokenprovider.PasswordGrantTokenProvider;
import org.cloudfoundry.reactor.uaa.ReactorUaaClient;
import org.cloudfoundry.routing.RoutingClient;
-import org.junit.Assert;
import org.junit.Assume;
-import org.junit.Ignore;
import org.junit.Test;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.context.ApplicationContext;
-import reactor.core.publisher.Flux;
-import reactor.util.function.Tuple2;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import static org.assertj.core.api.Assertions.assertThat;
public class CloudFoundryClientAutoConfigurationTest {
- @SpringBootApplication
- public static class MyConfig {
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(CloudFoundryClientAutoConfiguration.class));
+
+ private final static String SPRING_CLOUD_PROPERTIES[] = {
+ "spring.cloud.cloudfoundry.username",
+ "spring.cloud.cloudfoundry.password",
+ };
+
+ private static boolean requiredPropertiesSet() {
+ for (String k : SPRING_CLOUD_PROPERTIES) {
+ if (System.getenv(envVarFromProperty(k)) == null) {
+ return false;
+ }
+ }
+ return true;
}
private static String envVarFromProperty(String propertyName) {
@@ -57,89 +58,65 @@ public class CloudFoundryClientAutoConfigurationTest {
.toUpperCase();
}
- private static String CONFIG_KEYS[] = {"spring.cloud.cloudfoundry.username",
- "spring.cloud.cloudfoundry.password", "spring.cloud.cloudfoundry.space", "spring.cloud.cloudfoundry.org"};
-
- private static Map defaultConfig() {
- Map kvs = new HashMap<>();
- for (String k : CONFIG_KEYS)
- kvs.put(k, System.getenv(envVarFromProperty(k)));
- return kvs;
- }
-
- private static boolean configExists() {
- for (String k : CONFIG_KEYS)
- if (System.getenv(envVarFromProperty(k)) == null)
- return false;
- return true;
- }
-
@Test
- public void producesAllBeans() {
+ public void autoConfiguresBeansWithAllProperties() {
+ this.contextRunner
+ .withPropertyValues(
+ "spring.cloud.cloudfoundry.username=user",
+ "spring.cloud.cloudfoundry.password=secret",
+ "spring.cloud.cloudfoundry.org=myorg",
+ "spring.cloud.cloudfoundry.space=myspace")
+ .run((context) -> {
+ assertCloudFoundryClientBeansPresent(context);
- Assume.assumeTrue(configExists());
-
- ApplicationContext ctx = new SpringApplicationBuilder()
- .sources(MyConfig.class)
- .properties(defaultConfig())
- .run();
-
- Class[] tags = {ReactorCloudFoundryClient.class, DefaultCloudFoundryOperations.class,
- DefaultConnectionContext.class, DopplerClient.class, RoutingClient.class, PasswordGrantTokenProvider.class,
- ReactorUaaClient.class};
- for (Class> c : tags) {
- Assertions.assertThat(ctx.getBean(c)).isNotNull();
- }
- }
-
- @Test
- public void testConnectivity() throws Exception {
- Assume.assumeTrue(configExists());
-
- ApplicationContext ctx = new SpringApplicationBuilder()
- .sources(MyConfig.class)
- .properties(defaultConfig())
- .run();
-
- CloudFoundryOperations operations = ctx.getBean(CloudFoundryOperations.class);
- Assert.assertNotNull(operations);
- OrganizationSummary summary = operations
- .organizations()
- .list()
- .blockFirst();
- Assertions.assertThat(summary).isNotNull();
- Assertions.assertThat(summary.getId()).isNotEmpty();
- Assertions.assertThat(summary.getName()).isNotEmpty();
- }
-
- @Ignore
- @Test
- public void instances() throws Exception {
-
- Assume.assumeTrue(configExists());
-
- Log log = LogFactory.getLog(getClass());
- ApplicationContext ctx = new SpringApplicationBuilder()
- .sources(MyConfig.class)
- .properties(defaultConfig())
- .run();
-
- CloudFoundryOperations cf = ctx.getBean(CloudFoundryOperations.class);
- Flux> mapMany = cf
- .applications()
- .get(GetApplicationRequest.builder().name("lo-test").build())
- .flatMapMany(applicationDetail -> {
- List instanceDetails = applicationDetail.getInstanceDetails();
- Flux ids = Flux.fromStream(instanceDetails.stream());
- Flux generate = Flux.generate(sink -> sink.next(applicationDetail));
- return generate.zipWith(ids);
+ DefaultCloudFoundryOperations operations = context.getBean(DefaultCloudFoundryOperations.class);
+ assertThat(operations.getOrganization()).isEqualTo("myorg");
+ assertThat(operations.getSpace()).isEqualTo("myspace");
});
- mapMany
- .subscribe(p ->
- log.info(p.getT1().getName() + ':' + p.getT1().getId() + ':' + p.getT2().getIndex() + ':' +
- p.getT2().getState()));
-
- Thread.sleep(5 * 1000);
}
+ @Test
+ public void autoConfiguresBeansWithMinimalProperties() {
+ this.contextRunner
+ .withPropertyValues(
+ "spring.cloud.cloudfoundry.username=user",
+ "spring.cloud.cloudfoundry.password=secret")
+ .run((context) -> {
+ assertCloudFoundryClientBeansPresent(context);
+
+ DefaultCloudFoundryOperations operations = context.getBean(DefaultCloudFoundryOperations.class);
+ assertThat(operations.getOrganization()).isNullOrEmpty();
+ assertThat(operations.getSpace()).isNullOrEmpty();
+ });
+ }
+
+ @Test
+ public void organizationsRetrievedWithUserProvidedProperties() {
+ Assume.assumeTrue(requiredPropertiesSet());
+
+ this.contextRunner
+ .run((context) -> {
+ assertCloudFoundryClientBeansPresent(context);
+ CloudFoundryOperations operations = context.getBean(CloudFoundryOperations.class);
+
+ OrganizationSummary summary = operations
+ .organizations()
+ .list()
+ .blockFirst();
+
+ assertThat(summary).isNotNull();
+ assertThat(summary.getId()).isNotEmpty();
+ assertThat(summary.getName()).isNotEmpty();
+ });
+ }
+
+ private void assertCloudFoundryClientBeansPresent(AssertableApplicationContext context) {
+ assertThat(context).hasSingleBean(ReactorCloudFoundryClient.class);
+ assertThat(context).hasSingleBean(DefaultCloudFoundryOperations.class);
+ assertThat(context).hasSingleBean(DefaultConnectionContext.class);
+ assertThat(context).hasSingleBean(DopplerClient.class);
+ assertThat(context).hasSingleBean(RoutingClient.class);
+ assertThat(context).hasSingleBean(PasswordGrantTokenProvider.class);
+ assertThat(context).hasSingleBean(ReactorUaaClient.class);
+ }
}
\ No newline at end of file
diff --git a/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClient.java b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClient.java
index 1205089..ad9d3f7 100644
--- a/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClient.java
+++ b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClient.java
@@ -20,7 +20,6 @@ import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.applications.ApplicationDetail;
import org.cloudfoundry.operations.applications.ApplicationSummary;
import org.cloudfoundry.operations.applications.InstanceDetail;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
@@ -44,10 +43,6 @@ public class CloudFoundryDiscoveryClient implements DiscoveryClient {
private final String description = "Cloud Foundry " + DiscoveryClient.class.getName() + " implementation";
- @Value("${vcap.application.name:${spring.application.name:application}}")
- private String vcapApplicationName = "application";
-
-
CloudFoundryDiscoveryClient(CloudFoundryOperations cloudFoundryOperations,
CloudFoundryService svc) {
this.cloudFoundryService = svc;
@@ -86,8 +81,7 @@ public class CloudFoundryDiscoveryClient implements DiscoveryClient {
@Override
public List getServices() {
- return this
- .cloudFoundryOperations
+ return this.cloudFoundryOperations
.applications()
.list()
.map(ApplicationSummary::getName)
diff --git a/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClientConfiguration.java b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClientConfiguration.java
index 4e84892..bf63744 100644
--- a/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClientConfiguration.java
+++ b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClientConfiguration.java
@@ -17,7 +17,6 @@
package org.springframework.cloud.cloudfoundry.discovery;
import org.cloudfoundry.operations.CloudFoundryOperations;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -35,9 +34,6 @@ import org.springframework.context.annotation.Configuration;
@EnableConfigurationProperties(CloudFoundryDiscoveryProperties.class)
public class CloudFoundryDiscoveryClientConfiguration {
- @Autowired
- private CloudFoundryDiscoveryProperties discovery;
-
@Bean
@ConditionalOnMissingBean(CloudFoundryDiscoveryClient.class)
public CloudFoundryDiscoveryClient cloudFoundryDiscoveryClient(
diff --git a/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryServerList.java b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryServerList.java
index 463143a..d5f91c4 100644
--- a/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryServerList.java
+++ b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryServerList.java
@@ -30,12 +30,11 @@ import com.netflix.loadbalancer.AbstractServerList;
* @author Josh Long
*/
public class CloudFoundryServerList extends AbstractServerList {
-
- private String serviceId;
-
private final CloudFoundryService cloudFoundryService;
private final CloudFoundryDiscoveryProperties properties;
+
private IClientConfig clientConfig;
+ private String serviceId;
CloudFoundryServerList(CloudFoundryService svc, CloudFoundryDiscoveryProperties properties) {
this.cloudFoundryService = svc;
@@ -45,17 +44,17 @@ public class CloudFoundryServerList extends AbstractServerList getInitialListOfServers() {
- return this.cloudFoundryServers();
+ return cloudFoundryServers();
}
@Override
public List getUpdatedListOfServers() {
- return this.cloudFoundryServers();
+ return cloudFoundryServers();
}
private List cloudFoundryServers() {
@@ -69,7 +68,7 @@ public class CloudFoundryServerList extends AbstractServerList