update to use Ecwid/consul-api, all working except events
This commit is contained in:
32
pom.xml
32
pom.xml
@@ -107,6 +107,23 @@
|
||||
<artifactId>spring-cloud-config-client</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ecwid.consul</groupId>
|
||||
<artifactId>consul-api</artifactId>
|
||||
<version>0.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- force httpclient version -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zuul</artifactId>
|
||||
@@ -132,21 +149,6 @@
|
||||
<artifactId>spring-cloud-netflix-core</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-slf4j</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.ribbon</groupId>
|
||||
<artifactId>ribbon</artifactId>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.springframework.cloud.consul.bus;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -8,7 +9,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.cloud.bus.BusAutoConfiguration;
|
||||
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
|
||||
import org.springframework.cloud.consul.client.EventClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.dsl.IntegrationFlow;
|
||||
@@ -22,7 +22,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(EventClient.class)
|
||||
@ConditionalOnClass(ConsulClient.class)
|
||||
@ConditionalOnExpression("${bus.consul.enabled:true}")
|
||||
@AutoConfigureAfter(BusAutoConfiguration.class)
|
||||
@EnableScheduling
|
||||
|
||||
@@ -2,8 +2,6 @@ package org.springframework.cloud.consul.bus;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.consul.client.EventService;
|
||||
import org.springframework.cloud.consul.model.Event;
|
||||
import org.springframework.integration.endpoint.MessageProducerSupport;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
@@ -18,8 +16,8 @@ import java.util.Map;
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class ConsulInboundChannelAdapter extends MessageProducerSupport {
|
||||
@Autowired
|
||||
private EventService eventService;
|
||||
//@Autowired
|
||||
//private EventService eventService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
@@ -47,7 +45,7 @@ public class ConsulInboundChannelAdapter extends MessageProducerSupport {
|
||||
|
||||
@Scheduled(fixedDelayString = "10")
|
||||
public void getEvents() throws IOException {
|
||||
List<Event> events = eventService.watch();
|
||||
/*FIXME: List<Event> events = eventService.watch();
|
||||
for (Event event : events) {
|
||||
Map<String, Object> headers = new HashMap<>();
|
||||
//headers.put(MessageHeaders.REPLY_CHANNEL, outputChannel.)
|
||||
@@ -56,7 +54,7 @@ public class ConsulInboundChannelAdapter extends MessageProducerSupport {
|
||||
.withPayload(objectMapper.readValue(event.getDecoded(), String.class))
|
||||
//TODO: support headers
|
||||
.build());
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.springframework.cloud.consul.bus;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.QueryParams;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.event.model.Event;
|
||||
import com.ecwid.consul.v1.event.model.EventParams;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.consul.client.EventService;
|
||||
import org.springframework.cloud.consul.model.Event;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
@@ -13,14 +16,14 @@ import org.springframework.messaging.Message;
|
||||
public class ConsulOutboundEndpoint extends AbstractReplyProducingMessageHandler {
|
||||
|
||||
@Autowired
|
||||
protected EventService eventService;
|
||||
protected ConsulClient consul;
|
||||
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
Object payload = requestMessage.getPayload();
|
||||
//TODO: support headers
|
||||
//TODO: support consul event filters: NodeFilter, ServiceFilter, TagFilter
|
||||
Event event = eventService.fire("springCloudBus", (String) payload);
|
||||
Response<Event> event = consul.eventFire("springCloudBus", (String) payload, new EventParams(), QueryParams.DEFAULT);
|
||||
//TODO: return event?
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
package org.springframework.cloud.consul.config;
|
||||
|
||||
import org.springframework.cloud.consul.client.KeyValueClient;
|
||||
import org.springframework.cloud.consul.client.NotFoundException;
|
||||
import org.springframework.cloud.consul.model.KeyValue;
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.QueryParams;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.kv.model.GetValue;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.common.base.Charsets.UTF_8;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class ConsulPropertySource extends EnumerablePropertySource<KeyValueClient> {
|
||||
public class ConsulPropertySource extends EnumerablePropertySource<ConsulClient> {
|
||||
|
||||
private String context;
|
||||
|
||||
private Map<String, String> properties = new LinkedHashMap<>();
|
||||
|
||||
public ConsulPropertySource(String context, KeyValueClient source) {
|
||||
public ConsulPropertySource(String context, ConsulClient source) {
|
||||
super(context, source);
|
||||
this.context = context;
|
||||
|
||||
@@ -26,21 +30,26 @@ public class ConsulPropertySource extends EnumerablePropertySource<KeyValueClien
|
||||
}
|
||||
|
||||
public void init() {
|
||||
try {
|
||||
List<KeyValue> keyValues = source.getKeyValueRecurse(context);
|
||||
Response<List<GetValue>> response = source.getKVValues(context, QueryParams.DEFAULT);
|
||||
List<GetValue> values = response.getValue();
|
||||
|
||||
for (KeyValue keyValue : keyValues) {
|
||||
String key = keyValue.getKey()
|
||||
.replace(context, "")
|
||||
.replace('/', '.');
|
||||
String value = keyValue.getDecoded();
|
||||
if (values != null) {
|
||||
for (GetValue getValue : values) {
|
||||
String key = getValue.getKey()
|
||||
.replace(context, "")
|
||||
.replace('/', '.');
|
||||
String value = getDecoded(getValue.getValue());
|
||||
properties.put(key, value);
|
||||
}
|
||||
} catch (NotFoundException e) {
|
||||
//not found, do nothing
|
||||
}
|
||||
}
|
||||
|
||||
public String getDecoded(String value) {
|
||||
if (value == null)
|
||||
return null;
|
||||
return new String(base64().decode(value), UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
return properties.get(name);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package org.springframework.cloud.consul.config;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.config.client.PropertySourceLocator;
|
||||
import org.springframework.cloud.consul.ConsulProperties;
|
||||
import org.springframework.cloud.consul.client.KeyValueClient;
|
||||
import org.springframework.core.env.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -16,7 +16,7 @@ import java.util.List;
|
||||
public class ConsulPropertySourceLocator implements PropertySourceLocator {
|
||||
|
||||
@Autowired
|
||||
private KeyValueClient keyValueClient;
|
||||
private ConsulClient consul;
|
||||
|
||||
@Autowired
|
||||
private ConsulProperties properties;
|
||||
@@ -53,7 +53,7 @@ public class ConsulPropertySourceLocator implements PropertySourceLocator {
|
||||
}
|
||||
|
||||
private ConsulPropertySource create(String context) {
|
||||
return new ConsulPropertySource(context, keyValueClient);
|
||||
return new ConsulPropertySource(context, consul);
|
||||
}
|
||||
|
||||
private void addProfiles(List<String> contexts, String baseContext, List<String> profiles) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?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">
|
||||
<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>
|
||||
|
||||
<artifactId>spring-cloud-consul-core</artifactId>
|
||||
@@ -24,21 +25,13 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-slf4j</artifactId>
|
||||
<groupId>com.ecwid.consul</groupId>
|
||||
<artifactId>consul-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
@@ -51,10 +44,10 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package org.springframework.cloud.consul;
|
||||
|
||||
import feign.Feign;
|
||||
import feign.Logger;
|
||||
import feign.jackson.JacksonDecoder;
|
||||
import feign.jackson.JacksonEncoder;
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.consul.client.*;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -16,11 +12,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public class ConsulAutoConfiguration {
|
||||
protected Feign.Builder builder = Feign.builder()
|
||||
.logger(new Logger.JavaLogger())
|
||||
.errorDecoder(new ConsulErrorDecoder())
|
||||
.decoder(new JacksonDecoder())
|
||||
.encoder(new JacksonEncoder());
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@@ -30,32 +21,8 @@ public class ConsulAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AgentClient agentClient() {
|
||||
return builder.target(AgentClient.class, consulProperties().getUrl());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CatalogClient catalogClient() {
|
||||
return builder.target(CatalogClient.class, consulProperties().getUrl());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public KeyValueClient kvClient() {
|
||||
return builder.target(KeyValueClient.class, consulProperties().getUrl());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EventClient eventClient() {
|
||||
return builder.target(EventClient.class, consulProperties().getUrl());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EventService eventService() {
|
||||
return new EventService();
|
||||
public ConsulClient consulClient() {
|
||||
return new ConsulClient(consulProperties().getHost(), consulProperties().getPort());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package org.springframework.cloud.consul;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.QueryParams;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.agent.model.Service;
|
||||
import com.ecwid.consul.v1.catalog.model.CatalogService;
|
||||
import com.ecwid.consul.v1.catalog.model.Node;
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.consul.client.AgentClient;
|
||||
import org.springframework.cloud.consul.client.CatalogClient;
|
||||
import org.springframework.cloud.consul.client.KeyValueClient;
|
||||
import org.springframework.cloud.consul.model.KeyValue;
|
||||
import org.springframework.cloud.consul.model.Service;
|
||||
import org.springframework.cloud.consul.model.ServiceNode;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -22,13 +22,7 @@ import java.util.Map;
|
||||
public class ConsulEndpoint extends AbstractEndpoint<ConsulEndpoint.ConsulData> {
|
||||
|
||||
@Autowired
|
||||
KeyValueClient keyValueClient;
|
||||
|
||||
@Autowired
|
||||
CatalogClient catalogClient;
|
||||
|
||||
@Autowired
|
||||
AgentClient agentClient;
|
||||
private ConsulClient consul;
|
||||
|
||||
@Autowired
|
||||
public ConsulEndpoint() {
|
||||
@@ -39,25 +33,31 @@ public class ConsulEndpoint extends AbstractEndpoint<ConsulEndpoint.ConsulData>
|
||||
public ConsulData invoke() {
|
||||
ConsulData data = new ConsulData();
|
||||
//data.setKeyValues(kvClient.getKeyValueRecurse());
|
||||
data.setCatalogServices(catalogClient.getServices());
|
||||
Map<String, Service> services = agentClient.getServices();
|
||||
data.setAgentServices(services);
|
||||
Response<Map<String, Service>> agentServices = consul.getAgentServices();
|
||||
data.setAgentServices(agentServices.getValue());
|
||||
|
||||
for (String serviceId : services.keySet()) {
|
||||
data.getCatalogServiceNodes().put(serviceId, catalogClient.getServiceNodes(serviceId));
|
||||
Response<Map<String, List<String>>> catalogServices = consul.getCatalogServices(QueryParams.DEFAULT);
|
||||
|
||||
|
||||
for (String serviceId : catalogServices.getValue().keySet()) {
|
||||
Response<List<CatalogService>> response = consul.getCatalogService(serviceId, QueryParams.DEFAULT);
|
||||
data.getCatalogServices().put(serviceId, response.getValue());
|
||||
}
|
||||
|
||||
Response<List<Node>> catalogNodes = consul.getCatalogNodes(QueryParams.DEFAULT);
|
||||
data.setCatalogNodes(catalogNodes.getValue());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ConsulData {
|
||||
Map<String, List<String>> catalogServices;
|
||||
|
||||
Map<String, List<ServiceNode>> catalogServiceNodes = new LinkedHashMap<>();
|
||||
Map<String, List<CatalogService>> catalogServices = new LinkedHashMap<>();
|
||||
|
||||
Map<String, Service> agentServices;
|
||||
|
||||
List<KeyValue> keyValues;
|
||||
List<Node> catalogNodes;
|
||||
|
||||
//List<KeyValue> keyValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package org.springframework.cloud.consul;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.QueryParams;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.agent.model.Self;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.cloud.consul.client.CatalogClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -14,13 +17,16 @@ import java.util.Map;
|
||||
public class ConsulHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
@Autowired
|
||||
private CatalogClient catalogClient;
|
||||
private ConsulClient consul;
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
try {
|
||||
Map<String, List<String>> services = catalogClient.getServices();
|
||||
builder.up().withDetail("services", services);
|
||||
Response<Self> self = consul.getAgentSelf();
|
||||
Response<Map<String, List<String>>> services = consul.getCatalogServices(QueryParams.DEFAULT);
|
||||
builder.up()
|
||||
.withDetail("services", services.getValue())
|
||||
.withDetail("agent", self.getValue());
|
||||
} catch (Exception e) {
|
||||
builder.down(e);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ import java.util.List;
|
||||
@Data
|
||||
public class ConsulProperties {
|
||||
@NotNull
|
||||
private String url = "http://localhost:8500";
|
||||
private String host = "localhost";
|
||||
|
||||
@NotNull
|
||||
private int port = 8500;
|
||||
|
||||
private List<String> tags = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import feign.Param;
|
||||
import feign.RequestLine;
|
||||
import org.springframework.cloud.consul.model.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface AgentClient {
|
||||
@RequestLine("GET /v1/agent/services")
|
||||
Map<String, Service> getServices();
|
||||
|
||||
@RequestLine("GET /v1/agent/self")
|
||||
//TODO change map to an object
|
||||
Map<String, Object> getSelf();
|
||||
|
||||
@RequestLine("PUT /v1/agent/service/register")
|
||||
void register(Service service);
|
||||
|
||||
@RequestLine("PUT /v1/agent/service/deregister/{serviceId}")
|
||||
void deregister(@Param("serviceId") String serviceId);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import feign.Param;
|
||||
import feign.RequestLine;
|
||||
import org.springframework.cloud.consul.model.ServiceNode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface CatalogClient {
|
||||
@RequestLine("GET /v1/catalog/services")
|
||||
Map<String, List<String>> getServices();
|
||||
|
||||
@RequestLine("GET /v1/catalog/service/{serviceId}")
|
||||
List<ServiceNode> getServiceNodes(@Param("serviceId") String serviceId);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import feign.Response;
|
||||
import feign.codec.ErrorDecoder;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class ConsulErrorDecoder extends ErrorDecoder.Default {
|
||||
@Override
|
||||
public Exception decode(String methodKey, Response response) {
|
||||
if (response.status() == 404) {
|
||||
throw new NotFoundException(response);
|
||||
}
|
||||
return super.decode(methodKey, response);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import feign.Param;
|
||||
import feign.RequestLine;
|
||||
import feign.Response;
|
||||
import org.springframework.cloud.consul.model.Event;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface EventClient {
|
||||
//?node=, ?service=, and ?tag= ?dc=
|
||||
@RequestLine("PUT /v1/event/fire/{name}")
|
||||
Event fire(@Param("name") String name, String payload);
|
||||
|
||||
//?name=
|
||||
//?wait=<interval>&index=<idx>
|
||||
@RequestLine("GET /v1/event/list")
|
||||
List<Event> getEvents();
|
||||
|
||||
@RequestLine("GET /v1/event/list")
|
||||
Response getEventsResponse();
|
||||
|
||||
@RequestLine("GET /v1/event/list?wait={wait}&index={index}")
|
||||
Response watch(@Param("wait") String wait, @Param("index") String index);
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
import com.google.common.base.Throwables;
|
||||
import feign.Param;
|
||||
import feign.Response;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.consul.model.Event;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class EventService {
|
||||
|
||||
@Autowired
|
||||
protected EventClient client;
|
||||
|
||||
@Autowired(required = false)
|
||||
protected ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private AtomicReference<BigInteger> lastIndex = new AtomicReference<>();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
Response response = getEventsResponse();
|
||||
setLastIndex(response);
|
||||
}
|
||||
|
||||
private void setLastIndex(Response response) {
|
||||
Collection<String> header = response.headers().get("X-Consul-Index");
|
||||
if (header != null && header.iterator().hasNext()) {
|
||||
lastIndex.set(new BigInteger(header.iterator().next()));
|
||||
}
|
||||
}
|
||||
|
||||
public BigInteger getLastIndex() {
|
||||
return lastIndex.get();
|
||||
}
|
||||
|
||||
public Event fire(@Param("name") String name, String payload) {
|
||||
return client.fire(name, payload);
|
||||
}
|
||||
|
||||
public Response getEventsResponse() {
|
||||
return client.getEventsResponse();
|
||||
}
|
||||
|
||||
public List<Event> getEvents() {
|
||||
return client.getEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* from https://github.com/armon/consul-api/blob/master/event.go#L92-L104
|
||||
// IDToIndex is a bit of a hack. This simulates the index generation to
|
||||
// convert an event ID into a WaitIndex.
|
||||
func (e *Event) IDToIndex(uuid string) uint64 {
|
||||
lower := uuid[0:8] + uuid[9:13] + uuid[14:18]
|
||||
upper := uuid[19:23] + uuid[24:36]
|
||||
lowVal, err := strconv.ParseUint(lower, 16, 64)
|
||||
if err != nil {
|
||||
panic("Failed to convert " + lower)
|
||||
}
|
||||
highVal, err := strconv.ParseUint(upper, 16, 64)
|
||||
if err != nil {
|
||||
panic("Failed to convert " + upper)
|
||||
}
|
||||
return lowVal ^ highVal
|
||||
//^ bitwise XOR integers
|
||||
}
|
||||
*/
|
||||
public BigInteger toIndex(String eventId) {
|
||||
String lower = eventId.substring(0, 8) + eventId.substring(9, 13) + eventId.substring(14, 18);
|
||||
String upper = eventId.substring(19, 23) + eventId.substring(24, 36);
|
||||
BigInteger lowVal = new BigInteger(lower, 16);
|
||||
BigInteger highVal = new BigInteger(upper, 16);
|
||||
BigInteger index = lowVal.xor(highVal);
|
||||
return index;
|
||||
}
|
||||
|
||||
public List<Event> getEvents(BigInteger lastIndex) {
|
||||
return filterEvents(readEvents(getEventsResponse()), lastIndex);
|
||||
}
|
||||
|
||||
public List<Event> watch() {
|
||||
return watch(lastIndex.get());
|
||||
}
|
||||
|
||||
public List<Event> watch(BigInteger lastIndex) {
|
||||
//TODO: parameterized or configurable watch time
|
||||
return filterEvents(readEvents(client.watch("2s", lastIndex.toString())), lastIndex);
|
||||
}
|
||||
|
||||
protected List<Event> readEvents(Response response) {
|
||||
try {
|
||||
setLastIndex(response);
|
||||
return objectMapper.readValue(response.body().asInputStream(),
|
||||
TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, Event.class));
|
||||
} catch (IOException e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* from https://github.com/hashicorp/consul/blob/master/watch/funcs.go#L169-L194
|
||||
*/
|
||||
protected List<Event> filterEvents(List<Event> toFilter, BigInteger lastIndex) {
|
||||
List<Event> events = toFilter;
|
||||
if (lastIndex != null) {
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
Event event = events.get(i);
|
||||
BigInteger eventIndex = toIndex(event.getId());
|
||||
if (eventIndex.equals(lastIndex)) {
|
||||
events = events.subList(i + 1, events.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import feign.Param;
|
||||
import feign.RequestLine;
|
||||
import org.springframework.cloud.consul.model.KeyValue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface KeyValueClient {
|
||||
@RequestLine("GET /v1/kv/{key}")
|
||||
List<KeyValue> getKeyValue(@Param("key") String key);
|
||||
|
||||
@RequestLine("GET /v1/kv/?recurse=true")
|
||||
List<KeyValue> getKeyValueRecurse();
|
||||
|
||||
@RequestLine("GET /v1/kv/{key}?recurse=true")
|
||||
List<KeyValue> getKeyValueRecurse(@Param("key") String key);
|
||||
|
||||
@RequestLine("GET /v1/kv/?keys=true")
|
||||
List<String> getKeys();
|
||||
|
||||
@RequestLine("GET /v1/kv/{key}?keys=true")
|
||||
List<String> getKeys(@Param("key") String key);
|
||||
|
||||
@RequestLine("PUT /v1/kv/{key}")
|
||||
boolean put(@Param("key") String key, Object value);
|
||||
|
||||
@RequestLine("DELETE /v1/kv/{key}")
|
||||
void delete(@Param("key") String key);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import feign.Response;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
public class NotFoundException extends RuntimeException {
|
||||
private final Response response;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.springframework.cloud.consul.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
public class Check {
|
||||
@JsonProperty("Script")
|
||||
private String script;
|
||||
|
||||
@JsonProperty("Interval")
|
||||
private int interval;
|
||||
|
||||
@JsonProperty("TTL")
|
||||
private int ttl;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package org.springframework.cloud.consul.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import static com.google.common.base.Charsets.UTF_8;
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* Example:
|
||||
* "ID": "b54fe110-7af5-cafc-d1fb-afc8ba432b1c",
|
||||
"Name": "deploy",
|
||||
"Payload": null,
|
||||
"NodeFilter": "",
|
||||
"ServiceFilter": "",
|
||||
"TagFilter": "",
|
||||
"Version": 1,
|
||||
"LTime": 0
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Event {
|
||||
@JsonProperty("ID")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("Name")
|
||||
private String name;
|
||||
|
||||
@JsonProperty("NodeFilter")
|
||||
private String nodeFilter;
|
||||
|
||||
@JsonProperty("ServiceFilter")
|
||||
private String serviceFilter;
|
||||
|
||||
@JsonProperty("TagFilter")
|
||||
private String tagFilter;
|
||||
|
||||
@JsonProperty("Version")
|
||||
private Long version;
|
||||
|
||||
@JsonProperty("LTime")
|
||||
private Long lTime;
|
||||
|
||||
@JsonProperty("Payload")
|
||||
private String payload;
|
||||
|
||||
public String getDecoded() {
|
||||
if (payload == null)
|
||||
return null;
|
||||
return new String(base64().decode(payload), UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this)
|
||||
.add("id", id)
|
||||
.add("name", name)
|
||||
.add("nodeFilter", nodeFilter)
|
||||
.add("serviceFilter", serviceFilter)
|
||||
.add("tagFilter", tagFilter)
|
||||
.add("version", version)
|
||||
.add("lTime", lTime)
|
||||
.add("payload", payload)
|
||||
.add("decodedPayload", getDecoded())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package org.springframework.cloud.consul.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import static com.google.common.base.Charsets.UTF_8;
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
public class KeyValue {
|
||||
@JsonProperty("Key")
|
||||
private String key;
|
||||
|
||||
@JsonProperty("Value")
|
||||
private String value;
|
||||
|
||||
@JsonProperty("CreateIndex")
|
||||
private Long createIndex;
|
||||
|
||||
@JsonProperty("ModifyIndex")
|
||||
private Long modifyIndex;
|
||||
|
||||
@JsonProperty("Flags")
|
||||
private Long flags;
|
||||
|
||||
//TODO: use jackson to do the encoded/decoding
|
||||
public String getDecoded() {
|
||||
if (value == null)
|
||||
return null;
|
||||
return new String(base64().decode(value), UTF_8);
|
||||
}
|
||||
|
||||
public void setUnencoded(String unencoded) {
|
||||
setValue(base64().encode(unencoded.getBytes(UTF_8)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this)
|
||||
.add("key", key)
|
||||
.add("value", value)
|
||||
.add("decodedValue", getDecoded())
|
||||
.add("createIndex", createIndex)
|
||||
.add("modifyIndex", modifyIndex)
|
||||
.add("flags", flags)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.springframework.cloud.consul.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Service {
|
||||
@JsonProperty("ID")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("Name")
|
||||
private String name;
|
||||
|
||||
@JsonProperty("Tags")
|
||||
private List<String> tags;
|
||||
|
||||
@JsonProperty("Port")
|
||||
private int port;
|
||||
|
||||
@JsonProperty("Check")
|
||||
private Check check;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.springframework.cloud.consul.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ServiceNode {
|
||||
@JsonProperty("Node")
|
||||
private String node;
|
||||
|
||||
@JsonProperty("Address")
|
||||
private String address;
|
||||
|
||||
@JsonProperty("ServiceID")
|
||||
private String serviceID;
|
||||
|
||||
@JsonProperty("ServiceName")
|
||||
private String serviceName;
|
||||
|
||||
@JsonProperty("ServiceTags")
|
||||
private List<String> serviceTags;
|
||||
|
||||
@JsonProperty("ServicePort")
|
||||
private int servicePort;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.consul.model.Check;
|
||||
import org.springframework.cloud.consul.model.Service;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* Date: 4/18/14
|
||||
* Time: 11:04 AM
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@SpringApplicationConfiguration(classes = TestClientConfiguration.class)
|
||||
public class AgentClientIT {
|
||||
|
||||
@Autowired
|
||||
AgentClient client;
|
||||
|
||||
@Test
|
||||
public void test001RegisterService() {
|
||||
Service service = new Service();
|
||||
service.setId("test1id");
|
||||
service.setName("test1Name");
|
||||
service.setPort(9999);
|
||||
service.setTags(Lists.newArrayList("test1tag1", "test1tag2"));
|
||||
Check check = new Check();
|
||||
check.setScript("/usr/local/bin/gtrue");
|
||||
check.setInterval(60);
|
||||
service.setCheck(check);
|
||||
client.register(service);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test002GetServices() {
|
||||
Map<String, Service> services = client.getServices();
|
||||
assertNotNull("services was null", services);
|
||||
assertFalse("services was empty", services.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test003DeregisterService() {
|
||||
client.deregister("test1id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test004GetSelf() {
|
||||
Map<String, Object> self = client.getSelf();
|
||||
assertNotNull("self was null", self);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.consul.model.ServiceNode;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* Date: 4/18/14
|
||||
* Time: 11:04 AM
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = TestClientConfiguration.class)
|
||||
public class CatalogClientIT {
|
||||
|
||||
@Autowired
|
||||
CatalogClient client;
|
||||
|
||||
@Test
|
||||
public void testGetServices() {
|
||||
Map<String, List<String>> services = client.getServices();
|
||||
assertNotNull("services is null", services);
|
||||
assertTrue("No consul key", services.containsKey("consul"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetService() {
|
||||
List<ServiceNode> serviceNodes = client.getServiceNodes("consul");
|
||||
assertNotNull("serviceNodes is null", serviceNodes);
|
||||
assertFalse("serviceNodes is empty", serviceNodes.isEmpty());
|
||||
|
||||
ServiceNode node = serviceNodes.get(0);
|
||||
|
||||
assertNotNull("address is null", node.getAddress());
|
||||
assertNotNull("node is null", node.getNode());
|
||||
assertNotNull("serviceId is null", node.getServiceID());
|
||||
assertNotNull("serviceName is null", node.getServiceName());
|
||||
assertTrue("servicePort is wrong", node.getServicePort() > 0);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.consul.model.Event;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = TestClientConfiguration.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class EventClientIT {
|
||||
|
||||
public static final String NAME = "testEvent";
|
||||
public static final String PAYLOAD = "TestPayload." + System.currentTimeMillis();
|
||||
|
||||
@Autowired
|
||||
private EventClient client;
|
||||
|
||||
@Test
|
||||
public void test001Fire() {
|
||||
Event event = client.fire(NAME, PAYLOAD);
|
||||
assertNotNull("Event was null", event);
|
||||
assertNotNull("Event Id was null", event.getId());
|
||||
assertEquals("Event name was wrong", NAME, event.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test002Get() {
|
||||
List<Event> values = client.getEvents();
|
||||
assertNotNull("events is null", values);
|
||||
assertFalse("Values is empty", values.isEmpty());
|
||||
/*assertTrue("Values is not size 1", values.size() == 1);
|
||||
KeyValue keyValue = values.get(0);
|
||||
//TODO: how to deal with this?
|
||||
String decoded = objectMapper.readValue(keyValue.getDecoded(), String.class);
|
||||
|
||||
assertEquals(decoded, VALUE);*/
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.consul.model.Event;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = TestClientConfiguration.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class EventServiceIT {
|
||||
|
||||
@Autowired
|
||||
private EventService service;
|
||||
|
||||
@Test
|
||||
public void test001InitialIndex() {
|
||||
assertNotNull("initialIndex was null", service.getLastIndex());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test002ToIndex() {
|
||||
String eventId = "bf24ae36-d240-9666-7343-1a87346d2f94";
|
||||
BigInteger index = service.toIndex(eventId);
|
||||
assertEquals("wrong index generated", new BigInteger("14728939782502463986"), index);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test003GetEvents() {
|
||||
Event event = service.fire("testEvent", "test003GetEvents" + System.currentTimeMillis());
|
||||
assertNotNull("event was null", event);
|
||||
|
||||
List<Event> events = service.getEvents(service.getLastIndex());
|
||||
assertNotNull("events was null", events);
|
||||
assertFalse("events was empty", events.isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.consul.model.KeyValue;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = TestClientConfiguration.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class KeyValueClientIT {
|
||||
|
||||
public static final String KEY = "test/testkey";
|
||||
public static final String VALUE = "TestPut." + System.currentTimeMillis();
|
||||
|
||||
@Autowired
|
||||
KeyValueClient keyValueClient;
|
||||
|
||||
@Autowired(required = false)
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
public void test001Put() {
|
||||
|
||||
boolean actual = keyValueClient.put(KEY, VALUE);
|
||||
assertTrue("Invalid resposne", actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test002Get() throws IOException {
|
||||
List<KeyValue> values = keyValueClient.getKeyValue(KEY);
|
||||
assertNotNull("values is null", values);
|
||||
assertFalse("Values is null", values.isEmpty());
|
||||
assertTrue("Values is not size 1", values.size() == 1);
|
||||
KeyValue keyValue = values.get(0);
|
||||
//TODO: how to deal with this?
|
||||
String decoded = objectMapper.readValue(keyValue.getDecoded(), String.class);
|
||||
|
||||
assertEquals(decoded, VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test003GetKeyRecurse() {
|
||||
List<KeyValue> values = keyValueClient.getKeyValueRecurse(KEY);
|
||||
assertNotNull("values is null", values);
|
||||
assertFalse("Values is null", values.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test004GetRecurse() {
|
||||
List<KeyValue> values = keyValueClient.getKeyValueRecurse();
|
||||
assertNotNull("values is null", values);
|
||||
assertFalse("Values is null", values.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test005Delete() {
|
||||
keyValueClient.delete(KEY);
|
||||
}
|
||||
|
||||
@Test(expected = NotFoundException.class)
|
||||
public void test006KeyNotFound() {
|
||||
keyValueClient.getKeyValue(System.currentTimeMillis()+"a123");
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package org.springframework.cloud.consul.client;
|
||||
|
||||
import org.springframework.cloud.consul.ConsulAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@Import(ConsulAutoConfiguration.class)
|
||||
public class TestClientConfiguration {
|
||||
}
|
||||
@@ -47,6 +47,10 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package org.springframework.cloud.consul.discovery;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.consul.client.AgentClient;
|
||||
import org.springframework.cloud.consul.client.CatalogClient;
|
||||
import org.springframework.cloud.consul.model.Service;
|
||||
import org.springframework.cloud.consul.model.ServiceNode;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -27,10 +24,7 @@ public class ConsulDiscoveryClient implements DiscoveryClient {
|
||||
ApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
AgentClient agentClient;
|
||||
|
||||
@Autowired
|
||||
CatalogClient catalogClient;
|
||||
ConsulClient client;
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
@@ -39,7 +33,7 @@ public class ConsulDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
@Override
|
||||
public ServiceInstance getLocalServiceInstance() {
|
||||
Map<String, Service> services = agentClient.getServices();
|
||||
/*Map<String, Service> services = agentClient.getServices();
|
||||
Service service = services.get(context.getId());
|
||||
if (service == null) {
|
||||
throw new IllegalStateException("Unable to locate service in consul agent: "+context.getId());
|
||||
@@ -52,12 +46,13 @@ public class ConsulDiscoveryClient implements DiscoveryClient {
|
||||
host = (String) member.get("Name");
|
||||
}
|
||||
}
|
||||
return new DefaultServiceInstance(service.getId(), host, service.getPort());
|
||||
return new DefaultServiceInstance(service.getId(), host, service.getPort());*/
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(final String serviceId) {
|
||||
List<ServiceNode> nodes = catalogClient.getServiceNodes(serviceId);
|
||||
/*List<ServiceNode> nodes = catalogClient.getServiceNodes(serviceId);
|
||||
Iterable<ServiceInstance> instances = transform(nodes, new Function<ServiceNode, ServiceInstance>() {
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -66,12 +61,13 @@ public class ConsulDiscoveryClient implements DiscoveryClient {
|
||||
}
|
||||
});
|
||||
|
||||
return Lists.newArrayList(instances);
|
||||
return Lists.newArrayList(instances);*/
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getAllInstances() {
|
||||
Iterable<ServiceInstance> instances = transform(concat(transform(catalogClient.getServices().keySet(), new Function<String, List<ServiceNode>>() {
|
||||
/*Iterable<ServiceInstance> instances = transform(concat(transform(catalogClient.getServices().keySet(), new Function<String, List<ServiceNode>>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public List<ServiceNode> apply(@Nullable String input) {
|
||||
@@ -85,11 +81,13 @@ public class ConsulDiscoveryClient implements DiscoveryClient {
|
||||
}
|
||||
});
|
||||
|
||||
return Lists.newArrayList(instances);
|
||||
return Lists.newArrayList(instances);*/
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
return Lists.newArrayList(catalogClient.getServices().keySet());
|
||||
//return Lists.newArrayList(catalogClient.getServices().keySet());
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package org.springframework.cloud.consul.discovery;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.agent.model.NewService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.client.discovery.AbstractDiscoveryLifecycle;
|
||||
import org.springframework.cloud.consul.ConsulProperties;
|
||||
import org.springframework.cloud.consul.client.AgentClient;
|
||||
import org.springframework.cloud.consul.model.Service;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -14,15 +14,16 @@ import org.springframework.cloud.consul.model.Service;
|
||||
public class ConsulLifecycle extends AbstractDiscoveryLifecycle {
|
||||
|
||||
@Autowired
|
||||
private AgentClient agentClient;
|
||||
private ConsulClient client;
|
||||
|
||||
@Autowired
|
||||
private ConsulProperties consulProperties;
|
||||
|
||||
@Override
|
||||
protected void register() {
|
||||
Service service = new Service();
|
||||
NewService service = new NewService();
|
||||
String appName = getAppName();
|
||||
//TODO: move id to properties with context ID as default
|
||||
service.setId(getContext().getId());
|
||||
service.setName(appName);
|
||||
//TODO: support port = 0 random assignment
|
||||
@@ -36,7 +37,7 @@ public class ConsulLifecycle extends AbstractDiscoveryLifecycle {
|
||||
|
||||
@Override
|
||||
protected void registerManagement() {
|
||||
Service management = new Service();
|
||||
NewService management = new NewService();
|
||||
management.setId(getManagementServiceId());
|
||||
management.setName(getManagementServiceName());
|
||||
management.setPort(getManagementPort());
|
||||
@@ -45,9 +46,9 @@ public class ConsulLifecycle extends AbstractDiscoveryLifecycle {
|
||||
register(management);
|
||||
}
|
||||
|
||||
protected void register(Service service) {
|
||||
protected void register(NewService service) {
|
||||
log.info("Registering service with consul: {}", service.toString());
|
||||
agentClient.register(service);
|
||||
client.agentServiceRegister(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +67,7 @@ public class ConsulLifecycle extends AbstractDiscoveryLifecycle {
|
||||
}
|
||||
|
||||
private void deregister(String serviceId) {
|
||||
agentClient.deregister(serviceId);
|
||||
client.agentServiceDeregister(serviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.springframework.cloud.consul.discovery;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.netflix.client.config.DefaultClientConfigImpl;
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
@@ -9,7 +10,6 @@ import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
|
||||
import org.springframework.cloud.consul.client.CatalogClient;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
@@ -24,7 +24,7 @@ public class ConsulLoadBalancerClient implements LoadBalancerClient {
|
||||
private ConcurrentHashMap<String, IClientConfig> namedClientConfigs = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
CatalogClient catalogClient;
|
||||
ConsulClient client;
|
||||
|
||||
@Override
|
||||
public ServiceInstance choose(String serviceId) {
|
||||
@@ -44,7 +44,7 @@ public class ConsulLoadBalancerClient implements LoadBalancerClient {
|
||||
.withRule(new AvailabilityFilteringRule())
|
||||
//TODO: figure out ping
|
||||
//.withPing()
|
||||
.withDynamicServerList(new ConsulServerList(catalogClient, serviceId))
|
||||
//FIXME: .withDynamicServerList(new ConsulServerList(catalogClient, serviceId))
|
||||
.buildDynamicServerListLoadBalancer();
|
||||
namedLoadBalancers.put(serviceId, lb);
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ import static com.netflix.client.config.CommonClientConfigKey.*;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.cloud.consul.client.CatalogClient;
|
||||
import org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -46,7 +46,7 @@ import com.netflix.loadbalancer.ZoneAvoidanceRule;
|
||||
@Configuration
|
||||
public class ConsulRibbonClientConfiguration implements BeanPostProcessor {
|
||||
@Autowired
|
||||
CatalogClient client;
|
||||
private ConsulClient client;
|
||||
|
||||
@Value("${ribbon.client.name}")
|
||||
private String serviceId = "client";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.springframework.cloud.consul.discovery;
|
||||
|
||||
import com.ecwid.consul.v1.catalog.model.CatalogService;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import org.springframework.cloud.consul.model.ServiceNode;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -10,12 +10,12 @@ public class ConsulServer extends Server {
|
||||
|
||||
private final MetaInfo metaInfo;
|
||||
|
||||
public ConsulServer(final ServiceNode node) {
|
||||
super(node.getNode(), node.getServicePort());
|
||||
public ConsulServer(final CatalogService service) {
|
||||
super(service.getNode(), service.getServicePort());
|
||||
metaInfo = new MetaInfo() {
|
||||
@Override
|
||||
public String getAppName() {
|
||||
return node.getServiceName();
|
||||
return service.getServiceName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -30,7 +30,7 @@ public class ConsulServer extends Server {
|
||||
|
||||
@Override
|
||||
public String getInstanceId() {
|
||||
return node.getServiceID();
|
||||
return service.getServiceId();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package org.springframework.cloud.consul.discovery;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.QueryParams;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.catalog.model.CatalogService;
|
||||
import com.google.common.base.Function;
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.AbstractServerList;
|
||||
import org.springframework.cloud.consul.client.CatalogClient;
|
||||
import org.springframework.cloud.consul.model.ServiceNode;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
@@ -19,19 +21,19 @@ import static com.google.common.collect.Lists.newArrayList;
|
||||
*/
|
||||
public class ConsulServerList extends AbstractServerList<ConsulServer> {
|
||||
|
||||
private CatalogClient client;
|
||||
private ConsulClient client;
|
||||
|
||||
private String serviceId;
|
||||
|
||||
public ConsulServerList() {
|
||||
}
|
||||
|
||||
public ConsulServerList(CatalogClient client, String serviceId) {
|
||||
public ConsulServerList(ConsulClient client, String serviceId) {
|
||||
this.client = client;
|
||||
this.serviceId = serviceId;
|
||||
}
|
||||
|
||||
public void setClient(CatalogClient client) {
|
||||
public void setClient(ConsulClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@@ -54,15 +56,15 @@ public class ConsulServerList extends AbstractServerList<ConsulServer> {
|
||||
if (client == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<ServiceNode> nodes = client.getServiceNodes(serviceId);
|
||||
if (nodes == null || nodes.isEmpty()) {
|
||||
Response<List<CatalogService>> response = client.getCatalogService(this.serviceId, QueryParams.DEFAULT);
|
||||
if (response.getValue() == null || response.getValue().isEmpty()) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
Collection<ConsulServer> servers = transform(nodes, new Function<ServiceNode, ConsulServer>() {
|
||||
Collection<ConsulServer> servers = transform(response.getValue(), new Function<CatalogService, ConsulServer>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public ConsulServer apply(@Nullable ServiceNode node) {
|
||||
ConsulServer server = new ConsulServer(node);
|
||||
public ConsulServer apply(@Nullable CatalogService service) {
|
||||
ConsulServer server = new ConsulServer(service);
|
||||
return server;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.springframework.cloud.consul.discovery;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.agent.model.Service;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.consul.ConsulAutoConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@SpringApplicationConfiguration(classes = TestConfig.class)
|
||||
@IntegrationTest({"server.port=0", "spring.application.name=myTestService"})
|
||||
@WebAppConfiguration
|
||||
public class ConsulLifecycleTests {
|
||||
|
||||
@Autowired
|
||||
ConsulLifecycle lifecycle;
|
||||
|
||||
@Autowired
|
||||
ConsulClient consul;
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
Response<Map<String, Service>> response = consul.getAgentServices();
|
||||
Map<String, Service> services = response.getValue();
|
||||
Service service = services.get(context.getId());
|
||||
assertNotNull("service was null", service);
|
||||
assertEquals("service id was wrong", service.getId(), context.getId());
|
||||
assertEquals("service name was wrong", service.getService(), "myTestService");
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@Import({ConsulAutoConfiguration.class, ConsulDiscoveryClientConfiguration.class})
|
||||
class TestConfig {
|
||||
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
@@ -37,6 +38,7 @@ import java.lang.annotation.*;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = SidecarApplicationTests.SidecarApplication.class)
|
||||
@IntegrationTest("server.port=0")
|
||||
@WebAppConfiguration
|
||||
public class SidecarApplicationTests {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -28,10 +28,12 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = ZuulApplicationTests.ZuulApplication.class)
|
||||
@IntegrationTest("server.port=0")
|
||||
@WebAppConfiguration
|
||||
public class ZuulApplicationTests {
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user