Browse Source

Change /routes endpoint to use EndpointMvcAdapter and AbstractEndpoint (#1802)

Change /routes endpoint to use EndpointMvcAdapter and AbstractEndpoint.  

Fixes #1797
pull/6/head
Ryan Baxter 8 years ago committed by Spencer Gibb
parent
commit
62cb0ae28f
  1. 3
      docs/src/main/asciidoc/spring-cloud-netflix.adoc
  2. 53
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RoutesEndpoint.java
  3. 58
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RoutesMvcEndpoint.java
  4. 5
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java
  5. 2
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ContextPathZuulProxyApplicationTests.java
  6. 85
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/RoutesEndpointIntegrationTests.java
  7. 86
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/RoutesEndpointTests.java
  8. 91
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/RoutesMvcEndpointTests.java
  9. 2
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ServletPathZuulProxyApplicationTests.java
  10. 2
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/SimpleZuulProxyApplicationTests.java
  11. 4
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/CustomHostRoutingFilterTests.java
  12. 4
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/discovery/PatternServiceRouteMapperIntegrationTests.java
  13. 4
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/ZuulProxyTestBase.java

3
docs/src/main/asciidoc/spring-cloud-netflix.adoc

@ -1589,7 +1589,8 @@ If you are using `@EnableZuulProxy` with tha Spring Boot Actuator you @@ -1589,7 +1589,8 @@ If you are using `@EnableZuulProxy` with tha Spring Boot Actuator you
will enable (by default) an additional endpoint, available via HTTP as
`/routes`. A GET to this endpoint will return a list of the mapped
routes. A POST will force a refresh of the existing routes (e.g. in
case there have been changes in the service catalog).
case there have been changes in the service catalog). You can disable
this endpoint by setting `endpoints.routes.enabled` to `false`.
NOTE: the routes should respond automatically to changes in the
service catalog, but the POST to /routes is a way to force the change

53
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RoutesEndpoint.java

@ -20,74 +20,43 @@ import java.util.LinkedHashMap; @@ -20,74 +20,43 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Endpoint to display and reset the zuul proxy routes
* Endpoint to display the zuul proxy routes
*
* @author Spencer Gibb
* @author Dave Syer
* @author Ryan Baxter
*/
@ManagedResource(description = "Can be used to list and reset the reverse proxy routes")
public class RoutesEndpoint implements MvcEndpoint, ApplicationEventPublisherAware {
@ManagedResource(description = "Can be used to list the reverse proxy routes")
@ConfigurationProperties(prefix = "endpoints.routes")
public class RoutesEndpoint extends AbstractEndpoint<Map<String, String>> {
private static final String ID = "routes";
private RouteLocator routes;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Autowired
public RoutesEndpoint(RouteLocator routes) {
super(ID, true);
this.routes = routes;
}
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
@ManagedOperation
public Map<String, String> reset() {
this.publisher.publishEvent(new RoutesRefreshedEvent(this.routes));
return getRoutes();
}
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
@ManagedAttribute
public Map<String, String> getRoutes() {
public Map<String, String> invoke() {
Map<String, String> map = new LinkedHashMap<>();
for (Route route : this.routes.getRoutes()) {
map.put(route.getFullPath(), route.getLocation());
}
return map;
}
@Override
public String getPath() {
return "/routes";
}
@Override
public boolean isSensitive() {
return true;
}
@Override
public Class<? extends Endpoint<?>> getEndpointType() {
return null;
}
}

58
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RoutesMvcEndpoint.java

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
/*
*
* * Copyright 2013-2016 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.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Endpoint used to reset the reverse proxy routes
* @author Ryan Baxter
*/
@ManagedResource(description = "Can be used to reset the reverse proxy routes")
public class RoutesMvcEndpoint extends EndpointMvcAdapter implements ApplicationEventPublisherAware {
private RouteLocator routes;
private ApplicationEventPublisher publisher;
public RoutesMvcEndpoint(RoutesEndpoint endpoint, RouteLocator routes) {
super(endpoint);
this.routes = routes;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
@ManagedOperation
public Object reset() {
this.publisher.publishEvent(new RoutesRefreshedEvent(this.routes));
return super.invoke();
}
}

5
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java

@ -139,6 +139,11 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @@ -139,6 +139,11 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
return new RoutesEndpoint(routeLocator);
}
@Bean
public RoutesMvcEndpoint zuulMvcEndpoint(RouteLocator routeLocator, RoutesEndpoint endpoint) {
return new RoutesMvcEndpoint(endpoint, routeLocator);
}
@Bean
public ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) {
TraceProxyRequestHelper helper = new TraceProxyRequestHelper();

2
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ContextPathZuulProxyApplicationTests.java

@ -61,7 +61,7 @@ public class ContextPathZuulProxyApplicationTests { @@ -61,7 +61,7 @@ public class ContextPathZuulProxyApplicationTests {
private DiscoveryClientRouteLocator routes;
@Autowired
private RoutesEndpoint endpoint;
private RoutesMvcEndpoint endpoint;
@Before
public void setTestRequestContext() {

85
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/RoutesEndpointIntegrationTests.java

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
/*
*
* * Copyright 2013-2016 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 java.util.Map;
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.boot.test.web.client.TestRestTemplate;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RestController;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Ryan Baxter
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
value = {"zuul.routes.sslservice.url=https://localhost:8443", "management.security.enabled=false"})
@DirtiesContext
public class RoutesEndpointIntegrationTests {
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private SimpleZuulProxyApplication.RoutesRefreshListener refreshListener;
@Test
public void getRoutesTest() {
Map<String, String> routes = restTemplate.getForObject("/admin/routes", Map.class);
assertEquals("https://localhost:8443", routes.get("/sslservice/**"));
}
@Test
public void postRoutesTest() {
Map<String, String> routes = restTemplate.postForObject("/admin/routes", null, Map.class);
assertEquals("https://localhost:8443", routes.get("/sslservice/**"));
assertTrue(refreshListener.wasCalled());
}
@Configuration
@EnableAutoConfiguration
@RestController
@EnableZuulProxy
static class SimpleZuulProxyApplication {
@Component
static class RoutesRefreshListener implements ApplicationListener<RoutesRefreshedEvent> {
private boolean called = false;
@Override
public void onApplicationEvent(RoutesRefreshedEvent routesRefreshedEvent) {
called = true;
}
public boolean wasCalled() {
return called;
}
}
}
}

86
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/RoutesEndpointTests.java

@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
/*
*
* * Copyright 2013-2016 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 java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Ryan Baxter
*/
public class RoutesEndpointTests {
private RouteLocator locator;
@Before
public void setUp() {
this.locator = new RouteLocator() {
@Override
public Collection<String> getIgnoredPaths() {
return null;
}
@Override
public List<Route> getRoutes() {
List<Route> routes = new ArrayList<>();
routes.add(new Route("foo", "foopath", "foolocation", null, true, Collections.EMPTY_SET));
routes.add(new Route("bar", "barpath", "barlocation", null, true, Collections.EMPTY_SET));
return routes;
}
@Override
public Route getMatchingRoute(String path) {
return null;
}
};
}
@Test
public void testInvoke() {
RoutesEndpoint endpoint = new RoutesEndpoint(locator);
Map<String, String> result = new HashMap<String, String>();
for(Route r : locator.getRoutes()) {
result.put(r.getFullPath(), r.getLocation());
}
assertEquals(result , endpoint.invoke());
}
@Test
public void testId() {
RoutesEndpoint endpoint = new RoutesEndpoint(locator);
assertEquals("routes", endpoint.getId());
}
@Test
public void testIsSensitive() {
RoutesEndpoint endpoint = new RoutesEndpoint(locator);
assertTrue(endpoint.isSensitive());
}
}

91
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/RoutesMvcEndpointTests.java

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
/*
*
* * Copyright 2013-2016 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 java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.context.ApplicationEventPublisher;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* @author Ryan Baxter
*/
@SpringBootTest
@RunWith(MockitoJUnitRunner.class)
public class RoutesMvcEndpointTests {
private RouteLocator locator;
private RoutesEndpoint endpoint;
@Mock
private ApplicationEventPublisher publisher;
@Before
public void setUp() {
this.locator = new RouteLocator() {
@Override
public Collection<String> getIgnoredPaths() {
return null;
}
@Override
public List<Route> getRoutes() {
List<Route> routes = new ArrayList<>();
routes.add(new Route("foo", "foopath", "foolocation", null, true, Collections.EMPTY_SET));
routes.add(new Route("bar", "barpath", "barlocation", null, true, Collections.EMPTY_SET));
return routes;
}
@Override
public Route getMatchingRoute(String path) {
return null;
}
};
endpoint = spy(new RoutesEndpoint(locator));
}
@Test
public void reset() throws Exception {
RoutesMvcEndpoint mvcEndpoint = new RoutesMvcEndpoint(endpoint, locator);
mvcEndpoint.setApplicationEventPublisher(publisher);
Map<String, String> result = new HashMap<String, String>();
for(Route r : locator.getRoutes()) {
result.put(r.getFullPath(), r.getLocation());
}
assertEquals(result , mvcEndpoint.reset());
verify(endpoint, times(1)).invoke();
verify(publisher, times(1)).publishEvent(isA(RoutesRefreshedEvent.class));
}
}

2
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ServletPathZuulProxyApplicationTests.java

@ -66,7 +66,7 @@ public class ServletPathZuulProxyApplicationTests { @@ -66,7 +66,7 @@ public class ServletPathZuulProxyApplicationTests {
private DiscoveryClientRouteLocator routes;
@Autowired
private RoutesEndpoint endpoint;
private RoutesMvcEndpoint endpoint;
@Before
public void setTestRequestContext() {

2
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/SimpleZuulProxyApplicationTests.java

@ -66,7 +66,7 @@ public class SimpleZuulProxyApplicationTests { @@ -66,7 +66,7 @@ public class SimpleZuulProxyApplicationTests {
private DiscoveryClientRouteLocator routes;
@Autowired
private RoutesEndpoint endpoint;
private RoutesMvcEndpoint endpoint;
@Before
public void setTestRequestContext() {

4
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/CustomHostRoutingFilterTests.java

@ -23,7 +23,7 @@ import org.springframework.boot.test.context.SpringBootTest; @@ -23,7 +23,7 @@ import org.springframework.boot.test.context.SpringBootTest;
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.RoutesEndpoint;
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;
@ -59,7 +59,7 @@ public class CustomHostRoutingFilterTests { @@ -59,7 +59,7 @@ public class CustomHostRoutingFilterTests {
private DiscoveryClientRouteLocator routes;
@Autowired
private RoutesEndpoint endpoint;
private RoutesMvcEndpoint endpoint;
@Before
public void setTestRequestcontext() {

4
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/discovery/PatternServiceRouteMapperIntegrationTests.java

@ -22,7 +22,7 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; @@ -22,7 +22,7 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.RoutesEndpoint;
import org.springframework.cloud.netflix.zuul.RoutesMvcEndpoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
@ -59,7 +59,7 @@ public class PatternServiceRouteMapperIntegrationTests { @@ -59,7 +59,7 @@ public class PatternServiceRouteMapperIntegrationTests {
private DiscoveryClientRouteLocator routes;
@Autowired
private RoutesEndpoint endpoint;
private RoutesMvcEndpoint endpoint;
@Before
public void setTestRequestcontext() {

4
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/ZuulProxyTestBase.java

@ -37,7 +37,7 @@ import org.springframework.boot.autoconfigure.web.ErrorAttributes; @@ -37,7 +37,7 @@ import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.netflix.zuul.RoutesEndpoint;
import org.springframework.cloud.netflix.zuul.RoutesMvcEndpoint;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator;
@ -88,7 +88,7 @@ public abstract class ZuulProxyTestBase { @@ -88,7 +88,7 @@ public abstract class ZuulProxyTestBase {
protected DiscoveryClientRouteLocator routes;
@Autowired
protected RoutesEndpoint endpoint;
protected RoutesMvcEndpoint endpoint;
@Autowired
protected RibbonCommandFactory<?> ribbonCommandFactory;

Loading…
Cancel
Save