Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Slave/Rack Resource use proxy to leader #1938

Merged
merged 1 commit into from
May 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;

import org.apache.curator.framework.recipes.leader.LeaderLatch;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.hubspot.singularity.MachineState;
import com.hubspot.singularity.SingularityAction;
Expand All @@ -20,15 +23,17 @@
import com.hubspot.singularity.data.AbstractMachineManager.StateChangeResult;
import com.hubspot.singularity.data.SingularityValidator;
import com.hubspot.singularity.expiring.SingularityExpiringMachineState;
import com.ning.http.client.AsyncHttpClient;

public abstract class AbstractMachineResource<T extends SingularityMachineAbstraction<T>> {
public abstract class AbstractMachineResource<T extends SingularityMachineAbstraction<T>> extends AbstractLeaderAwareResource {

protected final AbstractMachineManager<T> manager;

protected final SingularityAuthorizationHelper authorizationHelper;
private final SingularityValidator validator;

public AbstractMachineResource(AbstractMachineManager<T> manager, SingularityAuthorizationHelper authorizationHelper, SingularityValidator validator) {
public AbstractMachineResource(AsyncHttpClient httpClient, LeaderLatch leaderLatch, ObjectMapper objectMapper, AbstractMachineManager<T> manager, SingularityAuthorizationHelper authorizationHelper, SingularityValidator validator) {
super(httpClient, leaderLatch, objectMapper);
this.manager = manager;
this.authorizationHelper = authorizationHelper;
this.validator = validator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@

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 javax.ws.rs.core.Response;

import org.apache.curator.framework.recipes.leader.LeaderLatch;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.hubspot.singularity.MachineState;
Expand All @@ -24,6 +30,7 @@
import com.hubspot.singularity.data.RackManager;
import com.hubspot.singularity.data.SingularityValidator;
import com.hubspot.singularity.expiring.SingularityExpiringMachineState;
import com.ning.http.client.AsyncHttpClient;

import io.dropwizard.auth.Auth;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -40,8 +47,13 @@
public class RackResource extends AbstractMachineResource<SingularityRack> {

@Inject
public RackResource(RackManager rackManager, SingularityAuthorizationHelper authorizationHelper, SingularityValidator validator) {
super(rackManager, authorizationHelper, validator);
public RackResource(AsyncHttpClient httpClient,
LeaderLatch leaderLatch,
ObjectMapper objectMapper,
RackManager rackManager,
SingularityAuthorizationHelper authorizationHelper,
SingularityValidator validator) {
super(httpClient, leaderLatch, objectMapper, rackManager, authorizationHelper, validator);
}

@Override
Expand Down Expand Up @@ -72,52 +84,73 @@ public List<SingularityMachineStateHistoryUpdate> getRackHistory(
@DELETE
@Path("/rack/{rackId}")
@Operation(summary = "Remove a known rack, erasing history. This operation will cancel decommissioning of racks")
public void removeRack(
public Response removeRack(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Rack ID") @PathParam("rackId") String rackId) {
super.remove(rackId, user);
return maybeProxyToLeader(requestContext, Response.class, null, () -> {
super.remove(rackId, user);
return Response.ok().build();
});
}

@POST
@Path("/rack/{rackId}/decommission")
@Operation(summary = "Begin decommissioning a specific active rack")
public void decommissionRack(
public Response decommissionRack(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Rack ID") @PathParam("rackId") String rackId,
@RequestBody(description = "Settings related to changing the state of a rack") SingularityMachineChangeRequest changeRequest) {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.decommission(rackId, maybeChangeRequest, user, SingularityAction.DECOMMISSION_RACK);
return maybeProxyToLeader(requestContext, Response.class, changeRequest, () -> {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.decommission(rackId, maybeChangeRequest, user, SingularityAction.DECOMMISSION_RACK);
return Response.ok().build();
});

}

@POST
@Path("/rack/{rackId}/freeze")
@Operation(summary = "Freeze a specific rack")
public void freezeRack(
public Response freezeRack(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Rack ID") @PathParam("rackId") String rackId,
@RequestBody(description = "Settings related to changing the state of a slave") SingularityMachineChangeRequest changeRequest) {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.freeze(rackId, maybeChangeRequest, user, SingularityAction.FREEZE_RACK);
return maybeProxyToLeader(requestContext, Response.class, changeRequest, () -> {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.freeze(rackId, maybeChangeRequest, user, SingularityAction.FREEZE_RACK);
return Response.ok().build();
});
}

@POST
@Path("/rack/{rackId}/activate")
@Operation(summary = "Activate a decomissioning rack, canceling decomission without erasing history")
public void activateRack(
public Response activateRack(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Rack ID") @PathParam("rackId") String rackId,
@RequestBody(description = "Settings related to changing the state of a slave") SingularityMachineChangeRequest changeRequest) {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.activate(rackId, maybeChangeRequest, user, SingularityAction.ACTIVATE_RACK);
return maybeProxyToLeader(requestContext, Response.class, changeRequest, () -> {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.activate(rackId, maybeChangeRequest, user, SingularityAction.ACTIVATE_RACK);
return Response.ok().build();
});
}

@DELETE
@Path("/rack/{rackId}/expiring")
@Operation(summary = "Delete any expiring machine state changes for this rack")
public void deleteExpiringStateChange(
public Response deleteExpiringStateChange(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Rack ID") @PathParam("rackId") String rackId) {
super.cancelExpiring(rackId, user);
return maybeProxyToLeader(requestContext, Response.class, null, () -> {
super.cancelExpiring(rackId, user);
return Response.ok().build();
});
}

@GET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
Expand All @@ -10,8 +11,13 @@
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 javax.ws.rs.core.Response;

import org.apache.curator.framework.recipes.leader.LeaderLatch;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.hubspot.singularity.MachineState;
Expand All @@ -25,6 +31,7 @@
import com.hubspot.singularity.data.SingularityValidator;
import com.hubspot.singularity.data.SlaveManager;
import com.hubspot.singularity.expiring.SingularityExpiringMachineState;
import com.ning.http.client.AsyncHttpClient;

import io.dropwizard.auth.Auth;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -40,8 +47,13 @@
@Tags({@Tag(name = "Slaves")})
public class SlaveResource extends AbstractMachineResource<SingularitySlave> {
@Inject
public SlaveResource(SlaveManager slaveManager, SingularityAuthorizationHelper authorizationHelper, SingularityValidator validator) {
super(slaveManager, authorizationHelper, validator);
public SlaveResource(AsyncHttpClient httpClient,
LeaderLatch leaderLatch,
ObjectMapper objectMapper,
SlaveManager slaveManager,
SingularityAuthorizationHelper authorizationHelper,
SingularityValidator validator) {
super(httpClient, leaderLatch, objectMapper, slaveManager, authorizationHelper, validator);
}

@Override
Expand Down Expand Up @@ -82,20 +94,32 @@ public Optional<SingularitySlave> getSlave(
@DELETE
@Path("/slave/{slaveId}")
@Operation(summary = "Remove a known slave, erasing history. This operation will cancel decomissioning of the slave")
public void removeSlave(
public Response removeSlave(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Active SlaveId") @PathParam("slaveId") String slaveId) {
super.remove(slaveId, user);
return maybeProxyToLeader(requestContext, Response.class, null, () -> {
super.remove(slaveId, user);
return Response.ok().build();
});
}

@POST
@Path("/slave/{slaveId}/decommission")
@Operation(summary = "Begin decommissioning a specific active slave")
@Consumes({ MediaType.APPLICATION_JSON })
public void decommissionSlave(
public Response decommissionSlave(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Active slaveId") @PathParam("slaveId") String slaveId,
@RequestBody(description = "Settings related to changing the state of a slave") SingularityMachineChangeRequest changeRequest) {
return maybeProxyToLeader(requestContext, Response.class, changeRequest, () -> {
decommissionSlave(user, slaveId, changeRequest);
return Response.ok().build();
});
}

public void decommissionSlave(SingularityUser user, String slaveId, SingularityMachineChangeRequest changeRequest) {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.decommission(slaveId, maybeChangeRequest, user, SingularityAction.DECOMMISSION_SLAVE);
}
Expand All @@ -104,10 +128,18 @@ public void decommissionSlave(
@Path("/slave/{slaveId}/freeze")
@Operation(summary = "Freeze tasks on a specific slave")
@Consumes({ MediaType.APPLICATION_JSON })
public void freezeSlave(
public Response freezeSlave(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Slave ID") @PathParam("slaveId") String slaveId,
@RequestBody(description = "Settings related to changing the state of a slave") SingularityMachineChangeRequest changeRequest) {
return maybeProxyToLeader(requestContext, Response.class, changeRequest, () -> {
freezeSlave(user, slaveId, changeRequest);
return Response.ok().build();
});
}

public void freezeSlave(SingularityUser user, String slaveId, SingularityMachineChangeRequest changeRequest) {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.freeze(slaveId, maybeChangeRequest, user, SingularityAction.FREEZE_SLAVE);
}
Expand All @@ -116,21 +148,33 @@ public void freezeSlave(
@Path("/slave/{slaveId}/activate")
@Operation(summary = "Activate a decomissioning slave, canceling decomission without erasing history")
@Consumes({ MediaType.APPLICATION_JSON })
public void activateSlave(
public Response activateSlave(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Active slaveId") @PathParam("slaveId") String slaveId,
@RequestBody(description = "Settings related to changing the state of a slave") SingularityMachineChangeRequest changeRequest) {
return maybeProxyToLeader(requestContext, Response.class, changeRequest, () -> {
activateSlave(user, slaveId, changeRequest);
return Response.ok().build();
});
}

public void activateSlave(SingularityUser user, String slaveId, SingularityMachineChangeRequest changeRequest) {
final Optional<SingularityMachineChangeRequest> maybeChangeRequest = Optional.fromNullable(changeRequest);
super.activate(slaveId, maybeChangeRequest, user, SingularityAction.ACTIVATE_SLAVE);
}

@DELETE
@Path("/slave/{slaveId}/expiring")
@Operation(summary = "Delete any expiring machine state changes for this slave")
public void deleteExpiringStateChange(
public Response deleteExpiringStateChange(
@Context HttpServletRequest requestContext,
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "Active slaveId") @PathParam("slaveId") String slaveId) {
super.cancelExpiring(slaveId, user);
return maybeProxyToLeader(requestContext, Response.class, null, () -> {
super.cancelExpiring(slaveId, user);
return Response.ok().build();
});
}

@GET
Expand All @@ -142,8 +186,11 @@ public List<SingularityExpiringMachineState> getExpiringStateChanges(@Parameter(

@DELETE
@Path("/dead")
public void clearAllDeadSlaves(@Auth SingularityUser user) {
authorizationHelper.checkAdminAuthorization(user);
manager.getObjectsFiltered(MachineState.DEAD).forEach((s) -> manager.deleteObject(s.getId()));
public Response clearAllDeadSlaves(@Context HttpServletRequest requestContext, @Auth SingularityUser user) {
return maybeProxyToLeader(requestContext, Response.class, null, () -> {
authorizationHelper.checkAdminAuthorization(user);
manager.getObjectsFiltered(MachineState.DEAD).forEach((s) -> manager.deleteObject(s.getId()));
return Response.ok().build();
});
}
}