Commit dbb60595 by Dave Syer

Simplify config server discovery with DiscoverClient metadata

Since DiscoverClient now supports metadata natively, we can use that and not rely on Eureka interafces at all. Fixes gh-787. Also fixes https://github.com/spring-cloud/spring-cloud-config/issues/302
parent 92a35ba7
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
package org.springframework.cloud.netflix.eureka.config; package org.springframework.cloud.netflix.eureka.config;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
...@@ -32,7 +30,6 @@ import org.springframework.context.annotation.Import; ...@@ -32,7 +30,6 @@ import org.springframework.context.annotation.Import;
import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient; import com.netflix.discovery.EurekaClient;
import lombok.extern.apachecommons.CommonsLog; import lombok.extern.apachecommons.CommonsLog;
...@@ -56,21 +53,16 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration { ...@@ -56,21 +53,16 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration {
@Autowired @Autowired
private DiscoveryClient client; private DiscoveryClient client;
@Autowired
private EurekaClient eurekaClient;
@EventListener(ContextRefreshedEvent.class) @EventListener(ContextRefreshedEvent.class)
public void onApplicationEvent(ContextRefreshedEvent event) { public void onApplicationEvent(ContextRefreshedEvent event) {
refresh(); refresh();
} }
// TODO: re-instate heart beat (maybe? isn't it handled in the child context?)
private void refresh() { private void refresh() {
try { try {
log.debug("Locating configserver via discovery"); log.debug("Locating configserver via discovery");
InstanceInfo server = this.eurekaClient.getNextServerFromEureka( ServiceInstance server = this.client
this.config.getDiscovery().getServiceId(), false); .getInstances(this.config.getDiscovery().getServiceId()).get(0);
String url = getHomePage(server); String url = getHomePage(server);
if (server.getMetadata().containsKey("password")) { if (server.getMetadata().containsKey("password")) {
String user = server.getMetadata().get("user"); String user = server.getMetadata().get("user");
...@@ -93,13 +85,8 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration { ...@@ -93,13 +85,8 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration {
} }
} }
private String getHomePage(InstanceInfo server) { private String getHomePage(ServiceInstance server) {
List<ServiceInstance> instances = this.client return server.getUri().toString() + "/";
.getInstances(this.config.getDiscovery().getServiceId());
if (instances == null || instances.isEmpty()) {
return server.getHomePageUrl();
}
return instances.get(0).getUri().toString() + "/";
} }
} }
...@@ -46,12 +46,13 @@ public class EurekaInstanceConfigBeanTests { ...@@ -46,12 +46,13 @@ public class EurekaInstanceConfigBeanTests {
private String ipAddress; private String ipAddress;
@Before @Before
public void init() { public void init() throws Exception {
InetUtils.HostInfo hostInfo = new InetUtils(new InetUtilsProperties()) try (InetUtils utils = new InetUtils(new InetUtilsProperties())) {
.findFirstNonLoopbackHostInfo(); InetUtils.HostInfo hostInfo = utils.findFirstNonLoopbackHostInfo();
this.hostName = hostInfo.getHostname(); this.hostName = hostInfo.getHostname();
this.ipAddress = hostInfo.getIpAddress(); this.ipAddress = hostInfo.getIpAddress();
} }
}
@After @After
public void clear() { public void clear() {
...@@ -147,8 +148,8 @@ public class EurekaInstanceConfigBeanTests { ...@@ -147,8 +148,8 @@ public class EurekaInstanceConfigBeanTests {
@Test @Test
public void testDefaultInitialStatus() { public void testDefaultInitialStatus() {
setupContext(); setupContext();
assertEquals("initialStatus wrong", InstanceStatus.UP, getInstanceConfig() assertEquals("initialStatus wrong", InstanceStatus.UP,
.getInitialStatus()); getInstanceConfig().getInitialStatus());
} }
@Test(expected = BeanCreationException.class) @Test(expected = BeanCreationException.class)
...@@ -161,8 +162,8 @@ public class EurekaInstanceConfigBeanTests { ...@@ -161,8 +162,8 @@ public class EurekaInstanceConfigBeanTests {
public void testCustomInitialStatus() { public void testCustomInitialStatus() {
addEnvironment(this.context, "eureka.instance.initial-status:STARTING"); addEnvironment(this.context, "eureka.instance.initial-status:STARTING");
setupContext(); setupContext();
assertEquals("initialStatus wrong", InstanceStatus.STARTING, getInstanceConfig() assertEquals("initialStatus wrong", InstanceStatus.STARTING,
.getInitialStatus()); getInstanceConfig().getInitialStatus());
} }
@Test @Test
...@@ -170,8 +171,8 @@ public class EurekaInstanceConfigBeanTests { ...@@ -170,8 +171,8 @@ public class EurekaInstanceConfigBeanTests {
addEnvironment(this.context, "eureka.instance.preferIpAddress:true"); addEnvironment(this.context, "eureka.instance.preferIpAddress:true");
setupContext(); setupContext();
EurekaInstanceConfigBean instance = getInstanceConfig(); EurekaInstanceConfigBean instance = getInstanceConfig();
assertTrue("Wrong hostname: " + instance.getHostname(), getInstanceConfig() assertTrue("Wrong hostname: " + instance.getHostname(),
.getHostname().equals(instance.getIpAddress())); getInstanceConfig().getHostname().equals(instance.getIpAddress()));
} }
......
package org.springframework.cloud.netflix.eureka; package org.springframework.cloud.netflix.eureka;
import java.io.IOException;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
...@@ -19,10 +21,12 @@ public class InstanceInfoFactoryTests { ...@@ -19,10 +21,12 @@ public class InstanceInfoFactoryTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@Test @Test
public void instanceIdIsHostNameByDefault() { public void instanceIdIsHostNameByDefault() throws IOException {
InstanceInfo instanceInfo = setupInstance(); InstanceInfo instanceInfo = setupInstance();
assertEquals(new InetUtils(new InetUtilsProperties()) try (InetUtils utils = new InetUtils(new InetUtilsProperties())) {
.findFirstNonLoopbackHostInfo().getHostname(), instanceInfo.getId()); assertEquals(utils.findFirstNonLoopbackHostInfo().getHostname(),
instanceInfo.getId());
}
} }
@Test @Test
...@@ -38,8 +42,9 @@ public class InstanceInfoFactoryTests { ...@@ -38,8 +42,9 @@ public class InstanceInfoFactoryTests {
} }
private InstanceInfo setupInstance(String... pairs) { private InstanceInfo setupInstance(String... pairs) {
for (String pair : pairs) for (String pair : pairs) {
addEnvironment(this.context, pair); addEnvironment(this.context, pair);
}
this.context.register(PropertyPlaceholderAutoConfiguration.class, this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class); TestConfiguration.class);
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package org.springframework.cloud.netflix.eureka.config; package org.springframework.cloud.netflix.eureka.config;
import java.util.Arrays;
import org.junit.After; import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
...@@ -24,8 +26,6 @@ import org.springframework.boot.test.EnvironmentTestUtils; ...@@ -24,8 +26,6 @@ import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.cloud.config.client.ConfigClientProperties; import org.springframework.cloud.config.client.ConfigClientProperties;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration; import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration; import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration;
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientConfigServiceAutoConfiguration;
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientConfigServiceBootstrapConfiguration;
import org.springframework.cloud.util.UtilAutoConfiguration; import org.springframework.cloud.util.UtilAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -64,7 +64,7 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests { ...@@ -64,7 +64,7 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests {
assertEquals(1, this.context.getBeanNamesForType( assertEquals(1, this.context.getBeanNamesForType(
DiscoveryClientConfigServiceAutoConfiguration.class).length); DiscoveryClientConfigServiceAutoConfiguration.class).length);
EurekaClient eurekaClient = this.context.getParent().getBean(EurekaClient.class); EurekaClient eurekaClient = this.context.getParent().getBean(EurekaClient.class);
Mockito.verify(eurekaClient, times(2)).getNextServerFromEureka("CONFIGSERVER", Mockito.verify(eurekaClient, times(2)).getInstancesByVipAddress("CONFIGSERVER",
false); false);
Mockito.verify(eurekaClient, times(1)).shutdown(); Mockito.verify(eurekaClient, times(1)).shutdown();
ConfigClientProperties locator = this.context ConfigClientProperties locator = this.context
...@@ -99,7 +99,8 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests { ...@@ -99,7 +99,8 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests {
public EurekaClient eurekaClient(ApplicationInfoManager manager) { public EurekaClient eurekaClient(ApplicationInfoManager manager) {
InstanceInfo info = manager.getInfo(); InstanceInfo info = manager.getInfo();
EurekaClient client = Mockito.mock(EurekaClient.class); EurekaClient client = Mockito.mock(EurekaClient.class);
given(client.getNextServerFromEureka("CONFIGSERVER", false)).willReturn(info); given(client.getInstancesByVipAddress("CONFIGSERVER", false))
.willReturn(Arrays.asList(info));
return client; return client;
} }
......
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
package org.springframework.cloud.netflix.eureka.config; package org.springframework.cloud.netflix.eureka.config;
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import java.util.Arrays; import java.util.Arrays;
import org.junit.After; import org.junit.After;
...@@ -26,14 +23,15 @@ import org.junit.Test; ...@@ -26,14 +23,15 @@ import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.config.client.ConfigClientProperties; import org.springframework.cloud.config.client.ConfigClientProperties;
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientConfigServiceBootstrapConfiguration;
import org.springframework.cloud.util.UtilAutoConfiguration; import org.springframework.cloud.util.UtilAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.netflix.appinfo.InstanceInfo; import static org.junit.Assert.assertEquals;
import com.netflix.appinfo.InstanceInfo.PortType; import static org.mockito.BDDMockito.given;
import com.netflix.discovery.EurekaClient;
/** /**
* @author Dave Syer * @author Dave Syer
...@@ -42,10 +40,9 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests { ...@@ -42,10 +40,9 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
private AnnotationConfigApplicationContext context; private AnnotationConfigApplicationContext context;
private EurekaClient client = Mockito.mock(EurekaClient.class); private DiscoveryClient client = Mockito.mock(DiscoveryClient.class);
private InstanceInfo info = InstanceInfo.Builder.newBuilder().setAppName("app") private ServiceInstance info = new DefaultServiceInstance("app", "foo", 8877, false);
.setHostName("foo").setHomePageUrl("/", null).build();
@After @After
public void close() { public void close() {
...@@ -58,40 +55,33 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests { ...@@ -58,40 +55,33 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
public void offByDefault() throws Exception { public void offByDefault() throws Exception {
this.context = new AnnotationConfigApplicationContext( this.context = new AnnotationConfigApplicationContext(
DiscoveryClientConfigServiceBootstrapConfiguration.class); DiscoveryClientConfigServiceBootstrapConfiguration.class);
assertEquals(0, this.context.getBeanNamesForType(EurekaClient.class).length); assertEquals(0, this.context.getBeanNamesForType(DiscoveryClient.class).length);
assertEquals( assertEquals(0, this.context.getBeanNamesForType(
0, DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
this.context
.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
} }
@Test @Test
public void onWhenRequested() throws Exception { public void onWhenRequested() throws Exception {
given(this.client.getNextServerFromEureka("CONFIGSERVER", false)).willReturn( given(this.client.getInstances("CONFIGSERVER"))
this.info); .willReturn(Arrays.asList(this.info));
setup("spring.cloud.config.discovery.enabled=true"); setup("spring.cloud.config.discovery.enabled=true");
assertEquals( assertEquals(1, this.context.getBeanNamesForType(
1, DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
this.context Mockito.verify(this.client).getInstances("CONFIGSERVER");
.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
Mockito.verify(this.client).getNextServerFromEureka("CONFIGSERVER", false);
ConfigClientProperties locator = this.context ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class); .getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/", locator.getRawUri()); assertEquals("http://foo:8877/", locator.getRawUri());
} }
@Test @Test
public void secureWhenRequested() throws Exception { public void secureWhenRequested() throws Exception {
this.info = InstanceInfo.Builder.newBuilder().setAppName("app").setHostName("foo") this.info = new DefaultServiceInstance("app", "foo", 443, true);
.setHomePageUrl("/", null).enablePort(PortType.SECURE, true).setSecurePort(443).build(); given(this.client.getInstances("CONFIGSERVER"))
given(this.client.getNextServerFromEureka("CONFIGSERVER", false))
.willReturn(this.info);
given(this.client.getInstancesByVipAddress("CONFIGSERVER", false))
.willReturn(Arrays.asList(this.info)); .willReturn(Arrays.asList(this.info));
setup("spring.cloud.config.discovery.enabled=true"); setup("spring.cloud.config.discovery.enabled=true");
assertEquals(1, this.context.getBeanNamesForType( assertEquals(1, this.context.getBeanNamesForType(
DiscoveryClientConfigServiceBootstrapConfiguration.class).length); DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
Mockito.verify(this.client).getNextServerFromEureka("CONFIGSERVER", false); Mockito.verify(this.client).getInstances("CONFIGSERVER");
ConfigClientProperties locator = this.context ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class); .getBean(ConfigClientProperties.class);
assertEquals("https://foo:443/", locator.getRawUri()); assertEquals("https://foo:443/", locator.getRawUri());
...@@ -100,12 +90,12 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests { ...@@ -100,12 +90,12 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
@Test @Test
public void setsPasssword() throws Exception { public void setsPasssword() throws Exception {
this.info.getMetadata().put("password", "bar"); this.info.getMetadata().put("password", "bar");
given(this.client.getNextServerFromEureka("CONFIGSERVER", false)).willReturn( given(this.client.getInstances("CONFIGSERVER"))
this.info); .willReturn(Arrays.asList(this.info));
setup("spring.cloud.config.discovery.enabled=true"); setup("spring.cloud.config.discovery.enabled=true");
ConfigClientProperties locator = this.context ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class); .getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/", locator.getRawUri()); assertEquals("http://foo:8877/", locator.getRawUri());
assertEquals("bar", locator.getPassword()); assertEquals("bar", locator.getPassword());
assertEquals("user", locator.getUsername()); assertEquals("user", locator.getUsername());
} }
...@@ -113,19 +103,20 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests { ...@@ -113,19 +103,20 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
@Test @Test
public void setsPath() throws Exception { public void setsPath() throws Exception {
this.info.getMetadata().put("configPath", "/bar"); this.info.getMetadata().put("configPath", "/bar");
given(this.client.getNextServerFromEureka("CONFIGSERVER", false)).willReturn( given(this.client.getInstances("CONFIGSERVER"))
this.info); .willReturn(Arrays.asList(this.info));
setup("spring.cloud.config.discovery.enabled=true"); setup("spring.cloud.config.discovery.enabled=true");
ConfigClientProperties locator = this.context ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class); .getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/bar", locator.getRawUri()); assertEquals("http://foo:8877/bar", locator.getRawUri());
} }
private void setup(String... env) { private void setup(String... env) {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, env); EnvironmentTestUtils.addEnvironment(this.context, env);
this.context.getDefaultListableBeanFactory().registerSingleton( EnvironmentTestUtils.addEnvironment(this.context, "eureka.client.enabled=false");
"eurekaClient", this.client); this.context.getDefaultListableBeanFactory().registerSingleton("discoveryClient",
this.client);
this.context.register(UtilAutoConfiguration.class, this.context.register(UtilAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
DiscoveryClientConfigServiceBootstrapConfiguration.class, DiscoveryClientConfigServiceBootstrapConfiguration.class,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment