Skip to content

Commit

Permalink
Merge pull request #245 from HubSpot/client
Browse files Browse the repository at this point in the history
Expose the hosts provider and support ssl in client
  • Loading branch information
ssalinas authored Feb 15, 2018
2 parents d872a68 + 9870717 commit 6c700e4
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<String> hosts;

public BaragonClientModule() {
Expand Down Expand Up @@ -72,4 +79,12 @@ public static LinkedBindingBuilder<String> bindContextPath(Binder binder) {
public static LinkedBindingBuilder<Optional<String>> bindAuthkey(Binder binder) {
return binder.bind(new TypeLiteral<Optional<String>>() {}).annotatedWith(Names.named(AUTHKEY_PROPERTY_NAME));
}

public static LinkedBindingBuilder<Provider<List<String>>> bindBaseUrlProvider(Binder binder) {
return binder.bind(new TypeLiteral<Provider<List<String>>>() {}).annotatedWith(Names.named(BASE_URL_PROVIDER_NAME));
}

public static LinkedBindingBuilder<Provider<Optional<String>>> bindAuthkeyProvider(Binder binder) {
return binder.bind(new TypeLiteral<Provider<Optional<String>>>() {}).annotatedWith(Names.named(AUTHKEY_PROVIDER_PROPERTY_NAME));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -22,7 +23,9 @@ public class BaragonClientProvider implements Provider<BaragonServiceClient> {

private String contextPath = DEFAULT_CONTEXT_PATH;
private List<String> hosts = Collections.emptyList();
private Provider<List<String>> baseUrlProvider = null;
private Optional<String> authkey = Optional.absent();
private Provider<Optional<String>> authkeyProvider = null;

@Inject
public BaragonClientProvider(@Named(BaragonClientModule.HTTP_CLIENT_NAME) HttpClient httpClient) {
Expand All @@ -42,7 +45,7 @@ public BaragonClientProvider setHosts(@Named(BaragonClientModule.HOSTS_PROPERTY_

@Inject(optional=true)
public BaragonClientProvider setHosts(@Named(BaragonClientModule.HOSTS_PROPERTY_NAME) List<String> hosts) {
this.hosts = ImmutableList.copyOf(hosts);
mapAndSetHosts(hosts);
return this;
}

Expand All @@ -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<String> 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<List<String>> baseUrlProvider) {
this.baseUrlProvider = baseUrlProvider;
return this;
}

@Inject(optional = true)
public BaragonClientProvider setAuthkeyProvider(@Named(BaragonClientModule.AUTHKEY_PROVIDER_PROPERTY_NAME) Provider<Optional<String>> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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";
Expand All @@ -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<Collection<String>> STRING_COLLECTION = new TypeReference<Collection<String>>() {};
private static final TypeReference<Collection<BaragonGroup>> BARAGON_GROUP_COLLECTION = new TypeReference<Collection<BaragonGroup>>() {};
Expand All @@ -60,27 +63,34 @@ public class BaragonServiceClient {
private static final TypeReference<Collection<BaragonServiceState>> BARAGON_SERVICE_STATE_COLLECTION = new TypeReference<Collection<BaragonServiceState>>() {};

private final Random random;
private final Provider<List<String>> hostsProvider;
private final String contextPath;
private final Provider<List<String>> baseUrlProvider;
private final Provider<Optional<String>> authkeyProvider;

private final HttpClient httpClient;

public BaragonServiceClient(String contextPath, HttpClient httpClient, List<String> hosts, Optional<String> authkey) {
this(contextPath, httpClient, ProviderUtils.<List<String>>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<List<String>> hostsProvider, Provider<Optional<String>> authkeyProvider) {
public BaragonServiceClient(HttpClient httpClient, Provider<List<String>> baseUrlProvider, Provider<Optional<String>> 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<String> hosts = hostsProvider.get();
return hosts.get(random.nextInt(hosts.size()));
private String getBaseUrl() {
final List<String> 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) {
Expand Down Expand Up @@ -156,7 +166,7 @@ private <T> Collection<T> getCollection(String uri, String type, TypeReference<C
HttpResponse response = httpClient.execute(buildRequest(uri).build());

if (response.getStatusCode() == 404) {
return ImmutableList.of();
throw new BaragonClientException(String.format("%s not found", type), 404);
}

checkResponse(type, response);
Expand Down Expand Up @@ -224,129 +234,129 @@ private HttpResponse post(String uri, String type, Optional<?> body, Map<String,

// BaragonService overall status

public Optional<BaragonServiceStatus> getBaragonServiceStatus(String hostname) {
final String uri = String.format(STATUS_FORMAT, hostname, contextPath);
public Optional<BaragonServiceStatus> getBaragonServiceStatus(String baseUrl) {
final String uri = String.format(STATUS_FORMAT, baseUrl);
return getSingle(uri, "status", "", BaragonServiceStatus.class);
}

public Optional<BaragonServiceStatus> getAnyBaragonServiceStatus() {
return getBaragonServiceStatus(getHost());
return getBaragonServiceStatus(getBaseUrl());
}


// BaragonService service states

public Collection<BaragonServiceState> 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<BaragonServiceState> 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<BaragonResponse> deleteService(String serviceId) {
final String uri = String.format(STATE_SERVICE_ID_FORMAT, getHost(), contextPath, serviceId);
return delete(uri, "service state", serviceId, Collections.<String, String>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<BaragonResponse> 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));
}


// BaragonService Workers

public Collection<String> 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);
}


// BaragonService load balancer group actions

public Collection<String> 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<BaragonGroup> 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<BaragonAgentMetadata> 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<BaragonAgentMetadata> 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.<String, String>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<BaragonGroup> 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<BaragonGroup> 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<String> 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<BaragonService> 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));
}


// BaragonService request actions

public Optional<BaragonResponse> 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<BaragonResponse> 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<BaragonResponse> 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.<String, String>emptyMap(), Optional.of(BaragonResponse.class));
}


// BaragonService queued request actions

public Collection<QueuedRequestId> 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);
}
}

0 comments on commit 6c700e4

Please sign in to comment.