diff --git a/.bettercodehub.yml b/.bettercodehub.yml new file mode 100644 index 0000000..dc42046 --- /dev/null +++ b/.bettercodehub.yml @@ -0,0 +1 @@ +component_depth: 9 diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..d3dd412 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,95 @@ +version: 2.1 + +# ----------------------------------------------------------------------------- +# YAML Anchors +# ----------------------------------------------------------------------------- + +_anchors: + - &mvn-cache-key consul-{{ .Branch }}-{{ checksum "pom.xml" }} + - &mvn-cache-key-fallback consul-{{ .Branch }} + + - &build-image cimg/openjdk:8.0 + + - &default-env + MAVEN_CONFIG_DIR: .circleci/mvn + +# ----------------------------------------------------------------------------- +# Jobs +# ----------------------------------------------------------------------------- + +jobs: + + # jobs: build --------------------------------------------------------------- + + build: + docker: [ image: *build-image ] + steps: + - checkout + + - restore_cache: + keys: [ *mvn-cache-key, *mvn-cache-key-fallback ] + + - run: mvn verify + + - save_cache: + paths: [ ~/.m2 ] + key: *mvn-cache-key + + # jobs: deploy -------------------------------------------------------------- + + deploy: + docker: [ image: *build-image ] + steps: + - checkout + + - run: + name: Install GPG signing keys + environment: + <<: *default-env + GPG_KEY_FILENAME: codesigning.asc + command: | + openssl aes-256-cbc -d -a -in ${MAVEN_CONFIG_DIR}/${GPG_KEY_FILENAME}.enc -out ${MAVEN_CONFIG_DIR}/${GPG_KEY_FILENAME} -k "${ENCRYPTION_KEY}" + gpg --batch --fast-import ${MAVEN_CONFIG_DIR}/${GPG_KEY_FILENAME} + + - restore_cache: + keys: [ *mvn-cache-key, *mvn-cache-key-fallback ] + + - run: + name: mvn deploy + environment: + <<: *default-env + command: | + export GPG_TTY=$(tty) + mvn -B -s ${MAVEN_CONFIG_DIR}/settings.xml -Dstyle.color=always -Dmaven.install.skip deploy + + - save_cache: + paths: [ ~/.m2 ] + key: *mvn-cache-key + + +# ----------------------------------------------------------------------------- +# Workflows +# ----------------------------------------------------------------------------- + +workflows: + + version: 2 + + # workflow: pr-check -------------------------------------------------------- + + pr-check: + jobs: + - build: + filters: + branches: + ignore: master + + # workflow: master ---------------------------------------------------------- + + deploy: + jobs: + - deploy: + context: ossrh + filters: + branches: + only: master diff --git a/.circleci/mvn/codesigning.asc.enc b/.circleci/mvn/codesigning.asc.enc new file mode 100644 index 0000000..13b708f --- /dev/null +++ b/.circleci/mvn/codesigning.asc.enc @@ -0,0 +1,157 @@ +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 diff --git a/.circleci/mvn/settings.xml b/.circleci/mvn/settings.xml new file mode 100644 index 0000000..99cc307 --- /dev/null +++ b/.circleci/mvn/settings.xml @@ -0,0 +1,27 @@ + + + + + + ossrh + ${env.OSSRH_USERNAME} + ${env.OSSRH_PASSWORD} + + + + + + ossrh + + true + + + gpg + ${env.GPG_KEYNAME} + ${env.GPG_PASSPHRASE} + + + + + diff --git a/.gitignore b/.gitignore index 8360da6..2f7896d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1 @@ -.settings/ -.classpath -.project target/ diff --git a/.lgtm.yml b/.lgtm.yml new file mode 100644 index 0000000..21c370a --- /dev/null +++ b/.lgtm.yml @@ -0,0 +1,7 @@ +extraction: + java: + index: + java_version: 8 + xml_mode: ALL + maven: + version: 3.6.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index f61f3d1..d1a528b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,26 +6,28 @@ and this project adheres to [semantic versioning](https://semver.org/spec/v2.0.0 ## Unreleased -### Changed - -- Bump docker-java to 3.1.1 -- Rewritten discovery to utilise containers internal IPs and ports -- Renamed `@EnableConsul` to `@TCPHealthCheck` and its property `exposedPort` to `port` -- Renamed property `exposedPort` in `@WebHealthCheck` to `port` -- `@UseConsulDns` now sets the Consul container IP (instead of the Docker bridge one) as primary DNS for your containers and this makes it usable on MacOS +## 0.1.1 - (11 Nov 2020) +### Changed -### Removed - -- Goodbye to gliderlabs/registrator -- Goodbye to `qzagarese` in package names :-) + - Bumped `lombok` to version `1.8.16` + - Bumped `jackson` to version `2.11.3` + - Bumped `httpcore` to version `4.4.13` + - Introduced new system property called `consul.image` for overriding the default DockerHub Consul image + - Minor formatting changes -## 1.0.1 [01 Mar 2019] +## [0.1.0] - (01 Mar 2019) -### Added +### Changed -- New boolean flag `-Dconsul.dns.enabled` to disable consul DNS (fixes [#12](https://github.com/qzagarese/dockerunit/issues/12)) + - Bump docker-java to 3.1.1 + - Rewritten discovery to utilise containers internal IPs and ports + - Renamed `@EnableConsul` to `@TCPHealthCheck` and its property `exposedPort` to `port` + - Renamed property `exposedPort` in `@WebHealthCheck` to `port` + - `@UseConsulDns` now sets the Consul container IP (instead of the Docker bridge one) as primary DNS for your containers and this makes it usable on MacOS -## 1.0.0 [06 Feb 2019] +### Removed -_Initial Release_ + - Goodbye to gliderlabs/registrator + - Goodbye to `qzagarese` in package names :-) + - New boolean flag `-Dconsul.dns.enabled` to disable Consul DNS (fixes [#12](https://github.com/qzagarese/dockerunit/issues/12)) diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE diff --git a/README.md b/README.md index 1a88529..04ffc63 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,36 @@ -dockerunit-consul - A Consul based discovery provider for Dockerunit -=========================================================================== +[![CircleCI](https://img.shields.io/circleci/build/gh/dockerunit/dockerunit-consul/master.svg?style=flat)](https://circleci.com/gh/dockerunit/dockerunit-consul/tree/master) +  +[![Codacy](https://img.shields.io/codacy/coverage/22445615da7d47e8b50e17f937ca9b49.svg?style=flat)](https://app.codacy.com/project/dockerunit/dockerunit-consul/dashboard) +  +[![Coverity](https://img.shields.io/coverity/scan/18572.svg?style=flat)](https://scan.coverity.com/projects/dockerunit-dockerunit-consul) +  +[![License](https://img.shields.io/github/license/dockerunit/dockerunit-consul.svg?style=flat)](https://choosealicense.com/licenses/apache-2.0/) + +[![Codacy](https://img.shields.io/codacy/grade/22445615da7d47e8b50e17f937ca9b49.svg?style=flat&label=codacy)](https://app.codacy.com/project/dockerunit/dockerunit-consul/dashboard) +  +[![BetterCodeHub](https://bettercodehub.com/edge/badge/dockerunit/dockerunit-consul?branch=master)](https://bettercodehub.com/) +  +[![LGTM](https://img.shields.io/lgtm/grade/java/github/dockerunit/dockerunit-consul.svg?style=flat&label=lgtm)](https://lgtm.com/projects/g/dockerunit/dockerunit-consul/context:java) +  +[![LGTM](https://img.shields.io/lgtm/alerts/github/dockerunit/dockerunit-consul.svg?style=flat&label=lgtm)](https://lgtm.com/projects/g/dockerunit/dockerunit-consul/alerts) + +[![Maven](https://img.shields.io/maven-central/v/com.github.dockerunit/dockerunit-consul.svg?style=flat)](https://search.maven.org/search?q=g:com.github.dockerunit%20AND%20a:dockerunit-consul&core=gav) +  +[![Javadoc](https://javadoc.io/badge/com.github.dockerunit/dockerunit-consul.svg)](https://www.javadoc.io/doc/com.github.dockerunit/dockerunit-consul) +  +[![Nexus](https://img.shields.io/nexus/s/https/oss.sonatype.org/com.github.dockerunit/dockerunit-consul.svg?style=flat)](https://oss.sonatype.org/index.html#nexus-search;gav~com.github.dockerunit~dockerunit-consul~~~) + +[![Discord](https://img.shields.io/discord/587583543081959435.svg?style=flat)](https://discordapp.com/channels/587583543081959435/587583543081959437) This module allows you to configure the discovery phase for the testing of your services. -Service Discovery is necessary for dockerunit to start and for your tests to execute successfully. +Service Discovery is necessary for dockerunit to start and for your tests to execute successfully. Usage (set `dockerunit.consul.version` property to the version you intend to use): ```xml com.github.dockerunit dockerunit-consul - ${dockerunit.consul.version} + ${dockerunit.version} test ``` @@ -17,27 +38,26 @@ Usage (set `dockerunit.consul.version` property to the version you intend to use Discovery configuration can be specified by means of the following Java annotations: -- `@TCPHealthCheck`: A basic health-check that probes your container to check if it's +- `@TCPHealthCheck`: A basic health-check that probes your container to check if it's able to accept TCP connections. -- `@WebHealthCheck`: Health-check for HTTP/HTTPS services. Consul will consider the health-check as passing only +- `@WebHealthCheck`: Health-check for HTTP/HTTPS services. Consul will consider the health-check as passing only when it returns a 200 HTTP status code. -- `@UseConsulDns`: Injects the Consul container IP as a DNS server for your container(s). This allows -your services to reference other services by using their `dockerunit name`, which is the value -that you have set in the corresponding `@Named` annotation. +- `@UseConsulDns`: Injects the Consul container IP as a DNS server for your container(s). This allows +your services to reference other services by using their `dockerunit name`, which is the value +that you have set in the corresponding `@Svc` annotation. The last annotation can be better explained with an example. Say you have two services: `service-a` and `service-b`. Our test only talks to `service-a` which is a client of `service-b`. Both services listen on port `8080`. - + Hereafter the dockerunit descriptors for the two services: ```java -@Named("service-a") -@Image("service-a-image") +@Svc(name="service-a", image="service-a-image") @WebHealthCheck(port=8080) -@PortBinding(exposedPort=8080, hostPort=8080) +@PublishPort(host=8080, container=8080) @UseConsulDns public class DescriptorForA{} @@ -46,8 +66,12 @@ public class DescriptorForA{} @WebHealthCheck(port=8080) public class DescriptorForB{} ``` -- Because `service-a` is using `@UseConsulDns`, it can reference `service-b` +- Because `service-a` is using `@UseConsulDns`, it can reference `service-b` by using the `service-b.service.consul` name. -- `service-b` is not declaring any `@PortBinding` because our test does not need to talk to it. -Only `service-a` will talk to it, but it can do it by using the container IP to which -the `service-b.service.consul` name resolves to. +- `service-b` is not declaring any `@PublishPort` because our test does not need to talk to it. +Only `service-a` will talk to it, but it can do it by using the container IP to which +the `service-b.service.consul` name resolves to. + +--- +By default, the `dockerunit-consul` module uses Consul Docker image from DockerHub. +To override the default using a different Consul Docker image the System property `consul.image` can be provided. diff --git a/pom.xml b/pom.xml index 6c6d2bd..4931388 100644 --- a/pom.xml +++ b/pom.xml @@ -1,83 +1,134 @@ - + + + 4.0.0 com.github.dockerunit dockerunit-parent - 2.0.0-SNAPSHOT + 0.2.0-SNAPSHOT + dockerunit-consul - 2.0.0-SNAPSHOT - dockerunit-consul Java Framework for testing of dockerised applications and services. Consul based service discovery package. https://github.com/dockerunit/dockerunit-consul - - - - Quirino Zagarese - - - Pedro Nuno Santos - - - Vincenzo Candela - - - Francesco Sorice - - + + + scm:https://github.com/dockerunit/dockerunit-consul.git + scm:https://github.com/dockerunit/dockerunit-consul.git + https://github.com/dockerunit/dockerunit-consul.git + + - 2.0.0-SNAPSHOT - 1.16.6 + 1.18.16 + 2.11.3 + 3.2.7 + 4.5.12 + 4.4.13 - - - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - + + + + com.fasterxml.jackson + jackson-bom + ${jackson.version} + import + pom + + + - - com.github.dockerunit - dockerunit-core - ${dockerunit.core.version} - org.projectlombok lombok ${lombok.version} provided + + ${project.groupId} + dockerunit-core + ${project.version} + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + com.github.docker-java + docker-java-api + ${docker-java.version} + + + com.github.docker-java + docker-java-core + ${docker-java.version} + runtime + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-logging + commons-logging + + + + + org.slf4j + jcl-over-slf4j + runtime + + + + ossrh-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + maven-compiler-plugin - - org.sonatype.plugins - nexus-staging-maven-plugin + maven-surefire-plugin - - maven-source-plugin + org.jacoco + jacoco-maven-plugin - - maven-javadoc-plugin + maven-source-plugin - - maven-gpg-plugin + maven-javadoc-plugin - + diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ConsulDescriptor.java b/src/main/java/com/github/dockerunit/discovery/consul/ConsulDescriptor.java index b42724e..70dea16 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ConsulDescriptor.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ConsulDescriptor.java @@ -1,5 +1,11 @@ package com.github.dockerunit.discovery.consul; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.logging.Logger; + import com.github.dockerjava.api.command.CreateContainerCmd; import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.HostConfig; @@ -9,42 +15,37 @@ import com.github.dockerunit.core.annotation.Svc; import com.github.dockerunit.discovery.consul.annotation.UseConsulDns; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Logger; - -import static com.github.dockerunit.discovery.consul.ConsulDiscoveryConfig.CONSUL_DNS_ENABLED_DEFAULT; -import static com.github.dockerunit.discovery.consul.ConsulDiscoveryConfig.CONSUL_DNS_ENABLED_PROPERTY; - -@Svc(name = "consul", image = "consul:1.4.4") +@Svc(name = "consul", image = "") public class ConsulDescriptor { + private static final Logger logger = Logger.getLogger(ConsulDescriptor.class.getSimpleName()); static final int CONSUL_DNS_PORT = 53; static final int CONSUL_PORT = 8500; - private static final Logger logger = Logger.getLogger(ConsulDescriptor.class.getSimpleName()); - - @ContainerBuilder public CreateContainerCmd setup(CreateContainerCmd cmd) { - List ports = new ArrayList<>(Arrays.asList(cmd.getExposedPorts())); + List ports = new ArrayList<>(Arrays.asList(Objects.requireNonNull(cmd.getExposedPorts()))); ExposedPort consulPort = ExposedPort.tcp(CONSUL_PORT); ports.add(consulPort); - - Ports bindings = cmd.getHostConfig().getPortBindings(); + + Ports bindings = Objects.requireNonNull(cmd.getHostConfig()).getPortBindings(); if (bindings == null) { bindings = new Ports(); } - boolean enableDnsFlag = Boolean.parseBoolean(System.getProperty(CONSUL_DNS_ENABLED_PROPERTY, CONSUL_DNS_ENABLED_DEFAULT)); + boolean enableDnsFlag = Boolean.parseBoolean( + System.getProperty( + ConsulDiscoveryConfig.CONSUL_DNS_ENABLED_PROPERTY, + ConsulDiscoveryConfig.CONSUL_DNS_ENABLED_DEFAULT) + ); - if(enableDnsFlag) { + if (enableDnsFlag) { activateDns(ports); } else { - logger.warning("Consul DNS has been disabled. Usages of @" + UseConsulDns.class.getSimpleName() + " will be ignored."); + logger.warning("Consul DNS has been disabled. Usages of @" + UseConsulDns.class.getSimpleName() + + " will be ignored."); } bindings.bind(consulPort, Binding.bindPort(8500)); @@ -53,13 +54,19 @@ public CreateContainerCmd setup(CreateContainerCmd cmd) { return cmd.withHostConfig(hc) .withExposedPorts(ports) + .withImage( + System.getProperty( + ConsulDiscoveryConfig.CONSUL_IMAGE, + ConsulDiscoveryConfig.CONSUL_DEFAULT_IMAGE + ) + ) .withCmd("sh", "-c", "exec consul agent -dev -client=0.0.0.0 -enable-script-checks -dns-port=53"); - } private void activateDns(List ports) { ExposedPort dnsPort = ExposedPort.udp(CONSUL_DNS_PORT); ports.add(dnsPort); } + } diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryConfig.java b/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryConfig.java index 00f91ab..74edba6 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryConfig.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryConfig.java @@ -1,21 +1,26 @@ package com.github.dockerunit.discovery.consul; -import com.github.dockerunit.core.annotation.WithSvc; - import static com.github.dockerunit.discovery.consul.ConsulDiscoveryConfig.CONSUL_CONTAINER_NAME; -@WithSvc(svc =ConsulDescriptor.class, containerNamePrefix =CONSUL_CONTAINER_NAME) +import com.github.dockerunit.core.annotation.WithSvc; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@WithSvc(svc = ConsulDescriptor.class, containerNamePrefix = CONSUL_CONTAINER_NAME) public class ConsulDiscoveryConfig { - public static final String DOCKER_BRIDGE_IP_PROPERTY = "docker.bridge.ip"; - public static final String DOCKER_BRIDGE_IP_DEFAULT = "172.17.42.1"; - public static final String DOCKER_HOST_PROPERTY = "docker.host"; - public static final String SERVICE_DISCOVERY_TIMEOUT = "service.discovery.timeout"; - public static final String SERVICE_DISCOVERY_TIMEOUT_DEFAULT = "30"; - public static final String CONSUL_POLLING_PERIOD = "consul.polling.period"; - public static final String CONSUL_POLLING_PERIOD_DEFAULT = "1"; - public static final String CONSUL_DNS_ENABLED_PROPERTY = "consul.dns.enabled"; - public static final String CONSUL_DNS_ENABLED_DEFAULT = "true"; - public static final String CONSUL_CONTAINER_NAME = "consul"; + public static final String DOCKER_BRIDGE_IP_PROPERTY = "docker.bridge.ip"; + public static final String DOCKER_BRIDGE_IP_DEFAULT = "172.17.42.1"; + public static final String DOCKER_HOST_PROPERTY = "docker.host"; + public static final String SERVICE_DISCOVERY_TIMEOUT = "service.discovery.timeout"; + public static final String SERVICE_DISCOVERY_TIMEOUT_DEFAULT = "30"; + public static final String CONSUL_POLLING_PERIOD = "consul.polling.period"; + public static final String CONSUL_POLLING_PERIOD_DEFAULT = "1"; + public static final String CONSUL_DNS_ENABLED_PROPERTY = "consul.dns.enabled"; + public static final String CONSUL_DNS_ENABLED_DEFAULT = "true"; + public static final String CONSUL_CONTAINER_NAME = "consul"; + public static final String CONSUL_IMAGE = "consul.image"; + public static final String CONSUL_DEFAULT_IMAGE = "consul:1.4.4"; } diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryProvider.java b/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryProvider.java index ff66140..e9518b5 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryProvider.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryProvider.java @@ -83,8 +83,11 @@ private Service doDiscovery(Service s) { Set withPorts = s.getInstances().stream() .map(si -> { InspectContainerResponse r = dockerClient.inspectContainerCmd(si.getContainerId()).exec(); - return si.withPort(findPort(r, records).orElse(0)) - .withIp(DOCKER_HOST) + return si.withGatewayPort(findPort(r, records).orElse(0)) + .withContainerPort(records.stream().findFirst().map(sr -> sr.getPort()).orElse(0)) + .withGatewayAddress(DOCKER_HOST) + .withContainerName(r.getName()) + .withContainerIp(ContainerUtils.extractBridgeIpAddress(r.getNetworkSettings()).orElse("")) .withStatus(ServiceInstance.Status.DISCOVERED) .withStatusDetails("Discovered via consul"); }).collect(Collectors.toSet()); diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryProviderFactory.java b/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryProviderFactory.java index 3a3b992..6e65c70 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryProviderFactory.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ConsulDiscoveryProviderFactory.java @@ -5,9 +5,9 @@ public class ConsulDiscoveryProviderFactory implements DiscoveryProviderFactory { - @Override - public DiscoveryProvider getProvider() { - return new ConsulDiscoveryProvider(); - } + @Override + public DiscoveryProvider getProvider() { + return new ConsulDiscoveryProvider(); + } } diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ConsulRegistrator.java b/src/main/java/com/github/dockerunit/discovery/consul/ConsulRegistrator.java index 1215496..3d21230 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ConsulRegistrator.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ConsulRegistrator.java @@ -1,27 +1,24 @@ package com.github.dockerunit.discovery.consul; +import java.io.UnsupportedEncodingException; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.logging.Logger; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.model.Container; import org.apache.http.HttpResponse; -import org.apache.http.NoHttpResponseException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPut; -import org.apache.http.conn.HttpHostConnectException; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; -import java.io.UnsupportedEncodingException; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.logging.Logger; - public class ConsulRegistrator { public static final String ACCEPT = "Accept"; @@ -41,7 +38,6 @@ public class ConsulRegistrator { private final ObjectWriter objectWriter; private final ConsulServiceFactory svcFactory; - public ConsulRegistrator(DockerClient client, int pollingPeriod, String consulHost, int consulPort) { this.client = client; this.pollingPeriod = pollingPeriod; @@ -65,7 +61,7 @@ private void onDetectHook(Container container) { } private void onDestroyHook(Container container) { - if(container != null && services.containsKey(container.getId())) { + if (container != null && services.containsKey(container.getId())) { deregisterSvc(services.get(container.getId())); trackers.remove(container.getId()); services.remove(container.getId()); @@ -77,7 +73,7 @@ private void registerSvc(ConsulService svc) { try { executePut("/v1/agent/service/register", objectWriter.writeValueAsString(svc), errorMessage, - ex -> { + ex -> { throw new RuntimeException(errorMessage.get(), ex); }); } catch (JsonProcessingException e) { @@ -86,18 +82,22 @@ private void registerSvc(ConsulService svc) { } private void deregisterSvc(ConsulService svc) { - Supplier errorMessage = () ->"Could not deregister container " + svc.getContainerId() + " from Consul."; + Supplier errorMessage = () -> "Could not deregister container " + svc.getContainerId() + + " from Consul."; executePut("/v1/agent/service/deregister/" + svc.getId(), null, errorMessage, ex -> logger.info("Consul has already stopped. Service de-registration aborted.")); } - private void executePut(String endpoint, String body, Supplier errorMessage, Consumer onFailure) { + private void executePut(String endpoint, + String body, + Supplier errorMessage, + Consumer onFailure) { HttpPut put = new HttpPut("http://" + host + ":" + port + endpoint); put.setHeader(ACCEPT, APPLICATION_JSON); put.setHeader(CONTENT_TYPE, APPLICATION_JSON); - if(body != null) { + if (body != null) { try { put.setEntity(new StringEntity(body)); } catch (UnsupportedEncodingException e) { diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ConsulServiceFactory.java b/src/main/java/com/github/dockerunit/discovery/consul/ConsulServiceFactory.java index 8b80ba1..fbfc1cc 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ConsulServiceFactory.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ConsulServiceFactory.java @@ -1,18 +1,19 @@ package com.github.dockerunit.discovery.consul; -import com.github.dockerjava.api.DockerClient; -import com.github.dockerjava.api.command.InspectContainerResponse; -import com.github.dockerunit.discovery.consul.annotation.TCPHealthCheck; -import com.github.dockerunit.discovery.consul.annotation.WebHealthCheck; - import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerunit.discovery.consul.annotation.TCPHealthCheck; +import com.github.dockerunit.discovery.consul.annotation.WebHealthCheck; + public class ConsulServiceFactory { private static final String SERVICE_NAME_PREFIX = "SERVICE_"; @@ -21,7 +22,8 @@ public class ConsulServiceFactory { + "health-check by using @" + WebHealthCheck.class.getSimpleName() + " or @" + TCPHealthCheck.class.getSimpleName(); - private static final String SVC_HEALTH_CHECK_PORT_NOT_FOUND_MSG = "No health-check port definition detected" + DEFINE_HEALTH_CHECK_MSG; + private static final String SVC_HEALTH_CHECK_PORT_NOT_FOUND_MSG = + "No health-check port definition detected" + DEFINE_HEALTH_CHECK_MSG; private static final String SVC_NAME_NOT_FOUND_ERROR_MSG = "No svc name detected. " + DEFINE_HEALTH_CHECK_MSG; private static final String DOCKERUNIT = "dockerunit"; @@ -42,13 +44,19 @@ public ConsulService createSvc(String containerId) { InspectContainerResponse r = client.inspectContainerCmd(containerId).exec(); Map options = buildKeyValueMap(r.getConfig().getLabels(), r.getConfig().getEnv()); - String svcName = null; + + String svcName; try { - svcName = URLEncoder.encode(findName(options).orElseThrow(() -> new RuntimeException(SVC_NAME_NOT_FOUND_ERROR_MSG)), "UTF-8"); + svcName = URLEncoder.encode( + findName(options).orElseThrow(() -> new RuntimeException(SVC_NAME_NOT_FOUND_ERROR_MSG)), + StandardCharsets.UTF_8.name() + ); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Invalid svc name detected.", e); } - Integer port = extractHealthCheckPort(options).orElseThrow(() -> new RuntimeException(SVC_HEALTH_CHECK_PORT_NOT_FOUND_MSG)); + + Integer port = extractHealthCheckPort(options) + .orElseThrow(() -> new RuntimeException(SVC_HEALTH_CHECK_PORT_NOT_FOUND_MSG)); String address = ContainerUtils.extractBridgeIpAddress(r.getNetworkSettings()) .orElseThrow(() -> new RuntimeException(SVC_ADDRESS_NOT_FOUND_ERROR_MSG)); @@ -63,10 +71,10 @@ public ConsulService createSvc(String containerId) { } private Map buildKeyValueMap(Map labels, String[] env) { - if(env == null) { + if (env == null) { return labels != null ? labels : new HashMap<>(); } - if(labels == null) { + if (labels == null) { return new HashMap<>(); } Map keyValueMap = labels.entrySet() @@ -83,8 +91,9 @@ private ConsulService.ConsulCheck buildCheck(Map options, String ConsulService.ConsulCheck.ConsulCheckBuilder builder = ConsulService.ConsulCheck.builder(); builder.interval(options.get(SERVICE_CHECK_INTERVAL)); builder.http(interpolateCheckScript( - options.getOrDefault(SERVICE_CHECK_HTTP, null), address, port)); - builder.tcp(interpolateCheckScript(options.getOrDefault(SERVICE_CHECK_TCP, null), address,port)); + options.getOrDefault(SERVICE_CHECK_HTTP, null), address, port) + ); + builder.tcp(interpolateCheckScript(options.getOrDefault(SERVICE_CHECK_TCP, null), address, port)); builder.method(options.getOrDefault(SERVICE_CHECK_METHOD, null)); builder.tlsSkipVerify(true); builder.status(options.getOrDefault(SERVICE_CHECK_INITIAL_STATUS, null)); @@ -99,10 +108,10 @@ private String interpolateCheckScript(String script, String address, Integer por private Optional extractHealthCheckPort(Map options) { return options.entrySet().stream() - .filter(kv -> hasServiceName(kv)) + .filter(this::hasServiceName) .findFirst() .map(kv -> extractPortString(kv.getKey())) - .map(port -> asInteger(port)); + .map(this::asInteger); } private Integer asInteger(String port) { @@ -115,9 +124,9 @@ private Integer asInteger(String port) { private Optional findName(Map options) { return options.entrySet().stream() - .filter(kv -> hasServiceName(kv)) - .findFirst() - .map(kv -> kv.getValue()); + .filter(this::hasServiceName) + .findFirst() + .map(Map.Entry::getValue); } private boolean hasServiceName(Map.Entry kv) { @@ -126,7 +135,7 @@ private boolean hasServiceName(Map.Entry kv) { } private String extractPortString(String s) { - if (! (s.lastIndexOf("_") > (s.indexOf("_") + 1))) { + if (!(s.lastIndexOf("_") > (s.indexOf("_") + 1))) { return null; } return s.substring(s.indexOf("_") + 1, s.lastIndexOf("_")); diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ContainerTracker.java b/src/main/java/com/github/dockerunit/discovery/consul/ContainerTracker.java index a58f877..c4948cc 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ContainerTracker.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ContainerTracker.java @@ -1,15 +1,15 @@ package com.github.dockerunit.discovery.consul; -import com.github.dockerjava.api.DockerClient; -import com.github.dockerjava.api.model.Container; - -import java.util.Arrays; +import java.util.Collections; import java.util.Optional; import java.util.Timer; import java.util.TimerTask; import java.util.function.Consumer; import java.util.logging.Logger; +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.model.Container; + public class ContainerTracker { private static final Logger logger = Logger.getLogger(ContainerTracker.class.getSimpleName()); @@ -17,11 +17,19 @@ public class ContainerTracker { private final DockerClient client; private final String containerId; private final int pollingPeriod; + private final Consumer onDetect; private final Consumer onDestroy; + private Container latestContainer; - public ContainerTracker(DockerClient client, String containerId, int pollingPeriod, Consumer onDetect, Consumer onDestroy) { + public ContainerTracker( + DockerClient client, + String containerId, + int pollingPeriod, + Consumer onDetect, + Consumer onDestroy + ) { this.client = client; this.containerId = containerId; this.pollingPeriod = pollingPeriod; @@ -37,22 +45,24 @@ public ContainerTracker(DockerClient client, String containerId, int pollingPeri } private void init() { - latestContainer = findContainer().orElseThrow(() -> new RuntimeException("Could not detect container with id: " + containerId)); + latestContainer = findContainer().orElseThrow(() -> new RuntimeException( + "Could not detect container with id: " + containerId)); onDetect.accept(latestContainer); track(); } private Optional findContainer() { - return client.listContainersCmd().withIdFilter(Arrays.asList(containerId)).exec() - .stream() - .findFirst(); + return client.listContainersCmd().withIdFilter(Collections.singletonList(containerId)).exec() + .stream() + .findFirst(); } private void track() { TimerTask repeatedTask = new TimerTask() { public void run() { try { - latestContainer = findContainer().orElseThrow(() -> new RuntimeException("Container " + containerId + " has been removed.")); + latestContainer = findContainer() + .orElseThrow(() -> new RuntimeException("Container " + containerId + " has been removed.")); } catch (Exception e) { this.cancel(); onDestroy.accept(latestContainer); diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ContainerUtils.java b/src/main/java/com/github/dockerunit/discovery/consul/ContainerUtils.java index f59fe35..bcb991d 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ContainerUtils.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ContainerUtils.java @@ -1,20 +1,22 @@ package com.github.dockerunit.discovery.consul; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; + import com.github.dockerjava.api.model.Container; import com.github.dockerjava.api.model.ContainerNetwork; import com.github.dockerjava.api.model.ContainerNetworkSettings; import com.github.dockerjava.api.model.NetworkSettings; import com.github.dockerunit.core.internal.docker.DefaultDockerClientProvider; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; -import java.util.Arrays; -import java.util.Map; -import java.util.Optional; - +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class ContainerUtils { private static final com.github.dockerjava.api.DockerClient dockerClient = new DefaultDockerClientProvider().getClient(); - public static Optional extractBridgeIpAddress(ContainerNetworkSettings settings) { return extractIp(settings.getNetworks()); } @@ -29,22 +31,20 @@ public static Optional extractMappedPort(int port, NetworkSettings netw .map(Map.Entry::getValue) .filter(bindings -> bindings != null && bindings.length > 0) .findFirst() - .flatMap(bindings -> parsePort(bindings[0].getHostPortSpec())); + .flatMap(bindings -> parsePort(bindings[0].getHostPortSpec())); } public static Container getConsulContainer() { return dockerClient.listContainersCmd().exec().stream() - .filter(c -> isConsul(c)) + .filter(ContainerUtils::isConsul) .findFirst() .orElseThrow(() -> new RuntimeException(("Could not detect the Consul container."))); } - private static boolean isConsul(Container c) { - return Arrays.stream(c.getNames()).anyMatch(s -> s.equals("/" + ConsulDiscoveryConfig.CONSUL_CONTAINER_NAME)); + return Arrays.asList(c.getNames()).contains("/" + ConsulDiscoveryConfig.CONSUL_CONTAINER_NAME); } - private static Optional extractIp(Map networks) { return Optional.ofNullable(networks.entrySet().stream() .filter(network -> "bridge".equals(network.getKey())) @@ -61,4 +61,5 @@ private static Optional parsePort(String s) { return Optional.empty(); } } + } diff --git a/src/main/java/com/github/dockerunit/discovery/consul/ServiceRecord.java b/src/main/java/com/github/dockerunit/discovery/consul/ServiceRecord.java index ab33c93..712d020 100644 --- a/src/main/java/com/github/dockerunit/discovery/consul/ServiceRecord.java +++ b/src/main/java/com/github/dockerunit/discovery/consul/ServiceRecord.java @@ -4,78 +4,81 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; - +import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.experimental.Wither; +import lombok.NoArgsConstructor; +import lombok.With; -@Wither +@With @Getter @AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) @JsonIgnoreProperties(ignoreUnknown = true) public class ServiceRecord { - @JsonProperty("ServiceName") - private final String name; - - @JsonProperty("Address") - private final String address; - - @JsonProperty("ServicePort") - private final int port; - - @JsonProperty("ServiceAddress") - private String serviceAddress; - - @JsonProperty("Service") - private final Service service; - - @JsonProperty("Checks") - private final List checks; - - - public String getName() { - return service != null ? service.getName() : name; - } - - public String getAddress() { - return service != null ? service.getAddress() : address; - } - - public int getPort() { - return service != null ? service.getPort() : port; - } - - @Wither - @Getter - @AllArgsConstructor - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Service { - - @JsonProperty("Service") - private final String name; - - @JsonProperty("Address") - private final String address; - - @JsonProperty("Port") - private final int port; - - } - - @Wither - @Getter - @AllArgsConstructor - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Check { - - public static final String PASSING = "passing"; - - @JsonProperty("Name") - private final String name; - - @JsonProperty("Status") - private final String status; - - } + @JsonProperty("ServiceName") + private String name; + + @JsonProperty("Address") + private String address; + + @JsonProperty("ServicePort") + private int port; + + @JsonProperty("ServiceAddress") + private String serviceAddress; + + @JsonProperty("Service") + private Service service; + + @JsonProperty("Checks") + private List checks; + + public String getName() { + return service != null ? service.getName() : name; + } + + public String getAddress() { + return service != null ? service.getAddress() : address; + } + + public int getPort() { + return service != null ? service.getPort() : port; + } + + @With + @Getter + @AllArgsConstructor + @NoArgsConstructor(access = AccessLevel.PRIVATE) + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Service { + + @JsonProperty("Service") + private String name; + + @JsonProperty("Address") + private String address; + + @JsonProperty("Port") + private int port; + + } + + @With + @Getter + @AllArgsConstructor + @NoArgsConstructor(access = AccessLevel.PRIVATE) + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Check { + + public static final String PASSING = "passing"; + + @JsonProperty("Name") + private String name; + + @JsonProperty("Status") + private String status; + + } }