package com.hubspot.baragon.service.resources; import java.util.Collection; import javax.validation.Valid; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import com.amazonaws.AmazonClientException; import com.amazonaws.services.elasticloadbalancingv2.model.CreateListenerRequest; import com.amazonaws.services.elasticloadbalancingv2.model.CreateRuleRequest; import com.amazonaws.services.elasticloadbalancingv2.model.CreateTargetGroupRequest; import com.amazonaws.services.elasticloadbalancingv2.model.Listener; import com.amazonaws.services.elasticloadbalancingv2.model.ListenerNotFoundException; import com.amazonaws.services.elasticloadbalancingv2.model.LoadBalancer; import com.amazonaws.services.elasticloadbalancingv2.model.ModifyListenerRequest; import com.amazonaws.services.elasticloadbalancingv2.model.ModifyRuleRequest; import com.amazonaws.services.elasticloadbalancingv2.model.ModifyTargetGroupRequest; import com.amazonaws.services.elasticloadbalancingv2.model.Rule; import com.amazonaws.services.elasticloadbalancingv2.model.RuleNotFoundException; import com.amazonaws.services.elasticloadbalancingv2.model.TargetGroup; import com.amazonaws.services.elasticloadbalancingv2.model.TargetGroupNotFoundException; import com.amazonaws.services.elasticloadbalancingv2.model.TargetHealthDescription; import com.google.common.base.Optional; import com.google.inject.Inject; import com.hubspot.baragon.auth.NoAuth; import com.hubspot.baragon.models.AgentCheckInResponse; import com.hubspot.baragon.service.config.ElbConfiguration; import com.hubspot.baragon.service.elb.ApplicationLoadBalancer; import com.hubspot.baragon.service.exceptions.BaragonWebException; @Path("/albs") @Produces(MediaType.APPLICATION_JSON) public class AlbResource { private final ApplicationLoadBalancer applicationLoadBalancer; private final Optional<ElbConfiguration> config; @Inject public AlbResource(ApplicationLoadBalancer applicationLoadBalancer, Optional<ElbConfiguration> config) { this.applicationLoadBalancer = applicationLoadBalancer; this.config = config; } @GET @NoAuth @Path("/load-balancers") public Collection<LoadBalancer> getAllLoadBalancers() { if (config.isPresent()) { return applicationLoadBalancer.getAllLoadBalancers(); } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @GET @NoAuth @Path("/load-balancers/{elbName}") public LoadBalancer getLoadBalancer(@PathParam("elbName") String elbName) { if (config.isPresent()) { try { Optional<LoadBalancer> maybeLoadBalancer = applicationLoadBalancer.getLoadBalancer(elbName); if (maybeLoadBalancer.isPresent()) { return maybeLoadBalancer.get(); } else { throw new WebApplicationException(String.format("ELB %s not found", elbName), Status.NOT_FOUND); } } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @GET @NoAuth @Path("/load-balancers/{elbName}/listeners") public Collection<Listener> getListeners(@PathParam("elbName") String elbName) { if (config.isPresent()) { try { return applicationLoadBalancer.getListenersForElb(elbName); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @POST @Path("/load-balancers/{elbName}/listeners") public Listener createListeners(@PathParam("elbName") String elbName, @Valid CreateListenerRequest createListenerRequest) { if (config.isPresent()) { Optional<LoadBalancer> maybeLoadBalancer = applicationLoadBalancer .getLoadBalancer(elbName); if (maybeLoadBalancer.isPresent()) { return applicationLoadBalancer .createListener(createListenerRequest .withLoadBalancerArn(maybeLoadBalancer.get().getLoadBalancerArn())); } else { throw new WebApplicationException(String.format("Could not find an elb with name %s", elbName), Status.NOT_FOUND); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @POST @Path("/listeners/{listenerArn:.+}") public Listener updateListener(@PathParam("elbName") String elbName, @PathParam("listenerArn") String listenerArn, @Valid ModifyListenerRequest modifyListenerRequest) { if (config.isPresent()) { try { return applicationLoadBalancer .modifyListener(modifyListenerRequest.withListenerArn(listenerArn)); } catch (ListenerNotFoundException notFound) { throw new WebApplicationException(String.format("No listener with ARN %s found", listenerArn), Status.NOT_FOUND); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @DELETE @Path("/listeners/{listenerArn:.+}") public Response removeListener(@PathParam("elbName") String elbName, @PathParam("listenerArn") String listenerArn) { if (config.isPresent()) { try { applicationLoadBalancer.deleteListener(listenerArn); return Response.noContent().build(); } catch (ListenerNotFoundException notFound) { throw new WebApplicationException(String.format("No listener with ARN %s found", listenerArn), Status.NOT_FOUND); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @GET @NoAuth @Path("/listeners/rules/{listenerArn:.+}") public Collection<Rule> getRules(@PathParam("elbName") String elbName, @PathParam("listenerArn") String listenerArn) { if (config.isPresent()) { try { return applicationLoadBalancer.getRulesByListener(listenerArn); } catch (ListenerNotFoundException notFound) { throw new WebApplicationException(String.format("Listener with ARN %s not found", listenerArn), Status.NOT_FOUND); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @POST @Path("/listeners/rules/{listenerArn:.+}") public Rule createRule(@PathParam("elbName") String elbName, @PathParam("listenerArn") String listenerArn, @Valid CreateRuleRequest createRuleRequest) { if (config.isPresent()) { try { return applicationLoadBalancer .createRule(createRuleRequest .withListenerArn(listenerArn)); } catch (ListenerNotFoundException notFound) { throw new WebApplicationException(String.format("Listener with ARN %s not found", listenerArn), Status.NOT_FOUND); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @POST @Path("/rules/{ruleArn:.+}") public Rule updateRule(@PathParam("elbName") String elbName, @PathParam("listenerArn") String listenerArn, @PathParam("ruleArn") String ruleArn, @Valid ModifyRuleRequest modifyRuleRequest) { if (config.isPresent()) { try { return applicationLoadBalancer .modifyRule(modifyRuleRequest.withRuleArn(ruleArn)); } catch (RuleNotFoundException notFound) { throw new WebApplicationException(String.format("Rule with ARN %s found", ruleArn), Status.NOT_FOUND); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @DELETE @Path("/rules/{ruleArn:.+}") public Response deleteRule(@PathParam("elbName") String elbName, @PathParam("listenerArn") String listenerArn, @PathParam("ruleArn") String ruleArn) { if (config.isPresent()) { try { applicationLoadBalancer.deleteRule(ruleArn); return Response.noContent().build(); } catch (RuleNotFoundException notFound) { throw new WebApplicationException(String.format("Rule with ARN %s not found", ruleArn), Status.NOT_FOUND); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("Amazon client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @GET @NoAuth @Path("/target-groups") public Collection<TargetGroup> getAllTargetGroups() { if (config.isPresent()) { return applicationLoadBalancer.getAllTargetGroups(); } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @POST @PathParam("/target-groups") public TargetGroup createTargetGroup(@Valid CreateTargetGroupRequest createTargetGroupRequest) { if (config.isPresent()) { try { return applicationLoadBalancer.createTargetGroup(createTargetGroupRequest); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @GET @NoAuth @Path("/target-groups/{targetGroup}") public TargetGroup getTargetGroup(@PathParam("targetGroup") String targetGroup) { if (config.isPresent()) { try { Optional<TargetGroup> maybeTargetGroup = applicationLoadBalancer.getTargetGroup(targetGroup); if (maybeTargetGroup.isPresent()) { return maybeTargetGroup.get(); } else { throw new WebApplicationException(String.format("TargetGroup with name %s not found", targetGroup), Status.NOT_FOUND); } } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS Client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @POST @Path("/target-groups/{targetGroup}") public TargetGroup modifyTargetGroup(@PathParam("targetGroup") String targetGroup, @Valid ModifyTargetGroupRequest modifyTargetGroupRequest) { if (config.isPresent()) { try { return applicationLoadBalancer .modifyTargetGroup(modifyTargetGroupRequest); } catch (TargetGroupNotFoundException notFound) { throw new WebApplicationException(String.format("Target group %s not found", targetGroup), Status.NOT_FOUND); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @GET @NoAuth @Path("/target-groups/{targetGroup}/targets") public Collection<TargetHealthDescription> getTargets(@PathParam("targetGroup") String targetGroup) { if (config.isPresent()) { try { Optional<TargetGroup> maybeTargetGroup = applicationLoadBalancer.getTargetGroup(targetGroup); if (maybeTargetGroup.isPresent()) { return applicationLoadBalancer.getTargetsOn(maybeTargetGroup.get()); } else { throw new WebApplicationException(String.format("TargetGroup with name %s not found", targetGroup), Status.NOT_FOUND); } } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("AWS Client exception %s", exn)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } @DELETE @Path("/target-groups/{targetGroup}/targets/{instanceId}") public AgentCheckInResponse removeFromTargetGroup(@PathParam("targetGroup") String targetGroup, @PathParam("instanceId") String instanceId) { if (instanceId == null) { throw new BaragonWebException("Must provide instance ID to remove target from group"); } else if (config.isPresent()) { AgentCheckInResponse result = applicationLoadBalancer.removeInstance(instanceId, targetGroup); if (result.getExceptionMessage().isPresent()) { throw new WebApplicationException(result.getExceptionMessage().get(), Status.INTERNAL_SERVER_ERROR); } return result; } else { throw new BaragonWebException("ElbSync and related actions not currently enabled"); } } @POST @Path("/target-group/{targetGroup}/targets") public AgentCheckInResponse addToTargetGroup(@PathParam("targetGroup") String targetGroup, @QueryParam("instanceId") String instanceId) { if (instanceId == null) { throw new BaragonWebException("Must provide instance ID to add target to group"); } else if (config.isPresent()) { try { return applicationLoadBalancer.registerInstance(instanceId, targetGroup); } catch (TargetGroupNotFoundException notFound) { throw new WebApplicationException(String.format("Target group %s not found", targetGroup), Status.NOT_FOUND); } catch (AmazonClientException exn) { throw new BaragonWebException(String.format("Failed to add instance %s to target group %s", instanceId, targetGroup)); } } else { throw new BaragonWebException("ElbSync and related actions are not currently enabled"); } } }