From 9877e90f9d7e3a450d0efeb66475e27c6da75e3c Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 23 Apr 2018 22:56:54 -0400 Subject: [PATCH] Adds test to verify route is added when HeartbeatEvent signals new route. --- .../gateway/route/RouteRefreshListener.java | 6 +- ...outeDefinitionLocatorIntegrationTests.java | 111 ++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocatorIntegrationTests.java diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteRefreshListener.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteRefreshListener.java index ea331db3..5877992d 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteRefreshListener.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteRefreshListener.java @@ -21,10 +21,12 @@ import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent; +import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.util.Assert; // see ZuulDiscoveryRefreshListener @@ -42,7 +44,9 @@ public class RouteRefreshListener @Override public void onApplicationEvent(ApplicationEvent event) { - if (event instanceof InstanceRegisteredEvent) { + if (event instanceof ContextRefreshedEvent + || event instanceof RefreshScopeRefreshedEvent + || event instanceof InstanceRegisteredEvent) { reset(); } else if (event instanceof ParentHeartbeatEvent) { diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocatorIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocatorIntegrationTests.java new file mode 100644 index 00000000..8ba0ba4c --- /dev/null +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocatorIntegrationTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2013-2018 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.gateway.discovery; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.event.HeartbeatEvent; +import org.springframework.cloud.gateway.route.Route; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = DiscoveryClientRouteDefinitionLocatorIntegrationTests.Config.class, + properties = {"spring.cloud.gateway.discovery.locator.enabled=true", + "spring.cloud.gateway.discovery.locator.route-id-prefix=test__", }) +public class DiscoveryClientRouteDefinitionLocatorIntegrationTests { + + @Autowired + private RouteLocator routeLocator; + + @Autowired + private ApplicationEventPublisher publisher; + + @Test + public void newServiceAddsRoute() { + List routes = routeLocator.getRoutes() + .filter(route -> route.getId().startsWith("test__")) + .collectList().block(); + assertThat(routes).hasSize(1); + + publisher.publishEvent(new HeartbeatEvent(this, 1L)); + + routes = routeLocator.getRoutes() + .filter(route -> route.getId().startsWith("test__")) + .collectList().block(); + assertThat(routes).hasSize(2); + } + + @SpringBootConfiguration + @EnableAutoConfiguration + protected static class Config { + + @Bean + DiscoveryClient discoveryClient() { + DefaultServiceInstance instance1 = new DefaultServiceInstance("service1", "localhost", 8001, + false); + DefaultServiceInstance instance2 = new DefaultServiceInstance("service2", "localhost", 8001, + false); + return new DiscoveryClient() { + + AtomicInteger calls = new AtomicInteger(0); + + @Override + public String description() { + return null; + } + + @Override + public List getInstances(String serviceId) { + if (serviceId.equals("service1")) { + return Collections.singletonList(instance1); + } + if (serviceId.equals("service2")) { + return Collections.singletonList(instance2); + } + return Collections.emptyList(); + } + + @Override + public List getServices() { + if (calls.compareAndSet(0, 1)) { + return Collections.singletonList("service1"); + } + return Arrays.asList("service1", "service2"); + } + }; + } + } +}