From 246830c9d3a2b78ad5d2aba389445abb922086dc Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 16 Jun 2015 23:23:45 -0600 Subject: [PATCH] Upgrade to Eureka 1.2.0 Implements forwarding of eureka CacheRefreshedEvent as HeartbeatEvent, rather thank serialization hack. Uses new Eureka DI functionality (mostly there, some issues). Updates EurekaJacksonCodec to be "DataCenterAware". Reference EurekaClient interface rather than DiscoveryClient class. fixes gh-349 --- pom.xml | 7 +- spring-cloud-netflix-core/pom.xml | 6 + ...yClientConfigServiceAutoConfiguration.java | 16 +- ...ntConfigServiceBootstrapConfiguration.java | 12 +- ...kaClientConfigServerAutoConfiguration.java | 4 +- .../netflix/eureka/CloudEurekaClient.java | 54 +++++++ .../eureka/DataCenterAwareJacksonCodec.java | 144 ++++++++++++++++++ .../DataCenterAwareMarshallingStrategy.java | 93 ++--------- .../eureka/DiscoveryManagerInitializer.java | 47 ------ .../eureka/EurekaClientAutoConfiguration.java | 10 +- .../eureka/EurekaClientConfigBean.java | 13 ++ .../netflix/eureka/EurekaDiscoveryClient.java | 16 +- .../EurekaDiscoveryClientConfiguration.java | 89 ++++------- .../netflix/eureka/EurekaHealthIndicator.java | 14 +- .../eureka/EurekaServerConfigBean.java | 19 +++ .../eureka/InstanceIdDataCenterInfo.java | 44 ++++++ .../netflix/eureka/InstanceInfoFactory.java | 87 +++++++++++ ...ntConfigServiceAutoConfigurationTests.java | 21 ++- ...figServiceBootstrapConfigurationTests.java | 16 +- .../eureka/server/EurekaController.java | 20 ++- .../server/EurekaServerConfiguration.java | 12 +- .../EurekaServerInitializerConfiguration.java | 36 ++--- .../event/LeaseManagerMessageBroker.java | 4 +- .../sidecar/SidecarClientApplication.java | 52 +++++++ spring-cloud-netflix-turbine/pom.xml | 5 + .../turbine/EurekaInstanceDiscovery.java | 22 +-- .../netflix/turbine/TurbineConfiguration.java | 10 +- .../turbine/EurekaInstanceDiscoveryTest.java | 12 +- 28 files changed, 572 insertions(+), 313 deletions(-) create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DataCenterAwareJacksonCodec.java delete mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DiscoveryManagerInitializer.java create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/InstanceIdDataCenterInfo.java create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/InstanceInfoFactory.java create mode 100644 spring-cloud-netflix-sidecar/src/test/java/org/springframework/cloud/netflix/sidecar/SidecarClientApplication.java diff --git a/pom.xml b/pom.xml index 88be448b..7ac1de3b 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ 1.1.0.BUILD-SNAPSHOT ${basedir} 0.6.5 - 1.1.147 + 1.2.0 8.6.0 1.4.13 2.0.0 @@ -187,6 +187,11 @@ + + com.netflix.governator + governator + 1.3.3 + com.netflix.eureka eureka-core diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index a9d685ef..79f36e92 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -59,6 +59,12 @@ eureka-client true + + com.netflix.governator + governator + 1.3.3 + true + com.netflix.eureka eureka-core diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java index 362982bd..e8d98693 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java @@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.config; import javax.annotation.PostConstruct; +import com.netflix.discovery.EurekaClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -25,9 +26,7 @@ import org.springframework.boot.context.properties.ConfigurationPropertiesBindin import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration; import org.springframework.context.annotation.Configuration; -import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.EurekaInstanceConfig; -import com.netflix.discovery.DiscoveryManager; import com.netflix.discovery.EurekaClientConfig; /** @@ -53,17 +52,18 @@ public class DiscoveryClientConfigServiceAutoConfiguration { @Autowired private EurekaDiscoveryClientConfiguration lifecycle; + @Autowired + private EurekaClient eurekaClient; + @PostConstruct public void init() { this.lifecycle.stop(); rebind(this.clientConfig, "eurekaClientConfig"); rebind(this.instanceConfig, "eurekaInstanceConfig"); - if (DiscoveryManager.getInstance().getDiscoveryClient() != null) { - DiscoveryManager.getInstance().getDiscoveryClient().shutdown(); - } - ApplicationInfoManager.getInstance().initComponent(this.instanceConfig); - DiscoveryManager.getInstance().initComponent(this.instanceConfig, - this.clientConfig); + eurekaClient.shutdown();; + // FIXME: reinit EurekaClient and ApplicationInfoManager + //applicationInfoManager.initComponent(this.instanceConfig); + //discoveryManager.initComponent(this.instanceConfig, this.clientConfig); this.lifecycle.start(); } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfiguration.java index 5f8a8b53..0d6ed4ab 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfiguration.java @@ -34,8 +34,7 @@ import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.SmartApplicationListener; import com.netflix.appinfo.InstanceInfo; -import com.netflix.discovery.DiscoveryClient; -import com.netflix.discovery.DiscoveryManager; +import com.netflix.discovery.EurekaClient; /** * Bootstrap configuration for a config client that wants to lookup the config server via @@ -43,7 +42,7 @@ import com.netflix.discovery.DiscoveryManager; * * @author Dave Syer */ -@ConditionalOnClass({ DiscoveryClient.class, ConfigServicePropertySourceLocator.class }) +@ConditionalOnClass({ EurekaClient.class, ConfigServicePropertySourceLocator.class }) @ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false) @Configuration @EnableDiscoveryClient @@ -57,6 +56,9 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration implements @Autowired private ConfigClientProperties config; + @Autowired + private EurekaClient eurekaClient; + @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent) { @@ -88,9 +90,7 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration implements private void refresh() { try { log.info("Locating configserver via discovery"); - InstanceInfo server = DiscoveryManager - .getInstance() - .getDiscoveryClient() + InstanceInfo server = eurekaClient .getNextServerFromEureka(this.config.getDiscovery().getServiceId(), false); String url = server.getHomePageUrl(); diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/EurekaClientConfigServerAutoConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/EurekaClientConfigServerAutoConfiguration.java index 5fe44d69..9fc31d6f 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/EurekaClientConfigServerAutoConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/EurekaClientConfigServerAutoConfiguration.java @@ -26,7 +26,7 @@ import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; -import com.netflix.discovery.DiscoveryClient; +import com.netflix.discovery.EurekaClient; /** * Extra configuration for config server if it happens to be a Eureka instance. @@ -35,7 +35,7 @@ import com.netflix.discovery.DiscoveryClient; */ @Configuration @EnableConfigurationProperties -@ConditionalOnClass({ EurekaInstanceConfigBean.class, DiscoveryClient.class, +@ConditionalOnClass({ EurekaInstanceConfigBean.class, EurekaClient.class, ConfigServerProperties.class }) public class EurekaClientConfigServerAutoConfiguration { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java new file mode 100644 index 00000000..984c4c58 --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.eureka; + +import java.util.concurrent.atomic.AtomicLong; + +import lombok.extern.apachecommons.CommonsLog; + +import org.springframework.cloud.client.discovery.event.HeartbeatEvent; +import org.springframework.context.ApplicationContext; + +import com.netflix.appinfo.ApplicationInfoManager; +import com.netflix.discovery.DiscoveryClient; +import com.netflix.discovery.EurekaClientConfig; + +/** + * @author Spencer Gibb + */ +@CommonsLog +public class CloudEurekaClient extends DiscoveryClient { + + private final AtomicLong cacheRefreshedCount = new AtomicLong(0); + + private ApplicationContext context; + + public CloudEurekaClient(ApplicationInfoManager applicationInfoManager, + EurekaClientConfig config, ApplicationContext context) { + super(applicationInfoManager, config); + this.context = context; + } + + @Override + protected void onCacheRefreshed() { + if (this.cacheRefreshedCount != null) { //might be call during construction and won't be inited yet + long newCount = this.cacheRefreshedCount.incrementAndGet(); + log.trace("onCacheRefreshed called with count: " + newCount); + this.context.publishEvent(new HeartbeatEvent(this, newCount)); + } + } +} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DataCenterAwareJacksonCodec.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DataCenterAwareJacksonCodec.java new file mode 100644 index 00000000..ea18e02d --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DataCenterAwareJacksonCodec.java @@ -0,0 +1,144 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.eureka; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Map; + +import lombok.SneakyThrows; +import lombok.extern.apachecommons.CommonsLog; + +import org.springframework.util.ReflectionUtils; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.netflix.appinfo.DataCenterInfo; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.appinfo.LeaseInfo; +import com.netflix.discovery.converters.EurekaJacksonCodec; +import com.netflix.discovery.converters.StringCache; +import com.netflix.discovery.shared.Application; +import com.netflix.discovery.shared.Applications; + +/** + * @author Spencer Gibb + */ +public class DataCenterAwareJacksonCodec extends EurekaJacksonCodec { + private static final Version VERSION = new Version(1, 1, 0, null); + + @SneakyThrows + public DataCenterAwareJacksonCodec() { + super(); + + ObjectMapper mapper = new ObjectMapper(); + + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + SimpleModule module = new SimpleModule("eureka1.x", VERSION); + module.addSerializer(DataCenterInfo.class, new DataCenterInfoSerializer()); + module.addSerializer(InstanceInfo.class, new DCAwareInstanceInfoSerializer()); + module.addSerializer(Application.class, new ApplicationSerializer()); + module.addSerializer(Applications.class, new ApplicationsSerializer(getVersionDeltaKey(), getAppHashCodeKey())); + + module.addDeserializer(DataCenterInfo.class, new DataCenterInfoDeserializer(getCache())); + module.addDeserializer(LeaseInfo.class, new LeaseInfoDeserializer()); + module.addDeserializer(InstanceInfo.class, new DCAwareInstanceInfoDeserializer(getCache())); + module.addDeserializer(Application.class, new ApplicationDeserializer(mapper, getCache())); + module.addDeserializer(Applications.class, new ApplicationsDeserializer(mapper, getVersionDeltaKey(), getAppHashCodeKey())); + + mapper.registerModule(module); + + Map, ObjectReader> readers = getField("objectReaderByClass"); + readers.put(InstanceInfo.class, mapper.reader().withType(InstanceInfo.class).withRootName("instance")); + readers.put(Application.class, mapper.reader().withType(Application.class).withRootName("application")); + readers.put(Applications.class, mapper.reader().withType(Applications.class).withRootName("applications")); + + Map, ObjectWriter> writers = getField("objectWriterByClass"); + writers.put(InstanceInfo.class, mapper.writer().withType(InstanceInfo.class).withRootName("instance")); + writers.put(Application.class, mapper.writer().withType(Application.class).withRootName("application")); + writers.put(Applications.class, mapper.writer().withType(Applications.class).withRootName("applications")); + + Field field = ReflectionUtils.findField(EurekaJacksonCodec.class, "mapper"); + ReflectionUtils.makeAccessible(field); + field.set(this, mapper); + } + + private T getField(String name) throws IllegalAccessException { + Field field = ReflectionUtils.findField(EurekaJacksonCodec.class, name); + ReflectionUtils.makeAccessible(field); + return (T) field.get(this); + } + + @SneakyThrows + public static void init() { + if (!(EurekaJacksonCodec.getInstance() instanceof DataCenterAwareJacksonCodec)) { + INSTANCE = new DataCenterAwareJacksonCodec(); + } + } + + @CommonsLog + private static class DCAwareInstanceInfoSerializer extends + InstanceInfoSerializer { + + @Override + public void serialize(InstanceInfo info, JsonGenerator jgen, + SerializerProvider provider) throws IOException { + String instanceId = info.getMetadata().get("instanceId"); + DataCenterInfo dataCenter = info.getDataCenterInfo(); + if (instanceId != null + && DataCenterInfo.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(); + } + + super.serialize(info, jgen, provider); + } + } + + private class DCAwareInstanceInfoDeserializer extends InstanceInfoDeserializer { + private DCAwareInstanceInfoDeserializer(StringCache cache) { + super(getMapper(), cache); + } + + @Override + public InstanceInfo deserialize(JsonParser jp, DeserializationContext context) + throws IOException { + InstanceInfo info = super.deserialize(jp, context); + String instanceId = info.getMetadata().get("instanceId"); + DataCenterInfo dataCenter = info.getDataCenterInfo(); + if (instanceId != null && DataCenterInfo.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(); + } + return info; + } + } + +} 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 b6d36b37..49d67d6a 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 @@ -16,19 +16,12 @@ package org.springframework.cloud.netflix.eureka; -import lombok.extern.apachecommons.CommonsLog; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.cloud.client.discovery.event.HeartbeatEvent; -import org.springframework.context.ApplicationContext; - import com.netflix.appinfo.DataCenterInfo; import com.netflix.appinfo.DataCenterInfo.Name; import com.netflix.appinfo.InstanceInfo; -import com.netflix.appinfo.UniqueIdentifier; import com.netflix.discovery.converters.Converters.ApplicationsConverter; import com.netflix.discovery.converters.Converters.InstanceInfoConverter; +import com.netflix.discovery.converters.StringCache; import com.netflix.discovery.shared.Applications; import com.thoughtworks.xstream.MarshallingStrategy; import com.thoughtworks.xstream.converters.Converter; @@ -57,59 +50,29 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy { private TreeMarshallingStrategy delegate = new TreeMarshallingStrategy(); - private ApplicationContext context; - - public DataCenterAwareMarshallingStrategy(ApplicationContext context) { - this.context = context; + public DataCenterAwareMarshallingStrategy() { } @Override public Object unmarshal(Object root, HierarchicalStreamReader reader, DataHolder dataHolder, ConverterLookup converterLookup, Mapper mapper) { - ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup, - this.context); + ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup); return this.delegate.unmarshal(root, reader, dataHolder, wrapped, mapper); } @Override public void marshal(HierarchicalStreamWriter writer, Object obj, ConverterLookup converterLookup, Mapper mapper, DataHolder dataHolder) { - ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup, - this.context); + ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup); this.delegate.marshal(writer, obj, wrapped, mapper, dataHolder); } - public static class InstanceIdDataCenterInfo implements DataCenterInfo, - UniqueIdentifier { - - private String instanceId; - - public InstanceIdDataCenterInfo(String instanceId) { - this.instanceId = instanceId; - } - - @Override - public Name getName() { - return Name.MyOwn; - } - - @Override - public String getId() { - return this.instanceId; - } - - } - private static class DataCenterAwareConverterLookup implements ConverterLookup { private ConverterLookup delegate; - private ApplicationContext context; - - public DataCenterAwareConverterLookup(ConverterLookup delegate, - ApplicationContext context) { + public DataCenterAwareConverterLookup(ConverterLookup delegate) { this.delegate = delegate; - this.context = context; } @Override @@ -119,57 +82,19 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy { return new DataCenterAwareConverter(); } else if (Applications.class == type) { - return new PublishingApplicationsConverter(this.context); + return new ApplicationsConverter(); } return converter; } } - private static class PublishingApplicationsConverter extends ApplicationsConverter { - - private ApplicationContext context; - - public PublishingApplicationsConverter(ApplicationContext context) { - this.context = context; - } - - @Override - public Object unmarshal(HierarchicalStreamReader reader, - UnmarshallingContext unmarshallingContext) { - Object obj = super.unmarshal(reader, unmarshallingContext); - - ProxyFactory factory = new ProxyFactory(obj); - factory.addAdvice(new SetVersionInterceptor(this.context)); - return factory.getProxy(); - } - } - - @CommonsLog - private static class SetVersionInterceptor implements MethodInterceptor { - - private ApplicationContext context; - - public SetVersionInterceptor(ApplicationContext context) { - this.context = context; - } + private static class DataCenterAwareConverter extends InstanceInfoConverter { - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - Object ret = invocation.proceed(); - if ("setVersion".equals(invocation.getMethod().getName())) { - Long version = Long.class.cast(invocation.getArguments()[0]); - log.debug("Applications.setVersion() called with version: " + version); - this.context.publishEvent(new HeartbeatEvent(invocation - .getThis(), version)); - } - return ret; + public DataCenterAwareConverter() { + super(new StringCache()); } - } - - private static class DataCenterAwareConverter extends InstanceInfoConverter { - @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DiscoveryManagerInitializer.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DiscoveryManagerInitializer.java deleted file mode 100644 index 2e98cc65..00000000 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/DiscoveryManagerInitializer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2013-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.netflix.eureka; - -import org.springframework.beans.factory.annotation.Autowired; - -import com.netflix.appinfo.ApplicationInfoManager; -import com.netflix.appinfo.EurekaInstanceConfig; -import com.netflix.discovery.DiscoveryManager; -import com.netflix.discovery.EurekaClientConfig; - -/** - * @author Spencer Gibb - */ -public class DiscoveryManagerInitializer { - - @Autowired - private EurekaClientConfig clientConfig; - - @Autowired - private EurekaInstanceConfig instanceConfig; - - public synchronized void init() { - if (DiscoveryManager.getInstance().getDiscoveryClient() == null) { - DiscoveryManager.getInstance().initComponent(this.instanceConfig, - this.clientConfig); - } - if (ApplicationInfoManager.getInstance().getInfo() == null) { - ApplicationInfoManager.getInstance().initComponent(this.instanceConfig); - } - } - -} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java index ea237a38..8dc5e34c 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java @@ -21,7 +21,6 @@ import java.util.concurrent.ConcurrentMap; import javax.annotation.PostConstruct; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -40,7 +39,6 @@ import org.springframework.context.annotation.Configuration; import com.netflix.appinfo.EurekaInstanceConfig; import com.netflix.discovery.EurekaClientConfig; -import com.netflix.discovery.converters.JsonXStream; import com.netflix.discovery.converters.XmlXStream; /** @@ -53,9 +51,6 @@ import com.netflix.discovery.converters.XmlXStream; @AutoConfigureBefore(NoopDiscoveryClientAutoConfiguration.class) public class EurekaClientAutoConfiguration implements ApplicationListener { - @Autowired - private ApplicationContext applicationContext; - private static final ConcurrentMap listenerAdded = new ConcurrentHashMap<>(); @Value("${server.port:${SERVER_PORT:${PORT:8080}}}") @@ -63,10 +58,9 @@ public class EurekaClientAutoConfiguration implements ApplicationListener getInstances(String serviceId) { - List infos = this.discovery.getInstancesByVipAddress(serviceId, + List infos = this.eurekaClient.getInstancesByVipAddress(serviceId, false); - List instances = new ArrayList(); + List instances = new ArrayList<>(); for (InstanceInfo info : infos) { instances.add(new EurekaServiceInstance(info)); } @@ -130,12 +132,12 @@ public class EurekaDiscoveryClient implements DiscoveryClient { @Override public List getServices() { - Applications applications = this.discovery.getApplications(); + Applications applications = this.eurekaClient.getApplications(); if (applications == null) { return Collections.emptyList(); } List registered = applications.getRegisteredApplications(); - List names = new ArrayList(); + List names = new ArrayList<>(); for (Application app : registered) { if (app.getInstances().isEmpty()) { continue; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java index e9f232c9..474f48ae 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java @@ -16,7 +16,6 @@ package org.springframework.cloud.netflix.eureka; -import java.lang.reflect.Field; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -24,6 +23,7 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.PreDestroy; +import lombok.SneakyThrows; import lombok.extern.apachecommons.CommonsLog; import org.springframework.beans.factory.annotation.Autowired; @@ -43,19 +43,15 @@ import org.springframework.context.ApplicationListener; import org.springframework.context.SmartLifecycle; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.core.Ordered; -import org.springframework.util.ReflectionUtils; import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.EurekaInstanceConfig; import com.netflix.appinfo.HealthCheckHandler; +import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo.InstanceStatus; -import com.netflix.discovery.DiscoveryManager; +import com.netflix.discovery.EurekaClient; import com.netflix.discovery.EurekaClientConfig; -import com.netflix.discovery.shared.EurekaJerseyClient; /** * @author Dave Syer @@ -73,50 +69,18 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order private AtomicInteger port = new AtomicInteger(0); + @Autowired + private EurekaClientConfig clientConfig; + @Autowired private EurekaInstanceConfigBean instanceConfig; @Autowired(required = false) private HealthCheckHandler healthCheckHandler; - @Autowired - private DiscoveryManagerInitializer discoveryManagerInitializer; - @Autowired private ApplicationContext context; - @PreDestroy - public void close() { - closeDiscoveryClientJersey(); - log.info("Removing application " + this.instanceConfig.getAppname() - + " from eureka"); - DiscoveryManager.getInstance().shutdownComponent(); - } - - private void closeDiscoveryClientJersey() { - log.info("Closing DiscoveryClient.jerseyClient"); - Field jerseyClientField = ReflectionUtils.findField( - com.netflix.discovery.DiscoveryClient.class, "discoveryJerseyClient", - EurekaJerseyClient.JerseyClient.class); - if (jerseyClientField != null) { - try { - jerseyClientField.setAccessible(true); - if (DiscoveryManager.getInstance() != null - && DiscoveryManager.getInstance().getDiscoveryClient() != null) { - Object obj = jerseyClientField.get(DiscoveryManager.getInstance() - .getDiscoveryClient()); - if (obj != null) { - EurekaJerseyClient.JerseyClient jerseyClient = (EurekaJerseyClient.JerseyClient) obj; - jerseyClient.destroyResources(); - } - } - } - catch (Exception ex) { - log.error("Error closing DiscoveryClient.jerseyClient", ex); - } - } - } - @Override public void start() { // only set the port if the nonSecurePort is 0 and this.port != 0 @@ -126,18 +90,16 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order // only initialize if nonSecurePort is greater than 0 and it isn't already running // because of containerPortInitializer below if (!this.running.get() && this.instanceConfig.getNonSecurePort() > 0) { - this.discoveryManagerInitializer.init(); log.info("Registering application " + this.instanceConfig.getAppname() + " with eureka with status " + this.instanceConfig.getInitialStatus()); - ApplicationInfoManager.getInstance().setInstanceStatus( + applicationInfoManager().setInstanceStatus( this.instanceConfig.getInitialStatus()); if (this.healthCheckHandler != null) { - DiscoveryManager.getInstance().getDiscoveryClient() - .registerHealthCheck(this.healthCheckHandler); + eurekaClient().registerHealthCheck(this.healthCheckHandler); } this.context.publishEvent(new InstanceRegisteredEvent<>(this, this.instanceConfig)); @@ -149,8 +111,8 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order public void stop() { log.info("Unregistering application " + this.instanceConfig.getAppname() + " with eureka with status DOWN"); - if (ApplicationInfoManager.getInstance().getInfo() != null) { - ApplicationInfoManager.getInstance().setInstanceStatus( + if (applicationInfoManager().getInfo() != null) { + applicationInfoManager().setInstanceStatus( InstanceStatus.DOWN); } this.running.set(false); @@ -182,23 +144,23 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order return this.order; } - @Configuration - protected static class DiscoveryManagerInitializerConfiguration { - - @Bean - @ConditionalOnMissingBean(DiscoveryManagerInitializer.class) - public DiscoveryManagerInitializer discoveryManagerInitializer() { - return new DiscoveryManagerInitializer(); - } + @Bean + @ConditionalOnMissingBean(EurekaClient.class) + @SneakyThrows + public EurekaClient eurekaClient() { + return new CloudEurekaClient(applicationInfoManager(), clientConfig, context); + } + @Bean + @ConditionalOnMissingBean(ApplicationInfoManager.class) + public ApplicationInfoManager applicationInfoManager() { + return new ApplicationInfoManager(instanceConfig, instanceInfo()); } @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) - @ConditionalOnMissingBean(com.netflix.discovery.DiscoveryClient.class) - public com.netflix.discovery.DiscoveryClient eurekaDiscoveryClient() { - return DiscoveryManager.getInstance().getDiscoveryClient(); + @ConditionalOnMissingBean(InstanceInfo.class) + public InstanceInfo instanceInfo() { + return new InstanceInfoFactory().create(instanceConfig); } @Bean @@ -231,9 +193,10 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order @Bean @ConditionalOnMissingBean public EurekaHealthIndicator eurekaHealthIndicator( - com.netflix.discovery.DiscoveryClient eurekaDiscoveryClient, EurekaInstanceConfig config) { +EurekaClient eurekaClient, + EurekaInstanceConfig config) { CompositeMetricReader metrics = new CompositeMetricReader(this.metricReaders.toArray(new MetricReader[0])); - return new EurekaHealthIndicator(eurekaDiscoveryClient, metrics, config); + return new EurekaHealthIndicator(eurekaClient, metrics, config); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthIndicator.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthIndicator.java index 33f38dc9..8c389266 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthIndicator.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthIndicator.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import com.netflix.discovery.EurekaClient; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.Health.Builder; import org.springframework.boot.actuate.health.Status; @@ -28,7 +29,6 @@ import org.springframework.boot.actuate.metrics.reader.MetricReader; import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator; import com.netflix.appinfo.EurekaInstanceConfig; -import com.netflix.discovery.DiscoveryClient; import com.netflix.discovery.shared.Application; import com.netflix.discovery.shared.Applications; @@ -37,7 +37,7 @@ import com.netflix.discovery.shared.Applications; */ public class EurekaHealthIndicator implements DiscoveryHealthIndicator { - private final DiscoveryClient discovery; + private final EurekaClient eurekaClient; private final MetricReader metrics; @@ -45,10 +45,10 @@ public class EurekaHealthIndicator implements DiscoveryHealthIndicator { private int failCount = 0; - public EurekaHealthIndicator(DiscoveryClient discovery, MetricReader metrics, + public EurekaHealthIndicator(EurekaClient eurekaClient, MetricReader metrics, EurekaInstanceConfig instanceConfig) { super(); - this.discovery = discovery; + this.eurekaClient = eurekaClient; this.metrics = metrics; this.instanceConfig = instanceConfig; } @@ -67,7 +67,7 @@ public class EurekaHealthIndicator implements DiscoveryHealthIndicator { } private Status getStatus(Builder builder) { - Status status = new Status(this.discovery.getInstanceRemoteStatus().toString(), + Status status = new Status(this.eurekaClient.getInstanceRemoteStatus().toString(), "Remote status from Eureka server"); @SuppressWarnings("unchecked") Metric value = (Metric) this.metrics @@ -89,11 +89,11 @@ public class EurekaHealthIndicator implements DiscoveryHealthIndicator { } private Map getApplications() { - Applications applications = this.discovery.getApplications(); + Applications applications = this.eurekaClient.getApplications(); if (applications == null) { return Collections.emptyMap(); } - Map result = new HashMap(); + Map result = new HashMap<>(); for (Application application : applications.getRegisteredApplications()) { result.put(application.getName(), application.getInstances().size()); } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaServerConfigBean.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaServerConfigBean.java index 16533774..743779c2 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaServerConfigBean.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaServerConfigBean.java @@ -80,10 +80,14 @@ public class EurekaServerConfigBean implements EurekaServerConfig { private long aSGUpdateIntervalMs = 5 * MINUTES; + private long aSGCacheExpiryTimeoutMs = 10 * MINUTES; // defaults to longer than the asg update interval + private long responseCacheAutoExpirationInSeconds = 180; private long responseCacheUpdateIntervalMs = 30 * 1000; + private boolean useReadOnlyResponseCache = true; + private boolean disableDelta; private long maxIdleThreadInMinutesAgeForStatusReplication = 10; @@ -132,6 +136,8 @@ public class EurekaServerConfigBean implements EurekaServerConfig { private int remoteRegionRegistryFetchInterval = 30; + private int remoteRegionFetchThreadPoolSize = 20; + private String remoteRegionTrustStore = ""; private String remoteRegionTrustStorePassword = "changeit"; @@ -154,6 +160,10 @@ public class EurekaServerConfigBean implements EurekaServerConfig { private boolean logIdentityHeaders = true; + private String listAutoScalingGroupsRoleName = "ListAutoScalingGroups"; + + private boolean enableReplicatedRequestCompression = false; + @Override public boolean shouldEnableSelfPreservation() { return this.enableSelfPreservation; @@ -205,4 +215,13 @@ public class EurekaServerConfigBean implements EurekaServerConfig { return this.logIdentityHeaders; } + @Override + public boolean shouldUseReadOnlyResponseCache() { + return this.useReadOnlyResponseCache; + } + + @Override + public boolean shouldEnableReplicatedRequestCompression() { + return this.enableReplicatedRequestCompression; + } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/InstanceIdDataCenterInfo.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/InstanceIdDataCenterInfo.java new file mode 100644 index 00000000..b5003e5f --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/InstanceIdDataCenterInfo.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.eureka; + +import com.netflix.appinfo.DataCenterInfo; +import com.netflix.appinfo.UniqueIdentifier; + +/** + * @author Spencer Gibb + */ +public class InstanceIdDataCenterInfo implements DataCenterInfo, + UniqueIdentifier { + + private String instanceId; + + public InstanceIdDataCenterInfo(String instanceId) { + this.instanceId = instanceId; + } + + @Override + public Name getName() { + return Name.MyOwn; + } + + @Override + public String getId() { + return this.instanceId; + } + +} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/InstanceInfoFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/InstanceInfoFactory.java new file mode 100644 index 00000000..6b2c26be --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/InstanceInfoFactory.java @@ -0,0 +1,87 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.eureka; + +import java.util.Map; + +import lombok.extern.apachecommons.CommonsLog; + +import com.netflix.appinfo.EurekaInstanceConfig; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.appinfo.LeaseInfo; + +/** + * See com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider + * @author Spencer Gibb + */ +@CommonsLog +public class InstanceInfoFactory { + + public InstanceInfo create(EurekaInstanceConfig config) { + LeaseInfo.Builder leaseInfoBuilder = LeaseInfo.Builder.newBuilder() + .setRenewalIntervalInSecs(config.getLeaseRenewalIntervalInSeconds()) + .setDurationInSecs(config.getLeaseExpirationDurationInSeconds()); + + // Builder the instance information to be registered with eureka + // server + InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder(); + + builder.setNamespace(config.getNamespace()) + .setAppName(config.getAppname()) + .setAppGroupName(config.getAppGroupName()) + .setDataCenterInfo(config.getDataCenterInfo()) + .setIPAddr(config.getIpAddress()) + .setHostName(config.getHostName(false)) + .setPort(config.getNonSecurePort()) + .enablePort(InstanceInfo.PortType.UNSECURE, + config.isNonSecurePortEnabled()) + .setSecurePort(config.getSecurePort()) + .enablePort(InstanceInfo.PortType.SECURE, config.getSecurePortEnabled()) + .setVIPAddress(config.getVirtualHostName()) + .setSecureVIPAddress(config.getSecureVirtualHostName()) + .setHomePageUrl(config.getHomePageUrlPath(), config.getHomePageUrl()) + .setStatusPageUrl(config.getStatusPageUrlPath(), + config.getStatusPageUrl()) + .setHealthCheckUrls(config.getHealthCheckUrlPath(), + config.getHealthCheckUrl(), config.getSecureHealthCheckUrl()) + .setASGName(config.getASGName()); + + // Start off with the STARTING state to avoid traffic + if (!config.isInstanceEnabledOnit()) { + InstanceInfo.InstanceStatus initialStatus = InstanceInfo.InstanceStatus.STARTING; + log.info("Setting initial instance status as: " + initialStatus); + builder.setStatus(initialStatus); + } + else { + log.info("Setting initial instance status as: " + + InstanceInfo.InstanceStatus.UP + + ". This may be too early for the instance to advertise itself as available. " + + "You would instead want to control this via a healthcheck handler."); + } + + // Add any user-specific metadata information + for (Map.Entry mapEntry : config.getMetadataMap().entrySet()) { + String key = mapEntry.getKey(); + String value = mapEntry.getValue(); + builder.add(key, value); + } + + InstanceInfo instanceInfo = builder.build(); + instanceInfo.setLeaseInfo(leaseInfoBuilder.build()); + return instanceInfo; + } +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfigurationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfigurationTests.java index 5b5f5e02..164b2b1e 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfigurationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfigurationTests.java @@ -16,6 +16,10 @@ package org.springframework.cloud.netflix.config; +import static org.junit.Assert.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; + import javax.annotation.PostConstruct; import org.junit.After; @@ -31,11 +35,7 @@ import org.springframework.core.env.ConfigurableEnvironment; import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.InstanceInfo; -import com.netflix.discovery.DiscoveryClient; -import com.netflix.discovery.DiscoveryManager; - -import static org.junit.Assert.assertEquals; -import static org.mockito.BDDMockito.given; +import com.netflix.discovery.EurekaClient; /** * @author Dave Syer @@ -44,7 +44,7 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests { private AnnotationConfigApplicationContext context; - private DiscoveryClient client = Mockito.mock(DiscoveryClient.class); + private EurekaClient client = Mockito.mock(EurekaClient.class); private InstanceInfo info = InstanceInfo.Builder.newBuilder().setAppName("app") .setHostName("foo").setHomePageUrl("/", null).build(); @@ -68,21 +68,20 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests { 1, this.context .getBeanNamesForType(DiscoveryClientConfigServiceAutoConfiguration.class).length); - Mockito.verify(this.client).getNextServerFromEureka("CONFIGSERVER", false); + Mockito.verify(this.client, times(2)).getNextServerFromEureka("CONFIGSERVER", false); Mockito.verify(this.client).shutdown(); ConfigClientProperties locator = this.context .getBean(ConfigClientProperties.class); assertEquals("http://foo:7001/", locator.getRawUri()); - assertEquals("bar", ApplicationInfoManager.getInstance().getInfo().getMetadata() - .get("foo")); + ApplicationInfoManager infoManager = this.context.getBean(ApplicationInfoManager.class); + assertEquals("bar", infoManager.getInfo().getMetadata().get("foo")); } private void setup(String... env) { AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); EnvironmentTestUtils.addEnvironment(parent, env); - parent.getDefaultListableBeanFactory().registerSingleton("mockDiscoveryClient", + parent.getDefaultListableBeanFactory().registerSingleton("eurekaClient", this.client); - DiscoveryManager.getInstance().setDiscoveryClient(this.client); parent.register(PropertyPlaceholderAutoConfiguration.class, DiscoveryClientConfigServiceBootstrapConfiguration.class, EnvironmentKnobbler.class, ConfigClientProperties.class); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfigurationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfigurationTests.java index a9819837..4581208c 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfigurationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfigurationTests.java @@ -16,6 +16,9 @@ package org.springframework.cloud.netflix.config; +import static org.junit.Assert.assertEquals; +import static org.mockito.BDDMockito.given; + import org.junit.After; import org.junit.Test; import org.mockito.Mockito; @@ -25,11 +28,7 @@ import org.springframework.cloud.config.client.ConfigClientProperties; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.netflix.appinfo.InstanceInfo; -import com.netflix.discovery.DiscoveryClient; -import com.netflix.discovery.DiscoveryManager; - -import static org.junit.Assert.assertEquals; -import static org.mockito.BDDMockito.given; +import com.netflix.discovery.EurekaClient; /** * @author Dave Syer @@ -38,7 +37,7 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests { private AnnotationConfigApplicationContext context; - private DiscoveryClient client = Mockito.mock(DiscoveryClient.class); + private EurekaClient client = Mockito.mock(EurekaClient.class); private InstanceInfo info = InstanceInfo.Builder.newBuilder().setAppName("app") .setHostName("foo").setHomePageUrl("/", null).build(); @@ -54,7 +53,7 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests { public void offByDefault() throws Exception { this.context = new AnnotationConfigApplicationContext( DiscoveryClientConfigServiceBootstrapConfiguration.class); - assertEquals(0, this.context.getBeanNamesForType(DiscoveryClient.class).length); + assertEquals(0, this.context.getBeanNamesForType(EurekaClient.class).length); assertEquals( 0, this.context @@ -104,8 +103,7 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests { this.context = new AnnotationConfigApplicationContext(); EnvironmentTestUtils.addEnvironment(this.context, env); this.context.getDefaultListableBeanFactory().registerSingleton( - "mockDiscoveryClient", this.client); - DiscoveryManager.getInstance().setDiscoveryClient(this.client); + "eurekaClient", this.client); this.context.register(PropertyPlaceholderAutoConfiguration.class, DiscoveryClientConfigServiceBootstrapConfiguration.class, ConfigClientProperties.class); diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaController.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaController.java index 4946a4ed..2d1f5078 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaController.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaController.java @@ -39,7 +39,7 @@ import com.netflix.appinfo.InstanceInfo; import com.netflix.config.ConfigurationManager; import com.netflix.discovery.shared.Application; import com.netflix.discovery.shared.Pair; -import com.netflix.eureka.PeerAwareInstanceRegistry; +import com.netflix.eureka.PeerAwareInstanceRegistryImpl; import com.netflix.eureka.cluster.PeerEurekaNode; import com.netflix.eureka.resources.StatusResource; import com.netflix.eureka.util.StatusInfo; @@ -53,6 +53,11 @@ public class EurekaController { @Value("${eureka.dashboard.path:/}") private String dashboardPath = ""; + private ApplicationInfoManager applicationInfoManager; + + public EurekaController(ApplicationInfoManager applicationInfoManager) { + this.applicationInfoManager = applicationInfoManager; + } @RequestMapping(method = RequestMethod.GET) public String status(HttpServletRequest request, Map model) { @@ -73,7 +78,7 @@ public class EurekaController { @RequestMapping(value = "/lastn", method = RequestMethod.GET) public String lastn(HttpServletRequest request, Map model) { populateBase(request, model); - PeerAwareInstanceRegistry registery = PeerAwareInstanceRegistry.getInstance(); + PeerAwareInstanceRegistryImpl registery = PeerAwareInstanceRegistryImpl.getInstance(); ArrayList> lastNCanceled = new ArrayList<>(); List> list = registery.getLastNCanceledInstances(); for (Pair entry : list) { @@ -114,11 +119,10 @@ public class EurekaController { .getDeploymentEnvironment()); model.put("datacenter", ConfigurationManager.getDeploymentContext() .getDeploymentDatacenter()); - model.put("registry", PeerAwareInstanceRegistry.getInstance()); - model.put("isBelowRenewThresold", PeerAwareInstanceRegistry.getInstance() + model.put("registry", PeerAwareInstanceRegistryImpl.getInstance()); + model.put("isBelowRenewThresold", PeerAwareInstanceRegistryImpl.getInstance() .isBelowRenewThresold() == 1); - DataCenterInfo info = ApplicationInfoManager.getInstance().getInfo() - .getDataCenterInfo(); + DataCenterInfo info = applicationInfoManager.getInfo().getDataCenterInfo(); if (info.getName() == DataCenterInfo.Name.Amazon) { AmazonInfo amazonInfo = (AmazonInfo) info; model.put("amazonInfo", amazonInfo); @@ -131,7 +135,7 @@ public class EurekaController { private void populateNavbar(HttpServletRequest request, Map model) { Map replicas = new LinkedHashMap<>(); - List list = PeerAwareInstanceRegistry.getInstance() + List list = PeerAwareInstanceRegistryImpl.getInstance() .getReplicaNodes(); for (PeerEurekaNode node : list) { try { @@ -147,7 +151,7 @@ public class EurekaController { } private void populateApps(Map model) { - List sortedApplications = PeerAwareInstanceRegistry + List sortedApplications = PeerAwareInstanceRegistryImpl .getInstance().getSortedApplications(); ArrayList> apps = new ArrayList<>(); for (Application app : sortedApplications) { diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java index 26d195aa..e4764442 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java @@ -26,6 +26,7 @@ import javax.servlet.Filter; import javax.ws.rs.Path; import javax.ws.rs.ext.Provider; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -44,6 +45,7 @@ import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.util.ClassUtils; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import com.netflix.appinfo.ApplicationInfoManager; import com.sun.jersey.api.core.DefaultResourceConfig; import com.sun.jersey.spi.container.servlet.ServletContainer; @@ -58,13 +60,17 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter { /** * List of packages containing Jersey resources required by the Eureka server */ - private static String[] EUREKA_PACKAGES = new String[] { "com.netflix.discovery", - "com.netflix.eureka" }; + private static String[] EUREKA_PACKAGES = new String[] { + "com.netflix.discovery", + "com.netflix.eureka"}; + + @Autowired + private ApplicationInfoManager applicationInfoManager; @Bean @ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true) public EurekaController eurekaController() { - return new EurekaController(); + return new EurekaController(applicationInfoManager); } /** diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerInitializerConfiguration.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerInitializerConfiguration.java index f9d332ea..1750d94c 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerInitializerConfiguration.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerInitializerConfiguration.java @@ -33,12 +33,11 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aop.framework.ProxyFactory; 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.context.properties.EnableConfigurationProperties; import org.springframework.boot.logging.LoggingSystem; import org.springframework.boot.logging.log4j.Log4JLoggingSystem; +import org.springframework.cloud.netflix.eureka.DataCenterAwareJacksonCodec; import org.springframework.cloud.netflix.eureka.DataCenterAwareMarshallingStrategy; -import org.springframework.cloud.netflix.eureka.DiscoveryManagerInitializer; import org.springframework.cloud.netflix.eureka.EurekaServerConfigBean; import org.springframework.cloud.netflix.eureka.server.advice.LeaseManagerLite; import org.springframework.cloud.netflix.eureka.server.advice.PiggybackMethodInterceptor; @@ -59,13 +58,13 @@ import org.springframework.web.context.ServletContextAware; import com.netflix.blitz4j.DefaultBlitz4jConfig; import com.netflix.blitz4j.LoggingConfiguration; -import com.netflix.discovery.converters.JsonXStream; import com.netflix.discovery.converters.XmlXStream; +import com.netflix.eureka.AbstractInstanceRegistry; import com.netflix.eureka.EurekaBootStrap; import com.netflix.eureka.EurekaServerConfig; import com.netflix.eureka.EurekaServerConfigurationManager; -import com.netflix.eureka.InstanceRegistry; import com.netflix.eureka.PeerAwareInstanceRegistry; +import com.netflix.eureka.PeerAwareInstanceRegistryImpl; /** * @author Dave Syer @@ -125,15 +124,8 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware } } - @Bean - @ConditionalOnMissingBean(DiscoveryManagerInitializer.class) - public DiscoveryManagerInitializer discoveryManagerIntitializer() { - return new DiscoveryManagerInitializer(); - } - @Override public void start() { - discoveryManagerIntitializer().init(); new Thread(new Runnable() { @Override public void run() { @@ -160,14 +152,8 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware XmlXStream .getInstance() .setMarshallingStrategy( - new DataCenterAwareMarshallingStrategy( - EurekaServerInitializerConfiguration.this.applicationContext)); - JsonXStream - .getInstance() - .setMarshallingStrategy( - new DataCenterAwareMarshallingStrategy( - EurekaServerInitializerConfiguration.this.applicationContext)); - // PeerAwareInstanceRegistry.getInstance(); + new DataCenterAwareMarshallingStrategy()); + DataCenterAwareJacksonCodec.init(); EurekaServerInitializerConfiguration.this.applicationContext .publishEvent(new EurekaRegistryAvailableEvent( EurekaServerInitializerConfiguration.this.eurekaServerConfig)); @@ -226,7 +212,7 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware @Autowired private ApplicationContext applicationContext; - private PeerAwareInstanceRegistry instance; + private PeerAwareInstanceRegistryImpl instance; @Bean public LeaseManagerMessageBroker leaseManagerMessageBroker() { @@ -236,7 +222,7 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware @Override public void onApplicationEvent(EurekaRegistryAvailableEvent event) { if (this.instance == null) { - this.instance = PeerAwareInstanceRegistry.getInstance(); + this.instance = PeerAwareInstanceRegistryImpl.getInstance(); safeInit(); replaceInstance(getProxyForInstance()); expectRegistrations(1); @@ -245,13 +231,13 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware private void safeInit() { Method method = ReflectionUtils - .findMethod(InstanceRegistry.class, "postInit"); + .findMethod(AbstractInstanceRegistry.class, "postInit"); ReflectionUtils.makeAccessible(method); ReflectionUtils.invokeMethod(method, this.instance); } private void replaceInstance(Object proxy) { - Field field = ReflectionUtils.findField(PeerAwareInstanceRegistry.class, + Field field = ReflectionUtils.findField(PeerAwareInstanceRegistryImpl.class, "instance"); try { // Awful ugly hack to work around lack of DI in eureka @@ -285,7 +271,7 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware * registrations (when it's zero, even a successful registration won't reset * the rate threshold in InstanceRegistry.register()). */ - Field field = ReflectionUtils.findField(PeerAwareInstanceRegistry.class, + Field field = ReflectionUtils.findField(AbstractInstanceRegistry.class, "expectedNumberOfRenewsPerMin"); try { // Awful ugly hack to work around lack of DI in eureka @@ -304,7 +290,7 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware /** * Additional aspect for intercepting method invocations on * PeerAwareInstanceRegistry. If - * {@link PeerAwareInstanceRegistry#openForTraffic(int)} is called with a zero + * {@link PeerAwareInstanceRegistryImpl#openForTraffic(int)} is called with a zero * argument, it means that leases are not automatically cancelled if the instance * hasn't sent any renewals recently. This happens for a standalone server. It * seems like a bad default, so we set it to the smallest non-zero value we can, diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/event/LeaseManagerMessageBroker.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/event/LeaseManagerMessageBroker.java index 695a8cce..5d802b07 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/event/LeaseManagerMessageBroker.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/event/LeaseManagerMessageBroker.java @@ -26,7 +26,7 @@ import org.springframework.context.ApplicationContext; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.shared.Application; -import com.netflix.eureka.PeerAwareInstanceRegistry; +import com.netflix.eureka.PeerAwareInstanceRegistryImpl; import com.netflix.eureka.lease.Lease; /** @@ -66,7 +66,7 @@ public class LeaseManagerMessageBroker implements LeaseManagerLite boolean isReplication) { log.debug("renew " + appName + " serverId " + serverId + ", isReplication {}" + isReplication); - List applications = PeerAwareInstanceRegistry.getInstance() + List applications = PeerAwareInstanceRegistryImpl.getInstance() .getSortedApplications(); for (Application input : applications) { if (input.getName().equals(appName)) { diff --git a/spring-cloud-netflix-sidecar/src/test/java/org/springframework/cloud/netflix/sidecar/SidecarClientApplication.java b/spring-cloud-netflix-sidecar/src/test/java/org/springframework/cloud/netflix/sidecar/SidecarClientApplication.java new file mode 100644 index 00000000..63ace623 --- /dev/null +++ b/spring-cloud-netflix-sidecar/src/test/java/org/springframework/cloud/netflix/sidecar/SidecarClientApplication.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.sidecar; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author Spencer Gibb + */ +@EnableAutoConfiguration +@EnableDiscoveryClient +@Configuration +@RestController +public class SidecarClientApplication { + + @Autowired + public LoadBalancerClient lb; + + @RequestMapping("/") + public ServiceInstance home() { + return lb.choose("sidecarTest"); + } + + public static void main(String[] args) { + new SpringApplicationBuilder() + .properties("spring.application.name=sidecarClient") + .sources(SidecarClientApplication.class) + .run(args); + } +} diff --git a/spring-cloud-netflix-turbine/pom.xml b/spring-cloud-netflix-turbine/pom.xml index 3e7cad3f..59fc3714 100644 --- a/spring-cloud-netflix-turbine/pom.xml +++ b/spring-cloud-netflix-turbine/pom.xml @@ -84,5 +84,10 @@ compile true + + org.mockito + mockito-core + test + diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/EurekaInstanceDiscovery.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/EurekaInstanceDiscovery.java index d94b92f1..c854ea33 100644 --- a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/EurekaInstanceDiscovery.java +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/EurekaInstanceDiscovery.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import com.netflix.discovery.EurekaClient; import lombok.extern.apachecommons.CommonsLog; import org.springframework.expression.Expression; @@ -34,8 +35,6 @@ import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo.InstanceStatus; import com.netflix.config.DynamicPropertyFactory; import com.netflix.config.DynamicStringProperty; -import com.netflix.discovery.DiscoveryClient; -import com.netflix.discovery.DiscoveryManager; import com.netflix.discovery.shared.Application; import com.netflix.turbine.discovery.Instance; import com.netflix.turbine.discovery.InstanceDiscovery; @@ -60,13 +59,11 @@ public class EurekaInstanceDiscovery implements InstanceDiscovery { private static final DynamicStringProperty ApplicationList = DynamicPropertyFactory .getInstance().getStringProperty("turbine.appConfig", ""); + private final EurekaClient eurekaClient; private final Expression clusterNameExpression; - public EurekaInstanceDiscovery(TurbineProperties turbineProperties) { - // Eureka client should already be configured by spring-platform-netflix-core - // initialize eureka client. - // DiscoveryManager.getInstance().initComponent(new MyDataCenterInstanceConfig(), - // new DefaultEurekaClientConfig()); + public EurekaInstanceDiscovery(TurbineProperties turbineProperties, EurekaClient eurekaClient) { + this.eurekaClient = eurekaClient; SpelExpressionParser parser = new SpelExpressionParser(); this.clusterNameExpression = parser.parseExpression(turbineProperties .getClusterNameExpression()); @@ -78,7 +75,7 @@ public class EurekaInstanceDiscovery implements InstanceDiscovery { */ @Override public Collection getInstanceList() throws Exception { - List instances = new ArrayList(); + List instances = new ArrayList<>(); List appNames = parseApps(); if (appNames == null || appNames.size() == 0) { log.info("No apps configured, returning an empty instance list"); @@ -111,14 +108,9 @@ public class EurekaInstanceDiscovery implements InstanceDiscovery { * @throws Exception */ private List getInstancesForApp(String appName) throws Exception { - List instances = new ArrayList(); + List instances = new ArrayList<>(); log.info("Fetching instances for app: " + appName); - DiscoveryClient client = DiscoveryManager.getInstance().getDiscoveryClient(); - if (client == null) { - log.info("Discovery client not ready for: " + appName); - return instances; - } - Application app = client.getApplication(appName); + Application app = eurekaClient.getApplication(appName); if (app == null) { log.warn("Eureka returned null for app: " + appName); } diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineConfiguration.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineConfiguration.java index 3ae895f2..352fd9a1 100644 --- a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineConfiguration.java +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.cloud.netflix.turbine; +import com.netflix.discovery.EurekaClient; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @@ -37,6 +39,9 @@ import com.netflix.turbine.streaming.servlet.TurbineStreamServlet; @EnableDiscoveryClient public class TurbineConfiguration implements SmartLifecycle, Ordered { + @Autowired + private EurekaClient eurekaClient; + @Bean public ServletRegistrationBean turbineStreamServlet() { return new ServletRegistrationBean(new TurbineStreamServlet(), "/turbine.stream"); @@ -49,7 +54,7 @@ public class TurbineConfiguration implements SmartLifecycle, Ordered { @Bean public InstanceDiscovery instanceDiscovery() { - return new EurekaInstanceDiscovery(turbineProperties()); + return new EurekaInstanceDiscovery(turbineProperties(), eurekaClient); } private boolean running; @@ -66,9 +71,6 @@ public class TurbineConfiguration implements SmartLifecycle, Ordered { @Override public void start() { - // TODO: figure out ordering, so this is already run by - // EurekaDiscoveryClientConfiguration - // DiscoveryManager.getInstance().initComponent(instanceConfig, clientConfig); PluginsFactory.setClusterMonitorFactory(new SpringAggregatorFactory()); PluginsFactory.setInstanceDiscovery(instanceDiscovery()); TurbineInit.init(); diff --git a/spring-cloud-netflix-turbine/src/test/java/org/springframework/cloud/netflix/turbine/EurekaInstanceDiscoveryTest.java b/spring-cloud-netflix-turbine/src/test/java/org/springframework/cloud/netflix/turbine/EurekaInstanceDiscoveryTest.java index b4b46033..90b26cd5 100644 --- a/spring-cloud-netflix-turbine/src/test/java/org/springframework/cloud/netflix/turbine/EurekaInstanceDiscoveryTest.java +++ b/spring-cloud-netflix-turbine/src/test/java/org/springframework/cloud/netflix/turbine/EurekaInstanceDiscoveryTest.java @@ -16,6 +16,9 @@ package org.springframework.cloud.netflix.turbine; +import static org.mockito.Mockito.*; + +import com.netflix.discovery.EurekaClient; import org.junit.Test; import com.netflix.appinfo.InstanceInfo; @@ -29,9 +32,10 @@ public class EurekaInstanceDiscoveryTest { @Test public void testGetClusterName() { + EurekaClient eurekaClient = mock(EurekaClient.class); String appName = "testAppName"; EurekaInstanceDiscovery discovery = new EurekaInstanceDiscovery( - new TurbineProperties()); + new TurbineProperties(), eurekaClient); InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder().setAppName(appName) .build(); String clusterName = discovery.getClusterName(instanceInfo); @@ -40,9 +44,10 @@ public class EurekaInstanceDiscoveryTest { @Test public void testGetClusterNameCustomExpression() { + EurekaClient eurekaClient = mock(EurekaClient.class); TurbineProperties turbineProperties = new TurbineProperties(); turbineProperties.setClusterNameExpression("aSGName"); - EurekaInstanceDiscovery discovery = new EurekaInstanceDiscovery(turbineProperties); + EurekaInstanceDiscovery discovery = new EurekaInstanceDiscovery(turbineProperties, eurekaClient); String asgName = "myAsgName"; InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder() .setAppName("testApp").setASGName(asgName).build(); @@ -52,9 +57,10 @@ public class EurekaInstanceDiscoveryTest { @Test public void testGetClusterNameInstanceMetadataMapExpression() { + EurekaClient eurekaClient = mock(EurekaClient.class); TurbineProperties turbineProperties = new TurbineProperties(); turbineProperties.setClusterNameExpression("metadata['cluster']"); - EurekaInstanceDiscovery discovery = new EurekaInstanceDiscovery(turbineProperties); + EurekaInstanceDiscovery discovery = new EurekaInstanceDiscovery(turbineProperties, eurekaClient); String metadataProperty = "myCluster"; InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder() .setAppName("testApp").add("cluster", metadataProperty).build();