/* * Copyright © 2019 Smoke Turner, LLC ([email protected]) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.smoketurner.dropwizard.consul; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableMap; import com.google.common.net.HostAndPort; import com.orbitz.consul.Consul; import io.dropwizard.util.Duration; import io.dropwizard.validation.MinDuration; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import javax.validation.constraints.NotNull; public class ConsulFactory { private static final String CONSUL_AUTH_HEADER_KEY = "X-Consul-Token"; @NotNull private HostAndPort endpoint = HostAndPort.fromParts(Consul.DEFAULT_HTTP_HOST, Consul.DEFAULT_HTTP_PORT); @Nullable private String serviceName; private boolean enabled = true; private Optional<String> serviceId = Optional.empty(); private Optional<Integer> servicePort = Optional.empty(); private Optional<Integer> adminPort = Optional.empty(); private Optional<String> serviceAddress = Optional.empty(); private Optional<Iterable<String>> tags = Optional.empty(); private Optional<String> aclToken = Optional.empty(); private Optional<Map<String, String>> serviceMeta = Optional.empty(); private boolean servicePing = true; @Nullable @MinDuration(value = 1, unit = TimeUnit.SECONDS) private Duration retryInterval; @NotNull @MinDuration(value = 1, unit = TimeUnit.SECONDS) private Duration checkInterval = Duration.seconds(1); @NotNull @MinDuration(value = 1, unit = TimeUnit.MINUTES) private Duration deregisterInterval = Duration.minutes(1); @JsonProperty public boolean isEnabled() { return enabled; } @JsonProperty public void setEnabled(boolean enabled) { this.enabled = enabled; } @JsonProperty public HostAndPort getEndpoint() { return endpoint; } @JsonProperty public void setEndpoint(HostAndPort endpoint) { this.endpoint = endpoint; } @JsonProperty public Optional<String> getServiceId() { return serviceId; } @JsonProperty public void setServiceId(@Nullable String serviceId) { this.serviceId = Optional.ofNullable(serviceId); } @Nullable @JsonProperty public String getServiceName() { return serviceName; } @JsonProperty public void setSeviceName(@Nullable String serviceName) { this.serviceName = serviceName; } @JsonProperty public Optional<Iterable<String>> getTags() { return tags; } @JsonProperty public void setTags(Iterable<String> tags) { this.tags = Optional.ofNullable(tags); } @JsonProperty public Optional<Integer> getServicePort() { return servicePort; } @JsonProperty public void setServicePort(Integer servicePort) { this.servicePort = Optional.ofNullable(servicePort); } @JsonProperty public Optional<Integer> getAdminPort() { return adminPort; } @JsonProperty public void setAdminPort(Integer adminPort) { this.adminPort = Optional.ofNullable(adminPort); } @JsonProperty public Optional<String> getServiceAddress() { return serviceAddress; } @JsonProperty public void setServiceAddress(String serviceAddress) { this.serviceAddress = Optional.ofNullable(serviceAddress); } @JsonProperty public Optional<Duration> getRetryInterval() { return Optional.ofNullable(retryInterval); } @JsonProperty public void setRetryInterval(@Nullable Duration interval) { this.retryInterval = interval; } @JsonProperty public Duration getCheckInterval() { return checkInterval; } @JsonProperty public void setCheckInterval(Duration interval) { this.checkInterval = interval; } @JsonProperty public Duration getDeregisterInterval() { return deregisterInterval; } @JsonProperty public void setDeregisterInterval(Duration interval) { this.deregisterInterval = interval; } @JsonProperty public Optional<String> getAclToken() { return aclToken; } @JsonProperty public void setAclToken(@Nullable String aclToken) { this.aclToken = Optional.ofNullable(aclToken); } @JsonProperty public Optional<Map<String, String>> getServiceMeta() { return serviceMeta; } @JsonProperty public void setServiceMeta(Map<String, String> serviceMeta) { this.serviceMeta = Optional.ofNullable(serviceMeta); } @JsonProperty public boolean isServicePing() { return servicePing; } @JsonProperty public void setServicePing(boolean servicePing) { this.servicePing = servicePing; } @JsonIgnore public Consul build() { final Consul.Builder builder = Consul.builder().withHostAndPort(endpoint).withPing(servicePing); aclToken.ifPresent( token -> { // setting both acl token here and with header, supplying an auth // header. This should cover both use cases: endpoint supports // legacy ?token query param and other case in which endpoint // requires an X-Consul-Token header. // @see https://www.consul.io/api/index.html#acls builder.withAclToken(token).withHeaders(ImmutableMap.of(CONSUL_AUTH_HEADER_KEY, token)); }); return builder.build(); } @Override public int hashCode() { return Objects.hash( endpoint, serviceName, enabled, servicePort, adminPort, serviceAddress, tags, retryInterval, checkInterval, deregisterInterval, aclToken, serviceMeta, servicePing); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } final ConsulFactory other = (ConsulFactory) obj; return Objects.equals(this.endpoint, other.endpoint) && Objects.equals(this.serviceName, other.serviceName) && Objects.equals(this.enabled, other.enabled) && Objects.equals(this.servicePort, other.servicePort) && Objects.equals(this.adminPort, other.adminPort) && Objects.equals(this.serviceAddress, other.serviceAddress) && Objects.equals(this.tags, other.tags) && Objects.equals(this.retryInterval, other.retryInterval) && Objects.equals(this.checkInterval, other.checkInterval) && Objects.equals(this.deregisterInterval, other.deregisterInterval) && Objects.equals(this.aclToken, other.aclToken) && Objects.equals(this.serviceMeta, other.serviceMeta) && Objects.equals(this.servicePing, other.servicePing); } }