diff --git a/spring-cloud-netflix-turbine/pom.xml b/spring-cloud-netflix-turbine/pom.xml index 3d3b84ba..4fa0583b 100644 --- a/spring-cloud-netflix-turbine/pom.xml +++ b/spring-cloud-netflix-turbine/pom.xml @@ -64,10 +64,12 @@ org.springframework.cloud spring-cloud-netflix-core + true com.netflix.eureka eureka-client + true org.apache.httpcomponents @@ -85,8 +87,8 @@ true - org.mockito - mockito-core + org.springframework.boot + spring-boot-starter-test test diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/CommonsInstanceDiscovery.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/CommonsInstanceDiscovery.java new file mode 100644 index 00000000..223f167b --- /dev/null +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/CommonsInstanceDiscovery.java @@ -0,0 +1,190 @@ +/* + * 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.turbine; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.expression.Expression; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import com.netflix.turbine.discovery.Instance; +import com.netflix.turbine.discovery.InstanceDiscovery; + +import lombok.extern.apachecommons.CommonsLog; + +/** + * Class that encapsulates an {@link InstanceDiscovery} + * implementation that uses Eureka (see https://github.com/Netflix/eureka) The plugin + * requires a list of applications configured. It then queries the set of instances for + * each application. Instance information retrieved from Eureka must be translated to + * something that Turbine can understand i.e the + * {@link Instance} class. + *

+ * All the logic to perform this translation can be overriden here, so that you can + * provide your own implementation if needed. + * + * @author Spencer Gibb + */ +@CommonsLog +public class CommonsInstanceDiscovery implements InstanceDiscovery { + + private static final String DEFAULT_CLUSTER_NAME_EXPRESSION = "serviceId"; + + private final Expression clusterNameExpression; + private DiscoveryClient discoveryClient; + private TurbineProperties turbineProperties; + + public CommonsInstanceDiscovery(TurbineProperties turbineProperties, DiscoveryClient discoveryClient) { + this(turbineProperties, DEFAULT_CLUSTER_NAME_EXPRESSION); + this.discoveryClient = discoveryClient; + } + + protected CommonsInstanceDiscovery(TurbineProperties turbineProperties, String defaultExpression) { + this.turbineProperties = turbineProperties; + SpelExpressionParser parser = new SpelExpressionParser(); + String clusterNameExpression = turbineProperties + .getClusterNameExpression(); + if (clusterNameExpression == null) { + clusterNameExpression = defaultExpression; + } + this.clusterNameExpression = parser.parseExpression(clusterNameExpression); + } + + protected Expression getClusterNameExpression() { + return clusterNameExpression; + } + + public TurbineProperties getTurbineProperties() { + return turbineProperties; + } + + /** + * Method that queries Eureka service for a list of configured application names + * @return Collection + */ + @Override + public Collection getInstanceList() throws Exception { + List instances = new ArrayList<>(); + List appNames = getTurbineProperties().getAppConfigList(); + if (appNames == null || appNames.size() == 0) { + log.info("No apps configured, returning an empty instance list"); + return instances; + } + log.info("Fetching instance list for apps: " + appNames); + for (String appName : appNames) { + try { + instances.addAll(getInstancesForApp(appName)); + } + catch (Exception ex) { + log.error("Failed to fetch instances for app: " + appName + + ", retrying once more", ex); + try { + instances.addAll(getInstancesForApp(appName)); + } + catch (Exception retryException) { + log.error("Failed again to fetch instances for app: " + appName + + ", giving up", ex); + } + } + } + return instances; + } + + /** + * helper that fetches the Instances for each application from DiscoveryClient. + * @param serviceId + * @return List + * @throws Exception + */ + protected List getInstancesForApp(String serviceId) throws Exception { + List instances = new ArrayList<>(); + log.info("Fetching instances for app: " + serviceId); + List serviceInstances = discoveryClient.getInstances(serviceId); + if (serviceInstances == null || serviceInstances.isEmpty()) { + log.warn("DiscoveryClient returned null or empty for service: " + serviceId); + return instances; + } + try { + log.info("Received instance list for service: " + serviceId + ", size=" + + serviceInstances.size()); + for (ServiceInstance serviceInstance : serviceInstances) { + Instance instance = marshall(serviceInstance); + if (instance != null) { + instances.add(instance); + } + } + } + catch (Exception e) { + log.warn("Failed to retrieve instances from DiscoveryClient", e); + } + return instances; + } + + /** + * Private helper that marshals the information from each instance into something that + * Turbine can understand. Override this method for your own implementation for + * parsing Eureka info. + * @param serviceInstance + * @return Instance + */ + private Instance marshall(ServiceInstance serviceInstance) { + String hostname = serviceInstance.getHost(); + String cluster = getClusterName(serviceInstance); + Boolean status = Boolean.TRUE; //TODO: where to get? + if (hostname != null && cluster != null && status != null) { + Instance instance = new Instance(hostname, cluster, status); + + // TODO: reimplement when metadata is in commons + // add metadata + /*Map metadata = instanceInfo.getMetadata(); + if (metadata != null) { + instance.getAttributes().putAll(metadata); + }*/ + + // add ports + instance.getAttributes().put("port", String.valueOf(serviceInstance.getPort())); + boolean securePortEnabled = serviceInstance.isSecure(); + if (securePortEnabled) { + instance.getAttributes().put("securePort", String.valueOf(serviceInstance.getPort())); + } + return instance; + } + else { + return null; + } + } + + /** + * Helper that fetches the cluster name. Cluster is a Turbine concept and not a Eureka + * concept. By default we choose the amazon asg name as the cluster. A custom + * implementation can be plugged in by overriding this method. + */ + protected String getClusterName(Object object) { + StandardEvaluationContext context = new StandardEvaluationContext(object); + Object value = this.clusterNameExpression.getValue(context); + if (value != null) { + return value.toString(); + } + return null; + } + +} diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/EnableTurbine.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/EnableTurbine.java index 23bd0fea..9dab18ed 100644 --- a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/EnableTurbine.java +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/EnableTurbine.java @@ -30,7 +30,7 @@ import org.springframework.context.annotation.Import; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(TurbineConfiguration.class) +@Import(TurbineHttpConfiguration.class) public @interface EnableTurbine { } 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 0955f255..f388ef83 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 @@ -17,27 +17,18 @@ package org.springframework.cloud.netflix.turbine; import java.util.ArrayList; -import java.util.Arrays; -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; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; - import com.netflix.appinfo.AmazonInfo; import com.netflix.appinfo.DataCenterInfo; 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.EurekaClient; import com.netflix.discovery.shared.Application; import com.netflix.turbine.discovery.Instance; -import com.netflix.turbine.discovery.InstanceDiscovery; + +import lombok.extern.apachecommons.CommonsLog; /** * Class that encapsulates an {@link com.netflix.turbine.discovery.InstanceDiscovery} @@ -53,74 +44,39 @@ import com.netflix.turbine.discovery.InstanceDiscovery; * @author Spencer Gibb */ @CommonsLog -public class EurekaInstanceDiscovery implements InstanceDiscovery { +public class EurekaInstanceDiscovery extends CommonsInstanceDiscovery { - // Property the controls the list of applications that are enabled in Eureka - private static final DynamicStringProperty ApplicationList = DynamicPropertyFactory - .getInstance().getStringProperty("turbine.appConfig", ""); + private static final String EUREKA_DEFAULT_CLUSTER_NAME_EXPRESSION = "appName"; private final EurekaClient eurekaClient; - private final Expression clusterNameExpression; public EurekaInstanceDiscovery(TurbineProperties turbineProperties, EurekaClient eurekaClient) { + super(turbineProperties, EUREKA_DEFAULT_CLUSTER_NAME_EXPRESSION); this.eurekaClient = eurekaClient; - SpelExpressionParser parser = new SpelExpressionParser(); - this.clusterNameExpression = parser.parseExpression(turbineProperties - .getClusterNameExpression()); - } - - /** - * Method that queries Eureka service for a list of configured application names - * @return Collection - */ - @Override - public Collection getInstanceList() throws Exception { - List instances = new ArrayList<>(); - List appNames = parseApps(); - if (appNames == null || appNames.size() == 0) { - log.info("No apps configured, returning an empty instance list"); - return instances; - } - log.info("Fetching instance list for apps: " + appNames); - for (String appName : appNames) { - try { - instances.addAll(getInstancesForApp(appName)); - } - catch (Exception ex) { - log.error("Failed to fetch instances for app: " + appName - + ", retrying once more", ex); - try { - instances.addAll(getInstancesForApp(appName)); - } - catch (Exception retryException) { - log.error("Failed again to fetch instances for app: " + appName - + ", giving up", ex); - } - } - } - return instances; } /** * Private helper that fetches the Instances for each application. - * @param appName + * @param serviceId * @return List * @throws Exception */ - private List getInstancesForApp(String appName) throws Exception { + @Override + protected List getInstancesForApp(String serviceId) throws Exception { List instances = new ArrayList<>(); - log.info("Fetching instances for app: " + appName); - Application app = eurekaClient.getApplication(appName); + log.info("Fetching instances for app: " + serviceId); + Application app = eurekaClient.getApplication(serviceId); if (app == null) { - log.warn("Eureka returned null for app: " + appName); + log.warn("Eureka returned null for app: " + serviceId); + return instances; } try { List instancesForApp = app.getInstances(); if (instancesForApp != null) { - log.info("Received instance list for app: " + appName + ", size=" + log.info("Received instance list for app: " + serviceId + ", size=" + instancesForApp.size()); for (InstanceInfo iInfo : instancesForApp) { - Instance instance = marshallInstanceInfo(iInfo); + Instance instance = marshall(iInfo); if (instance != null) { instances.add(instance); } @@ -140,7 +96,7 @@ public class EurekaInstanceDiscovery implements InstanceDiscovery { * @param instanceInfo * @return Instance */ - protected Instance marshallInstanceInfo(InstanceInfo instanceInfo) { + Instance marshall(InstanceInfo instanceInfo) { String hostname = instanceInfo.getHostName(); String cluster = getClusterName(instanceInfo); Boolean status = parseInstanceStatus(instanceInfo.getStatus()); @@ -187,36 +143,5 @@ public class EurekaInstanceDiscovery implements InstanceDiscovery { return status == InstanceStatus.UP; } - /** - * Helper that fetches the cluster name. Cluster is a Turbine concept and not a Eureka - * concept. By default we choose the amazon asg name as the cluster. A custom - * implementation can be plugged in by overriding this method. - */ - protected String getClusterName(InstanceInfo iInfo) { - StandardEvaluationContext context = new StandardEvaluationContext(iInfo); - Object value = this.clusterNameExpression.getValue(context); - if (value != null) { - return value.toString(); - } - return null; - } - - private List parseApps() { - // TODO: move to ConfigurationProperties Private helper that parses the list of - // application names. - String appList = ApplicationList.get(); - if (appList == null) { - return null; - } - appList = appList.trim(); - if (appList.length() == 0) { - return null; - } - String[] parts = appList.split(","); - if (parts != null && parts.length > 0) { - return Arrays.asList(parts); - } - return null; - } } diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/SpringAggregatorFactory.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/SpringAggregatorFactory.java index a03f14c8..548e14ed 100644 --- a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/SpringAggregatorFactory.java +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/SpringAggregatorFactory.java @@ -20,8 +20,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import lombok.extern.apachecommons.CommonsLog; - import com.netflix.config.DynamicPropertyFactory; import com.netflix.config.DynamicStringProperty; import com.netflix.turbine.data.AggDataFromCluster; @@ -33,6 +31,8 @@ import com.netflix.turbine.monitor.cluster.AggregateClusterMonitor; import com.netflix.turbine.monitor.cluster.ClusterMonitor; import com.netflix.turbine.monitor.cluster.ClusterMonitorFactory; +import lombok.extern.apachecommons.CommonsLog; + import static com.netflix.turbine.monitor.cluster.AggregateClusterMonitor.AggregatorClusterMonitorConsole; /** 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/TurbineHttpConfiguration.java similarity index 56% rename from spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineConfiguration.java rename to spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java index b5d08ecf..0c58625c 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/TurbineHttpConfiguration.java @@ -16,20 +16,19 @@ package org.springframework.cloud.netflix.turbine; -import com.netflix.discovery.EurekaClient; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.actuator.HasFeatures; +import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.context.SmartLifecycle; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.Ordered; +import com.netflix.discovery.EurekaClient; import com.netflix.turbine.discovery.InstanceDiscovery; -import com.netflix.turbine.init.TurbineInit; -import com.netflix.turbine.plugins.PluginsFactory; import com.netflix.turbine.streaming.servlet.TurbineStreamServlet; /** @@ -38,14 +37,11 @@ import com.netflix.turbine.streaming.servlet.TurbineStreamServlet; @Configuration @EnableConfigurationProperties @EnableDiscoveryClient -public class TurbineConfiguration implements SmartLifecycle, Ordered { - - @Autowired - private EurekaClient eurekaClient; +public class TurbineHttpConfiguration { @Bean public HasFeatures Feature() { - return HasFeatures.namedFeature("Turbine (HTTP)", TurbineConfiguration.class); + return HasFeatures.namedFeature("Turbine (HTTP)", TurbineHttpConfiguration.class); } @Bean @@ -59,47 +55,30 @@ public class TurbineConfiguration implements SmartLifecycle, Ordered { } @Bean - public InstanceDiscovery instanceDiscovery() { - return new EurekaInstanceDiscovery(turbineProperties(), eurekaClient); + public TurbineLifecycle turbineLifecycle(InstanceDiscovery instanceDiscovery) { + return new TurbineLifecycle(instanceDiscovery); } - private boolean running; + @Configuration + @ConditionalOnClass(EurekaClient.class) + protected static class EurekaTurbineConfiguration { + + @Bean + @ConditionalOnMissingBean + public InstanceDiscovery instanceDiscovery(TurbineProperties turbineProperties, EurekaClient eurekaClient) { + return new EurekaInstanceDiscovery(turbineProperties, eurekaClient); + } - @Override - public boolean isAutoStartup() { - return true; } - @Override - public void stop(Runnable callback) { - callback.run(); - } + @Configuration + @ConditionalOnMissingClass("com.netflix.discovery.EurekaClient") + protected static class DiscoveryClientTurbineConfiguration { - @Override - public void start() { - PluginsFactory.setClusterMonitorFactory(new SpringAggregatorFactory()); - PluginsFactory.setInstanceDiscovery(instanceDiscovery()); - TurbineInit.init(); + @Bean + @ConditionalOnMissingBean + public InstanceDiscovery instanceDiscovery(TurbineProperties turbineProperties, DiscoveryClient discoveryClient) { + return new CommonsInstanceDiscovery(turbineProperties, discoveryClient); + } } - - @Override - public void stop() { - this.running = false; - } - - @Override - public boolean isRunning() { - return this.running; - } - - @Override - public int getPhase() { - return 0; - } - - @Override - public int getOrder() { - return -1; - } - } diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineLifecycle.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineLifecycle.java new file mode 100644 index 00000000..1651ef6f --- /dev/null +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineLifecycle.java @@ -0,0 +1,76 @@ +/* + * 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.turbine; + +import org.springframework.context.SmartLifecycle; +import org.springframework.core.Ordered; + +import com.netflix.turbine.discovery.InstanceDiscovery; +import com.netflix.turbine.init.TurbineInit; +import com.netflix.turbine.plugins.PluginsFactory; + +/** + * @author Spencer Gibb + */ +public class TurbineLifecycle implements SmartLifecycle, Ordered { + + private final InstanceDiscovery instanceDiscovery; + + private boolean running; + + public TurbineLifecycle(InstanceDiscovery instanceDiscovery) { + this.instanceDiscovery = instanceDiscovery; + } + + @Override + public boolean isAutoStartup() { + return true; + } + + @Override + public void stop(Runnable callback) { + callback.run(); + } + + @Override + public void start() { + PluginsFactory.setClusterMonitorFactory(new SpringAggregatorFactory()); + PluginsFactory.setInstanceDiscovery(instanceDiscovery); + TurbineInit.init(); + } + + @Override + public void stop() { + this.running = false; + } + + @Override + public boolean isRunning() { + return this.running; + } + + @Override + public int getPhase() { + return 0; + } + + @Override + public int getOrder() { + return -1; + } + +} diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineProperties.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineProperties.java index c53eac18..d830145c 100644 --- a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineProperties.java +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineProperties.java @@ -16,9 +16,13 @@ package org.springframework.cloud.netflix.turbine; +import java.util.Arrays; +import java.util.List; + import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.StringUtils; /** * @author Spencer Gibb @@ -27,6 +31,18 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties("turbine") public class TurbineProperties { - private String clusterNameExpression = "appName"; + private String clusterNameExpression; + private String appConfig; + + public List getAppConfigList() { + if (!StringUtils.hasText(appConfig)) { + return null; + } + String[] parts = appConfig.trim().split(","); + if (parts != null && parts.length > 0) { + return Arrays.asList(parts); + } + return null; + } } 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 253f111d..bf95eb4b 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,16 +16,15 @@ package org.springframework.cloud.netflix.turbine; -import static org.mockito.Mockito.*; - -import com.netflix.discovery.EurekaClient; -import com.netflix.turbine.discovery.Instance; import org.junit.Before; import org.junit.Test; import com.netflix.appinfo.InstanceInfo; +import com.netflix.discovery.EurekaClient; +import com.netflix.turbine.discovery.Instance; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; /** * @author Spencer Gibb @@ -65,7 +64,7 @@ public class EurekaInstanceDiscoveryTest { .setHostName(hostName) .setPort(port) .build(); - Instance instance = discovery.marshallInstanceInfo(instanceInfo); + Instance instance = discovery.marshall(instanceInfo); assertEquals("port is wrong", String.valueOf(port), instance.getAttributes().get("port")); String urlPath = SpringClusterMonitor.ClusterConfigBasedUrlClosure.getUrlPath(instance); @@ -86,7 +85,7 @@ public class EurekaInstanceDiscoveryTest { .setSecurePort(securePort) .enablePort(InstanceInfo.PortType.SECURE, true) .build(); - Instance instance = discovery.marshallInstanceInfo(instanceInfo); + Instance instance = discovery.marshall(instanceInfo); assertEquals("port is wrong", String.valueOf(port), instance.getAttributes().get("port")); assertEquals("securePort is wrong", String.valueOf(securePort), instance.getAttributes().get("securePort")); diff --git a/spring-cloud-netflix-turbine/src/test/java/org/springframework/cloud/netflix/turbine/TurbineHttpTests.java b/spring-cloud-netflix-turbine/src/test/java/org/springframework/cloud/netflix/turbine/TurbineHttpTests.java new file mode 100644 index 00000000..36d8c450 --- /dev/null +++ b/spring-cloud-netflix-turbine/src/test/java/org/springframework/cloud/netflix/turbine/TurbineHttpTests.java @@ -0,0 +1,46 @@ +/* + * 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.turbine; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.WebIntegrationTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Spencer Gibb + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = TurbineHttpTests.TurbineHttpSampleApplication.class) +@WebIntegrationTest(randomPort = true) +public class TurbineHttpTests { + + @EnableAutoConfiguration + @EnableTurbine + public static class TurbineHttpSampleApplication { + public static void main(String[] args) { + new SpringApplicationBuilder().sources(TurbineHttpSampleApplication.class).run(args); + } + } + + @Test + public void contextLoads() { + } +} diff --git a/spring-cloud-starter-turbine/pom.xml b/spring-cloud-starter-turbine/pom.xml index fa17b95f..9ba20758 100644 --- a/spring-cloud-starter-turbine/pom.xml +++ b/spring-cloud-starter-turbine/pom.xml @@ -25,6 +25,10 @@ org.springframework.cloud spring-cloud-starter + + org.springframework.cloud + spring-cloud-starter-eureka + org.springframework.cloud spring-cloud-netflix-turbine