public static void checkSlotsVersion(String expectedSlotsVersion, Iterable<SlotStatus> slotStatuses) { Preconditions.checkNotNull(slotStatuses, "slotStatuses is null"); if (expectedSlotsVersion == null) { return; } String actualSlotsVersion = createSlotsVersion(slotStatuses); if (!expectedSlotsVersion.equals(actualSlotsVersion)) { throw new VersionConflictException(AIRSHIP_SLOTS_VERSION_HEADER, actualSlotsVersion); } }
public static void checkAgentsVersion(String expectedAgentsVersion, Iterable<AgentStatus> agentStatuses) { Preconditions.checkNotNull(agentStatuses, "agentStatuses is null"); if (expectedAgentsVersion == null) { return; } String actualAgentsVersion = createAgentsVersion(agentStatuses); if (!expectedAgentsVersion.equals(actualAgentsVersion)) { throw new VersionConflictException(AIRSHIP_AGENTS_VERSION_HEADER, actualAgentsVersion); } }
@POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response install( AssignmentRepresentation assignmentRepresentation, @DefaultValue("1") @QueryParam("limit") int limit, @Context UriInfo uriInfo, @HeaderParam(AIRSHIP_AGENTS_VERSION_HEADER) String expectedAgentsVersion) { Preconditions.checkNotNull(assignmentRepresentation, "assignmentRepresentation must not be null"); Preconditions.checkArgument(limit > 0, "limit must be at least 1"); Assignment assignment = assignmentRepresentation.toAssignment(); // select the target agents Predicate<AgentStatus> agentFilter = AgentFilterBuilder.build(uriInfo, transform(coordinator.getAgents(), idGetter()), transform(coordinator.getAllSlotStatus(), uuidGetter()), false, repository); List<AgentStatus> agents = coordinator.getAgents(agentFilter); // verify the expected status of agents checkAgentsVersion(expectedAgentsVersion, agents); // install the software List<SlotStatus> slots = coordinator.install(agentFilter, limit, assignment); // calculate unique prefix size with the new slots included return Response.ok(transform(slots, fromSlotStatus(coordinator.getAllSlotStatus(), repository))) .header(AIRSHIP_SLOTS_VERSION_HEADER, createSlotsVersion(slots)) .build(); }
@Path("{slotId}") @DELETE public Response terminateSlot(@HeaderParam(AIRSHIP_AGENT_VERSION_HEADER) String agentVersion, @HeaderParam(AIRSHIP_SLOT_VERSION_HEADER) String slotVersion, @PathParam("slotId") UUID slotId) { Preconditions.checkNotNull(slotId, "slotId must not be null"); Slot slot = agent.getSlot(slotId); if (slot == null) { return Response.status(Response.Status.NOT_FOUND).build(); } checkAgentVersion(agent.getAgentStatus(), agentVersion); checkSlotVersion(slot.status(), slotVersion); SlotStatus slotStatus = agent.terminateSlot(slotId); if (slotStatus == null) { return Response.status(Response.Status.NOT_FOUND).build(); } return Response.ok(SlotStatusRepresentation.from(slotStatus)) .header(AIRSHIP_AGENT_VERSION_HEADER, agent.getAgentStatus().getVersion()) .header(AIRSHIP_SLOT_VERSION_HEADER, slotStatus.getVersion()) .build(); }
this.assignment = assignment; this.state = state; this.version = VersionsUtil.createSlotVersion(id, state, assignment); this.installPath = installPath; this.expectedState = expectedState;
@Override public List<SlotStatusRepresentation> install(AgentFilter agentFilter, int count, Assignment assignment, String expectedAgentsVersion) { // select the target agents Predicate<AgentStatus> agentsPredicate = agentFilter.toAgentPredicate( transform(coordinator.getAgents(), idGetter()), transform(coordinator.getAllSlotStatus(), uuidGetter()), true, repository); List<AgentStatus> agents = coordinator.getAgents(agentsPredicate); // verify the expected status of agents checkAgentsVersion(expectedAgentsVersion, agents); // install the software List<SlotStatus> slots = coordinator.install(agentsPredicate, count, assignment); // update to latest state updateServiceInventory(); // calculate unique prefix size with the new slots included return transform(slots, fromSlotStatus(coordinator.getAllSlotStatus(), repository)); }
public List<SlotStatus> resetExpectedState(Predicate<SlotStatus> filter, String expectedSlotsVersion) { // filter the slots List<SlotStatus> filteredSlots = getAllSlotsStatus(filter); // verify the state of the system hasn't changed checkSlotsVersion(expectedSlotsVersion, filteredSlots); return ImmutableList.copyOf(transform(filteredSlots, new Function<SlotStatus, SlotStatus>() { @Override public SlotStatus apply(SlotStatus slotStatus) { if (slotStatus.getState() != SlotLifecycleState.UNKNOWN) { stateManager.setExpectedState(new ExpectedSlotStatus(slotStatus.getId(), slotStatus.getState(), slotStatus.getAssignment())); } else { stateManager.deleteExpectedState(slotStatus.getId()); } return slotStatus; } })); }
@POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response installSlot(@HeaderParam(AIRSHIP_AGENT_VERSION_HEADER) String agentVersion, InstallationRepresentation installation, @Context UriInfo uriInfo) { Preconditions.checkNotNull(installation, "installation must not be null"); checkAgentVersion(agent.getAgentStatus(), agentVersion); SlotStatus slotStatus = agent.install(installation.toInstallation()); return Response .created(getSelfUri(slotStatus.getId(), uriInfo.getBaseUri())) .entity(SlotStatusRepresentation.from(slotStatus)) .header(AIRSHIP_AGENT_VERSION_HEADER, agent.getAgentStatus().getVersion()) .header(AIRSHIP_SLOT_VERSION_HEADER, slotStatus.getVersion()) .build(); }
checkSlotVersion(slot.status(), slotVersion);
@Test public void testTerminateSlot() throws Exception { SlotStatus slotStatus = agent.install(appleInstallation); Request request = Request.Builder.prepareDelete() .setUri(urlFor("/v1/agent/slot", slotStatus.getId().toString())) .build(); Map<String, Object> response = client.execute(request, createJsonResponseHandler(mapCodec, Status.OK.getStatusCode())); assertNull(agent.getSlot(slotStatus.getId())); Map<String, Object> expected = ImmutableMap.<String, Object>builder() .put("id", slotStatus.getId().toString()) .put("shortId", slotStatus.getId().toString()) .put("self", urlFor(slotStatus).toASCIIString()) .put("externalUri", urlFor(slotStatus).toASCIIString()) .put("location", slotStatus.getLocation()) .put("shortLocation", slotStatus.getLocation()) .put("status", TERMINATED.toString()) .put("version", VersionsUtil.createSlotVersion(slotStatus.getId(), TERMINATED, null)) .put("resources", ImmutableMap.<String, Integer>of()) .build(); assertEquals(response, expected); }
@Override public List<SlotStatusRepresentation> install(AgentFilter agentFilter, int count, Assignment assignment, String expectedAgentsVersion) { // select the target agents Predicate<AgentStatus> agentsPredicate = agentFilter.toAgentPredicate( transform(coordinator.getAgents(), idGetter()), transform(coordinator.getAllSlotStatus(), uuidGetter()), true, repository); List<AgentStatus> agents = coordinator.getAgents(agentsPredicate); // verify the expected status of agents checkAgentsVersion(expectedAgentsVersion, agents); // install the software List<SlotStatus> slots = coordinator.install(agentsPredicate, count, assignment); // update to latest state updateServiceInventory(); // calculate unique prefix size with the new slots included return transform(slots, fromSlotStatus(coordinator.getAllSlotStatus(), repository)); }
@PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response assign(@HeaderParam(AIRSHIP_AGENT_VERSION_HEADER) String agentVersion, @HeaderParam(AIRSHIP_SLOT_VERSION_HEADER) String slotVersion, @PathParam("slotId") UUID slotId, InstallationRepresentation installation) { Preconditions.checkNotNull(slotId, "slotId must not be null"); Preconditions.checkNotNull(installation, "installation must not be null"); Slot slot = agent.getSlot(slotId); if (slot == null) { return Response.status(Response.Status.NOT_FOUND).build(); } checkAgentVersion(agent.getAgentStatus(), agentVersion); checkSlotVersion(slot.status(), slotVersion); SlotStatus status = slot.assign(installation.toInstallation()); return Response.ok(SlotStatusRepresentation.from(status)) .header(AIRSHIP_AGENT_VERSION_HEADER, agent.getAgentStatus().getVersion()) .header(AIRSHIP_SLOT_VERSION_HEADER, status.getVersion()) .build(); } }
private List<RemoteSlot> selectRemoteSlots(Predicate<SlotStatus> filter, String expectedSlotsVersion) { // filter the slots List<RemoteSlot> filteredSlots = ImmutableList.copyOf(filter(getAllSlots(), filterSlotsBy(filter))); // verify the state of the system hasn't changed checkSlotsVersion(expectedSlotsVersion, getAllSlotsStatus(filter, filteredSlots)); return filteredSlots; }
@GET @Produces(MediaType.APPLICATION_JSON) public Response getAllSlots(@Context UriInfo uriInfo) { // build filter List<UUID> uuids = transform(coordinator.getAllSlotStatus(), uuidGetter()); Predicate<SlotStatus> slotFilter = SlotFilterBuilder.build(uriInfo, false, uuids); // select slots List<SlotStatus> slots = coordinator.getAllSlotsStatus(slotFilter); // build response return Response.ok(Iterables.transform(slots, fromSlotStatus(coordinator.getAllSlotStatus(), repository))) .header(AIRSHIP_SLOTS_VERSION_HEADER, createSlotsVersion(slots)) .build(); }
@GET @Path("/agent") @Produces(MediaType.APPLICATION_JSON) public Response getAllAgents(@Context UriInfo uriInfo) { List<SlotStatus> allSlotStatus = coordinator.getAllSlotStatus(); Predicate<AgentStatus> agentPredicate = AgentFilterBuilder.build(uriInfo, transform(coordinator.getAgents(), idGetter()), transform(allSlotStatus, SlotStatus.uuidGetter()), false, repository); List<AgentStatus> agents = coordinator.getAgents(agentPredicate); return Response.ok(transform(agents, fromAgentStatus(coordinator.getAgents(), repository))) .header(AIRSHIP_AGENTS_VERSION_HEADER, createAgentsVersion(agents)) .build(); }
@Test public void testTerminateSlot() throws Exception { SlotStatus slotStatus = agent.install(appleInstallation); Request request = Request.Builder.prepareDelete() .setUri(urlFor("/v1/agent/slot", slotStatus.getId().toString())) .build(); Map<String, Object> response = client.execute(request, createJsonResponseHandler(mapCodec, Status.OK.getStatusCode())); assertNull(agent.getSlot(slotStatus.getId())); Map<String, Object> expected = ImmutableMap.<String, Object>builder() .put("id", slotStatus.getId().toString()) .put("shortId", slotStatus.getId().toString()) .put("self", urlFor(slotStatus).toASCIIString()) .put("externalUri", urlFor(slotStatus).toASCIIString()) .put("location", slotStatus.getLocation()) .put("shortLocation", slotStatus.getLocation()) .put("status", TERMINATED.toString()) .put("version", VersionsUtil.createSlotVersion(slotStatus.getId(), TERMINATED, null)) .put("resources", ImmutableMap.<String, Integer>of()) .build(); assertEquals(response, expected); }
@POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response upgrade(UpgradeVersions upgradeVersions, @Context UriInfo uriInfo, @HeaderParam(AIRSHIP_SLOTS_VERSION_HEADER) String expectedSlotsVersion, @HeaderParam(AIRSHIP_FORCE_HEADER) boolean force) { Preconditions.checkNotNull(upgradeVersions, "upgradeRepresentation must not be null"); // build filter List<UUID> uuids = Lists.transform(coordinator.getAllSlotStatus(), SlotStatus.uuidGetter()); Predicate<SlotStatus> slotFilter = SlotFilterBuilder.build(uriInfo, true, uuids); // upgrade slots List<SlotStatus> results = coordinator.upgrade(slotFilter, upgradeVersions, expectedSlotsVersion, force); // build response return Response.ok(transform(results, fromSlotStatus(coordinator.getAllSlotStatus(), repository))) .header(AIRSHIP_SLOTS_VERSION_HEADER, createSlotsVersion(results)) .build(); } }
@Override public CommanderResponse<List<AgentStatusRepresentation>> showAgents(AgentFilter agentFilter) { Predicate<AgentStatus> agentPredicate = agentFilter.toAgentPredicate( transform(coordinator.getAgents(), idGetter()), transform(coordinator.getAllSlotStatus(), SlotStatus.uuidGetter()), true, repository); List<AgentStatus> agentStatuses = coordinator.getAgents(agentPredicate); // update just in case something changed updateServiceInventory(); return createCommanderResponse(createAgentsVersion(agentStatuses), transform(agentStatuses, fromAgentStatus(coordinator.getAgents(), repository))); }
@Test public void testStart() throws Exception { SlotStatus slotStatus = agent.install(appleInstallation); Request request = Request.Builder.preparePut() .setUri(urlFor(slotStatus, "lifecycle")) .setBodyGenerator(createStaticBodyGenerator("running", UTF_8)) .build(); Map<String, Object> response = client.execute(request, createJsonResponseHandler(mapCodec, Status.OK.getStatusCode())); Map<String, Object> expected = ImmutableMap.<String, Object>builder() .put("id", slotStatus.getId().toString()) .put("shortId", slotStatus.getId().toString()) .put("binary", appleInstallation.getAssignment().getBinary()) .put("shortBinary", appleInstallation.getAssignment().getBinary()) .put("config", appleInstallation.getAssignment().getConfig()) .put("shortConfig", appleInstallation.getAssignment().getConfig()) .put("self", urlFor(slotStatus).toASCIIString()) .put("externalUri", urlFor(slotStatus).toASCIIString()) .put("location", slotStatus.getLocation()) .put("shortLocation", slotStatus.getLocation()) .put("status", RUNNING.toString()) .put("version", VersionsUtil.createSlotVersion(slotStatus.getId(), RUNNING, appleInstallation.getAssignment())) .put("installPath", slotStatus.getInstallPath()) .put("resources", ImmutableMap.<String, Integer>of("memory", 512)) .build(); assertEquals(response, expected); }
@DELETE @Produces(MediaType.APPLICATION_JSON) public Response terminateSlots(@Context UriInfo uriInfo, @HeaderParam(AIRSHIP_SLOTS_VERSION_HEADER) String expectedSlotsVersion) { // build filter List<UUID> uuids = transform(coordinator.getAllSlotStatus(), uuidGetter()); Predicate<SlotStatus> slotFilter = SlotFilterBuilder.build(uriInfo, true, uuids); // terminate slots List<SlotStatus> result = coordinator.terminate(slotFilter, expectedSlotsVersion); // build response return Response.ok(transform(result, fromSlotStatus(coordinator.getAllSlotStatus(), repository))) .header(AIRSHIP_SLOTS_VERSION_HEADER, createSlotsVersion(result)) .build(); } }