Tidy up failure cases of discovery client

This commit is contained in:
Dave Syer
2015-05-21 13:51:58 +01:00
parent e1bdaa7851
commit 24aca83e96
16 changed files with 741 additions and 603 deletions

View File

@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-cloudfoundry</artifactId>
<version>1.0.2.BUILD-SNAPSHOT</version>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<parent>

View File

@@ -1,80 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-cloudfoundry-discovery</artifactId>
<packaging>jar</packaging>
<description>Spring Cloud CloudFoundry Discovery</description>
<artifactId>spring-cloud-cloudfoundry-discovery</artifactId>
<packaging>jar</packaging>
<description>Spring Cloud CloudFoundry Discovery</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry</artifactId>
<version>1.0.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.cloudfoundry</groupId>
<artifactId>cloudfoundry-client-lib</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-httpclient</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
<optional>true</optional>
</dependency>
<!---->
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-ribbon</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<scope>test</scope>
<artifactId>feign-slf4j</artifactId>
</dependency>
<!---->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.cloudfoundry</groupId>
<artifactId>cloudfoundry-client-lib</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-ribbon</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<scope>test</scope>
<artifactId>feign-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -16,8 +16,15 @@
package org.springframework.cloud.cloudfoundry.discovery;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.client.lib.CloudCredentials;
@@ -32,147 +39,162 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* A Cloud Foundry v2 API-aware implementation of the {@link DiscoveryClient discovery client}
* SPI. Cloud Foundry already retains a registry of running applications which we expose here as services.
* Newer versions of Cloud Foundry support instance-specific networking, but as the Cloud Foundry client API doesn't
* yet support that, this {@link DiscoveryClient implementation doesn't either}.
* A Cloud Foundry v2 API-aware implementation of the {@link DiscoveryClient discovery
* client} SPI. Cloud Foundry already retains a registry of running applications which we
* expose here as services. Newer versions of Cloud Foundry support instance-specific
* networking, but as the Cloud Foundry client API doesn't yet support that, this
* {@link DiscoveryClient implementation doesn't either}.
* <p/>
* You need to provide an instance of the {@link CloudFoundryClient}. A workable configuration looks like this:
* You need to provide an instance of the {@link CloudFoundryClient}. A workable
* configuration looks like this:
* <p/>
*
* <pre class="code">
* &#064;Bean
* CloudFoundryClient cloudFoundryClient(
* &#064;Value("${MY_CUSTOM_CF_API:https://api.run.pivotal.io}") String api,
* CloudCredentials cc) throws MalformedURLException {
* CloudFoundryClient cloudFoundryClient = new CloudFoundryClient(cc, URI.create(api).toURL());
* cloudFoundryClient.login();
* return cloudFoundryClient;
* &#064;Value(&quot;${MY_CUSTOM_CF_API:https://api.run.pivotal.io}&quot;) String api,
* CloudCredentials cc) throws MalformedURLException {
* CloudFoundryClient cloudFoundryClient = new CloudFoundryClient(cc, URI.create(api)
* .toURL());
* cloudFoundryClient.login();
* return cloudFoundryClient;
* }
* </pre>
* <p/>
* You can configure all sorts of other things including which Cloud Foundry cloud controller URI to use,
* how and whether to use an HTTP proxy, and more using alternative constructors. As configured above, the client
* will talk to all services and applications deployed in <EM>all</EM> spaces and organizations. Use one of the
* {@link CloudFoundryClient#CloudFoundryClient(CloudCredentials, URL, String, String)} variants to specify which space
* and organization to use.
* You can configure all sorts of other things including which Cloud Foundry cloud
* controller URI to use, how and whether to use an HTTP proxy, and more using alternative
* constructors. As configured above, the client will talk to all services and
* applications deployed in <EM>all</EM> spaces and organizations. Use one of the
* {@link CloudFoundryClient#CloudFoundryClient(CloudCredentials, URL, String, String)}
* variants to specify which space and organization to use.
* <p/>
*
* @author <A href="mailto:josh@joshlong.com">Josh Long</A>
* @author Spencer Gibb
* @author Dave Syer
*/
public class CloudFoundryDiscoveryClient implements DiscoveryClient {
private static final String DESCRIPTION = "Cloud Foundry " + DiscoveryClient.class.getName() + " implementation";
private static final String DESCRIPTION = "Cloud Foundry "
+ DiscoveryClient.class.getName() + " implementation";
private final Log log = LogFactory.getLog(getClass());
private static final Log log = LogFactory.getLog(CloudFoundryDiscoveryClient.class);
private final ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();
private final ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();
private final CloudFoundryClient cloudFoundryClient;
private final CloudFoundryClient cloudFoundryClient;
private final String vcapApplicationName;
private final String vcapApplicationName;
public CloudFoundryDiscoveryClient(CloudFoundryClient cloudFoundryClient, Environment environment) {
public CloudFoundryDiscoveryClient(CloudFoundryClient cloudFoundryClient,
Environment environment) {
this.cloudFoundryClient = cloudFoundryClient;
this.cloudFoundryClient = cloudFoundryClient;
String vcapApplication = environment.getProperty("VCAP_APPLICATION");
String vcapApplication = environment.getProperty("VCAP_APPLICATION");
try {
JsonNode jsonNode = objectMapper.readTree(vcapApplication);
JsonNode appNameNode = jsonNode.get("application_name");
try {
JsonNode jsonNode = objectMapper.readTree(vcapApplication);
JsonNode appNameNode = jsonNode.get("application_name");
this.vcapApplicationName = appNameNode.toString().replaceAll("\"", "");
this.vcapApplicationName = appNameNode.toString().replaceAll("\"", "");
this.log.debug("Current ServiceInstance information...");
this.log.debug("\tvcapApplicationName: " + this.vcapApplicationName);
log.debug("Current ServiceInstance information...");
log.debug("\tvcapApplicationName: " + this.vcapApplicationName);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public String description() {
return DESCRIPTION;
}
@Override
public String description() {
return DESCRIPTION;
}
@Override
public ServiceInstance getLocalServiceInstance() {
CloudApplication application = this.cloudFoundryClient.getApplication(this.vcapApplicationName);
List<ServiceInstance> serviceInstances =
this.createServiceInstancesFromCloudApplications(Collections.singletonList(application));
return serviceInstances.size() > 0 ? serviceInstances.iterator().next() : null;
}
@Override
public ServiceInstance getLocalServiceInstance() {
List<ServiceInstance> serviceInstances = null;
try {
CloudApplication application = this.cloudFoundryClient
.getApplication(this.vcapApplicationName);
serviceInstances = this
.createServiceInstancesFromCloudApplications(Collections
.singletonList(application));
}
catch (Exception e) {
log.warn("Could not determine local service instance: " + e.getClass() + " ("
+ e.getMessage() + ")");
}
return serviceInstances != null && serviceInstances.size() > 0 ? serviceInstances
.iterator().next() : null;
}
@Override
public List<ServiceInstance> getInstances(String s) {
CloudApplication applications = this.cloudFoundryClient.getApplication(s);
return this.createServiceInstancesFromCloudApplications(
Collections.singletonList(applications));
}
@Override
public List<ServiceInstance> getInstances(String s) {
CloudApplication applications = this.cloudFoundryClient.getApplication(s);
return this.createServiceInstancesFromCloudApplications(Collections
.singletonList(applications));
}
private boolean isRunning(CloudApplication ca) {
InstancesInfo ii = this.cloudFoundryClient.getApplicationInstances(ca);
List<InstanceInfo> instances;
if (ii != null && (instances = ii.getInstances()) != null) {
for (InstanceInfo resolved : instances) {
InstanceState state = resolved.getState();
if (state != null && state.equals(InstanceState.RUNNING)) {
return true;
}
}
}
return false;
}
private boolean isRunning(CloudApplication ca) {
InstancesInfo ii = this.cloudFoundryClient.getApplicationInstances(ca);
List<InstanceInfo> instances;
if (ii != null && (instances = ii.getInstances()) != null) {
for (InstanceInfo resolved : instances) {
InstanceState state = resolved.getState();
if (state != null && state.equals(InstanceState.RUNNING)) {
return true;
}
}
}
return false;
}
@Override
public List<String> getServices() {
List<String> services = new ArrayList<>();
List<CloudApplication> applications = this.cloudFoundryClient.getApplications();
Set<String> serviceIds = new HashSet<>();
for (CloudApplication ca : applications) {
if (isRunning(ca)) {
serviceIds.add(ca.getName());
}
}
services.addAll(serviceIds);
return services;
}
@Override
public List<String> getServices() {
List<String> services = new ArrayList<>();
List<CloudApplication> applications = this.cloudFoundryClient.getApplications();
Set<String> serviceIds = new HashSet<>();
for (CloudApplication ca : applications) {
if (isRunning(ca)) {
serviceIds.add(ca.getName());
}
}
services.addAll(serviceIds);
return services;
}
protected List<ServiceInstance> createServiceInstancesFromCloudApplications(
Collection<CloudApplication> cloudApplications) {
Set<ServiceInstance> serviceInstances = new HashSet<>();
for (CloudApplication ca : cloudApplications) {
if (isRunning(ca)) {
serviceInstances.add(new CloudFoundryServiceInstance(ca));
}
}
List<ServiceInstance> instances = new ArrayList<>();
instances.addAll(serviceInstances);
return instances;
}
protected List<ServiceInstance> createServiceInstancesFromCloudApplications(
Collection<CloudApplication> cloudApplications) {
Set<ServiceInstance> serviceInstances = new HashSet<>();
for (CloudApplication ca : cloudApplications) {
if (isRunning(ca)) {
serviceInstances.add(new CloudFoundryServiceInstance(ca));
}
}
List<ServiceInstance> instances = new ArrayList<>();
instances.addAll(serviceInstances);
return instances;
}
public static class CloudFoundryServiceInstance extends DefaultServiceInstance {
public static class CloudFoundryServiceInstance extends DefaultServiceInstance {
private final CloudApplication cloudApplication;
private final CloudApplication cloudApplication;
public CloudApplication getCloudApplication() {
return cloudApplication;
}
public CloudApplication getCloudApplication() {
return cloudApplication;
}
public CloudFoundryServiceInstance(CloudApplication ca) {
super(ca.getName(),
ca.getUris().iterator().next(),
80,
false);
public CloudFoundryServiceInstance(CloudApplication ca) {
super(ca.getName(), ca.getUris().iterator().next(), 80, false);
this.cloudApplication = ca;
}
}
this.cloudApplication = ca;
}
}
}

View File

@@ -16,53 +16,58 @@
package org.springframework.cloud.cloudfoundry.discovery;
import java.net.MalformedURLException;
import java.net.URI;
import org.cloudfoundry.client.lib.CloudCredentials;
import org.cloudfoundry.client.lib.CloudFoundryClient;
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;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.net.MalformedURLException;
import java.net.URI;
/**
* @author <A href="mailto:josh@joshlong.com">Josh Long</A>
*/
@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(CloudFoundryClient.class)
@ConditionalOnProperty(value = "spring.cloud.cloudfoundry.discovery.enabled", matchIfMissing = true)
public class CloudFoundryDiscoveryClientConfiguration {
@Autowired
private CloudFoundryDiscoveryProperties cloudFoundryDiscoveryProperties;
@Autowired
private CloudFoundryDiscoveryProperties cloudFoundryDiscoveryProperties;
@Bean
@ConditionalOnMissingBean(CloudCredentials.class)
public CloudCredentials cloudCredentials() {
return new CloudCredentials(this.cloudFoundryDiscoveryProperties.getEmail(),
this.cloudFoundryDiscoveryProperties.getPassword());
}
@Bean
@ConditionalOnMissingBean(CloudCredentials.class)
public CloudCredentials cloudCredentials() {
return new CloudCredentials(this.cloudFoundryDiscoveryProperties.getEmail(),
this.cloudFoundryDiscoveryProperties.getPassword());
}
@Bean
@ConditionalOnMissingBean(CloudFoundryClient.class)
public CloudFoundryClient cloudFoundryClient(CloudCredentials cc) throws MalformedURLException {
CloudFoundryClient cloudFoundryClient = new CloudFoundryClient(cc,
URI.create(this.cloudFoundryDiscoveryProperties.getCloudControllerUrl()).toURL());
cloudFoundryClient.login();
return cloudFoundryClient;
}
@Bean
@ConditionalOnMissingBean(CloudFoundryClient.class)
public CloudFoundryClient cloudFoundryClient(CloudCredentials cc)
throws MalformedURLException {
CloudFoundryClient cloudFoundryClient = new CloudFoundryClient(cc, URI.create(
this.cloudFoundryDiscoveryProperties.getCloudControllerUrl()).toURL());
cloudFoundryClient.login();
return cloudFoundryClient;
}
@Bean
@ConditionalOnMissingBean(CloudFoundryDiscoveryClient.class)
public CloudFoundryDiscoveryClient cloudFoundryDiscoveryClient(
CloudFoundryClient cloudFoundryClient, Environment environment) {
return new CloudFoundryDiscoveryClient(cloudFoundryClient, environment);
}
@Bean
@ConditionalOnMissingBean(CloudFoundryDiscoveryClient.class)
public CloudFoundryDiscoveryClient cloudFoundryDiscoveryClient(
CloudFoundryClient cloudFoundryClient, Environment environment) {
return new CloudFoundryDiscoveryClient(cloudFoundryClient, environment);
}
@Bean
public CloudFoundryDiscoveryProperties cloudFoundryDiscoveryProperties() {
return new CloudFoundryDiscoveryProperties();
}
@Bean
public CloudFoundryDiscoveryProperties cloudFoundryDiscoveryProperties() {
return new CloudFoundryDiscoveryProperties();
}
}

View File

@@ -24,33 +24,43 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "spring.cloud.cloudfoundry.discovery")
public class CloudFoundryDiscoveryProperties {
private String cloudControllerUrl = "https://api.run.pivotal.io";
private String cloudControllerUrl = "https://api.run.pivotal.io";
private String email;
private String email;
private String password;
private String password;
public String getCloudControllerUrl() {
return cloudControllerUrl;
}
private boolean enabled = true;
public void setCloudControllerUrl(String cloudControllerUrl) {
this.cloudControllerUrl = cloudControllerUrl;
}
public boolean isEnabled() {
return enabled;
}
public String getEmail() {
return email;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void setEmail(String email) {
this.email = email;
}
public String getCloudControllerUrl() {
return cloudControllerUrl;
}
public String getPassword() {
return password;
}
public void setCloudControllerUrl(String cloudControllerUrl) {
this.cloudControllerUrl = cloudControllerUrl;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@@ -36,47 +36,52 @@ import javax.annotation.PostConstruct;
@Configuration
public class CloudFoundryRibbonClientConfiguration {
protected static final String DEFAULT_NAMESPACE = "ribbon";
protected static final String VALUE_NOT_SET = "__not__set__";
protected static final String DEFAULT_NAMESPACE = "ribbon";
protected static final String VALUE_NOT_SET = "__not__set__";
@Value("${ribbon.client.name}")
private String serviceId;
private String serviceId;
public CloudFoundryRibbonClientConfiguration (){ }
public CloudFoundryRibbonClientConfiguration() {
}
public CloudFoundryRibbonClientConfiguration (String svcId) {
this.serviceId = svcId;
}
public CloudFoundryRibbonClientConfiguration(String svcId) {
this.serviceId = svcId;
}
@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(CloudFoundryClient cloudFoundryClient, IClientConfig config) {
CloudFoundryServerList cloudFoundryServerList = new CloudFoundryServerList(cloudFoundryClient);
cloudFoundryServerList.initWithNiwsConfig(config);
return cloudFoundryServerList;
}
@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(CloudFoundryClient cloudFoundryClient,
IClientConfig config) {
CloudFoundryServerList cloudFoundryServerList = new CloudFoundryServerList(
cloudFoundryClient);
cloudFoundryServerList.initWithNiwsConfig(config);
return cloudFoundryServerList;
}
@PostConstruct
public void postConstruct() {
// FIXME: what should this be?
setProp(this.serviceId, CommonClientConfigKey.DeploymentContextBasedVipAddresses.key(), this.serviceId);
setProp(this.serviceId, CommonClientConfigKey.EnableZoneAffinity.key(), "true");
}
@PostConstruct
public void postConstruct() {
// FIXME: what should this be?
setProp(this.serviceId,
CommonClientConfigKey.DeploymentContextBasedVipAddresses.key(),
this.serviceId);
setProp(this.serviceId, CommonClientConfigKey.EnableZoneAffinity.key(), "true");
}
protected void setProp(String serviceId, String suffix, String value) {
// how to set the namespace properly?
String key = getKey(serviceId, suffix);
DynamicStringProperty property = getProperty(key);
if (property.get().equals(VALUE_NOT_SET)) {
ConfigurationManager.getConfigInstance().setProperty(key, value);
}
}
protected void setProp(String serviceId, String suffix, String value) {
// how to set the namespace properly?
String key = getKey(serviceId, suffix);
DynamicStringProperty property = getProperty(key);
if (property.get().equals(VALUE_NOT_SET)) {
ConfigurationManager.getConfigInstance().setProperty(key, value);
}
}
protected DynamicStringProperty getProperty(String key) {
return DynamicPropertyFactory.getInstance().getStringProperty(key, VALUE_NOT_SET);
}
protected DynamicStringProperty getProperty(String key) {
return DynamicPropertyFactory.getInstance().getStringProperty(key, VALUE_NOT_SET);
}
protected String getKey(String serviceId, String suffix) {
return serviceId + "." + DEFAULT_NAMESPACE + "." + suffix;
}
protected String getKey(String serviceId, String suffix) {
return serviceId + "." + DEFAULT_NAMESPACE + "." + suffix;
}
}

View File

@@ -24,37 +24,37 @@ import org.cloudfoundry.client.lib.domain.CloudApplication;
*/
public class CloudFoundryServer extends Server {
private final MetaInfo metaInfo;
private final MetaInfo metaInfo;
public CloudFoundryServer(final CloudApplication cloudApplication) {
public CloudFoundryServer(final CloudApplication cloudApplication) {
super(cloudApplication.getUris().iterator().next(), 80);
super(cloudApplication.getUris().iterator().next(), 80);
this.metaInfo = new MetaInfo() {
@Override
public String getAppName() {
return cloudApplication.getName();
}
this.metaInfo = new MetaInfo() {
@Override
public String getAppName() {
return cloudApplication.getName();
}
@Override
public String getServerGroup() {
return null;
}
@Override
public String getServerGroup() {
return null;
}
@Override
public String getServiceIdForDiscovery() {
return cloudApplication.getName();
}
@Override
public String getServiceIdForDiscovery() {
return cloudApplication.getName();
}
@Override
public String getInstanceId() {
return cloudApplication.getName();
}
};
}
@Override
public String getInstanceId() {
return cloudApplication.getName();
}
};
}
@Override
public MetaInfo getMetaInfo() {
return metaInfo;
}
@Override
public MetaInfo getMetaInfo() {
return metaInfo;
}
}

View File

@@ -18,6 +18,9 @@ package org.springframework.cloud.cloudfoundry.discovery;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractServerList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.client.lib.CloudFoundryClient;
import org.cloudfoundry.client.lib.domain.CloudApplication;
@@ -29,31 +32,40 @@ import java.util.List;
*/
public class CloudFoundryServerList extends AbstractServerList<CloudFoundryServer> {
protected String serviceId;
private static final Log log = LogFactory.getLog(CloudFoundryServerList.class);
private final CloudFoundryClient cloudFoundryClient;
protected String serviceId;
public CloudFoundryServerList(CloudFoundryClient cloudFoundryClient) {
this.cloudFoundryClient = cloudFoundryClient;
}
private final CloudFoundryClient cloudFoundryClient;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
this.serviceId = iClientConfig.getClientName();
}
public CloudFoundryServerList(CloudFoundryClient cloudFoundryClient) {
this.cloudFoundryClient = cloudFoundryClient;
}
@Override
public List<CloudFoundryServer> getInitialListOfServers() {
return this.cloudFoundryServers();
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
this.serviceId = iClientConfig.getClientName();
}
@Override
public List<CloudFoundryServer> getUpdatedListOfServers() {
return this.cloudFoundryServers();
}
@Override
public List<CloudFoundryServer> getInitialListOfServers() {
return this.cloudFoundryServers();
}
protected List<CloudFoundryServer> cloudFoundryServers() {
CloudApplication cloudApplications = this.cloudFoundryClient.getApplication(this.serviceId);
return Collections.singletonList(new CloudFoundryServer(cloudApplications));
}
@Override
public List<CloudFoundryServer> getUpdatedListOfServers() {
return this.cloudFoundryServers();
}
protected List<CloudFoundryServer> cloudFoundryServers() {
try {
CloudApplication cloudApplications = this.cloudFoundryClient
.getApplication(this.serviceId);
return Collections.singletonList(new CloudFoundryServer(cloudApplications));
}
catch (Exception e) {
log.warn("Cannot determine server list for " + serviceId + ": " + e.getClass() + "(" + e.getMessage() + ")");
return Collections.emptyList();
}
}
}

View File

@@ -14,7 +14,6 @@
* limitations under the License.
*/
package org.springframework.cloud.cloudfoundry.discovery;
import org.apache.commons.logging.LogFactory;
@@ -40,63 +39,65 @@ import java.util.Collections;
*/
public class CloudFoundryAutoConfigurationTest {
private ConfigurableApplicationContext context;
private ConfigurableApplicationContext context;
@Before
public void setUp() {
@Before
public void setUp() {
String hiServiceServiceId = "foo-service";
String hiServiceServiceId = "foo-service";
Object vcapAppl = "{\"limits\":{\"mem\":1024,\"disk\":1024,\"fds\":16384},\"application_version\":" +
"\"36eff082-96d6-498f-8214-508fda72ba65\",\"application_name\":\"" + hiServiceServiceId +
"\",\"application_uris\"" +
":[\"" + hiServiceServiceId +
".cfapps.io\"],\"version\":\"36eff082-96d6-498f-8214-508fda72ba65\",\"name\":" +
"\"hi-service\",\"space_name\":\"joshlong\",\"space_id\":\"e0cd969c-3461-41ae-abde-4e11bb5acbd1\"," +
"\"uris\":[\"hi-service.cfapps.io\"],\"users\":null,\"application_id\":\"af350f7c-88c4-4e35-a04e-698a1dbc7354\"," +
"\"instance_id\":\"e4843ca23bd947b28e6d4cb3f9b92cbb\",\"instance_index\":0,\"host\":\"0.0.0.0\",\"port\":61590," +
"\"started_at\":\"2015-05-07 20:00:10 +0000\",\"started_at_timestamp\":1431028810,\"start\":\"2015-05-07 20:00:10 +0000\"," +
"\"state_timestamp\":1431028810}";
Object vcapAppl = "{\"limits\":{\"mem\":1024,\"disk\":1024,\"fds\":16384},\"application_version\":"
+ "\"36eff082-96d6-498f-8214-508fda72ba65\",\"application_name\":\""
+ hiServiceServiceId
+ "\",\"application_uris\""
+ ":[\""
+ hiServiceServiceId
+ ".cfapps.io\"],\"version\":\"36eff082-96d6-498f-8214-508fda72ba65\",\"name\":"
+ "\"hi-service\",\"space_name\":\"joshlong\",\"space_id\":\"e0cd969c-3461-41ae-abde-4e11bb5acbd1\","
+ "\"uris\":[\"hi-service.cfapps.io\"],\"users\":null,\"application_id\":\"af350f7c-88c4-4e35-a04e-698a1dbc7354\","
+ "\"instance_id\":\"e4843ca23bd947b28e6d4cb3f9b92cbb\",\"instance_index\":0,\"host\":\"0.0.0.0\",\"port\":61590,"
+ "\"started_at\":\"2015-05-07 20:00:10 +0000\",\"started_at_timestamp\":1431028810,\"start\":\"2015-05-07 20:00:10 +0000\","
+ "\"state_timestamp\":1431028810}";
this.context = new SpringApplicationBuilder()
.properties(Collections.singletonMap("VCAP_APPLICATION", vcapAppl))
.sources(SimpleConfiguration.class)
.run();
}
this.context = new SpringApplicationBuilder()
.properties(Collections.singletonMap("VCAP_APPLICATION", vcapAppl))
.sources(SimpleConfiguration.class).run();
}
@After
public void after() throws Throwable {
synchronized (this) {
if (null != this.context)
this.context.close();
}
}
@After
public void after() throws Throwable {
synchronized (this) {
if (null != this.context)
this.context.close();
}
}
@Configuration
@EnableDiscoveryClient
@EnableFeignClients
@EnableAutoConfiguration
public static class SimpleConfiguration {
@Configuration
@EnableDiscoveryClient
@EnableFeignClients
@EnableAutoConfiguration
public static class SimpleConfiguration {
@Bean
CloudCredentials cloudCredentials() {
return Mockito.mock(CloudCredentials.class);
}
@Bean
CloudCredentials cloudCredentials() {
return Mockito.mock(CloudCredentials.class);
}
@Bean
CloudFoundryClient cloudFoundryClient() {
return Mockito.mock(CloudFoundryClient.class);
}
@Bean
CloudFoundryClient cloudFoundryClient() {
return Mockito.mock(CloudFoundryClient.class);
}
}
}
@Test
public void contextLoaded() {
LogFactory.getLog(getClass()).debug("contextLoad()");
Assert.assertTrue(this.context.getBeansOfType(CloudFoundryDiscoveryClient.class).size() > 0);
Assert.assertTrue(this.context.getBeansOfType(CloudFoundryDiscoveryProperties.class).size() > 0);
Assert.assertTrue(this.context.getBeansOfType(CloudFoundryClient.class).size() > 0);
}
@Test
public void contextLoaded() {
LogFactory.getLog(getClass()).debug("contextLoad()");
Assert.assertTrue(this.context.getBeansOfType(CloudFoundryDiscoveryClient.class)
.size() > 0);
Assert.assertTrue(this.context.getBeansOfType(
CloudFoundryDiscoveryProperties.class).size() > 0);
Assert.assertTrue(this.context.getBeansOfType(CloudFoundryClient.class).size() > 0);
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.cloud.cloudfoundry.discovery;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.client.lib.CloudFoundryClient;
import org.cloudfoundry.client.lib.CloudFoundryException;
import org.cloudfoundry.client.lib.domain.CloudApplication;
import org.cloudfoundry.client.lib.domain.InstanceInfo;
import org.cloudfoundry.client.lib.domain.InstanceState;
@@ -28,6 +29,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import java.util.ArrayList;
import java.util.Arrays;
@@ -43,114 +45,135 @@ import static org.mockito.BDDMockito.mock;
*/
public class CloudFoundryDiscoveryClientTest {
private final Log log = LogFactory.getLog(getClass());
private final Log log = LogFactory.getLog(getClass());
private CloudFoundryDiscoveryClient cloudFoundryDiscoveryClient;
private CloudFoundryDiscoveryClient cloudFoundryDiscoveryClient;
private CloudApplication cloudApplication;
private CloudApplication cloudApplication;
private String hiServiceServiceId = "hi-service";
private String hiServiceServiceId = "hi-service";
private CloudFoundryClient cloudFoundryClient;
private CloudFoundryClient cloudFoundryClient;
private CloudApplication fakeCloudApplication(String name, String... uri) {
CloudApplication cloudApplication = mock(CloudApplication.class);
given(cloudApplication.getName()).willReturn(name);
given(cloudApplication.getUris()).willReturn(Arrays.asList(uri));
return cloudApplication;
}
private CloudApplication fakeCloudApplication(String name, String... uri) {
CloudApplication cloudApplication = mock(CloudApplication.class);
given(cloudApplication.getName()).willReturn(name);
given(cloudApplication.getUris()).willReturn(Arrays.asList(uri));
return cloudApplication;
}
@Before
public void setUp() {
this.cloudFoundryClient = mock(CloudFoundryClient.class);
Environment environment = mock(Environment.class);
@Before
public void setUp() {
this.cloudFoundryClient = mock(CloudFoundryClient.class);
Environment environment = mock(Environment.class);
given(environment.getProperty("VCAP_APPLICATION"))
.willReturn("{\"limits\":{\"mem\":1024,\"disk\":1024,\"fds\":16384},\"application_version\":" +
"\"36eff082-96d6-498f-8214-508fda72ba65\",\"application_name\":\"" + hiServiceServiceId +
"\",\"application_uris\"" +
":[\"" + hiServiceServiceId +
".cfapps.io\"],\"version\":\"36eff082-96d6-498f-8214-508fda72ba65\",\"name\":" +
"\"hi-service\",\"space_name\":\"joshlong\",\"space_id\":\"e0cd969c-3461-41ae-abde-4e11bb5acbd1\"," +
"\"uris\":[\"hi-service.cfapps.io\"],\"users\":null,\"application_id\":\"af350f7c-88c4-4e35-a04e-698a1dbc7354\"," +
"\"instance_id\":\"e4843ca23bd947b28e6d4cb3f9b92cbb\",\"instance_index\":0,\"host\":\"0.0.0.0\",\"port\":61590," +
"\"started_at\":\"2015-05-07 20:00:10 +0000\",\"started_at_timestamp\":1431028810,\"start\":\"2015-05-07 20:00:10 +0000\"," +
"\"state_timestamp\":1431028810}");
given(environment.getProperty("VCAP_APPLICATION"))
.willReturn(
"{\"limits\":{\"mem\":1024,\"disk\":1024,\"fds\":16384},\"application_version\":"
+ "\"36eff082-96d6-498f-8214-508fda72ba65\",\"application_name\":\""
+ hiServiceServiceId
+ "\",\"application_uris\""
+ ":[\""
+ hiServiceServiceId
+ ".cfapps.io\"],\"version\":\"36eff082-96d6-498f-8214-508fda72ba65\",\"name\":"
+ "\"hi-service\",\"space_name\":\"joshlong\",\"space_id\":\"e0cd969c-3461-41ae-abde-4e11bb5acbd1\","
+ "\"uris\":[\"hi-service.cfapps.io\"],\"users\":null,\"application_id\":\"af350f7c-88c4-4e35-a04e-698a1dbc7354\","
+ "\"instance_id\":\"e4843ca23bd947b28e6d4cb3f9b92cbb\",\"instance_index\":0,\"host\":\"0.0.0.0\",\"port\":61590,"
+ "\"started_at\":\"2015-05-07 20:00:10 +0000\",\"started_at_timestamp\":1431028810,\"start\":\"2015-05-07 20:00:10 +0000\","
+ "\"state_timestamp\":1431028810}");
List<CloudApplication> cloudApplications = new ArrayList<>();
cloudApplications.add(fakeCloudApplication(this.hiServiceServiceId, "hi-service.cfapps.io", "hi-service-1.cfapps.io"));
cloudApplications.add(fakeCloudApplication("config-service", "conf-service.cfapps.io", "conf-service-1.cfapps.io"));
List<CloudApplication> cloudApplications = new ArrayList<>();
cloudApplications.add(fakeCloudApplication(this.hiServiceServiceId,
"hi-service.cfapps.io", "hi-service-1.cfapps.io"));
cloudApplications.add(fakeCloudApplication("config-service",
"conf-service.cfapps.io", "conf-service-1.cfapps.io"));
given(this.cloudFoundryClient.getApplications())
.willReturn(cloudApplications);
given(this.cloudFoundryClient.getApplications()).willReturn(cloudApplications);
cloudApplication = cloudApplications.get(0);
given(this.cloudFoundryClient.getApplication(this.hiServiceServiceId))
.willReturn(cloudApplication);
cloudApplication = cloudApplications.get(0);
given(this.cloudFoundryClient.getApplication(this.hiServiceServiceId))
.willReturn(cloudApplication);
given(this.cloudFoundryClient.getApplication(this.hiServiceServiceId))
.willReturn(this.cloudApplication);
given(this.cloudFoundryClient.getApplication(this.hiServiceServiceId))
.willReturn(this.cloudApplication);
InstanceInfo instanceInfo = mock(InstanceInfo.class);
InstancesInfo instancesInfo = mock(InstancesInfo.class);
given(instancesInfo.getInstances())
.willReturn(Collections.singletonList(instanceInfo));
given(instanceInfo.getState())
.willReturn(InstanceState.RUNNING);
InstanceInfo instanceInfo = mock(InstanceInfo.class);
InstancesInfo instancesInfo = mock(InstancesInfo.class);
given(instancesInfo.getInstances()).willReturn(
Collections.singletonList(instanceInfo));
given(instanceInfo.getState()).willReturn(InstanceState.RUNNING);
given(this.cloudFoundryClient.getApplicationInstances(this.cloudApplication))
.willReturn(instancesInfo);
given(this.cloudFoundryClient.getApplicationInstances(this.cloudApplication))
.willReturn(instancesInfo);
this.cloudFoundryDiscoveryClient = new CloudFoundryDiscoveryClient(cloudFoundryClient, environment);
}
this.cloudFoundryDiscoveryClient = new CloudFoundryDiscoveryClient(
cloudFoundryClient, environment);
}
@Test
public void testServiceResolution() {
List<String> serviceNames = this.cloudFoundryDiscoveryClient.getServices();
@Test
public void testServiceResolution() {
List<String> serviceNames = this.cloudFoundryDiscoveryClient.getServices();
Assert.assertTrue("there should be one registered service.", serviceNames.contains(
this.hiServiceServiceId));
Assert.assertTrue("there should be one registered service.",
serviceNames.contains(this.hiServiceServiceId));
for (String serviceName : serviceNames) {
this.log.debug("\t discovered serviceName: " + serviceName);
}
}
for (String serviceName : serviceNames) {
this.log.debug("\t discovered serviceName: " + serviceName);
}
}
@Test
public void testInstances() {
List<ServiceInstance> instances = this.cloudFoundryDiscoveryClient.getInstances(
this.hiServiceServiceId);
assertEquals(instances.size(), 1);
}
@Test
public void testInstances() {
List<ServiceInstance> instances = this.cloudFoundryDiscoveryClient
.getInstances(this.hiServiceServiceId);
assertEquals(instances.size(), 1);
}
@Test
public void testLocalServiceInstanceRunning() {
@Test
public void testLocalServiceInstanceRunning() {
InstanceInfo instanceInfo = mock(InstanceInfo.class);
InstancesInfo instancesInfo = mock(InstancesInfo.class);
given(instancesInfo.getInstances()).willReturn(Collections.singletonList(instanceInfo));
given(instanceInfo.getState()).willReturn(InstanceState.RUNNING);
InstanceInfo instanceInfo = mock(InstanceInfo.class);
InstancesInfo instancesInfo = mock(InstancesInfo.class);
given(instancesInfo.getInstances()).willReturn(
Collections.singletonList(instanceInfo));
given(instanceInfo.getState()).willReturn(InstanceState.RUNNING);
given(cloudFoundryClient.getApplicationInstances(this.cloudApplication)).willReturn(instancesInfo);
given(cloudFoundryClient.getApplicationInstances(this.cloudApplication))
.willReturn(instancesInfo);
ServiceInstance localServiceInstance = this.cloudFoundryDiscoveryClient.getLocalServiceInstance();
assertTrue(localServiceInstance.getHost().contains("hi-service.cfapps.io"));
assertTrue(localServiceInstance.getServiceId().equals(this.hiServiceServiceId));
assertEquals(localServiceInstance.getPort(), 80);
}
ServiceInstance localServiceInstance = this.cloudFoundryDiscoveryClient
.getLocalServiceInstance();
assertTrue(localServiceInstance.getHost().contains("hi-service.cfapps.io"));
assertTrue(localServiceInstance.getServiceId().equals(this.hiServiceServiceId));
assertEquals(localServiceInstance.getPort(), 80);
}
@Test
public void testLocalServiceInstanceNotRunning() {
@Test
public void testLocalServiceInstanceNotRunning() {
InstanceInfo instanceInfo = mock(InstanceInfo.class);
InstancesInfo instancesInfo = mock(InstancesInfo.class);
given(instancesInfo.getInstances()).willReturn(Collections.singletonList(instanceInfo));
given(instanceInfo.getState()).willReturn(InstanceState.CRASHED);
InstanceInfo instanceInfo = mock(InstanceInfo.class);
InstancesInfo instancesInfo = mock(InstancesInfo.class);
given(instancesInfo.getInstances()).willReturn(
Collections.singletonList(instanceInfo));
given(instanceInfo.getState()).willReturn(InstanceState.CRASHED);
given(cloudFoundryClient.getApplicationInstances(this.cloudApplication)).willReturn(instancesInfo);
given(cloudFoundryClient.getApplicationInstances(this.cloudApplication))
.willReturn(instancesInfo);
ServiceInstance localServiceInstance = this.cloudFoundryDiscoveryClient.getLocalServiceInstance();
assertNull(localServiceInstance);
}
ServiceInstance localServiceInstance = this.cloudFoundryDiscoveryClient
.getLocalServiceInstance();
assertNull(localServiceInstance);
}
@Test
public void testLocalServiceInstanceNotFoundg() {
given(cloudFoundryClient.getApplicationInstances(this.cloudApplication))
.willThrow(new CloudFoundryException(HttpStatus.NOT_FOUND));
ServiceInstance localServiceInstance = this.cloudFoundryDiscoveryClient
.getLocalServiceInstance();
assertNull(localServiceInstance);
}
}

View File

@@ -17,13 +17,16 @@
package org.springframework.cloud.cloudfoundry.discovery;
import com.netflix.client.config.IClientConfig;
import org.cloudfoundry.client.lib.CloudFoundryClient;
import org.cloudfoundry.client.lib.CloudFoundryException;
import org.cloudfoundry.client.lib.domain.CloudApplication;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.http.HttpStatus;
import java.util.Arrays;
import java.util.List;
@@ -36,40 +39,54 @@ import static org.mockito.BDDMockito.mock;
*/
public class CloudFoundryServerListTest {
private CloudFoundryServerList cloudFoundryServerList;
private String serviceId = "foo-service";
private CloudFoundryServerList cloudFoundryServerList;
private String serviceId = "foo-service";
private CloudFoundryClient cloudFoundryClient;
@Before
public void setUp() {
@Before
public void setUp() {
CloudApplication cloudApplication = mock(CloudApplication.class);
given(cloudApplication.getUris()).will(new Answer<List<String>>() {
@Override
public List<String> answer(InvocationOnMock invocationOnMock) throws Throwable {
return Arrays.asList("a-url.com", "b-url.com");
}
});
CloudApplication cloudApplication = mock(CloudApplication.class);
given(cloudApplication.getUris()).will(new Answer<List<String>>() {
@Override
public List<String> answer(InvocationOnMock invocationOnMock)
throws Throwable {
return Arrays.asList("a-url.com", "b-url.com");
}
});
CloudFoundryClient cloudFoundryClient = mock(CloudFoundryClient.class);
given(cloudFoundryClient.getApplication(this.serviceId)).willReturn(cloudApplication);
cloudFoundryClient = mock(CloudFoundryClient.class);
given(cloudFoundryClient.getApplication(this.serviceId)).willReturn(
cloudApplication);
IClientConfig iClientConfig = mock(IClientConfig.class);
given(iClientConfig.getClientName()).willReturn(this.serviceId);
IClientConfig iClientConfig = mock(IClientConfig.class);
given(iClientConfig.getClientName()).willReturn(this.serviceId);
this.cloudFoundryServerList = new CloudFoundryServerList(cloudFoundryClient);
this.cloudFoundryServerList.initWithNiwsConfig(iClientConfig);
}
this.cloudFoundryServerList = new CloudFoundryServerList(cloudFoundryClient);
this.cloudFoundryServerList.initWithNiwsConfig(iClientConfig);
}
@Test
public void testListOfServers() {
List<CloudFoundryServer> initialListOfServers = this.cloudFoundryServerList.getInitialListOfServers();
List<CloudFoundryServer> updatedListOfServers = this.cloudFoundryServerList.getUpdatedListOfServers();
Assert.assertEquals(updatedListOfServers, initialListOfServers);
Assert.assertTrue(initialListOfServers.size() == 1);
}
@Test
public void testListOfServers() {
List<CloudFoundryServer> initialListOfServers = this.cloudFoundryServerList
.getInitialListOfServers();
List<CloudFoundryServer> updatedListOfServers = this.cloudFoundryServerList
.getUpdatedListOfServers();
Assert.assertEquals(updatedListOfServers, initialListOfServers);
Assert.assertTrue(initialListOfServers.size() == 1);
}
@Test
public void testInit() {
Assert.assertEquals(this.cloudFoundryServerList.serviceId, this.serviceId);
}
@Test
public void testListOfServersFails() {
given(cloudFoundryClient.getApplication(this.serviceId)).willThrow(
new CloudFoundryException(HttpStatus.NOT_FOUND));
List<CloudFoundryServer> initialListOfServers = this.cloudFoundryServerList
.getInitialListOfServers();
Assert.assertTrue(initialListOfServers.size() == 0);
}
@Test
public void testInit() {
Assert.assertEquals(this.cloudFoundryServerList.serviceId, this.serviceId);
}
}

View File

@@ -33,26 +33,26 @@ import static org.mockito.BDDMockito.mock;
*/
public class CloudFoundryServerTest {
private CloudFoundryServer cloudFoundryServer;
private List<String> urls = Arrays.asList("a-url.com", "b-url.com");
private String serverName = "server-name";
private CloudFoundryServer cloudFoundryServer;
private List<String> urls = Arrays.asList("a-url.com", "b-url.com");
private String serverName = "server-name";
@Before
public void setUp() {
CloudApplication cloudApplication = mock(CloudApplication.class);
given(cloudApplication.getUris()).willReturn(this.urls);
given(cloudApplication.getName()).willReturn(this.serverName);
given(cloudApplication.getRunningInstances()).willReturn(1);
this.cloudFoundryServer = new CloudFoundryServer(cloudApplication);
}
@Before
public void setUp() {
CloudApplication cloudApplication = mock(CloudApplication.class);
given(cloudApplication.getUris()).willReturn(this.urls);
given(cloudApplication.getName()).willReturn(this.serverName);
given(cloudApplication.getRunningInstances()).willReturn(1);
this.cloudFoundryServer = new CloudFoundryServer(cloudApplication);
}
@Test
public void testProperConstruction() {
Server.MetaInfo metaInfo = this.cloudFoundryServer.getMetaInfo();
@Test
public void testProperConstruction() {
Server.MetaInfo metaInfo = this.cloudFoundryServer.getMetaInfo();
Assert.assertEquals(metaInfo.getAppName(), this.serverName);
Assert.assertEquals(metaInfo.getServiceIdForDiscovery(), this.serverName);
Assert.assertEquals(metaInfo.getInstanceId(), this.serverName);
Assert.assertEquals(this.cloudFoundryServer.getHost(), this.urls.get(0));
}
Assert.assertEquals(metaInfo.getAppName(), this.serverName);
Assert.assertEquals(metaInfo.getServiceIdForDiscovery(), this.serverName);
Assert.assertEquals(metaInfo.getInstanceId(), this.serverName);
Assert.assertEquals(this.cloudFoundryServer.getHost(), this.urls.get(0));
}
}

View File

@@ -1,61 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-cloudfoundry-sample</artifactId>
<packaging>jar</packaging>
<artifactId>spring-cloud-cloudfoundry-sample</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry</artifactId>
<version>1.0.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!--skip deploy -->
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-ribbon</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!--skip deploy -->
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-core</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-ribbon</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -16,6 +16,9 @@
package org.springframework.cloud.cloudfoundry.sample;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.logging.Log;
@@ -24,89 +27,105 @@ import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.cloudfoundry.discovery.CloudFoundryDiscoveryClient;
import org.springframework.cloud.cloudfoundry.discovery.EnableCloudFoundryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.Map;
/**
* This example assumes you've registered an application on <A href="http://cloudfoundry.org">Cloud Foundry</A>
* named {@code hi-service} that responds with a String at {@code /hi/{name}}. There is a sample file in the project
* root called {@code hi-service.groovy} which you can deploy using the {@code spring} CLI and the {@code cf} CLI that
* works appropriately for this demonstration.
* This example assumes you've registered an application on <A
* href="http://cloudfoundry.org">Cloud Foundry</A> named {@code hi-service} that responds
* with a String at {@code /hi/ name} . There is a sample file in the project root called
* {@code hi-service.groovy} which you can deploy using the {@code spring} CLI and the
* {@code cf} CLI that works appropriately for this demonstration.
*
* @author <a href="mailto:josh@joshlong.com">Josh Long</a>
* @author Spencer Gibb
* @author Dave Syer
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableCloudFoundryClient
@EnableFeignClients
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
private Log log = LogFactory.getLog(getClass());
private Log log = LogFactory.getLog(getClass());
@Bean
CommandLineRunner consume(final LoadBalancerClient loadBalancerClient,
final DiscoveryClient discoveryClient,
final HiServiceClient hiServiceClient,
final RestTemplate restTemplate) {
@Bean
CommandLineRunner consume(final LoadBalancerClient loadBalancerClient,
final CloudFoundryDiscoveryClient discoveryClient, final HiServiceClient hiServiceClient,
final RestTemplate restTemplate) {
return new CommandLineRunner() {
@Override
public void run(String... args) throws Exception {
return new CommandLineRunner() {
@Override
public void run(String... args) throws Exception {
// this demonstrates using the CF/Ribbon-aware RestTemplate interceptor
log.info("=====================================");
log.info("Hi: " + restTemplate.getForEntity("http://hi-service/hi/{name}", String.class, "Josh"));
try {
// this demonstrates using the CF/Ribbon-aware RestTemplate
// interceptor
log.info("=====================================");
log.info("Hi: "
+ restTemplate.getForEntity("http://hi-service/hi/{name}",
String.class, "Josh"));
}
catch (Exception e) {
log.warn("Failed to fetch hi-service", e);
}
// this demonstrates using the Spring Cloud Commons DiscoveryClient abstraction
log.info("=====================================");
for (String svc : discoveryClient.getServices()) {
log.info("service = " + svc);
List<ServiceInstance> instances = discoveryClient.getInstances(svc);
for (ServiceInstance si : instances) {
log.info("\t" + ReflectionToStringBuilder.reflectionToString(si, ToStringStyle.MULTI_LINE_STYLE));
}
}
// this demonstrates using the Spring Cloud Commons DiscoveryClient
// abstraction
log.info("=====================================");
for (String svc : discoveryClient.getServices()) {
log.info("service = " + svc);
List<ServiceInstance> instances = discoveryClient.getInstances(svc);
for (ServiceInstance si : instances) {
log.info("\t"
+ ReflectionToStringBuilder.reflectionToString(si,
ToStringStyle.MULTI_LINE_STYLE));
}
}
log.info("=====================================");
log.info("local: ");
log.info("\t" + ReflectionToStringBuilder.reflectionToString(
discoveryClient.getLocalServiceInstance(), ToStringStyle.MULTI_LINE_STYLE));
log.info("=====================================");
log.info("local: ");
log.info("\t"
+ ReflectionToStringBuilder.reflectionToString(
discoveryClient.getLocalServiceInstance(),
ToStringStyle.MULTI_LINE_STYLE));
// this demonstrates using a CF/Ribbon-aware Feign client
log.info("=====================================");
log.info("Hi:" + hiServiceClient.hi("Josh"));
try {
// this demonstrates using a CF/Ribbon-aware Feign client
log.info("=====================================");
log.info("Hi:" + hiServiceClient.hi("Josh"));
}
catch (Exception e) {
log.warn("Failed to fetch hi-service", e);
}
// this demonstrates using the Spring Cloud Commons LoadBalancerClient
log.info("=====================================");
ServiceInstance choose = loadBalancerClient.choose("hi-service");
log.info("chose: " + '(' + choose.getServiceId() + ") " + choose.getHost() + ':' + choose.getPort());
}
};
}
// this demonstrates using the Spring Cloud Commons LoadBalancerClient
log.info("=====================================");
ServiceInstance choose = loadBalancerClient.choose("hi-service");
if (choose != null) {
log.info("chose: " + '(' + choose.getServiceId() + ") "
+ choose.getHost() + ':' + choose.getPort());
}
}
};
}
}
@FeignClient("hi-service")
interface HiServiceClient {
@RequestMapping(value = "/hi/{name}", method = RequestMethod.GET)
Map<String, Object> hi(@PathVariable("name") String name);
@RequestMapping(value = "/hi/{name}", method = RequestMethod.GET)
Map<String, Object> hi(@PathVariable("name") String name);
}

View File

@@ -1,4 +1,4 @@
spring.application.name=test-app
spring.cloud.cloudfoundry.discovery.email=starbuxman@gmail.com
spring.cloud.cloudfoundry.discovery.password=xxxx
spring.cloud.cloudfoundry.discovery.email=${email:starbuxman@gmail.com}
spring.cloud.cloudfoundry.discovery.password=${password:xxxx}
VCAP_APPLICATION={"limits":{"mem":1024,"disk":1024,"fds":16384},"application_version":"36eff082-96d6-498f-8214-508fda72ba65","application_name":"hi-service","application_uris":["hi-service.cfapps.io"],"version":"36eff082-96d6-498f-8214-508fda72ba65","name":"hi-service","space_name":"joshlong","space_id":"e0cd969c-3461-41ae-abde-4e11bb5acbd1","uris":["hi-service.cfapps.io"],"users":null,"application_id":"af350f7c-88c4-4e35-a04e-698a1dbc7354","instance_id":"e4843ca23bd947b28e6d4cb3f9b92cbb","instance_index":0,"host":"0.0.0.0","port":61590,"started_at":"2015-05-07 20:00:10 +0000","started_at_timestamp":1431028810,"start":"2015-05-07 20:00:10 +0000","state_timestamp":1431028810}

View File

@@ -10,7 +10,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry</artifactId>
<version>1.0.2.BUILD-SNAPSHOT</version>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>