From 220cab870b9c1d9880a87b5e2b29b4e8b4138658 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 15 Dec 2015 14:13:16 +0100 Subject: [PATCH] [#54] Created the list of statuses for nested dependencies. Fixes #54 --- .../cloud/zookeeper/ZookeeperProperties.java | 2 +- ...ZookeeperDiscoveryClientConfiguration.java | 4 +- .../ZookeeperDiscoveryHealthIndicator.java | 31 ++--- .../ZookeeperRibbonClientConfiguration.java | 10 +- .../discovery/ZookeeperServiceInstances.java | 118 ++++++++++++++++++ .../ConditionalOnDependenciesNotPassed.java | 35 ++++++ .../DependenciesBasedLoadBalancer.java | 1 + .../DependenciesNotPassedCondition.java | 44 +++++++ .../CustomZookeeperServiceDiscovery.groovy | 10 +- ...thIndicatorWithNestedStructureISpec.groovy | 79 ++++++++++++ .../resources/application-nestedstructure.yml | 1 + 11 files changed, 308 insertions(+), 27 deletions(-) create mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstances.java create mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ConditionalOnDependenciesNotPassed.java create mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesNotPassedCondition.java create mode 100644 spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicatorWithNestedStructureISpec.groovy create mode 100644 spring-cloud-zookeeper-discovery/src/test/resources/application-nestedstructure.yml diff --git a/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperProperties.java b/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperProperties.java index 3891b44e..e2777213 100644 --- a/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperProperties.java +++ b/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperProperties.java @@ -41,7 +41,7 @@ public class ZookeeperProperties { /** * @param maxRetries max number of times to retry */ - private Integer maxRetries = 50; + private Integer maxRetries = 10; /** * @param maxSleepMs max time in ms to sleep on each retry diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClientConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClientConfiguration.java index 2cd91cf3..2ce9934c 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClientConfiguration.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClientConfiguration.java @@ -75,13 +75,15 @@ public class ZookeeperDiscoveryClientConfiguration { protected static class ZookeeperDiscoveryHealthConfig { @Autowired private ZookeeperServiceDiscovery serviceDiscovery; + @Autowired + private ZookeeperDiscoveryProperties zookeeperDiscoveryProperties; @Autowired(required = false) private ZookeeperDependencies zookeeperDependencies; @Bean @ConditionalOnMissingBean public ZookeeperDiscoveryHealthIndicator zookeeperDiscoveryHealthIndicator() { - return new ZookeeperDiscoveryHealthIndicator(serviceDiscovery, zookeeperDependencies); + return new ZookeeperDiscoveryHealthIndicator(serviceDiscovery, zookeeperDependencies, zookeeperDiscoveryProperties); } } diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicator.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicator.java index a47e2ff6..fcac244f 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicator.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicator.java @@ -16,15 +16,15 @@ package org.springframework.cloud.zookeeper.discovery; -import java.util.ArrayList; -import java.util.Collection; - +import lombok.extern.slf4j.Slf4j; import org.apache.curator.x.discovery.ServiceInstance; import org.springframework.boot.actuate.health.AbstractHealthIndicator; import org.springframework.boot.actuate.health.Health; import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies; -import lombok.extern.slf4j.Slf4j; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** * @author Spencer Gibb @@ -34,24 +34,20 @@ public class ZookeeperDiscoveryHealthIndicator extends AbstractHealthIndicator { private ZookeeperServiceDiscovery serviceDiscovery; private ZookeeperDependencies zookeeperDependencies; + private ZookeeperDiscoveryProperties zookeeperDiscoveryProperties; - public ZookeeperDiscoveryHealthIndicator(ZookeeperServiceDiscovery serviceDiscovery, ZookeeperDependencies zookeeperDependencies) { + public ZookeeperDiscoveryHealthIndicator(ZookeeperServiceDiscovery serviceDiscovery, ZookeeperDependencies zookeeperDependencies, + ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) { this.serviceDiscovery = serviceDiscovery; this.zookeeperDependencies = zookeeperDependencies; + this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties; } @Override protected void doHealthCheck(Health.Builder builder) throws Exception { try { - Collection names = getNamesToQuery(); - ArrayList> allInstances = new ArrayList<>(); - for (String name : names) { - Collection> instances = this.serviceDiscovery - .getServiceDiscovery().queryForInstances(name); - for (ServiceInstance instance : instances) { - allInstances.add(instance); - } - } + Iterable> allInstances = new ZookeeperServiceInstances(serviceDiscovery, + zookeeperDependencies, zookeeperDiscoveryProperties); builder.up().withDetail("services", allInstances); } catch (Exception e) { @@ -59,11 +55,4 @@ public class ZookeeperDiscoveryHealthIndicator extends AbstractHealthIndicator { builder.down(e); } } - - private Collection getNamesToQuery() throws Exception { - if (this.zookeeperDependencies == null) { - return this.serviceDiscovery.getServiceDiscovery().queryForNames(); - } - return this.zookeeperDependencies.getDependencyNames(); - } } diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperRibbonClientConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperRibbonClientConfiguration.java index 6f3dc681..819d92f1 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperRibbonClientConfiguration.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperRibbonClientConfiguration.java @@ -16,8 +16,6 @@ package org.springframework.cloud.zookeeper.discovery; -import javax.annotation.PostConstruct; - import com.netflix.client.config.IClientConfig; import com.netflix.config.ConfigurationManager; import com.netflix.config.DynamicPropertyFactory; @@ -26,16 +24,20 @@ import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.IPing; import com.netflix.loadbalancer.PingUrl; import com.netflix.loadbalancer.ServerList; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.zookeeper.discovery.dependency.ConditionalOnDependenciesNotPassed; import org.springframework.cloud.zookeeper.discovery.dependency.ConditionalOnDependenciesPassed; import org.springframework.cloud.zookeeper.discovery.dependency.DependenciesBasedLoadBalancer; import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import javax.annotation.PostConstruct; + import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses; import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity; @@ -49,6 +51,7 @@ import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity * @author Marcin Grzejszczak, 4financeIT */ @Configuration +@Slf4j public class ZookeeperRibbonClientConfiguration { protected static final String VALUE_NOT_SET = "__not__set__"; protected static final String DEFAULT_NAMESPACE = "ribbon"; @@ -68,6 +71,7 @@ public class ZookeeperRibbonClientConfiguration { public ServerList ribbonServerListFromDependencies(IClientConfig config, ZookeeperDependencies zookeeperDependencies) { ZookeeperServerList serverList = new ZookeeperServerList(this.serviceDiscovery.getServiceDiscovery()); serverList.initFromDependencies(config, zookeeperDependencies); + log.debug("Server list for Ribbon's dependencies based load balancing is [{}]", serverList); return serverList; } @@ -89,9 +93,11 @@ public class ZookeeperRibbonClientConfiguration { @Bean @ConditionalOnMissingBean + @ConditionalOnDependenciesNotPassed public ServerList ribbonServerList(IClientConfig config) { ZookeeperServerList serverList = new ZookeeperServerList(this.serviceDiscovery.getServiceDiscovery()); serverList.initWithNiwsConfig(config); + log.debug("Server list for Ribbon's non-dependency based load balancing is [{}]", serverList); return serverList; } diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstances.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstances.java new file mode 100644 index 00000000..7807d9e1 --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstances.java @@ -0,0 +1,118 @@ +package org.springframework.cloud.zookeeper.discovery; + +import lombok.extern.slf4j.Slf4j; +import org.apache.curator.x.discovery.ServiceInstance; +import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +@Slf4j +public class ZookeeperServiceInstances implements Iterable> { + + private final ZookeeperServiceDiscovery serviceDiscovery; + private final ZookeeperDependencies zookeeperDependencies; + private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties; + private final List> allInstances; + + public ZookeeperServiceInstances(ZookeeperServiceDiscovery serviceDiscovery, ZookeeperDependencies zookeeperDependencies, + ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) { + this.serviceDiscovery = serviceDiscovery; + this.zookeeperDependencies = zookeeperDependencies; + this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties; + this.allInstances = getZookeeperInstances(); + } + + private List> getZookeeperInstances() { + ArrayList> allInstances = new ArrayList<>(); + try { + Collection names = getNamesToQuery(); + for (String name : names) { + allInstances.addAll(nestedInstances(allInstances, name)); + } + return allInstances; + } + catch (Exception e) { + log.debug("Exception occurred while trying to build the list of instances", e); + return allInstances; + } + } + + private List> nestedInstances( + List> accumulator, String name) throws Exception { + String parentPath = prepareQueryName(name); + Collection> childrenInstances = tryToGetInstances(parentPath); + if (childrenInstances != null) { + return convertCollectionToList(childrenInstances); + } + try { + List children = this.serviceDiscovery.getCurator().getChildren().forPath(parentPath); + return iterateOverChildren(accumulator, parentPath, children); + } catch (Exception e) { + log.trace("Exception occurred while trying to retrieve children of [" + parentPath + "]", e); + return injectZookeeperServiceInstances(accumulator, parentPath); + } + } + + private String prepareQueryName(String name) { + if (name.startsWith(this.zookeeperDiscoveryProperties.getRoot())) { + return name; + } + String queryName = this.zookeeperDiscoveryProperties.getRoot(); + if (!queryName.endsWith("/")) { + queryName = queryName + "/"; + } + return queryName + name; + } + + private Collection> tryToGetInstances(String path) { + try { + return this.serviceDiscovery + .getServiceDiscovery().queryForInstances(path.substring( + this.zookeeperDiscoveryProperties.getRoot().length())); + } catch (Exception e) { + log.trace("Exception occurred while trying to retrieve instances of [" + path + "]", e); + return null; + } + } + + private List> injectZookeeperServiceInstances( + List> accumulator, String name) throws Exception { + Collection> instances = this.serviceDiscovery + .getServiceDiscovery().queryForInstances(name); + accumulator.addAll(convertCollectionToList(instances)); + return accumulator; + } + + private List> convertCollectionToList( + Collection> instances) { + List> serviceInstances = new ArrayList<>(); + for (ServiceInstance instance : instances) { + serviceInstances.add(instance); + } + return serviceInstances; + } + + private List> iterateOverChildren(List> accumulator, + String parentPath, List children) throws Exception { + List> lists = new ArrayList<>(); + for (String child : children) { + lists.addAll(nestedInstances(accumulator, parentPath + "/" + child)); + } + return lists; + } + + private Collection getNamesToQuery() throws Exception { + if (this.zookeeperDependencies == null) { + return this.serviceDiscovery.getServiceDiscovery().queryForNames(); + } + return this.zookeeperDependencies.getDependencyNames(); + } + + @Override + public Iterator> iterator() { + return allInstances.iterator(); + } +} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ConditionalOnDependenciesNotPassed.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ConditionalOnDependenciesNotPassed.java new file mode 100644 index 00000000..0977e56d --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ConditionalOnDependenciesNotPassed.java @@ -0,0 +1,35 @@ +/* + * 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.zookeeper.discovery.dependency; + +import org.springframework.context.annotation.Conditional; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to turn off a feature if Zookeeper dependencies have NOT been passed + * + * @author Marcin Grzejszczak + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Conditional(DependenciesNotPassedCondition.class) +public @interface ConditionalOnDependenciesNotPassed { +} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java index a0b02ee8..dfdc223d 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java @@ -55,6 +55,7 @@ public class DependenciesBasedLoadBalancer extends DynamicServerListLoadBalancer public Server chooseServer(Object key) { String keyAsString = (String) key; ZookeeperDependency dependency = this.zookeeperDependencies.getDependencyForAlias(keyAsString); + log.debug("Current dependencies are [{}]", this.zookeeperDependencies); if (dependency == null) { log.debug("No dependency found for alias [{}] - will use the default rule which is [{}]", keyAsString, this.rule); return this.rule.choose(key); diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesNotPassedCondition.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesNotPassedCondition.java new file mode 100644 index 00000000..08eee5a1 --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesNotPassedCondition.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.zookeeper.discovery.dependency; + +import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +/** + * Inverse of the {@link ConditionalOnDependenciesPassed} condition. Also checks if switch for zookeeper dependencies + * was turned on + * + * @author Marcin Grzejszczak + */ +public class DependenciesNotPassedCondition extends DependenciesPassedCondition { + + @Override + public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + ConditionOutcome propertiesSet = super.getMatchOutcome(context, metadata); + if (propertiesSet.isMatch()) { + return ConditionOutcome.inverse(propertiesSet); + } + Boolean dependenciesEnabled = context.getEnvironment() + .getProperty("spring.cloud.zookeeper.dependencies.enabled", Boolean.class, false); + if (dependenciesEnabled) { + return ConditionOutcome.noMatch("Dependencies are defined in configuration and switch is turned on"); + } + return ConditionOutcome.match("Dependencies are not defined in configuration and switch is turned off"); + } + +} diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/CustomZookeeperServiceDiscovery.groovy b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/CustomZookeeperServiceDiscovery.groovy index 94a301ca..0af34b48 100644 --- a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/CustomZookeeperServiceDiscovery.groovy +++ b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/CustomZookeeperServiceDiscovery.groovy @@ -10,13 +10,19 @@ import org.apache.curator.x.discovery.UriSpec class CustomZookeeperServiceDiscovery extends ZookeeperServiceDiscovery { private final String applicationName + private final String basePath - CustomZookeeperServiceDiscovery(String applicationName, CuratorFramework curator) { + CustomZookeeperServiceDiscovery(String applicationName, String basePath, CuratorFramework curator) { super(curator, null, null) this.applicationName = applicationName + this.basePath = basePath build() } + CustomZookeeperServiceDiscovery(String applicationName, CuratorFramework curator) { + this(applicationName, '/', curator) + } + @Override void build() { setPort(10) @@ -28,7 +34,7 @@ class CustomZookeeperServiceDiscovery extends ZookeeperServiceDiscovery { getServiceInstanceRef().set(instance) def discovery = ServiceDiscoveryBuilder .builder(Void) - .basePath('/') + .basePath(basePath) .client(getCurator()) .thisInstance(instance) .build() diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicatorWithNestedStructureISpec.groovy b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicatorWithNestedStructureISpec.groovy new file mode 100644 index 00000000..1f75b2c9 --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicatorWithNestedStructureISpec.groovy @@ -0,0 +1,79 @@ +package org.springframework.cloud.zookeeper.discovery + +import groovy.json.JsonSlurper +import org.apache.curator.framework.CuratorFramework +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.test.SpringApplicationContextLoader +import org.springframework.boot.test.WebIntegrationTest +import org.springframework.cloud.client.discovery.EnableDiscoveryClient +import org.springframework.cloud.client.loadbalancer.LoadBalanced +import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig +import org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Import +import org.springframework.context.annotation.Profile +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.ContextConfiguration +import org.springframework.web.client.RestTemplate +import spock.lang.Issue +import spock.lang.Specification + +import javax.annotation.PostConstruct +import javax.annotation.PreDestroy + +@ContextConfiguration(classes = Config, loader = SpringApplicationContextLoader) +@ActiveProfiles('nestedstructure') +@WebIntegrationTest(randomPort = true) +class ZookeeperDiscoveryHealthIndicatorWithNestedStructureISpec extends Specification implements PollingUtils { + + @Autowired TestRibbonClient testRibbonClient + + @Issue("#54 - ZookeeperDiscoveryHealthIndicator fails on nested structure") + def 'should return a response that app is in a healthy state when nested folders in zookeeper are present'() { + when: + String response = testRibbonClient.callService('me', 'health') + then: + twoServicesArePresentedInHealthEndpoint(response) + } + + private boolean twoServicesArePresentedInHealthEndpoint(String response) { + def services = new JsonSlurper().parseText(response).zookeeperDiscovery.services + assert ['me', '/a/b/c/d/anotherservice'].every { expectedServiceName -> + services.any { service -> + expectedServiceName == service.name + } + } + return true + } + + @Configuration + @EnableAutoConfiguration + @EnableDiscoveryClient + @Import(CommonTestConfig) + @Profile('nestedstructure') + static class Config { + + @Autowired CuratorFramework curatorFramework + CustomZookeeperServiceDiscovery customZookeeperServiceDiscovery + + @PostConstruct + void registerNestedDependency() { + customZookeeperServiceDiscovery = new CustomZookeeperServiceDiscovery("/a/b/c/d/anotherservice", + '/services', curatorFramework).build() + } + + @PreDestroy + void unregisterServiceDiscovery() { + customZookeeperServiceDiscovery?.close() + } + + @Bean + TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate, + @Value('${spring.application.name}') String springAppName) { + return new TestRibbonClient(restTemplate, springAppName) + } + } +} diff --git a/spring-cloud-zookeeper-discovery/src/test/resources/application-nestedstructure.yml b/spring-cloud-zookeeper-discovery/src/test/resources/application-nestedstructure.yml new file mode 100644 index 00000000..84c328cc --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/test/resources/application-nestedstructure.yml @@ -0,0 +1 @@ +spring.application.name: me