diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DataCenterAwareMarshallingStrategy.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DataCenterAwareMarshallingStrategy.java index 6fc2f541..81f1f75a 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DataCenterAwareMarshallingStrategy.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DataCenterAwareMarshallingStrategy.java @@ -24,6 +24,7 @@ import com.thoughtworks.xstream.MarshallingStrategy; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.ConverterLookup; import com.thoughtworks.xstream.converters.DataHolder; +import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.core.TreeMarshallingStrategy; import com.thoughtworks.xstream.io.HierarchicalStreamReader; @@ -57,7 +58,8 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy { @Override public void marshal(HierarchicalStreamWriter writer, Object obj, ConverterLookup converterLookup, Mapper mapper, DataHolder dataHolder) { - delegate.marshal(writer, obj, converterLookup, mapper, dataHolder); + ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup); + delegate.marshal(writer, obj, wrapped, mapper, dataHolder); } public static class InstanceIdDataCenterInfo implements DataCenterInfo, @@ -101,6 +103,22 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy { } private static class DataCenterAwareConverter extends InstanceInfoConverter { + + @Override + public void marshal(Object source, HierarchicalStreamWriter writer, + MarshallingContext context) { + InstanceInfo info = (InstanceInfo) source; + String instanceId = info.getMetadata().get("instanceId"); + DataCenterInfo dataCenter = info.getDataCenterInfo(); + if (instanceId != null && Name.Amazon != dataCenter.getName()) { + String old = info.getId(); + String id = old.endsWith(instanceId) ? old : old + ":" + instanceId; + info = new InstanceInfo.Builder(info).setDataCenterInfo( + new InstanceIdDataCenterInfo(id)).build(); + source = info; + } + super.marshal(source, writer, context); + } @Override public Object unmarshal(HierarchicalStreamReader reader, @@ -111,8 +129,9 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy { DataCenterInfo dataCenter = info.getDataCenterInfo(); if (instanceId != null && Name.Amazon != dataCenter.getName()) { String old = info.getId(); + String id = old.endsWith(instanceId) ? old : old + ":" + instanceId; info = new InstanceInfo.Builder(info).setDataCenterInfo( - new InstanceIdDataCenterInfo(old + ":" + instanceId)).build(); + new InstanceIdDataCenterInfo(id)).build(); obj = info; } return obj; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java index 113232c7..83e5f292 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java @@ -33,6 +33,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import com.netflix.appinfo.DataCenterInfo; import com.netflix.appinfo.EurekaInstanceConfig; import com.netflix.appinfo.InstanceInfo.InstanceStatus; +import com.netflix.appinfo.UniqueIdentifier; /** * @author Dave Syer @@ -76,10 +77,7 @@ public class EurekaInstanceConfigBean implements EurekaInstanceConfig { private Map metadataMap = new HashMap<>(); - private DataCenterInfo dataCenterInfo = new DataCenterInfo() { - @Getter @Setter - private Name name = Name.MyOwn; - }; + private DataCenterInfo dataCenterInfo = new IdentifyingDataCenterInfo(); private String ipAddress = hostInfo[0]; @@ -130,4 +128,21 @@ public class EurekaInstanceConfigBean implements EurekaInstanceConfig { return preferIpAddress ? ipAddress : hostname; } + private final class IdentifyingDataCenterInfo implements DataCenterInfo, UniqueIdentifier { + @Getter @Setter + private Name name = Name.MyOwn; + + @Override + public String getId() { + String instanceId = metadataMap.get("instanceId"); + if (instanceId != null) { + String old = hostname; + String id = old.endsWith(instanceId) ? old : old + ":" + instanceId; + return id; + } + return hostname; + } + + } + } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java index 48369568..7b121fae 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java @@ -22,10 +22,12 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.AbstractApplicationContext; +import com.netflix.appinfo.UniqueIdentifier; import com.netflix.appinfo.InstanceInfo.InstanceStatus; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import static org.springframework.boot.test.EnvironmentTestUtils.*; /** @@ -43,103 +45,102 @@ public class EurekaInstanceConfigBeanTests { } } + @Test + public void idFromInstanceId() throws Exception { + EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(); + instance.getMetadataMap().put("instanceId", "foo"); + instance.setHostname("bar"); + assertEquals("bar:foo", ((UniqueIdentifier) instance.getDataCenterInfo()).getId()); + } + @Test public void basicBinding() { addEnvironment(context, "eureka.instance.appGroupName=mygroup"); - setupContext(); + setupContext(); assertEquals("mygroup", getInstanceConfig().getAppGroupName()); } @Test public void nonSecurePort() { - testNonSecurePort("eureka.instance.nonSecurePort"); - } + testNonSecurePort("eureka.instance.nonSecurePort"); + } - @Test - public void nonSecurePort2() { - testNonSecurePort("server.port"); - } + @Test + public void nonSecurePort2() { + testNonSecurePort("server.port"); + } - @Test - public void nonSecurePort3() { - testNonSecurePort("SERVER_PORT"); - } + @Test + public void nonSecurePort3() { + testNonSecurePort("SERVER_PORT"); + } - @Test - public void nonSecurePort4() { - testNonSecurePort("PORT"); - } + @Test + public void nonSecurePort4() { + testNonSecurePort("PORT"); + } - private void testNonSecurePort(String propName) { - addEnvironment(context, propName + ":8888"); - setupContext(); - assertEquals(8888, getInstanceConfig().getNonSecurePort()); - } + private void testNonSecurePort(String propName) { + addEnvironment(context, propName + ":8888"); + setupContext(); + assertEquals(8888, getInstanceConfig().getNonSecurePort()); + } - @Test - public void testDefaultInitialStatus() { - setupContext(); - assertEquals("initialStatus wrong", InstanceStatus.UP, - getInstanceConfig().getInitialStatus()); - } + @Test + public void testDefaultInitialStatus() { + setupContext(); + assertEquals("initialStatus wrong", InstanceStatus.UP, getInstanceConfig() + .getInitialStatus()); + } - @Test(expected = BeanCreationException.class) - public void testBadInitialStatus() { - addEnvironment(context, "eureka.instance.initial-status:FOO"); - setupContext(); - } + @Test(expected = BeanCreationException.class) + public void testBadInitialStatus() { + addEnvironment(context, "eureka.instance.initial-status:FOO"); + setupContext(); + } - @Test - public void testCustomInitialStatus() { - addEnvironment(context, "eureka.instance.initial-status:STARTING"); - setupContext(); - assertEquals("initialStatus wrong", InstanceStatus.STARTING, - getInstanceConfig().getInitialStatus()); - } + @Test + public void testCustomInitialStatus() { + addEnvironment(context, "eureka.instance.initial-status:STARTING"); + setupContext(); + assertEquals("initialStatus wrong", InstanceStatus.STARTING, getInstanceConfig() + .getInitialStatus()); + } - private void setupContext() { - context.register(PropertyPlaceholderAutoConfiguration.class, - TestConfiguration.class); - context.refresh(); - } + private void setupContext() { + context.register(PropertyPlaceholderAutoConfiguration.class, + TestConfiguration.class); + context.refresh(); + } - protected EurekaInstanceConfigBean getInstanceConfig() { - return context.getBean(EurekaInstanceConfigBean.class); - } + protected EurekaInstanceConfigBean getInstanceConfig() { + return context.getBean(EurekaInstanceConfigBean.class); + } - /* - @Test - public void serviceUrlWithCompositePropertySource() { - CompositePropertySource source = new CompositePropertySource("composite"); - context.getEnvironment().getPropertySources().addFirst(source); - source.addPropertySource(new MapPropertySource("config", Collections - . singletonMap("eureka.client.serviceUrl.defaultZone", - "http://example.com"))); - context.register(PropertyPlaceholderAutoConfiguration.class, - TestConfiguration.class); - context.refresh(); - assertEquals("{defaultZone=http://example.com}", - context.getBean(EurekaInstanceConfigBean.class).getServiceUrl().toString()); - assertEquals( - "[http://example.com]", - context.getBean(EurekaInstanceConfigBean.class) - .getEurekaServerServiceUrls("defaultZone").toString()); - } - - @Test - public void serviceUrlWithDefault() { - EnvironmentTestUtils.addEnvironment(context, - "eureka.client.serviceUrl.defaultZone:", - "eureka.client.serviceUrl.default:http://example.com"); - context.register(PropertyPlaceholderAutoConfiguration.class, - TestConfiguration.class); - context.refresh(); - assertEquals( - "[http://example.com]", - context.getBean(EurekaInstanceConfigBean.class) - .getEurekaServerServiceUrls("defaultZone").toString()); - } - */ + /* + * @Test public void serviceUrlWithCompositePropertySource() { CompositePropertySource + * source = new CompositePropertySource("composite"); + * context.getEnvironment().getPropertySources().addFirst(source); + * source.addPropertySource(new MapPropertySource("config", Collections . singletonMap("eureka.client.serviceUrl.defaultZone", + * "http://example.com"))); + * context.register(PropertyPlaceholderAutoConfiguration.class, + * TestConfiguration.class); context.refresh(); + * assertEquals("{defaultZone=http://example.com}", + * context.getBean(EurekaInstanceConfigBean.class).getServiceUrl().toString()); + * assertEquals( "[http://example.com]", + * context.getBean(EurekaInstanceConfigBean.class) + * .getEurekaServerServiceUrls("defaultZone").toString()); } + * + * @Test public void serviceUrlWithDefault() { + * EnvironmentTestUtils.addEnvironment(context, + * "eureka.client.serviceUrl.defaultZone:", + * "eureka.client.serviceUrl.default:http://example.com"); + * context.register(PropertyPlaceholderAutoConfiguration.class, + * TestConfiguration.class); context.refresh(); assertEquals( "[http://example.com]", + * context.getBean(EurekaInstanceConfigBean.class) + * .getEurekaServerServiceUrls("defaultZone").toString()); } + */ @Configuration @EnableConfigurationProperties(EurekaInstanceConfigBean.class) protected static class TestConfiguration {