@Override public ImmutableList<ServiceDescriptor> getServiceInventory(Iterable<SlotStatus> allSlotStatus) { ImmutableList.Builder<ServiceDescriptor> newDescriptors = ImmutableList.builder(); for (SlotStatus slotStatus : allSlotStatus) { // if the self reference is null, the slot is totally offline so skip for now if (slotStatus.getSelf() == null) { continue; } List<ServiceDescriptor> serviceDescriptors = getServiceInventory(slotStatus); if (serviceDescriptors == null) { continue; } for (ServiceDescriptor serviceDescriptor : serviceDescriptors) { newDescriptors.add( new ServiceDescriptor( null, slotStatus.getId().toString(), serviceDescriptor.getType(), serviceDescriptor.getPool(), slotStatus.getLocation(), slotStatus.getState() == SlotLifecycleState.RUNNING ? ServiceState.RUNNING : ServiceState.STOPPED, interpolateProperties(serviceDescriptor.getProperties(), slotStatus))); } } return newDescriptors.build(); }
@Test public void testTerminate() throws Exception { initializeOneAgent(); AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId); SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId); SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId); Request request = Request.Builder.prepareDelete() .setUri( coordinatorUriBuilder() .appendPath("/v1/slot") .addParameter("host", "apple*") .build()) .build(); List<SlotStatusRepresentation> actual = httpClient.execute( request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode())); apple1Status = apple1Status.changeState(TERMINATED); apple2Status = apple2Status.changeState(TERMINATED); SlotStatus bananaStatus = coordinator.getAgentByAgentId(agentId).getSlotStatus(bananaSlotId); List<SlotStatusRepresentation> expected = ImmutableList.of( slotStatusRepresentationFactory.create(apple1Status), slotStatusRepresentationFactory.create(apple2Status.changeState(TERMINATED))); assertEqualsNoOrder(actual, expected); assertEquals(apple1Status.getState(), TERMINATED); assertEquals(apple2Status.getState(), TERMINATED); assertEquals(bananaStatus.getState(), STOPPED); }
private void assertOkResponse(Response response, SlotLifecycleState state, UUID... slotIds) { assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId); Builder<SlotStatusRepresentation> builder = ImmutableList.builder(); for (UUID slotId : slotIds) { SlotStatus slotStatus = agentStatus.getSlotStatus(slotId); builder.add( SlotStatusRepresentation.from(slotStatus.changeState(state), prefixSize, MOCK_REPO)); assertEquals(slotStatus.getAssignment(), APPLE_ASSIGNMENT); } assertEqualsNoOrder((Collection<?>) response.getEntity(), builder.build()); assertNull( response .getMetadata() .get("Content-Type")); // content type is set by jersey based on @Produces }
private Map<String, String> interpolateProperties( Map<String, String> properties, SlotStatus slotStatus) { ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); for (Entry<String, String> entry : properties.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); value = value.replaceAll(Pattern.quote("${airship.host}"), slotStatus.getSelf().getHost()); builder.put(key, value); } return builder.build(); }
@Test public void testLifecycleUnknown() throws Exception { initializeOneAgent(); Request request = Request.Builder.preparePut() .setUri( coordinatorUriBuilder() .appendPath("/v1/slot/lifecycle") .addParameter("binary", "apple:*") .build()) .setBodyGenerator(createStaticBodyGenerator("unknown", UTF_8)) .build(); StatusResponse response = httpClient.execute(request, createStatusResponseHandler()); AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId); SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId); SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId); SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId); assertEquals(response.getStatusCode(), Status.BAD_REQUEST.getStatusCode()); assertEquals(apple1Status.getState(), STOPPED); assertEquals(apple2Status.getState(), STOPPED); assertEquals(bananaStatus.getState(), STOPPED); }
@Test public void testKill() throws Exception { initializeOneAgent(); coordinator.setState(RUNNING, Predicates.<SlotStatus>alwaysTrue(), null); Request request = Request.Builder.preparePut() .setUri( coordinatorUriBuilder() .appendPath("/v1/slot/lifecycle") .addParameter("binary", "apple:*") .build()) .setBodyGenerator(createStaticBodyGenerator("killing", UTF_8)) .build(); List<SlotStatusRepresentation> actual = httpClient.execute( request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode())); AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId); SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId); SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId); SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId); List<SlotStatusRepresentation> expected = ImmutableList.of( slotStatusRepresentationFactory.create(apple1Status), slotStatusRepresentationFactory.create(apple2Status)); assertEqualsNoOrder(actual, expected); assertEquals(apple1Status.getState(), STOPPED); assertEquals(apple2Status.getState(), STOPPED); assertEquals(bananaStatus.getState(), RUNNING); }
@Test public void testUpgrade() throws Exception { initializeOneAgent(); UpgradeVersions upgradeVersions = new UpgradeVersions("2.0", "2.0"); Request request = Request.Builder.preparePost() .setUri( coordinatorUriBuilder() .appendPath("/v1/slot/assignment") .addParameter("host", "apple*") .build()) .setHeader(CONTENT_TYPE, APPLICATION_JSON) .setBodyGenerator(jsonBodyGenerator(upgradeVersionsCodec, upgradeVersions)) .build(); List<SlotStatusRepresentation> actual = httpClient.execute( request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode())); AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId); SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId); SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId); SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId); List<SlotStatusRepresentation> expected = ImmutableList.of( slotStatusRepresentationFactory.create(apple1Status), slotStatusRepresentationFactory.create(apple2Status)); assertEqualsNoOrder(actual, expected); assertEquals(apple1Status.getState(), STOPPED); assertEquals(apple2Status.getState(), STOPPED); assertEquals(bananaStatus.getState(), STOPPED); assertEquals( apple1Status.getAssignment(), upgradeVersions.upgradeAssignment(MOCK_REPO, APPLE_ASSIGNMENT)); assertEquals( apple2Status.getAssignment(), upgradeVersions.upgradeAssignment(MOCK_REPO, APPLE_ASSIGNMENT)); assertEquals(bananaStatus.getAssignment(), BANANA_ASSIGNMENT); }
private List<ServiceDescriptor> getServiceInventory(SlotStatus slotStatus) { Assignment assignment = slotStatus.getAssignment(); if (assignment == null) { return null; } String config = assignment.getConfig(); File cacheFile = getCacheFile(config); if (cacheFile.canRead()) { try { String json = CharStreams.toString(Files.newReaderSupplier(cacheFile, Charsets.UTF_8)); List<ServiceDescriptor> descriptors = descriptorsJsonCodec.fromJson(json); invalidServiceInventory.remove(config); return descriptors; } catch (Exception ignored) { // delete the bad cache file cacheFile.delete(); } } InputSupplier<? extends InputStream> configFile = ConfigUtils.newConfigEntrySupplier(repository, config, "airship-service-inventory.json"); if (configFile == null) { return null; } try { String json; try { json = CharStreams.toString(CharStreams.newReaderSupplier(configFile, Charsets.UTF_8)); } catch (FileNotFoundException e) { // no service inventory in the config, so replace with json null so caching works json = "null"; } invalidServiceInventory.remove(config); // cache json cacheFile.getParentFile().mkdirs(); Files.write(json, cacheFile, Charsets.UTF_8); List<ServiceDescriptor> descriptors = descriptorsJsonCodec.fromJson(json); return descriptors; } catch (Exception e) { if (invalidServiceInventory.add(config)) { log.error(e, "Unable to read service inventory for %s" + config); } } return null; }
@BeforeMethod public void setup() throws Exception { NodeInfo nodeInfo = new NodeInfo("testing"); MockProvisioner provisioner = new MockProvisioner(); coordinator = new Coordinator( nodeInfo, new HttpServerInfo(new HttpServerConfig(), nodeInfo), new CoordinatorConfig().setStatusExpiration(new Duration(1, TimeUnit.DAYS)), provisioner.getCoordinatorFactory(), provisioner.getAgentFactory(), MOCK_REPO, provisioner, new InMemoryStateManager(), new MockServiceInventory()); resource = new CoordinatorLifecycleResource(coordinator, MOCK_REPO); apple1SlotId = UUID.randomUUID(); SlotStatus appleSlotStatus1 = createSlotStatus( apple1SlotId, URI.create("fake://foo/v1/agent/slot/apple1"), URI.create("fake://foo/v1/agent/slot/apple1"), "instance", "/location", STOPPED, APPLE_ASSIGNMENT, "/apple1", ImmutableMap.<String, Integer>of()); apple2SlotId = UUID.randomUUID(); SlotStatus appleSlotStatus2 = createSlotStatus( apple2SlotId, URI.create("fake://foo/v1/agent/slot/apple1"), URI.create("fake://foo/v1/agent/slot/apple1"), "instance", "/location", STOPPED, APPLE_ASSIGNMENT, "/apple2", ImmutableMap.<String, Integer>of()); bananaSlotId = UUID.randomUUID(); SlotStatus bananaSlotStatus = createSlotStatus( bananaSlotId, URI.create("fake://foo/v1/agent/slot/banana"), URI.create("fake://foo/v1/agent/slot/banana"), "instance", "/location", STOPPED, BANANA_ASSIGNMENT, "/banana", ImmutableMap.<String, Integer>of()); agentId = UUID.randomUUID().toString(); AgentStatus agentStatus = new AgentStatus( agentId, ONLINE, "instance-id", URI.create("fake://foo/"), URI.create("fake://foo/"), "/unknown/location", "instance.type", ImmutableList.of(appleSlotStatus1, appleSlotStatus2, bananaSlotStatus), ImmutableMap.of("cpu", 8, "memory", 1024)); prefixSize = shortestUniquePrefix( asList( appleSlotStatus1.getId().toString(), appleSlotStatus2.getId().toString(), bananaSlotStatus.getId().toString()), MIN_PREFIX_SIZE); provisioner.addAgents(agentStatus); coordinator.updateAllAgents(); }