From 31a3ff61e8297ee5d8b0cb8750cc43a52aaecff3 Mon Sep 17 00:00:00 2001 From: Biju Kunjummen Date: Thu, 1 Jun 2017 12:12:42 -0700 Subject: [PATCH] GH-1916: Spring Boot Auto-configuration based Zuul Server and Proxy (#1951) --- .../cloud/netflix/zuul/EnableZuulProxy.java | 5 +- .../cloud/netflix/zuul/EnableZuulServer.java | 5 +- ...n.java => ZuulProxyAutoConfiguration.java} | 10 ++- .../zuul/ZuulProxyMarkerConfiguration.java | 39 ++++++++++++ ....java => ZuulServerAutoConfiguration.java} | 5 +- .../zuul/ZuulServerMarkerConfiguration.java | 39 ++++++++++++ .../main/resources/META-INF/spring.factories | 4 +- .../zuul/ZuulProxyAutoConfigurationTests.java | 62 +++++++++++++++++++ .../zuul/ZuulProxyConfigurationTests.java | 6 +- .../ZuulServerAutoConfigurationTests.java | 62 +++++++++++++++++++ .../filters/CustomHostRoutingFilterTests.java | 20 +++++- .../ZuulEmptyMetricsApplicationTests.java | 7 ++- 12 files changed, 246 insertions(+), 18 deletions(-) rename spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/{ZuulProxyConfiguration.java => ZuulProxyAutoConfiguration.java} (93%) create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyMarkerConfiguration.java rename spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/{ZuulConfiguration.java => ZuulServerAutoConfiguration.java} (97%) create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulServerMarkerConfiguration.java create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfigurationTests.java create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulServerAutoConfigurationTests.java diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/EnableZuulProxy.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/EnableZuulProxy.java index 73c1c835..f4766d97 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/EnableZuulProxy.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/EnableZuulProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 the original author or authors. + * Copyright 2013-2017 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. @@ -34,11 +34,12 @@ import org.springframework.context.annotation.Import; * * @author Spencer Gibb * @author Dave Syer + * @author Biju Kunjummen */ @EnableCircuitBreaker @EnableDiscoveryClient @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) -@Import(ZuulProxyConfiguration.class) +@Import(ZuulProxyMarkerConfiguration.class) public @interface EnableZuulProxy { } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/EnableZuulServer.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/EnableZuulServer.java index 6dc80970..6491e2bc 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/EnableZuulServer.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/EnableZuulServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 the original author or authors. + * Copyright 2013-2017 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. @@ -33,11 +33,12 @@ import org.springframework.context.annotation.Import; * @see EnableZuulProxy to see how to get reverse proxy out of the box * * @author Spencer Gibb + * @author Biju Kunjummen */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(ZuulConfiguration.class) +@Import(ZuulServerMarkerConfiguration.class) public @interface EnableZuulServer { } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration.java similarity index 93% rename from spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java rename to spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration.java index 3c41eb55..1f11d571 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 the original author or authors. + * Copyright 2013-2017 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. @@ -22,6 +22,7 @@ import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.trace.TraceRepository; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; @@ -53,12 +54,14 @@ import org.springframework.context.annotation.Import; /** * @author Spencer Gibb * @author Dave Syer + * @author Biju Kunjummen */ @Configuration @Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class, RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class, RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class }) -public class ZuulProxyConfiguration extends ZuulConfiguration { +@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class) +public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration { @SuppressWarnings("rawtypes") @Autowired(required = false) @@ -72,7 +75,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @Override public HasFeatures zuulFeature() { - return HasFeatures.namedFeature("Zuul (Discovery)", ZuulProxyConfiguration.class); + return HasFeatures.namedFeature("Zuul (Discovery)", ZuulProxyAutoConfiguration.class); } @Bean @@ -98,6 +101,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { } @Bean + @ConditionalOnMissingBean(SimpleHostRoutingFilter.class) public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties) { return new SimpleHostRoutingFilter(helper, zuulProperties); } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyMarkerConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyMarkerConfiguration.java new file mode 100644 index 00000000..0e88776c --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyMarkerConfiguration.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017 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.zuul; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Responsible for adding in a marker bean to trigger activation of + * {@link ZuulServerAutoConfiguration} + * + * @author Biju Kunjummen + */ + +@Configuration +public class ZuulProxyMarkerConfiguration { + @Bean + public Marker zuulProxyMarkerBean() { + return new Marker(); + } + + class Marker { + } +} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration.java similarity index 97% rename from spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java rename to spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration.java index 06b977da..4de557c3 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration.java @@ -74,9 +74,10 @@ import com.netflix.zuul.monitoring.TracerFactory; @Configuration @EnableConfigurationProperties({ ZuulProperties.class }) @ConditionalOnClass(ZuulServlet.class) +@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class) // Make sure to get the ServerProperties from the same place as a normal web app would @Import(ServerPropertiesAutoConfiguration.class) -public class ZuulConfiguration { +public class ZuulServerAutoConfiguration { @Autowired protected ZuulProperties zuulProperties; @@ -89,7 +90,7 @@ public class ZuulConfiguration { @Bean public HasFeatures zuulFeature() { - return HasFeatures.namedFeature("Zuul (Simple)", ZuulConfiguration.class); + return HasFeatures.namedFeature("Zuul (Simple)", ZuulServerAutoConfiguration.class); } @Bean diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulServerMarkerConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulServerMarkerConfiguration.java new file mode 100644 index 00000000..93947877 --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulServerMarkerConfiguration.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017 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.zuul; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Responsible for adding in a marker bean to trigger activation of + * {@link ZuulServerAutoConfiguration} + * + * @author Biju Kunjummen + */ + +@Configuration +public class ZuulServerMarkerConfiguration { + @Bean + public Marker zuulServerMarkerBean() { + return new Marker(); + } + + class Marker { + } +} diff --git a/spring-cloud-netflix-core/src/main/resources/META-INF/spring.factories b/spring-cloud-netflix-core/src/main/resources/META-INF/spring.factories index 09988567..15f51830 100644 --- a/spring-cloud-netflix-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-netflix-core/src/main/resources/META-INF/spring.factories @@ -8,7 +8,9 @@ org.springframework.cloud.netflix.hystrix.HystrixAutoConfiguration,\ org.springframework.cloud.netflix.hystrix.security.HystrixSecurityAutoConfiguration,\ org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration,\ org.springframework.cloud.netflix.rx.RxJavaAutoConfiguration,\ -org.springframework.cloud.netflix.metrics.servo.ServoMetricsAutoConfiguration +org.springframework.cloud.netflix.metrics.servo.ServoMetricsAutoConfiguration,\ +org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration,\ +org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\ org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfigurationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfigurationTests.java new file mode 100644 index 00000000..5d4d1b7e --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfigurationTests.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 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.zuul; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.zuul.filters.CompositeRouteLocator; +import org.springframework.cloud.netflix.zuul.filters.RouteLocator; +import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * To test the auto-configuration of Zuul Proxy + * + * @author Biju Kunjummen + * + */ + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ZuulProxyAutoConfigurationTests { + + @Autowired + private RouteLocator routeLocator; + + @Autowired(required = false) + private RibbonRoutingFilter ribbonRoutingFilter; + + @Test + public void testAutoConfiguredBeans() { + assertThat(routeLocator).isInstanceOf(CompositeRouteLocator.class); + assertThat(this.ribbonRoutingFilter).isNotNull(); + } + + + @Configuration + @EnableAutoConfiguration + @EnableZuulProxy + static class TestConfig { + } +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfigurationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfigurationTests.java index 3779da11..48ca7300 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfigurationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2016 the original author or authors. + * Copyright 2013-2017 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. @@ -36,6 +36,7 @@ import org.springframework.context.annotation.Bean; /** * @author Spencer Gibb + * @author Biju Kunjummen */ public class ZuulProxyConfigurationTests { @@ -60,7 +61,8 @@ public class ZuulProxyConfigurationTests { void testClient(Class clientType, String property) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(TestConfig.class, ZuulProxyConfiguration.class); + context.register(TestConfig.class, ZuulProxyMarkerConfiguration.class, + ZuulProxyAutoConfiguration.class); if (property != null) { EnvironmentTestUtils.addEnvironment(context, property); } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulServerAutoConfigurationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulServerAutoConfigurationTests.java new file mode 100644 index 00000000..95c8f8c1 --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ZuulServerAutoConfigurationTests.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 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.zuul; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.zuul.filters.CompositeRouteLocator; +import org.springframework.cloud.netflix.zuul.filters.RouteLocator; +import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * To test the auto-configuration of Zuul Proxy + * + * @author Biju Kunjummen + * + */ + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ZuulServerAutoConfigurationTests { + + @Autowired + private RouteLocator routeLocator; + + @Autowired(required = false) + private RibbonRoutingFilter ribbonRoutingFilter; + + @Test + public void testAutoConfiguredBeans() { + assertThat(routeLocator).isInstanceOf(CompositeRouteLocator.class); + assertThat(ribbonRoutingFilter).isNull(); + } + + + @Configuration + @EnableAutoConfiguration + @EnableZuulServer + static class TestConfig { + } +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/CustomHostRoutingFilterTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/CustomHostRoutingFilterTests.java index 66982903..5ede40d0 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/CustomHostRoutingFilterTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/CustomHostRoutingFilterTests.java @@ -1,3 +1,19 @@ +/* + * Copyright 2016-2017 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.zuul.filters; import static junit.framework.TestCase.assertFalse; @@ -24,7 +40,6 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.cloud.netflix.zuul.RoutesMvcEndpoint; -import org.springframework.cloud.netflix.zuul.ZuulProxyConfiguration; import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator; import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter; import org.springframework.context.annotation.Bean; @@ -186,10 +201,9 @@ class SampleCustomZuulProxyApplication { @Configuration @EnableZuulProxy - protected static class CustomZuulProxyConfig extends ZuulProxyConfiguration { + protected static class CustomZuulProxyConfig { @Bean - @Override public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties) { return new CustomHostRoutingFilter(helper, zuulProperties); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/metrics/ZuulEmptyMetricsApplicationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/metrics/ZuulEmptyMetricsApplicationTests.java index e9f30573..e91d6c37 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/metrics/ZuulEmptyMetricsApplicationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/metrics/ZuulEmptyMetricsApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 the original author or authors. + * Copyright 2013-2017 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. @@ -18,7 +18,8 @@ package org.springframework.cloud.netflix.zuul.metrics; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.cloud.ClassPathExclusions; -import org.springframework.cloud.netflix.zuul.ZuulConfiguration; +import org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration; +import org.springframework.cloud.netflix.zuul.ZuulServerMarkerConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -42,7 +43,7 @@ public class ZuulEmptyMetricsApplicationTests { public void setUp() throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(ZuulEmptyMetricsApplicationTestsConfiguration.class, - ZuulConfiguration.class); + ZuulServerMarkerConfiguration.class, ZuulServerAutoConfiguration.class); context.refresh(); this.context = context;