From f0ef4f08bf54242165046584c1b3fab7527b3d41 Mon Sep 17 00:00:00 2001 From: Toshiaki Maki Date: Wed, 18 Apr 2018 03:34:43 +0900 Subject: [PATCH] Support DNS based Service Discovery Adds new two DiscoveryClient implementations that depend on native Service Discovery supported by Cloud Foundry. CloudFoundryAppServiceDiscoveryClient uses cf-java-client and find container's index-based route (e.g. 0.billing.apps.internal, 1.billing.apps.internal, 2.billing.apps.internal). SimpleDnsBasedDiscoveryClient simply uses DNS and resolve container's ip (e.g. 10.250.56.12, 10.254.160.118, 10.254.112.192). does not depend on cf-java-client By default, existing CloudFoundryDiscoveryClient is chosen. Configuring spring.cloud.cloudfoundry.discovery.use-dns=true enables CloudFoundryAppServiceDiscoveryClient. Configuring spring.cloud.cloudfoundry.discovery.use-dns=true and spring.cloud.cloudfoundry.discovery.use-container-ip=true enables SimpleDnsBasedDiscoveryClient. This DiscoveryClient eliminates the limitation of Turbine on Cloud Foundry and does not need Turbine Stream. In some environments (such as in a PaaS setting), the classic Turbine model of pulling metrics from all the distributed Hystrix commands does not work. See gh-19 --- ...CloudFoundryAppServiceDiscoveryClient.java | 70 +++++++++++ .../CloudFoundryDiscoveryClient.java | 3 + ...udFoundryDiscoveryClientConfiguration.java | 48 ++++++-- .../SimpleDnsBasedDiscoveryClient.java | 80 ++++++++++++ ...itional-spring-configuration-metadata.json | 16 +++ ...dFoundryAppServiceDiscoveryClientTest.java | 116 ++++++++++++++++++ ...undryDiscoveryClientConfigurationTest.java | 98 +++++++++++++++ .../sample/CloudFoundryApplication.java | 4 +- 8 files changed, 426 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryAppServiceDiscoveryClient.java create mode 100644 spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/SimpleDnsBasedDiscoveryClient.java create mode 100644 spring-cloud-cloudfoundry-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json create mode 100644 spring-cloud-cloudfoundry-discovery/src/test/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryAppServiceDiscoveryClientTest.java create mode 100644 spring-cloud-cloudfoundry-discovery/src/test/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClientConfigurationTest.java diff --git a/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryAppServiceDiscoveryClient.java b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryAppServiceDiscoveryClient.java new file mode 100644 index 0000000..c782a69 --- /dev/null +++ b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryAppServiceDiscoveryClient.java @@ -0,0 +1,70 @@ +package org.springframework.cloud.cloudfoundry.discovery; + +import java.util.HashMap; +import java.util.List; + +import org.cloudfoundry.operations.CloudFoundryOperations; +import org.cloudfoundry.operations.applications.ApplicationDetail; +import org.cloudfoundry.operations.applications.InstanceDetail; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.cloudfoundry.CloudFoundryService; + +/** + * + * Discovery Client implementation using Cloud Foundry's Native DNS based Service + * Discovery + * + * @see CF App Service + * Discovery Release + * @see Polyglot + * Service Discovery for Container Networking in Cloud Foundry + * + * @author Toshiaki Maki + */ +public class CloudFoundryAppServiceDiscoveryClient extends CloudFoundryDiscoveryClient { + + private static final String INTERNAL_DOMAIN = "apps.internal"; + + CloudFoundryAppServiceDiscoveryClient(CloudFoundryOperations cloudFoundryOperations, + CloudFoundryService svc, CloudFoundryDiscoveryProperties cloudFoundryDiscoveryProperties) { + super(cloudFoundryOperations, svc, cloudFoundryDiscoveryProperties); + } + + @Override + public String description() { + return "CF App Service Discovery Client"; + } + + @Override + public List getInstances(String serviceId) { + return getCloudFoundryService() + .getApplicationInstances(serviceId) + .filter(tuple -> tuple.getT1().getUrls().stream() + .anyMatch(this::isInternalDomain)) + .map(tuple -> { + ApplicationDetail applicationDetail = tuple.getT1(); + InstanceDetail instanceDetail = tuple.getT2(); + String applicationId = applicationDetail.getId(); + String applicationIndex = instanceDetail.getIndex(); + String name = applicationDetail.getName(); + String url = applicationDetail.getUrls().stream() + .filter(this::isInternalDomain) + .findFirst() + .map(x -> instanceDetail.getIndex() + "." + x) + .get(); + HashMap metadata = new HashMap<>(); + metadata.put("applicationId", applicationId); + metadata.put("instanceId", applicationIndex); + return (ServiceInstance) new DefaultServiceInstance(name, url, 8080, + false, metadata); + }) + .collectList() + .block(); + } + + private boolean isInternalDomain(String url) { + return url != null && url.endsWith(INTERNAL_DOMAIN); + } +} 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 4d72b0e..1e19c88 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 @@ -98,4 +98,7 @@ public class CloudFoundryDiscoveryClient implements DiscoveryClient { return this.properties.getOrder(); } + CloudFoundryService getCloudFoundryService() { + return this.cloudFoundryService; + } } 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 3ce8aa2..1db38c9 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,12 +17,15 @@ package org.springframework.cloud.cloudfoundry.discovery; import org.cloudfoundry.operations.CloudFoundryOperations; - +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.cloudfoundry.CloudFoundryService; +import org.springframework.cloud.cloudfoundry.discovery.SimpleDnsBasedDiscoveryClient.ServiceIdToHostnameConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -35,15 +38,46 @@ import org.springframework.context.annotation.Configuration; @EnableConfigurationProperties(CloudFoundryDiscoveryProperties.class) public class CloudFoundryDiscoveryClientConfiguration { - @Bean - @ConditionalOnMissingBean(CloudFoundryDiscoveryClient.class) - public CloudFoundryDiscoveryClient cloudFoundryDiscoveryClient( - CloudFoundryOperations cf, CloudFoundryService svc, - CloudFoundryDiscoveryProperties cloudFoundryDiscoveryProperties) { - return new CloudFoundryDiscoveryClient(cf, svc, cloudFoundryDiscoveryProperties); + @Configuration + @ConditionalOnProperty(value = "spring.cloud.cloudfoundry.discovery.use-dns", havingValue = "false", matchIfMissing = true) + public static class CloudFoundryDiscoveryClientConfig { + @Bean + @ConditionalOnMissingBean(DiscoveryClient.class) + public DiscoveryClient cloudFoundryDiscoveryClient(CloudFoundryOperations cf, + CloudFoundryService svc, + CloudFoundryDiscoveryProperties cloudFoundryDiscoveryProperties) { + return new CloudFoundryDiscoveryClient(cf, svc, + cloudFoundryDiscoveryProperties); + } + } + + @Configuration + @ConditionalOnProperty(value = "spring.cloud.cloudfoundry.discovery.use-dns", havingValue = "true") + public static class DnsBasedCloudFoundryDiscoveryClientConfig { + + @Bean + @ConditionalOnProperty(value = "spring.cloud.cloudfoundry.discovery.use-container-ip", havingValue = "true") + @ConditionalOnMissingBean(DiscoveryClient.class) + public DiscoveryClient discoveryClient( + ObjectProvider provider) { + ServiceIdToHostnameConverter converter = provider.getIfAvailable(); + return converter == null ? new SimpleDnsBasedDiscoveryClient() + : new SimpleDnsBasedDiscoveryClient(converter); + } + + @Bean + @ConditionalOnProperty(value = "spring.cloud.cloudfoundry.discovery.use-container-ip", havingValue = "false", matchIfMissing = true) + @ConditionalOnMissingBean(DiscoveryClient.class) + public DiscoveryClient cloudFoundryDiscoveryClient(CloudFoundryOperations cf, + CloudFoundryService svc, + CloudFoundryDiscoveryProperties cloudFoundryDiscoveryProperties) { + return new CloudFoundryAppServiceDiscoveryClient(cf, svc, + cloudFoundryDiscoveryProperties); + } } @Bean + @ConditionalOnBean(CloudFoundryDiscoveryClient.class) public CloudFoundryHeartbeatSender cloudFoundryHeartbeatSender( CloudFoundryDiscoveryClient client) { return new CloudFoundryHeartbeatSender(client); diff --git a/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/SimpleDnsBasedDiscoveryClient.java b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/SimpleDnsBasedDiscoveryClient.java new file mode 100644 index 0000000..6ff3468 --- /dev/null +++ b/spring-cloud-cloudfoundry-discovery/src/main/java/org/springframework/cloud/cloudfoundry/discovery/SimpleDnsBasedDiscoveryClient.java @@ -0,0 +1,80 @@ + +package org.springframework.cloud.cloudfoundry.discovery; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; + +/** + * Discovery Client implementation using Cloud Foundry's Native DNS based Service + * Discovery + * + * @see Polyglot + * Service Discovery for Container Networking in Cloud Foundry + * + * @author Toshiaki Maki + */ +public class SimpleDnsBasedDiscoveryClient implements DiscoveryClient { + public static final String INTERNAL_DOMAIN = "apps.internal"; + private final Logger log = LoggerFactory + .getLogger(SimpleDnsBasedDiscoveryClient.class); + private final ServiceIdToHostnameConverter serviceIdToHostnameConverter; + + private static final ServiceIdToHostnameConverter DEFAULT_CONVERTER = serviceId -> serviceId + + "." + INTERNAL_DOMAIN; + + public SimpleDnsBasedDiscoveryClient( + ServiceIdToHostnameConverter serviceIdToHostnameConverter) { + this.serviceIdToHostnameConverter = serviceIdToHostnameConverter; + } + + public SimpleDnsBasedDiscoveryClient() { + this(DEFAULT_CONVERTER); + } + + @Override + public String description() { + return "DNS Based CF Service Discovery Client"; + } + + @Override + public List getInstances(String serviceId) { + String hostname = this.serviceIdToHostnameConverter.toHostname(serviceId); + try { + List serviceInstances = new ArrayList<>(); + InetAddress[] addresses = InetAddress.getAllByName(hostname); + if (addresses != null) { + for (InetAddress address : addresses) { + DefaultServiceInstance serviceInstance = new DefaultServiceInstance( + serviceId, address.getHostAddress(), 8080, false); + serviceInstances.add(serviceInstance); + } + } + return serviceInstances; + } + catch (UnknownHostException e) { + log.warn("{}", e.getMessage()); + return Collections.emptyList(); + } + } + + @Override + public List getServices() { + log.warn("getServices is not supported"); + return Collections.emptyList(); + } + + @FunctionalInterface + public interface ServiceIdToHostnameConverter { + String toHostname(String serviceId); + } +} \ No newline at end of file diff --git a/spring-cloud-cloudfoundry-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-cloudfoundry-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 0000000..8041ebf --- /dev/null +++ b/spring-cloud-cloudfoundry-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,16 @@ +{ + "properties": [ + { + "name": "spring.cloud.cloudfoundry.discovery.use-dns", + "type": "java.lang.Boolean", + "description": "Whether to use BOSH DNS for the discovery. In order to use this feature, your Cloud Foundry installation must support Service Discovery.", + "defaultValue": false + }, + { + "name": "spring.cloud.cloudfoundry.discovery.use-container-ip", + "type": "java.lang.Boolean", + "description": "Whether to resolve hostname when BOSH DNS is used. In order to use this feature, spring.cloud.cloudfoundry.discovery.use-dns must be true.", + "defaultValue": false + } + ] +} \ No newline at end of file diff --git a/spring-cloud-cloudfoundry-discovery/src/test/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryAppServiceDiscoveryClientTest.java b/spring-cloud-cloudfoundry-discovery/src/test/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryAppServiceDiscoveryClientTest.java new file mode 100644 index 0000000..ab4cbb3 --- /dev/null +++ b/spring-cloud-cloudfoundry-discovery/src/test/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryAppServiceDiscoveryClientTest.java @@ -0,0 +1,116 @@ +package org.springframework.cloud.cloudfoundry.discovery; + +import java.util.HashMap; +import java.util.List; + +import org.cloudfoundry.operations.CloudFoundryOperations; +import org.cloudfoundry.operations.applications.ApplicationDetail; +import org.cloudfoundry.operations.applications.InstanceDetail; +import org.junit.Before; +import org.junit.Test; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.cloudfoundry.CloudFoundryService; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +import reactor.core.publisher.Flux; +import reactor.util.function.Tuples; + +/** + * @author Toshiaki Maki + */ +public class CloudFoundryAppServiceDiscoveryClientTest { + private CloudFoundryAppServiceDiscoveryClient discoveryClient; + private CloudFoundryOperations cloudFoundryOperations; + private CloudFoundryService cloudFoundryService; + + @Before + public void setUp() { + this.cloudFoundryOperations = mock(CloudFoundryOperations.class); + this.cloudFoundryService = mock(CloudFoundryService.class); + this.discoveryClient = new CloudFoundryAppServiceDiscoveryClient( + this.cloudFoundryOperations, this.cloudFoundryService, + new CloudFoundryDiscoveryProperties()); + } + + @Test + public void getInstancesOneInstance() { + String serviceId = "billing"; + ApplicationDetail applicationDetail = ApplicationDetail.builder().id("billing1") + .name("billing").instances(1).memoryLimit(1024).stack("cflinux2") + .diskQuota(1024).requestedState("Running").runningInstances(1) + .url("billing.apps.example.com", "billing.apps.internal").build(); + given(this.cloudFoundryService.getApplicationInstances(serviceId)) + .willReturn(Flux.just(Tuples.of(applicationDetail, + InstanceDetail.builder().index("0").build()))); + List instances = this.discoveryClient.getInstances(serviceId); + + assertThat(instances).hasSize(1); + assertThat(instances.get(0)).isEqualTo(new DefaultServiceInstance(serviceId, + "0.billing.apps.internal", 8080, false, new HashMap() { + { + put("applicationId", "billing1"); + put("instanceId", "0"); + } + })); + } + + @Test + public void getInstancesThreeInstance() { + String serviceId = "billing"; + ApplicationDetail applicationDetail = ApplicationDetail.builder().id("billing-id") + .name("billing").instances(3).memoryLimit(1024).stack("cflinux2") + .diskQuota(1024).requestedState("Running").runningInstances(3) + .url("billing.apps.example.com", "billing.apps.internal").build(); + given(this.cloudFoundryService.getApplicationInstances(serviceId)) + .willReturn(Flux.just( + Tuples.of(applicationDetail, + InstanceDetail.builder().index("0").build()), + Tuples.of(applicationDetail, + InstanceDetail.builder().index("1").build()), + Tuples.of(applicationDetail, + InstanceDetail.builder().index("2").build()))); + List instances = this.discoveryClient.getInstances(serviceId); + + assertThat(instances).hasSize(3); + assertThat(instances.get(0)).isEqualTo(new DefaultServiceInstance(serviceId, + "0.billing.apps.internal", 8080, false, new HashMap() { + { + put("applicationId", "billing-id"); + put("instanceId", "0"); + } + })); + assertThat(instances.get(1)).isEqualTo(new DefaultServiceInstance(serviceId, + "1.billing.apps.internal", 8080, false, new HashMap() { + { + put("applicationId", "billing-id"); + put("instanceId", "1"); + } + })); + assertThat(instances.get(2)).isEqualTo(new DefaultServiceInstance(serviceId, + "2.billing.apps.internal", 8080, false, new HashMap() { + { + put("applicationId", "billing-id"); + put("instanceId", "2"); + } + })); + } + + @Test + public void getInstancesEmpty() { + String serviceId = "billing"; + ApplicationDetail applicationDetail = ApplicationDetail.builder().id("billing1") + .name("billing").instances(1).memoryLimit(1024).stack("cflinux2") + .diskQuota(1024).requestedState("Running").runningInstances(1) + .url("billing.apps.example.com").build(); + given(this.cloudFoundryService.getApplicationInstances(serviceId)) + .willReturn(Flux.just(Tuples.of(applicationDetail, + InstanceDetail.builder().index("0").build()))); + List instances = this.discoveryClient.getInstances(serviceId); + + assertThat(instances).isEmpty(); + } +} \ No newline at end of file diff --git a/spring-cloud-cloudfoundry-discovery/src/test/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClientConfigurationTest.java b/spring-cloud-cloudfoundry-discovery/src/test/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClientConfigurationTest.java new file mode 100644 index 0000000..aff67f5 --- /dev/null +++ b/spring-cloud-cloudfoundry-discovery/src/test/java/org/springframework/cloud/cloudfoundry/discovery/CloudFoundryDiscoveryClientConfigurationTest.java @@ -0,0 +1,98 @@ +package org.springframework.cloud.cloudfoundry.discovery; + +import org.cloudfoundry.operations.CloudFoundryOperations; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.cloudfoundry.CloudFoundryService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CloudFoundryDiscoveryClientConfiguration}. + * @author Toshiaki Maki + */ +public class CloudFoundryDiscoveryClientConfigurationTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations + .of(CloudFoundryDiscoveryClientConfiguration.class)); + + @Test + public void testDefault() { + this.contextRunner.withUserConfiguration(CloudFoundryConfig.class) + .run((context) -> { + DiscoveryClient discoveryClient = context + .getBean(DiscoveryClient.class); + assertThat(discoveryClient.getClass()) + .isEqualTo(CloudFoundryDiscoveryClient.class); + }); + } + + @Test + public void testUseDnsTrue() { + this.contextRunner.withUserConfiguration(CloudFoundryConfig.class) + .withPropertyValues("spring.cloud.cloudfoundry.discovery.use-dns=true") + .run((context) -> { + DiscoveryClient discoveryClient = context + .getBean(DiscoveryClient.class); + assertThat(discoveryClient.getClass()) + .isEqualTo(CloudFoundryAppServiceDiscoveryClient.class); + }); + } + + @Test + public void testUseDnsFalse() { + this.contextRunner.withUserConfiguration(CloudFoundryConfig.class) + .withPropertyValues("spring.cloud.cloudfoundry.discovery.use-dns=false") + .run((context) -> { + DiscoveryClient discoveryClient = context + .getBean(DiscoveryClient.class); + assertThat(discoveryClient.getClass()) + .isEqualTo(CloudFoundryDiscoveryClient.class); + }); + } + + @Test + public void testUseContainerIpFalse() { + this.contextRunner.withUserConfiguration(CloudFoundryConfig.class) + .withPropertyValues("spring.cloud.cloudfoundry.discovery.use-dns=true", + "spring.cloud.cloudfoundry.discovery.use-container-ip=false") + .run((context) -> { + DiscoveryClient discoveryClient = context + .getBean(DiscoveryClient.class); + assertThat(discoveryClient.getClass()) + .isEqualTo(CloudFoundryAppServiceDiscoveryClient.class); + }); + } + + @Test + public void testUseContainerIpTrue() { + this.contextRunner + .withPropertyValues("spring.cloud.cloudfoundry.discovery.use-dns=true", + "spring.cloud.cloudfoundry.discovery.use-container-ip=true") + .run((context) -> { + DiscoveryClient discoveryClient = context + .getBean(DiscoveryClient.class); + assertThat(discoveryClient.getClass()) + .isEqualTo(SimpleDnsBasedDiscoveryClient.class); + }); + } + + @Configuration + public static class CloudFoundryConfig { + @Bean + public CloudFoundryOperations cloudFoundryOperations() { + return Mockito.mock(CloudFoundryOperations.class); + } + + @Bean + public CloudFoundryService cloudFoundryService() { + return Mockito.mock(CloudFoundryService.class); + } + } +} \ No newline at end of file diff --git a/spring-cloud-cloudfoundry-sample/src/main/java/org/springframework/cloud/cloudfoundry/sample/CloudFoundryApplication.java b/spring-cloud-cloudfoundry-sample/src/main/java/org/springframework/cloud/cloudfoundry/sample/CloudFoundryApplication.java index 729a4e4..e9c4cea 100644 --- a/spring-cloud-cloudfoundry-sample/src/main/java/org/springframework/cloud/cloudfoundry/sample/CloudFoundryApplication.java +++ b/spring-cloud-cloudfoundry-sample/src/main/java/org/springframework/cloud/cloudfoundry/sample/CloudFoundryApplication.java @@ -22,7 +22,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.cloudfoundry.discovery.CloudFoundryDiscoveryClient; +import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.cloudfoundry.discovery.EnableCloudFoundryClient; import org.springframework.context.annotation.Bean; @@ -55,7 +55,7 @@ public class CloudFoundryApplication { } @Bean - CommandLineRunner demo(CloudFoundryDiscoveryClient discoveryClient) { + CommandLineRunner demo(DiscoveryClient discoveryClient) { Log log = LogFactory.getLog(getClass()); return args -> discoveryClient.getServices().forEach(svc -> { log.info("service = " + svc);