diff --git a/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonClientModule.java b/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonClientModule.java index c65d78ff6..b2be4c728 100644 --- a/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonClientModule.java +++ b/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonClientModule.java @@ -7,6 +7,7 @@ import com.google.common.base.Optional; import com.google.inject.AbstractModule; import com.google.inject.Binder; +import com.google.inject.Provider; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; import com.google.inject.binder.LinkedBindingBuilder; @@ -28,6 +29,12 @@ public class BaragonClientModule extends AbstractModule { // bind this to provide the authkey for baragon public static final String AUTHKEY_PROPERTY_NAME = "baragon.authkey"; + // bind this to a provider for the authkey for baragon + public static final String AUTHKEY_PROVIDER_PROPERTY_NAME = "baragon.authkey.provider"; + + // bind this to a provider for the full host:port and context path for baragon + public static final String BASE_URL_PROVIDER_NAME = "baragon.base.url.provider"; + private final List hosts; public BaragonClientModule() { @@ -72,4 +79,12 @@ public static LinkedBindingBuilder bindContextPath(Binder binder) { public static LinkedBindingBuilder> bindAuthkey(Binder binder) { return binder.bind(new TypeLiteral>() {}).annotatedWith(Names.named(AUTHKEY_PROPERTY_NAME)); } + + public static LinkedBindingBuilder>> bindBaseUrlProvider(Binder binder) { + return binder.bind(new TypeLiteral>>() {}).annotatedWith(Names.named(BASE_URL_PROVIDER_NAME)); + } + + public static LinkedBindingBuilder>> bindAuthkeyProvider(Binder binder) { + return binder.bind(new TypeLiteral>>() {}).annotatedWith(Names.named(AUTHKEY_PROVIDER_PROPERTY_NAME)); + } } diff --git a/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonClientProvider.java b/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonClientProvider.java index 649e9a23a..58bc2b32b 100644 --- a/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonClientProvider.java +++ b/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonClientProvider.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import javax.inject.Named; import javax.inject.Provider; @@ -22,7 +23,9 @@ public class BaragonClientProvider implements Provider { private String contextPath = DEFAULT_CONTEXT_PATH; private List hosts = Collections.emptyList(); + private Provider> baseUrlProvider = null; private Optional authkey = Optional.absent(); + private Provider> authkeyProvider = null; @Inject public BaragonClientProvider(@Named(BaragonClientModule.HTTP_CLIENT_NAME) HttpClient httpClient) { @@ -42,7 +45,7 @@ public BaragonClientProvider setHosts(@Named(BaragonClientModule.HOSTS_PROPERTY_ @Inject(optional=true) public BaragonClientProvider setHosts(@Named(BaragonClientModule.HOSTS_PROPERTY_NAME) List hosts) { - this.hosts = ImmutableList.copyOf(hosts); + mapAndSetHosts(hosts); return this; } @@ -53,15 +56,39 @@ public BaragonClientProvider setAuthkey(@Named(BaragonClientModule.AUTHKEY_PROPE } public BaragonClientProvider setHosts(String... hosts) { - this.hosts = Arrays.asList(hosts); + mapAndSetHosts(Arrays.asList(hosts)); + return this; + } + + private void mapAndSetHosts(List hosts) { + this.hosts = ImmutableList.copyOf(hosts.stream().map((h) -> h.startsWith("http") ? h : String.format("http://%s", h)).collect(Collectors.toList())); + } + + @Inject(optional = true) + public BaragonClientProvider setBaseUrlProvider(@Named(BaragonClientModule.BASE_URL_PROVIDER_NAME) Provider> baseUrlProvider) { + this.baseUrlProvider = baseUrlProvider; + return this; + } + + @Inject(optional = true) + public BaragonClientProvider setAuthkeyProvider(@Named(BaragonClientModule.AUTHKEY_PROVIDER_PROPERTY_NAME) Provider> authkeyProvider) { + this.authkeyProvider = authkeyProvider; return this; } @Override public BaragonServiceClient get() { - Preconditions.checkState(contextPath != null, "contextPath null"); - Preconditions.checkState(!hosts.isEmpty(), "no hosts provided"); - Preconditions.checkState(authkey != null, "authkey null"); - return new BaragonServiceClient(contextPath, httpClient, hosts, authkey); + if (baseUrlProvider == null) { + Preconditions.checkState(contextPath != null, "contextPath null"); + Preconditions.checkState(!hosts.isEmpty(), "no hosts provided"); + baseUrlProvider = ProviderUtils.of(hosts.stream().map((h) -> String.format("%s/%s", h, contextPath)).collect(Collectors.toList())); + } + + if (authkeyProvider == null) { + Preconditions.checkState(authkey != null, "authkey null"); + authkeyProvider = ProviderUtils.of(authkey); + } + + return new BaragonServiceClient(httpClient, baseUrlProvider, authkeyProvider); } } diff --git a/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonServiceClient.java b/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonServiceClient.java index 8889aeeaf..2968a56a2 100644 --- a/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonServiceClient.java +++ b/BaragonClient/src/main/java/com/hubspot/baragon/client/BaragonServiceClient.java @@ -1,13 +1,19 @@ package com.hubspot.baragon.client; +import static com.google.common.base.Preconditions.checkNotNull; + import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.stream.Collectors; import javax.inject.Provider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.fasterxml.jackson.core.type.TypeReference; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; @@ -24,17 +30,14 @@ import com.hubspot.horizon.HttpRequest; import com.hubspot.horizon.HttpRequest.Method; import com.hubspot.horizon.HttpResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import static com.google.common.base.Preconditions.checkNotNull; public class BaragonServiceClient { private static final Logger LOG = LoggerFactory.getLogger(BaragonServiceClient.class); - private static final String WORKERS_FORMAT = "http://%s/%s/workers"; + private static final String WORKERS_FORMAT = "%s/workers"; - private static final String LOAD_BALANCER_FORMAT = "http://%s/%s/load-balancer"; + private static final String LOAD_BALANCER_FORMAT = "%s/load-balancer"; private static final String LOAD_BALANCER_BASE_PATH_FORMAT = LOAD_BALANCER_FORMAT + "/%s/base-path"; private static final String LOAD_BALANCER_ALL_BASE_PATHS_FORMAT = LOAD_BALANCER_BASE_PATH_FORMAT + "/all"; private static final String LOAD_BALANCER_AGENTS_FORMAT = LOAD_BALANCER_FORMAT + "/%s/agents"; @@ -44,14 +47,14 @@ public class BaragonServiceClient { private static final String ALL_LOAD_BALANCER_GROUPS_FORMAT = LOAD_BALANCER_FORMAT + "/all"; private static final String LOAD_BALANCER_TRAFFIC_SOURCE_FORMAT = LOAD_BALANCER_GROUP_FORMAT + "/sources"; - private static final String REQUEST_FORMAT = "http://%s/%s/request"; + private static final String REQUEST_FORMAT = "%s/request"; private static final String REQUEST_ID_FORMAT = REQUEST_FORMAT + "/%s"; - private static final String STATE_FORMAT = "http://%s/%s/state"; + private static final String STATE_FORMAT = "%s/state"; private static final String STATE_SERVICE_ID_FORMAT = STATE_FORMAT + "/%s"; private static final String STATE_RELOAD_FORMAT = STATE_SERVICE_ID_FORMAT + "/reload"; - private static final String STATUS_FORMAT = "http://%s/%s/status"; + private static final String STATUS_FORMAT = "%s/status"; private static final TypeReference> STRING_COLLECTION = new TypeReference>() {}; private static final TypeReference> BARAGON_GROUP_COLLECTION = new TypeReference>() {}; @@ -60,27 +63,34 @@ public class BaragonServiceClient { private static final TypeReference> BARAGON_SERVICE_STATE_COLLECTION = new TypeReference>() {}; private final Random random; - private final Provider> hostsProvider; - private final String contextPath; + private final Provider> baseUrlProvider; private final Provider> authkeyProvider; private final HttpClient httpClient; public BaragonServiceClient(String contextPath, HttpClient httpClient, List hosts, Optional authkey) { - this(contextPath, httpClient, ProviderUtils.>of(ImmutableList.copyOf(hosts)), ProviderUtils.of(authkey)); + this( + httpClient, + ProviderUtils.of(ImmutableList.copyOf(hosts.stream().map((h) -> String.format("%s/%s", h, contextPath)).collect(Collectors.toList()))), + ProviderUtils.of(authkey) + ); } - public BaragonServiceClient(String contextPath, HttpClient httpClient, Provider> hostsProvider, Provider> authkeyProvider) { + public BaragonServiceClient(HttpClient httpClient, Provider> baseUrlProvider, Provider> authkeyProvider) { this.httpClient = httpClient; - this.contextPath = contextPath; - this.hostsProvider = hostsProvider; + this.baseUrlProvider = baseUrlProvider; this.authkeyProvider = authkeyProvider; this.random = new Random(); } - private String getHost() { - final List hosts = hostsProvider.get(); - return hosts.get(random.nextInt(hosts.size())); + private String getBaseUrl() { + final List baseUrls = baseUrlProvider.get(); + String chosenBaseUrl = baseUrls.get(random.nextInt(baseUrls.size())); + if (chosenBaseUrl.endsWith("/")) { + return chosenBaseUrl.substring(0, chosenBaseUrl.length() - 1); + } else { + return chosenBaseUrl; + } } private HttpRequest.Builder buildRequest(String uri) { @@ -156,7 +166,7 @@ private Collection getCollection(String uri, String type, TypeReference body, Map getBaragonServiceStatus(String hostname) { - final String uri = String.format(STATUS_FORMAT, hostname, contextPath); + public Optional getBaragonServiceStatus(String baseUrl) { + final String uri = String.format(STATUS_FORMAT, baseUrl); return getSingle(uri, "status", "", BaragonServiceStatus.class); } public Optional getAnyBaragonServiceStatus() { - return getBaragonServiceStatus(getHost()); + return getBaragonServiceStatus(getBaseUrl()); } // BaragonService service states public Collection getGlobalState() { - final String uri = String.format(STATE_FORMAT, getHost(), contextPath); + final String uri = String.format(STATE_FORMAT, getBaseUrl()); return getCollection(uri, "global state", BARAGON_SERVICE_STATE_COLLECTION); } public Optional getServiceState(String serviceId) { - final String uri = String.format(STATE_SERVICE_ID_FORMAT, getHost(), contextPath, serviceId); + final String uri = String.format(STATE_SERVICE_ID_FORMAT, getBaseUrl(), serviceId); return getSingle(uri, "service state", serviceId, BaragonServiceState.class); } public Optional deleteService(String serviceId) { - final String uri = String.format(STATE_SERVICE_ID_FORMAT, getHost(), contextPath, serviceId); - return delete(uri, "service state", serviceId, Collections.emptyMap(), Optional.of(BaragonResponse.class)); + final String uri = String.format(STATE_SERVICE_ID_FORMAT, getBaseUrl(), serviceId); + return delete(uri, "service state", serviceId, Collections.emptyMap(), Optional.of(BaragonResponse.class)); } public Optional reloadServiceConfigs(String serviceId){ - final String uri = String.format(STATE_RELOAD_FORMAT, getHost(), contextPath, serviceId); + final String uri = String.format(STATE_RELOAD_FORMAT, getBaseUrl(), serviceId); return post(uri, "service reload",Optional.absent(), Optional.of(BaragonResponse.class)); } @@ -260,7 +270,7 @@ public Optional reloadServiceConfigs(String serviceId){ // BaragonService Workers public Collection getBaragonServiceWorkers() { - final String requestUri = String.format(WORKERS_FORMAT, getHost(), contextPath); + final String requestUri = String.format(WORKERS_FORMAT, getBaseUrl()); return getCollection(requestUri, "baragon service workers", STRING_COLLECTION); } @@ -268,59 +278,59 @@ public Collection getBaragonServiceWorkers() { // BaragonService load balancer group actions public Collection getLoadBalancerGroups() { - final String requestUri = String.format(LOAD_BALANCER_FORMAT, getHost(), contextPath); + final String requestUri = String.format(LOAD_BALANCER_FORMAT, getBaseUrl()); return getCollection(requestUri, "load balancer groups", STRING_COLLECTION); } public Collection getAllLoadBalancerGroups() { - final String requestUri = String.format(ALL_LOAD_BALANCER_GROUPS_FORMAT, getHost(), contextPath); + final String requestUri = String.format(ALL_LOAD_BALANCER_GROUPS_FORMAT, getBaseUrl()); return getCollection(requestUri, "load balancer groups", BARAGON_GROUP_COLLECTION); } public Collection getLoadBalancerGroupAgentMetadata(String loadBalancerGroupName) { - final String requestUri = String.format(LOAD_BALANCER_AGENTS_FORMAT, getHost(), contextPath, loadBalancerGroupName); + final String requestUri = String.format(LOAD_BALANCER_AGENTS_FORMAT, getBaseUrl(), loadBalancerGroupName); return getCollection(requestUri, "load balancer agent metadata", BARAGON_AGENTS_COLLECTION); } public Collection getLoadBalancerGroupKnownAgentMetadata(String loadBalancerGroupName) { - final String requestUri = String.format(LOAD_BALANCER_KNOWN_AGENTS_FORMAT, getHost(), contextPath, loadBalancerGroupName); + final String requestUri = String.format(LOAD_BALANCER_KNOWN_AGENTS_FORMAT, getBaseUrl(), loadBalancerGroupName); return getCollection(requestUri, "load balancer known agent metadata", BARAGON_AGENTS_COLLECTION); } public void deleteLoadBalancerGroupKnownAgent(String loadBalancerGroupName, String agentId) { - final String requestUri = String.format(LOAD_BALANCER_DELETE_KNOWN_AGENT_FORMAT, getHost(), contextPath, loadBalancerGroupName, agentId); + final String requestUri = String.format(LOAD_BALANCER_DELETE_KNOWN_AGENT_FORMAT, getBaseUrl(), loadBalancerGroupName, agentId); delete(requestUri, "known agent", agentId, Collections.emptyMap()); } public BaragonGroup addTrafficSource(String loadBalancerGroupName, String source) { - final String requestUri = String.format(LOAD_BALANCER_TRAFFIC_SOURCE_FORMAT, getHost(), contextPath, loadBalancerGroupName); + final String requestUri = String.format(LOAD_BALANCER_TRAFFIC_SOURCE_FORMAT, getBaseUrl(), loadBalancerGroupName); return post(requestUri, "add source", Optional.absent(), Optional.of(BaragonGroup.class), ImmutableMap.of("source", source)).get(); } public Optional removeTrafficSource(String loadBalancerGroupName, String source) { - final String requestUri = String.format(LOAD_BALANCER_TRAFFIC_SOURCE_FORMAT, getHost(), contextPath, loadBalancerGroupName); + final String requestUri = String.format(LOAD_BALANCER_TRAFFIC_SOURCE_FORMAT, getBaseUrl(), loadBalancerGroupName); return delete(requestUri, "remove source", source, ImmutableMap.of("source", source), Optional.of(BaragonGroup.class)); } public Optional getGroupDetail(String loadBalancerGroupName) { - final String requestUri = String.format(LOAD_BALANCER_GROUP_FORMAT, getHost(), contextPath, loadBalancerGroupName); + final String requestUri = String.format(LOAD_BALANCER_GROUP_FORMAT, getBaseUrl(), loadBalancerGroupName); return getSingle(requestUri, "group detail", loadBalancerGroupName, BaragonGroup.class); } // BaragonService base path actions public Collection getOccupiedBasePaths(String loadBalancerGroupName) { - final String requestUri = String.format(LOAD_BALANCER_ALL_BASE_PATHS_FORMAT, getHost(), contextPath, loadBalancerGroupName); + final String requestUri = String.format(LOAD_BALANCER_ALL_BASE_PATHS_FORMAT, getBaseUrl(), loadBalancerGroupName); return getCollection(requestUri, "occupied base paths", STRING_COLLECTION); } public Optional getServiceForBasePath(String loadBalancerGroupName, String basePath) { - final String requestUri = String.format(LOAD_BALANCER_BASE_PATH_FORMAT, getHost(), contextPath, loadBalancerGroupName); + final String requestUri = String.format(LOAD_BALANCER_BASE_PATH_FORMAT, getBaseUrl(), loadBalancerGroupName); return getSingle(requestUri, "service for base path", "", BaragonService.class, ImmutableMap.of("basePath", basePath)); } public void clearBasePath(String loadBalancerGroupName, String basePath) { - final String requestUri = String.format(LOAD_BALANCER_BASE_PATH_FORMAT, getHost(), contextPath, loadBalancerGroupName); + final String requestUri = String.format(LOAD_BALANCER_BASE_PATH_FORMAT, getBaseUrl(), loadBalancerGroupName); delete(requestUri, "base path", "", ImmutableMap.of("basePath", basePath)); } @@ -328,17 +338,17 @@ public void clearBasePath(String loadBalancerGroupName, String basePath) { // BaragonService request actions public Optional getRequest(String requestId) { - final String uri = String.format(REQUEST_ID_FORMAT, getHost(), contextPath, requestId); + final String uri = String.format(REQUEST_ID_FORMAT, getBaseUrl(), requestId); return getSingle(uri, "request", requestId, BaragonResponse.class); } public Optional enqueueRequest(BaragonRequest request) { - final String uri = String.format(REQUEST_FORMAT, getHost(), contextPath); + final String uri = String.format(REQUEST_FORMAT, getBaseUrl()); return post(uri, "request", Optional.of(request), Optional.of(BaragonResponse.class)); } public Optional cancelRequest(String requestId) { - final String uri = String.format(REQUEST_ID_FORMAT, getHost(), contextPath, requestId); + final String uri = String.format(REQUEST_ID_FORMAT, getBaseUrl(), requestId); return delete(uri, "request", requestId, Collections.emptyMap(), Optional.of(BaragonResponse.class)); } @@ -346,7 +356,7 @@ public Optional cancelRequest(String requestId) { // BaragonService queued request actions public Collection getQueuedRequests() { - final String uri = String.format(REQUEST_FORMAT, getHost(), contextPath); + final String uri = String.format(REQUEST_FORMAT, getBaseUrl()); return getCollection(uri, "queued requests", QUEUED_REQUEST_COLLECTION); } }