Merge pull request #2 from marcingrzejszczak/serviceRegistration
4financeIT zookeper stuff vol.1 ;)
This commit is contained in:
84
pom.xml
84
pom.xml
@@ -39,17 +39,41 @@
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<useFile>false</useFile>
|
||||
<includes>
|
||||
<include>**/*Spec.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -161,6 +185,43 @@
|
||||
<version>1.12.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Spock -->
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-core</artifactId>
|
||||
<version>${spock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-spring</artifactId>
|
||||
<version>${spock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<version>2.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -171,6 +232,7 @@
|
||||
<spring.cloud.netflix.core>1.0.1.BUILD-SNAPSHOT</spring.cloud.netflix.core>
|
||||
<curator.version>2.7.0</curator.version>
|
||||
<ribbon.version>2.0-RC9</ribbon.version>
|
||||
<spock.version>1.0-groovy-2.4</spock.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
||||
@@ -11,17 +11,18 @@ import org.springframework.cloud.bus.event.RemoteApplicationEvent;
|
||||
@Data
|
||||
public class SimpleRemoteEvent extends RemoteApplicationEvent {
|
||||
|
||||
private String message;
|
||||
private String message;
|
||||
|
||||
private SimpleRemoteEvent(){}
|
||||
private SimpleRemoteEvent() {
|
||||
}
|
||||
|
||||
public SimpleRemoteEvent(Object source, String originService, String destinationService, String message) {
|
||||
super(source, originService, destinationService);
|
||||
this.message = message;
|
||||
}
|
||||
public SimpleRemoteEvent(Object source, String originService, String destinationService, String message) {
|
||||
super(source, originService, destinationService);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public SimpleRemoteEvent(Object source, String originService, String message) {
|
||||
super(source, originService);
|
||||
this.message = message;
|
||||
}
|
||||
public SimpleRemoteEvent(Object source, String originService, String message) {
|
||||
super(source, originService);
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
||||
@@ -42,16 +42,14 @@ public class ZookeeperPropertySource extends EnumerablePropertySource<CuratorFra
|
||||
cache = TreeCache.newBuilder(source, context).build();
|
||||
cache.start();
|
||||
running = true;
|
||||
/*
|
||||
TODO: race condition since TreeCache.process(..) is invoked asynchronously.
|
||||
Methods getProperty and getPropertyNames could be invoked before that TreeCache.process(..) receives
|
||||
all the WatchedEvents.
|
||||
*/
|
||||
}
|
||||
catch (NoNodeException e) {
|
||||
/*
|
||||
TODO: race condition since TreeCache.process(..) is invoked asynchronously.
|
||||
Methods getProperty and getPropertyNames could be invoked before that TreeCache.process(..) receives
|
||||
all the WatchedEvents.
|
||||
*/
|
||||
} catch (NoNodeException e) {
|
||||
// no node, ignore
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error initializing ZookeperPropertySource", e);
|
||||
}
|
||||
}
|
||||
@@ -79,10 +77,9 @@ public class ZookeeperPropertySource extends EnumerablePropertySource<CuratorFra
|
||||
return;
|
||||
for (Map.Entry<String, ChildData> entry : children.entrySet()) {
|
||||
ChildData child = entry.getValue();
|
||||
if (child.getData()==null || child.getData().length == 0) {
|
||||
if (child.getData() == null || child.getData().length == 0) {
|
||||
findKeys(keys, child.getPath());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
keys.add(child.getPath().replace(context + "/", "").replace('/', '.'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,19 @@
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -49,7 +62,37 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spock -->
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-spring</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
package org.springframework.cloud.zookeeper;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.apache.curator.RetryPolicy;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public class ZookeeperAutoConfiguration {
|
||||
|
||||
private @Autowired RetryPolicy retryPolicy;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ZookeeperProperties zookeeperProperties() {
|
||||
@@ -26,9 +31,7 @@ public class ZookeeperAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public CuratorFramework curatorFramework() {
|
||||
CuratorFramework curator = CuratorFrameworkFactory.builder()
|
||||
// TODO: configurable retry policy
|
||||
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
|
||||
// .retryPolicy(new RetryOneTime(100))
|
||||
.retryPolicy(retryPolicy)
|
||||
// TODO: support ensembleProvider via ExhibitorEnsembleProvider
|
||||
// .ensembleProvider(new ExhibitorEnsembleProvider())
|
||||
.connectString(zookeeperProperties().getConnectString()).build();
|
||||
@@ -41,6 +44,14 @@ public class ZookeeperAutoConfiguration {
|
||||
curatorFramework().close();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public RetryPolicy exponentialBackoffRetry() {
|
||||
return new ExponentialBackoffRetry(zookeeperProperties().getBaseSleepTimeMs(),
|
||||
zookeeperProperties().getMaxRetries(),
|
||||
zookeeperProperties().getMaxSleepMs());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ZookeeperEndpoint zookeeperEndpoint() {
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package org.springframework.cloud.zookeeper;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@@ -16,4 +15,20 @@ public class ZookeeperProperties {
|
||||
private String connectString = "localhost:2181";
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* @param baseSleepTimeMs initial amount of time to wait between retries
|
||||
*/
|
||||
private Integer baseSleepTimeMs = 50;
|
||||
|
||||
/**
|
||||
* @param maxRetries max number of times to retry
|
||||
*/
|
||||
private Integer maxRetries = 50;
|
||||
|
||||
/**
|
||||
* @param maxSleepMs max time in ms to sleep on each retry
|
||||
*/
|
||||
private Integer maxSleepMs = 500;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.springframework.cloud.zookeeper
|
||||
|
||||
import org.apache.curator.framework.CuratorFramework
|
||||
import org.apache.curator.test.TestingServer
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import spock.lang.Specification
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@ContextConfiguration(classes = [ TestConfig, ZookeeperAutoConfiguration ])
|
||||
class ZookeeperAutoConfigurationSpec extends Specification {
|
||||
|
||||
@Autowired(required = false)
|
||||
CuratorFramework curator
|
||||
|
||||
def 'should successfully inject Curator as a Spring bean'() {
|
||||
expect:
|
||||
curator != null
|
||||
}
|
||||
|
||||
static class TestConfig {
|
||||
@Bean
|
||||
ZookeeperProperties zookeeperProperties() throws Exception {
|
||||
ZookeeperProperties properties = new ZookeeperProperties()
|
||||
properties.connectString = testingServer().connectString
|
||||
return properties
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestingServer testingServer() throws Exception {
|
||||
return new TestingServer()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.springframework.cloud.zookeeper;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.test.TestingServer;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { ZookeeperAutoConfigurationTests.TestConfig.class,
|
||||
ZookeeperAutoConfiguration.class })
|
||||
public class ZookeeperAutoConfigurationTests {
|
||||
|
||||
@Autowired(required = false)
|
||||
CuratorFramework curator;
|
||||
|
||||
@Test
|
||||
public void testZookeeperFramework() {
|
||||
assertNotNull("curator is null", curator);
|
||||
}
|
||||
|
||||
static class TestConfig {
|
||||
@Bean
|
||||
public ZookeeperProperties zookeeperProperties() throws Exception {
|
||||
ZookeeperProperties properties = new ZookeeperProperties();
|
||||
properties.setConnectString(testingServer().getConnectString());
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestingServer testingServer() throws Exception {
|
||||
return new TestingServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,22 @@
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
@@ -52,6 +68,48 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Spock -->
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-spring</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>1.53</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2012-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;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* Configuration that registers a bean related to microservice's address and port providing.
|
||||
*
|
||||
* @see MicroserviceAddressProvider
|
||||
*
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Tomasz Dziurko, 4financeIT
|
||||
*/
|
||||
@Configuration
|
||||
public class AddressProviderConfiguration {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Bean
|
||||
MicroserviceAddressProvider microserviceAddressProvider() {
|
||||
String microserviceHost = environment.getProperty("microservice.host", getIpAddress());
|
||||
Integer microservicePort = Integer.valueOf(environment.getProperty("server.port", "8080"));
|
||||
return new MicroserviceAddressProvider(microserviceHost, microservicePort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a non loopback IPv4 address for the machine running this process.
|
||||
* If the machine has multiple network interfaces, the IP address for the
|
||||
* first interface returned by {@link java.net.NetworkInterface#getNetworkInterfaces}
|
||||
* is returned.
|
||||
*
|
||||
* @return non loopback IPv4 address for the machine running this process
|
||||
* @see java.net.NetworkInterface#getNetworkInterfaces
|
||||
* @see java.net.NetworkInterface#getInetAddresses
|
||||
*/
|
||||
public static String getIpAddress() {
|
||||
try {
|
||||
for (Enumeration<NetworkInterface> enumNic = NetworkInterface.getNetworkInterfaces();
|
||||
enumNic.hasMoreElements(); ) {
|
||||
NetworkInterface ifc = enumNic.nextElement();
|
||||
if (ifc.isUp()) {
|
||||
for (Enumeration<InetAddress> enumAddr = ifc.getInetAddresses();
|
||||
enumAddr.hasMoreElements(); ) {
|
||||
InetAddress address = enumAddr.nextElement();
|
||||
if (address instanceof Inet4Address && !address.isLoopbackAddress()) {
|
||||
return address.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2012-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;
|
||||
|
||||
/**
|
||||
* Holder for microservice's host and port
|
||||
*
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Adam Chudzik, 4financeIT
|
||||
*
|
||||
*/
|
||||
public class MicroserviceAddressProvider {
|
||||
private final String host;
|
||||
private final int port;
|
||||
|
||||
public MicroserviceAddressProvider(String microserviceHost, int microservicePort) {
|
||||
this.host = microserviceHost;
|
||||
this.port = microservicePort;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
package org.springframework.cloud.zookeeper.discovery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceDiscovery;
|
||||
import org.apache.curator.x.discovery.ServiceInstance;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import static org.springframework.util.ReflectionUtils.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
*/
|
||||
public class ZookeeperDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
@@ -29,6 +30,9 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
|
||||
@Autowired
|
||||
ServiceDiscovery<ZookeeperInstance> discovery;
|
||||
|
||||
@Autowired(required = false)
|
||||
ZookeeperDependencies zookeeperDependencies;
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Spring Cloud Zookeeper Discovery Client";
|
||||
@@ -59,18 +63,26 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
|
||||
@SneakyThrows
|
||||
public List<org.springframework.cloud.client.ServiceInstance> getInstances(
|
||||
final String serviceId) {
|
||||
String serviceIdToQuery = getServiceIdToQuery(serviceId);
|
||||
Collection<ServiceInstance<ZookeeperInstance>> zkInstances = discovery
|
||||
.queryForInstances(serviceId);
|
||||
.queryForInstances(serviceIdToQuery);
|
||||
|
||||
ArrayList<org.springframework.cloud.client.ServiceInstance> instances = new ArrayList<>();
|
||||
|
||||
for (ServiceInstance<ZookeeperInstance> instance : zkInstances) {
|
||||
instances.add(createServiceInstance(serviceId, instance));
|
||||
instances.add(createServiceInstance(serviceIdToQuery, instance));
|
||||
}
|
||||
|
||||
return instances;
|
||||
}
|
||||
|
||||
private String getServiceIdToQuery(String serviceId) {
|
||||
if (zookeeperDependencies != null && zookeeperDependencies.hasDependencies()) {
|
||||
return zookeeperDependencies.getPathForAlias(serviceId);
|
||||
}
|
||||
return serviceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
ArrayList<String> services = null;
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.apache.curator.x.discovery.UriSpec;
|
||||
import org.apache.curator.x.discovery.details.InstanceSerializer;
|
||||
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -19,6 +20,7 @@ import org.springframework.core.env.Environment;
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@Import(AddressProviderConfiguration.class)
|
||||
@EnableConfigurationProperties
|
||||
public class ZookeeperDiscoveryClientConfiguration {
|
||||
@Autowired
|
||||
@@ -40,13 +42,14 @@ public class ZookeeperDiscoveryClientConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServiceInstance<ZookeeperInstance> serviceInstance() throws Exception {
|
||||
@ConditionalOnMissingBean
|
||||
public ServiceInstance<ZookeeperInstance> serviceInstance(MicroserviceAddressProvider microserviceAddressProvider) throws Exception {
|
||||
Environment environment = context.getEnvironment();
|
||||
Integer port = new Integer(environment.getProperty("server.port", "8080"));
|
||||
UriSpec uriSpec = new UriSpec(zookeeperDiscoveryProperties().getUriSpec());
|
||||
return ServiceInstance.<ZookeeperInstance> builder()
|
||||
.name(environment.getProperty("spring.application.name"))
|
||||
.payload(new ZookeeperInstance(context.getId())).port(port)
|
||||
.payload(new ZookeeperInstance(context.getId())).port(microserviceAddressProvider.getPort())
|
||||
.address(microserviceAddressProvider.getHost())
|
||||
.uriSpec(uriSpec).build();
|
||||
}
|
||||
|
||||
@@ -56,15 +59,17 @@ public class ZookeeperDiscoveryClientConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServiceDiscovery<ZookeeperInstance> serviceDiscovery(CuratorFramework curator)
|
||||
@ConditionalOnMissingBean
|
||||
public ServiceDiscovery<ZookeeperInstance> serviceDiscovery(CuratorFramework curator, ServiceInstance<ZookeeperInstance> serviceInstance)
|
||||
throws Exception {
|
||||
return ServiceDiscoveryBuilder.builder(ZookeeperInstance.class).client(curator)
|
||||
.basePath(zookeeperDiscoveryProperties().getRoot())
|
||||
.serializer(instanceSerializer()).thisInstance(serviceInstance()).build();
|
||||
.serializer(instanceSerializer()).thisInstance(serviceInstance).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ZookeeperDiscoveryHealthIndicator zookeeperDiscoveryHealthIndicator() {
|
||||
return new ZookeeperDiscoveryHealthIndicator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,4 +15,9 @@ public class ZookeeperDiscoveryProperties {
|
||||
private String root = "/services";
|
||||
|
||||
private String uriSpec = "{scheme}://{address}:{port}";
|
||||
|
||||
/**
|
||||
* @param realm allows you to register a service under specified realm
|
||||
*/
|
||||
private String realm;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
@@ -16,23 +16,26 @@
|
||||
|
||||
package org.springframework.cloud.zookeeper.discovery;
|
||||
|
||||
import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
|
||||
import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceDiscovery;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.config.ConfigurationManager;
|
||||
import com.netflix.config.DynamicPropertyFactory;
|
||||
import com.netflix.config.DynamicStringProperty;
|
||||
import com.netflix.loadbalancer.ServerList;
|
||||
import org.apache.curator.x.discovery.ServiceDiscovery;
|
||||
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.DependenciesPassedCondition;
|
||||
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Preprocessor that configures defaults for eureka-discovered ribbon clients. Such as:
|
||||
@@ -41,6 +44,7 @@ import com.netflix.loadbalancer.ServerList;
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
*/
|
||||
@Configuration
|
||||
public class ZookeeperRibbonClientConfiguration {
|
||||
@@ -54,6 +58,16 @@ public class ZookeeperRibbonClientConfiguration {
|
||||
public ZookeeperRibbonClientConfiguration() {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Conditional(DependenciesPassedCondition.class)
|
||||
@ConditionalOnProperty(value = "zookeeper.dependencies.enabled", matchIfMissing = true)
|
||||
public ServerList<?> ribbonServerListFromDependencies(IClientConfig config, ZookeeperDependencies zookeeperDependencies) {
|
||||
ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery);
|
||||
serverList.initFromDependencies(config, zookeeperDependencies);
|
||||
return serverList;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ServerList<?> ribbonServerList(IClientConfig config) {
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
package org.springframework.cloud.zookeeper.discovery;
|
||||
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.AbstractServerList;
|
||||
import org.apache.curator.x.discovery.ServiceDiscovery;
|
||||
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.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceDiscovery;
|
||||
import org.apache.curator.x.discovery.ServiceInstance;
|
||||
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.AbstractServerList;
|
||||
|
||||
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
*/
|
||||
public class ZookeeperServerList extends AbstractServerList<ZookeeperServer> {
|
||||
|
||||
@@ -30,6 +31,10 @@ public class ZookeeperServerList extends AbstractServerList<ZookeeperServer> {
|
||||
this.serviceId = clientConfig.getClientName();
|
||||
}
|
||||
|
||||
public void initFromDependencies(IClientConfig clientConfig, ZookeeperDependencies zookeeperDependencies) {
|
||||
this.serviceId = zookeeperDependencies.getPathForAlias(clientConfig.getClientName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ZookeeperServer> getInitialListOfServers() {
|
||||
return getServers();
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2012-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.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
*/
|
||||
public class DependenciesPassedCondition extends SpringBootCondition {
|
||||
|
||||
private static final String ZOOKEEPER_DEPENDENCIES_PROP = "zookeeper.dependencies";
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
Map<String, Object> subProperties = new RelaxedPropertyResolver(context.getEnvironment()).getSubProperties(ZOOKEEPER_DEPENDENCIES_PROP);
|
||||
return subProperties.isEmpty() ?
|
||||
ConditionOutcome.noMatch("No dependencies have been passed for the service") :
|
||||
ConditionOutcome.match();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2012-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.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.Predicate;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.apache.commons.lang.StringUtils.EMPTY;
|
||||
import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
*/
|
||||
public enum LoadBalancerType {
|
||||
STICKY, RANDOM, ROUND_ROBIN;
|
||||
|
||||
public static LoadBalancerType fromName(final String strategyName) {
|
||||
LoadBalancerType loadBalancerType = (LoadBalancerType) CollectionUtils.find(Arrays.asList(values()), new Predicate() {
|
||||
@Override
|
||||
public boolean evaluate(Object o) {
|
||||
LoadBalancerType input = (LoadBalancerType) o;
|
||||
return input.name().equals(defaultIfEmpty(strategyName, EMPTY).toUpperCase());
|
||||
}
|
||||
});
|
||||
if (loadBalancerType == null) {
|
||||
return ROUND_ROBIN;
|
||||
}
|
||||
return loadBalancerType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2012-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 lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties("zookeeper")
|
||||
public class ZookeeperDependencies {
|
||||
|
||||
private String prefix = "";
|
||||
|
||||
private Map<String, ZookeeperDependency> dependencies = new LinkedHashMap<>();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
for (Map.Entry<String, ZookeeperDependency> entry : this.dependencies.entrySet()) {
|
||||
ZookeeperDependency value = entry.getValue();
|
||||
if (StringUtils.hasText(prefix)) {
|
||||
value.path = prefix + value.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class ZookeeperDependency {
|
||||
|
||||
private String id;
|
||||
|
||||
private String path;
|
||||
|
||||
private LoadBalancerType loadBalancerType;
|
||||
|
||||
private String contentTypeTemplate;
|
||||
|
||||
private String version;
|
||||
|
||||
private Map<String, String> headers;
|
||||
|
||||
private boolean required;
|
||||
}
|
||||
|
||||
public Collection<ZookeeperDependency> getDependencyConfigurations() {
|
||||
return dependencies.values();
|
||||
}
|
||||
|
||||
public boolean hasDependencies() {
|
||||
return !dependencies.isEmpty();
|
||||
}
|
||||
|
||||
public String getPathForAlias(final String alias) {
|
||||
for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : dependencies.entrySet()) {
|
||||
if (zookeeperDependencyEntry.getKey().equals(alias)) {
|
||||
return zookeeperDependencyEntry.getValue().getPath();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2012-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.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Provides autoconfiguration for Zookeeper dependency set up in properties.
|
||||
*
|
||||
* @see ZookeeperDependencies
|
||||
*
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@Conditional(DependenciesPassedCondition.class)
|
||||
@ConditionalOnProperty(value = "zookeeper.dependencies.enabled", matchIfMissing = true)
|
||||
@AutoConfigureAfter(ZookeeperAutoConfiguration.class)
|
||||
public class ZookeeperDependenciesAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ZookeeperDependencies zookeeperDependencies() {
|
||||
return new ZookeeperDependencies();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceCache;
|
||||
import org.apache.curator.x.discovery.ServiceDiscovery;
|
||||
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
|
||||
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies.ZookeeperDependency;
|
||||
import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
*/
|
||||
public class DefaultDependencyWatcher implements DependencyRegistrationHookProvider {
|
||||
|
||||
private final ServiceDiscovery serviceDiscovery;
|
||||
private final Map<String, ServiceCache> dependencyRegistry = new HashMap<>();
|
||||
private final List<DependencyWatcherListener> listeners;
|
||||
private final DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier;
|
||||
private final ZookeeperDependencies zookeeperDependencies;
|
||||
|
||||
public DefaultDependencyWatcher(ServiceDiscovery serviceDiscovery,
|
||||
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
|
||||
List<DependencyWatcherListener> dependencyWatcherListeners,
|
||||
ZookeeperDependencies zookeeperDependencies) {
|
||||
this.serviceDiscovery = serviceDiscovery;
|
||||
this.dependencyPresenceOnStartupVerifier = dependencyPresenceOnStartupVerifier;
|
||||
this.listeners = dependencyWatcherListeners;
|
||||
this.zookeeperDependencies = zookeeperDependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerDependencyRegistrationHooks() throws Exception {
|
||||
for (ZookeeperDependency zookeeperDependency : zookeeperDependencies.getDependencyConfigurations()) {
|
||||
String dependencyPath = zookeeperDependency.getPath();
|
||||
ServiceCache serviceCache = serviceDiscovery.serviceCacheBuilder().name(dependencyPath).build();
|
||||
serviceCache.start();
|
||||
dependencyPresenceOnStartupVerifier.verifyDependencyPresence(dependencyPath, serviceCache, zookeeperDependency.isRequired());
|
||||
dependencyRegistry.put(dependencyPath, serviceCache);
|
||||
serviceCache.addListener(new DependencyStateChangeListenerRegistry(listeners, dependencyPath, serviceCache));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearDependencyRegistrationHooks() throws IOException {
|
||||
for (ServiceCache cache : dependencyRegistry.values()) {
|
||||
cache.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.4financeit.com>4financeIT</a>
|
||||
*/
|
||||
public interface DependencyRegistrationHookProvider {
|
||||
|
||||
/**
|
||||
* Register hooks upon dependencies registration
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void registerDependencyRegistrationHooks() throws Exception;
|
||||
|
||||
/**
|
||||
* Unregister hooks upon dependencies registration
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
void clearDependencyRegistrationHooks() throws IOException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.4financeit.com>4financeIT</a>
|
||||
*/
|
||||
public enum DependencyState {
|
||||
CONNECTED,
|
||||
DISCONNECTED
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher;
|
||||
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.state.ConnectionState;
|
||||
import org.apache.curator.x.discovery.ServiceCache;
|
||||
import org.apache.curator.x.discovery.details.ServiceCacheListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Tomasz Nurkiewicz, 4financeIT
|
||||
*/
|
||||
public class DependencyStateChangeListenerRegistry implements ServiceCacheListener {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DependencyStateChangeListenerRegistry.class);
|
||||
|
||||
private final List<DependencyWatcherListener> listeners;
|
||||
private final String dependencyName;
|
||||
private final ServiceCache serviceCache;
|
||||
|
||||
public DependencyStateChangeListenerRegistry(List<DependencyWatcherListener> listeners, String dependencyName, ServiceCache serviceCache) {
|
||||
this.listeners = listeners;
|
||||
this.dependencyName = dependencyName;
|
||||
this.serviceCache = serviceCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cacheChanged() {
|
||||
DependencyState state = serviceCache.getInstances().isEmpty() ? DependencyState.DISCONNECTED : DependencyState.CONNECTED;
|
||||
logCurrentState(state);
|
||||
informListeners(state);
|
||||
}
|
||||
|
||||
private void logCurrentState(DependencyState dependencyState) {
|
||||
log.info("Service cache state change for '{}' instances, current service state: {}", dependencyName, dependencyState);
|
||||
}
|
||||
|
||||
private void informListeners(DependencyState state) {
|
||||
for (DependencyWatcherListener listener : listeners) {
|
||||
listener.stateChanged(dependencyName, state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(CuratorFramework client, ConnectionState newState) {
|
||||
// todo do something or ignore for what is worth
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.springframework.cloud.zookeeper.discovery.watcher;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface DependencyWatcher {
|
||||
|
||||
/**
|
||||
* Register hooks upon dependencies registration
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void registerDependencyRegistrationHooks() throws Exception;
|
||||
|
||||
/**
|
||||
* Unregister hooks upon dependencies registration
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
void clearDependencyRegistrationHooks() throws IOException;
|
||||
|
||||
/**
|
||||
* Register a listener for a dependency
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
void registerDependencyStateChangeListener(DependencyWatcherListener listener);
|
||||
|
||||
/**
|
||||
* Unregister a listener for a dependency
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
void clearDependencyStateChangeListener(DependencyWatcherListener listener);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceDiscovery;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.zookeeper.discovery.dependency.DependenciesPassedCondition;
|
||||
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
|
||||
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependenciesAutoConfiguration;
|
||||
import org.springframework.cloud.zookeeper.discovery.watcher.presence.DefaultDependencyPresenceOnStartupVerifier;
|
||||
import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides hooks for observing dependency lifecycle in Zookeeper.
|
||||
* Needs custom dependencies to be set in order to work.
|
||||
*
|
||||
* @see ZookeeperDependencies
|
||||
*
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@Conditional(DependenciesPassedCondition.class)
|
||||
@ConditionalOnProperty(value = "zookeeper.dependencies.enabled", matchIfMissing = true)
|
||||
@AutoConfigureAfter(ZookeeperDependenciesAutoConfiguration.class)
|
||||
public class DependencyWatcherAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<DependencyWatcherListener> dependencyWatcherListeners = new ArrayList<>();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier() {
|
||||
return new DefaultDependencyPresenceOnStartupVerifier();
|
||||
}
|
||||
|
||||
@Bean(initMethod = "registerDependencyRegistrationHooks", destroyMethod = "clearDependencyRegistrationHooks")
|
||||
@ConditionalOnMissingBean
|
||||
public DependencyRegistrationHookProvider dependencyWatcher(ServiceDiscovery serviceDiscovery,
|
||||
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
|
||||
ZookeeperDependencies zookeeperDependencies) {
|
||||
return new DefaultDependencyWatcher(serviceDiscovery,
|
||||
dependencyPresenceOnStartupVerifier,
|
||||
dependencyWatcherListeners,
|
||||
zookeeperDependencies);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher;
|
||||
|
||||
/**
|
||||
* Performs logic upon change of state of a dependency {@see DependencyState}
|
||||
* in the service discovery system.
|
||||
*
|
||||
* @author <a href="http://www.4financeit.com>4financeIT</a>
|
||||
*/
|
||||
public interface DependencyWatcherListener {
|
||||
|
||||
/**
|
||||
* Method executed upon state change of a dependency
|
||||
*
|
||||
* @param dependencyName - alias from microservice configuration {@see ZookeeperDependencies}
|
||||
* @param newState
|
||||
*/
|
||||
void stateChanged(String dependencyName, DependencyState newState);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher.presence;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.4financeit.com>4financeIT</a>
|
||||
*/
|
||||
public class DefaultDependencyPresenceOnStartupVerifier extends DependencyPresenceOnStartupVerifier {
|
||||
public DefaultDependencyPresenceOnStartupVerifier() {
|
||||
super(new LogMissingDependencyChecker());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher.presence;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceCache;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Tomasz Szymanski, 4financeIT
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract class DependencyPresenceOnStartupVerifier {
|
||||
private static final PresenceChecker MANDATORY_DEPENDENCY_CHECKER = new FailOnMissingDependencyChecker();
|
||||
private final PresenceChecker optionalDependencyChecker;
|
||||
|
||||
public DependencyPresenceOnStartupVerifier(PresenceChecker optionalDependencyChecker) {
|
||||
this.optionalDependencyChecker = optionalDependencyChecker;
|
||||
}
|
||||
|
||||
public void verifyDependencyPresence(String dependencyName, ServiceCache serviceCache, boolean required) {
|
||||
if (required) {
|
||||
MANDATORY_DEPENDENCY_CHECKER.checkPresence(dependencyName, serviceCache.getInstances());
|
||||
} else {
|
||||
optionalDependencyChecker.checkPresence(dependencyName, serviceCache.getInstances());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher.presence;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceInstance;
|
||||
import org.springframework.cloud.zookeeper.discovery.watcher.presence.NoInstancesRunningException;
|
||||
import org.springframework.cloud.zookeeper.discovery.watcher.presence.PresenceChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Adam Chudzik, 4financeIT
|
||||
*/
|
||||
public class FailOnMissingDependencyChecker implements PresenceChecker {
|
||||
@Override
|
||||
public void checkPresence(String dependencyName, List<ServiceInstance> serviceInstances) {
|
||||
if (serviceInstances.isEmpty()) {
|
||||
throw new NoInstancesRunningException(dependencyName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher.presence;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceInstance;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Tomasz Dziurko, 4financeIT
|
||||
*/
|
||||
public class LogMissingDependencyChecker implements PresenceChecker {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
@Override
|
||||
public void checkPresence(String dependencyName, List<ServiceInstance> serviceInstances) {
|
||||
if (serviceInstances.isEmpty()) {
|
||||
log.warn("Microservice dependency with name [" + dependencyName + "] is missing.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher.presence;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.4financeit.com>4financeIT</a>
|
||||
*/
|
||||
public class NoInstancesRunningException extends RuntimeException {
|
||||
public NoInstancesRunningException(String dependencyName) {
|
||||
super("Required microservice dependency with name [" + dependencyName + "] is missing");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher.presence;
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceInstance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.4financeit.com>4financeIT</a>
|
||||
*/
|
||||
public interface PresenceChecker {
|
||||
|
||||
/**
|
||||
* Checks if a given dependency is present
|
||||
*
|
||||
* @param dependencyName
|
||||
* @param serviceInstances - instances to check the dependency for
|
||||
*/
|
||||
void checkPresence(String dependencyName, List<ServiceInstance> serviceInstances);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
# Auto Configuration
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.zookeeper.discovery.RibbonZookeeperAutoConfiguration
|
||||
org.springframework.cloud.zookeeper.discovery.RibbonZookeeperAutoConfiguration,\
|
||||
org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependenciesAutoConfiguration,\
|
||||
org.springframework.cloud.zookeeper.discovery.watcher.DependencyWatcherAutoConfiguration
|
||||
|
||||
org.springframework.cloud.client.discovery.EnableDiscoveryClient=\
|
||||
org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryClientConfiguration
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.curator.framework.CuratorFramework
|
||||
import org.apache.curator.test.TestingServer
|
||||
import org.springframework.cloud.zookeeper.ZookeeperProperties
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.util.SocketUtils
|
||||
|
||||
@PackageScope
|
||||
@CompileStatic
|
||||
@Configuration
|
||||
class CommonTestConfig {
|
||||
@Bean(destroyMethod = 'close')
|
||||
TestingServer testingServer() {
|
||||
return new TestingServer(SocketUtils.findAvailableTcpPort())
|
||||
}
|
||||
|
||||
@Bean(initMethod = "start", destroyMethod = "stop")
|
||||
TestServiceRegistrar testServiceRegistrar(CuratorFramework curatorFramework) {
|
||||
return new TestServiceRegistrar(wiremockServer().port(), curatorFramework)
|
||||
}
|
||||
|
||||
@Bean(initMethod = "start", destroyMethod = "shutdown") WireMockServer wiremockServer() {
|
||||
return new WireMockServer(SocketUtils.findAvailableTcpPort())
|
||||
}
|
||||
|
||||
@Bean ZookeeperProperties zookeeperProperties() {
|
||||
return new ZookeeperProperties(connectString: "localhost:${testingServer().port}")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.curator.framework.CuratorFramework
|
||||
import org.apache.curator.x.discovery.ServiceDiscovery
|
||||
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder
|
||||
import org.apache.curator.x.discovery.ServiceInstance
|
||||
import org.apache.curator.x.discovery.UriSpec
|
||||
|
||||
@CompileStatic
|
||||
class TestServiceRegistrar {
|
||||
|
||||
private final int wiremockServerPort
|
||||
private final CuratorFramework curatorFramework
|
||||
private final ServiceDiscovery serviceDiscovery
|
||||
|
||||
TestServiceRegistrar(int wiremockServerPort, CuratorFramework curatorFramework) {
|
||||
this.wiremockServerPort = wiremockServerPort
|
||||
this.curatorFramework = curatorFramework
|
||||
this.serviceDiscovery = serviceDiscovery()
|
||||
}
|
||||
|
||||
void start() {
|
||||
serviceDiscovery.start()
|
||||
}
|
||||
|
||||
ServiceInstance serviceInstance() {
|
||||
return ServiceInstance.builder().uriSpec(new UriSpec("{scheme}://{address}:{port}/"))
|
||||
.address('localhost')
|
||||
.port(wiremockServerPort)
|
||||
.name('testInstance')
|
||||
.build()
|
||||
}
|
||||
|
||||
ServiceDiscovery serviceDiscovery() {
|
||||
return ServiceDiscoveryBuilder
|
||||
.builder(Void)
|
||||
.basePath('/services')
|
||||
.client(curatorFramework)
|
||||
.thisInstance(serviceInstance())
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
void stop() {
|
||||
serviceDiscovery.close()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.CompileStatic
|
||||
import org.springframework.web.client.RestTemplate
|
||||
|
||||
@PackageScope
|
||||
@CompileStatic
|
||||
class TestServiceRestClient {
|
||||
|
||||
final RestTemplate restTemplate;
|
||||
|
||||
TestServiceRestClient(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate
|
||||
}
|
||||
|
||||
String pingService(String alias) {
|
||||
return restTemplate.getForObject("http://$alias/ping", String)
|
||||
}
|
||||
|
||||
String pingOnUrl(String url) {
|
||||
return new RestTemplate().getForObject("http://$url/ping", String)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer
|
||||
import com.github.tomakehurst.wiremock.client.WireMock
|
||||
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.ServiceInstance
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.web.client.RestTemplate
|
||||
import spock.lang.Specification
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.*
|
||||
|
||||
@ContextConfiguration(classes = Config, loader = SpringApplicationContextLoader)
|
||||
@ActiveProfiles('ribbon')
|
||||
@WebIntegrationTest
|
||||
class ZookeeperDiscoveryISpec extends Specification {
|
||||
|
||||
public static final String TEST_INSTANCE_NAME = 'testInstance'
|
||||
|
||||
@Autowired TestRibbonClient testRibbonClient
|
||||
@Autowired WireMockServer wiremockServer
|
||||
@Autowired DiscoveryClient discoveryClient
|
||||
WireMock wireMock
|
||||
|
||||
def setup() {
|
||||
wireMock = new WireMock('localhost', wiremockServer.port())
|
||||
wireMock.register(get(urlEqualTo('/ping')).willReturn(aResponse().withBody('pong')))
|
||||
}
|
||||
|
||||
def 'should find a collaborator via Ribbon'() {
|
||||
expect:
|
||||
'pong' == testRibbonClient.pingService(TEST_INSTANCE_NAME)
|
||||
}
|
||||
|
||||
def 'should find the app by its name via Ribbon'() {
|
||||
expect:
|
||||
'{"status":"UP"}' == testRibbonClient.thisHealthCheck()
|
||||
}
|
||||
|
||||
def 'should find a collaborator via discovery client'() {
|
||||
given:
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances(TEST_INSTANCE_NAME)
|
||||
ServiceInstance instance = instances.first()
|
||||
expect:
|
||||
'pong' == testRibbonClient.pingOnUrl("${instance.host}:${instance.port}")
|
||||
}
|
||||
|
||||
def 'should properly find local instance'() {
|
||||
expect:
|
||||
AddressProviderConfiguration.ipAddress == discoveryClient.localServiceInstance.host
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@Import(CommonTestConfig)
|
||||
@EnableDiscoveryClient
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate,
|
||||
@Value('${spring.application.name}') String springAppName) {
|
||||
return new TestRibbonClient(restTemplate, springAppName)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestRibbonClient extends TestServiceRestClient {
|
||||
|
||||
private final String thisAppName
|
||||
|
||||
TestRibbonClient(RestTemplate restTemplate, String thisAppName) {
|
||||
super(restTemplate)
|
||||
this.thisAppName = thisAppName
|
||||
}
|
||||
|
||||
String thisHealthCheck() {
|
||||
return restTemplate.getForObject("http://$thisAppName/health", String)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer
|
||||
import com.github.tomakehurst.wiremock.client.WireMock
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
import org.springframework.boot.test.SpringApplicationContextLoader
|
||||
import org.springframework.cloud.client.ServiceInstance
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.web.client.RestTemplate
|
||||
import spock.lang.Specification
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.*
|
||||
|
||||
@ContextConfiguration(classes = Config, loader = SpringApplicationContextLoader)
|
||||
@ActiveProfiles('watcher')
|
||||
class ZookeeperDiscoveryWithDependenciesISpec extends Specification {
|
||||
|
||||
@Autowired TestRibbonClient testRibbonClient
|
||||
@Autowired WireMockServer wiremockServer
|
||||
@Autowired DiscoveryClient discoveryClient
|
||||
WireMock wireMock
|
||||
|
||||
def setup() {
|
||||
wireMock = new WireMock('localhost', wiremockServer.port())
|
||||
wireMock.register(get(urlEqualTo('/ping')).willReturn(aResponse().withBody('pong')))
|
||||
}
|
||||
|
||||
def 'should find a collaborator via Ribbon by using its alias from dependencies'() {
|
||||
expect:
|
||||
'pong' == testRibbonClient.pingService('someAlias')
|
||||
}
|
||||
|
||||
def 'should find a collaborator via discovery client'() {
|
||||
given:
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances('someAlias')
|
||||
ServiceInstance instance = instances.first()
|
||||
expect:
|
||||
'pong' == testRibbonClient.pingOnUrl("${instance.host}:${instance.port}")
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@Import(CommonTestConfig)
|
||||
@EnableDiscoveryClient
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate) {
|
||||
return new TestRibbonClient(restTemplate)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestRibbonClient extends TestServiceRestClient {
|
||||
|
||||
TestRibbonClient(RestTemplate restTemplate) {
|
||||
super(restTemplate)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher
|
||||
|
||||
import org.apache.curator.framework.CuratorFramework
|
||||
import org.apache.curator.framework.CuratorFrameworkFactory
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry
|
||||
import org.apache.curator.test.TestingServer
|
||||
import org.apache.curator.x.discovery.*
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
import org.springframework.boot.test.SpringApplicationContextLoader
|
||||
import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier
|
||||
import org.springframework.cloud.zookeeper.discovery.watcher.presence.LogMissingDependencyChecker
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.util.SocketUtils
|
||||
import spock.lang.Specification
|
||||
import spock.util.concurrent.PollingConditions
|
||||
|
||||
@ContextConfiguration(classes = Config, loader = SpringApplicationContextLoader)
|
||||
@ActiveProfiles('watcher')
|
||||
class DefaultDependencyWatcherSpringISpec extends Specification {
|
||||
|
||||
@Autowired AssertableDependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier
|
||||
@Autowired AssertableDependencyWatcherListener dependencyWatcherListener
|
||||
@Autowired ServiceDiscovery serviceDiscovery
|
||||
@Autowired ServiceInstance serviceInstance
|
||||
|
||||
def 'should verify that presence of a dependency has been checked'() {
|
||||
expect:
|
||||
dependencyPresenceOnStartupVerifier.startupPresenceVerified
|
||||
}
|
||||
|
||||
def 'should verify that dependency watcher listener is successfully registered and operational'() {
|
||||
when:
|
||||
serviceDiscovery.unregisterService(serviceInstance)
|
||||
then:
|
||||
new PollingConditions().eventually {
|
||||
dependencyWatcherListener.dependencyState == DependencyState.DISCONNECTED
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
static PropertySourcesPlaceholderConfigurer propertiesConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer()
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = 'close')
|
||||
TestingServer testingServer() {
|
||||
return new TestingServer(SocketUtils.findAvailableTcpPort())
|
||||
}
|
||||
|
||||
@Bean
|
||||
ServiceInstance serviceInstance() {
|
||||
return ServiceInstance.builder().uriSpec(new UriSpec("{scheme}://{address}:{port}/"))
|
||||
.address('anyUrl')
|
||||
.port(10)
|
||||
.name('testInstance')
|
||||
.build()
|
||||
}
|
||||
|
||||
@Bean(initMethod = 'start', destroyMethod = 'close')
|
||||
ServiceDiscovery serviceDiscovery() {
|
||||
return ServiceDiscoveryBuilder
|
||||
.builder(Void)
|
||||
.basePath('/')
|
||||
.client(curatorFramework())
|
||||
.thisInstance(serviceInstance())
|
||||
.build()
|
||||
}
|
||||
|
||||
@Bean(initMethod = 'start', destroyMethod = 'close')
|
||||
CuratorFramework curatorFramework() {
|
||||
return CuratorFrameworkFactory.newClient(testingServer().connectString, new ExponentialBackoffRetry(20, 20, 500))
|
||||
}
|
||||
|
||||
@Bean
|
||||
DependencyWatcherListener dependencyWatcherListener() {
|
||||
return new AssertableDependencyWatcherListener()
|
||||
}
|
||||
|
||||
@Bean
|
||||
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier() {
|
||||
return new AssertableDependencyPresenceOnStartupVerifier()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class AssertableDependencyWatcherListener implements DependencyWatcherListener {
|
||||
|
||||
DependencyState dependencyState = DependencyState.CONNECTED
|
||||
|
||||
@Override
|
||||
void stateChanged(String dependencyName, DependencyState newState) {
|
||||
dependencyState = newState
|
||||
}
|
||||
}
|
||||
|
||||
static class AssertableDependencyPresenceOnStartupVerifier extends DependencyPresenceOnStartupVerifier {
|
||||
|
||||
boolean startupPresenceVerified = false
|
||||
|
||||
AssertableDependencyPresenceOnStartupVerifier() {
|
||||
super(new LogMissingDependencyChecker())
|
||||
}
|
||||
|
||||
@Override
|
||||
void verifyDependencyPresence(String dependencyName, ServiceCache serviceCache, boolean required) {
|
||||
startupPresenceVerified = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher.presence
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceCache
|
||||
import org.codehaus.groovy.runtime.StackTraceUtils
|
||||
import spock.lang.Specification
|
||||
|
||||
class DefaultDependencyPresenceOnStartupVerifierSpec extends Specification {
|
||||
|
||||
private static final String SERVICE_NAME = 'service01'
|
||||
|
||||
def 'should throw exception if obligatory dependencies are missing'() {
|
||||
given:
|
||||
DefaultDependencyPresenceOnStartupVerifier dependencyVerifier = new DefaultDependencyPresenceOnStartupVerifier()
|
||||
ServiceCache serviceCache = Mock()
|
||||
serviceCache.instances >> []
|
||||
when:
|
||||
dependencyVerifier.verifyDependencyPresence(SERVICE_NAME, serviceCache, true)
|
||||
then:
|
||||
Throwable thrown = thrown(Throwable)
|
||||
StackTraceUtils.extractRootCause(thrown).class == NoInstancesRunningException
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012-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.watcher.presence
|
||||
|
||||
import org.apache.curator.x.discovery.ServiceCache
|
||||
import spock.lang.Specification
|
||||
|
||||
class DependencyPresenceOnStartupVerifierSpec extends Specification {
|
||||
|
||||
private static final String SERVICE_NAME = 'service01'
|
||||
|
||||
def 'should check optional dependency using optional dependency checker'() {
|
||||
given:
|
||||
PresenceChecker optionalDependencyChecker = Mock()
|
||||
DependencyPresenceOnStartupVerifier dependencyVerifier = new DependencyPresenceOnStartupVerifier(optionalDependencyChecker) {
|
||||
}
|
||||
ServiceCache serviceCache = Mock()
|
||||
serviceCache.instances >> []
|
||||
when:
|
||||
dependencyVerifier.verifyDependencyPresence(SERVICE_NAME, serviceCache, false)
|
||||
then:
|
||||
1 * optionalDependencyChecker.checkPresence(SERVICE_NAME, serviceCache.instances)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
spring.application.name: ribbonApp
|
||||
@@ -0,0 +1,20 @@
|
||||
spring.application.name: someName
|
||||
zookeeper:
|
||||
dependencies:
|
||||
someAlias:
|
||||
id: someId
|
||||
path: testInstance
|
||||
loadBalancerType: ROUND_ROBIN
|
||||
contentTypeTemplate: application/vnd.newsletter.$version+json
|
||||
version: v1
|
||||
headers:
|
||||
header1: value1
|
||||
header2: value2
|
||||
required: false
|
||||
testInstance2:
|
||||
id: someId2
|
||||
path: somePath2
|
||||
loadBalancerType: ROUND_ROBIN
|
||||
contentTypeTemplate: application/vnd.newsletter.$version+json2
|
||||
version: v1
|
||||
required: false
|
||||
@@ -1,58 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-zookeeper-sample</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Cloud Zookeeper Sample</name>
|
||||
<description>Spring Cloud Zookeeper Sample</description>
|
||||
<artifactId>spring-cloud-zookeeper-sample</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Cloud Zookeeper Sample</name>
|
||||
<description>Spring Cloud Zookeeper Sample</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-zookeeper</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-zookeeper</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!--skip deploy -->
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!--skip deploy -->
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-zookeeper-config</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-zookeeper-discovery</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-zookeeper-bus</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-zookeeper-config</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-zookeeper-discovery</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-zookeeper-bus</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
Reference in New Issue
Block a user