package com.hubspot.singularity.resources; import java.util.Collections; import java.util.List; import javax.servlet.http.HttpServletRequest; 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.core.Context; import javax.ws.rs.core.MediaType; import com.google.common.base.Optional; import com.google.inject.Inject; import com.hubspot.singularity.SingularityAction; import com.hubspot.singularity.SingularityDisabledAction; import com.hubspot.singularity.SingularityDisasterType; import com.hubspot.singularity.SingularityDisastersData; import com.hubspot.singularity.SingularityService; import com.hubspot.singularity.SingularityTaskCredits; import com.hubspot.singularity.SingularityUser; import com.hubspot.singularity.api.SingularityDisabledActionRequest; import com.hubspot.singularity.auth.SingularityAuthorizationHelper; import com.hubspot.singularity.data.DisasterManager; import com.wordnik.swagger.annotations.Api; import com.wordnik.swagger.annotations.ApiOperation; @Path(DisastersResource.PATH) @Produces(MediaType.APPLICATION_JSON) @Api(description="Manages Singularity Deploys for existing requests", value=DisastersResource.PATH) public class DisastersResource { public static final String PATH = SingularityService.API_BASE_PATH + "/disasters"; private final DisasterManager disasterManager; private final SingularityAuthorizationHelper authorizationHelper; private final Optional<SingularityUser> user; @Inject public DisastersResource(DisasterManager disasterManager, SingularityAuthorizationHelper authorizationHelper, Optional<SingularityUser> user) { this.disasterManager = disasterManager; this.authorizationHelper = authorizationHelper; this.user = user; } @GET @Path("/stats") @ApiOperation(value="Get current data related to disaster detection", response=SingularityDisastersData.class) public SingularityDisastersData disasterStats() { authorizationHelper.checkAdminAuthorization(user); return disasterManager.getDisastersData(); } @GET @Path("/active") @ApiOperation(value="Get a list of current active disasters") public List<SingularityDisasterType> activeDisasters() { authorizationHelper.checkAdminAuthorization(user); return disasterManager.getActiveDisasters(); } @POST @Path("/disable") @ApiOperation(value="Do not allow the automated poller to disable actions when a disaster is detected") public void disableAutomatedDisasterCreation() { authorizationHelper.checkAdminAuthorization(user); disasterManager.disableAutomatedDisabledActions(); } @POST @Path("/enable") @ApiOperation(value="Allow the automated poller to disable actions when a disaster is detected") public void enableAutomatedDisasterCreation() { authorizationHelper.checkAdminAuthorization(user); disasterManager.enableAutomatedDisabledActions(); } @DELETE @Path("/active/{type}") @ApiOperation(value="Remove an active disaster (make it inactive)") public void removeDisaster(@PathParam("type") SingularityDisasterType type) { authorizationHelper.checkAdminAuthorization(user); disasterManager.removeDisaster(type); } @POST @Path("/active/{type}") @ApiOperation(value="Create a new active disaster") public void newDisaster(@PathParam("type") SingularityDisasterType type) { authorizationHelper.checkAdminAuthorization(user); disasterManager.addDisaster(type); disasterManager.addDisabledActionsForDisasters(Collections.singletonList(type)); } @GET @Path("/disabled-actions") @ApiOperation(value="Get a list of actions that are currently disable") public List<SingularityDisabledAction> disabledActions() { authorizationHelper.checkAdminAuthorization(user); return disasterManager.getDisabledActions(); } @POST @Path("/disabled-actions/{action}") @ApiOperation(value="Disable a specific action") public void disableAction(@PathParam("action") SingularityAction action, SingularityDisabledActionRequest disabledActionRequest) { final Optional<SingularityDisabledActionRequest> maybeRequest = Optional.fromNullable(disabledActionRequest); authorizationHelper.checkAdminAuthorization(user); Optional<String> message = maybeRequest.isPresent() ? maybeRequest.get().getMessage() : Optional.<String>absent(); disasterManager.disable(action, message, user, false, Optional.<Long>absent()); } @DELETE @Path("/disabled-actions/{action}") @ApiOperation(value="Re-enable a specific action if it has been disabled") public void enableAction(@PathParam("action") SingularityAction action) { authorizationHelper.checkAdminAuthorization(user); disasterManager.enable(action); } @POST @Path("/task-credits") @ApiOperation(value="Add task credits, enables task credit system if not already enabled") public void addTaskCredits(@QueryParam("credits") Optional<Integer> credits) throws Exception { authorizationHelper.checkAdminAuthorization(user); disasterManager.enableTaskCredits(); disasterManager.enqueueCreditsChange(credits.or(0)); } @DELETE @Path("/task-credits") @ApiOperation(value="Disable task credit system") public void disableTaskCredits(@Context HttpServletRequest request) throws Exception { authorizationHelper.checkAdminAuthorization(user); disasterManager.disableTaskCredits(); } @GET @Path("/task-credits") @ApiOperation(value="Get task credit data") public SingularityTaskCredits getTaskCreditData() throws Exception { authorizationHelper.checkAdminAuthorization(user); return new SingularityTaskCredits(disasterManager.isTaskCreditEnabled(), disasterManager.getTaskCredits()); } }