/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.airlift.airship.coordinator; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.inject.Binder; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.util.Modules; import io.airlift.airship.shared.AgentLifecycleState; import io.airlift.airship.shared.AgentStatus; import io.airlift.airship.shared.AgentStatusRepresentation; import io.airlift.airship.shared.CoordinatorLifecycleState; import io.airlift.airship.shared.CoordinatorStatus; import io.airlift.airship.shared.CoordinatorStatusRepresentation; import io.airlift.airship.shared.HttpUriBuilder; import io.airlift.airship.shared.Repository; import io.airlift.airship.shared.SlotStatus; import io.airlift.airship.shared.SlotStatusRepresentation; import io.airlift.airship.shared.SlotStatusRepresentation.SlotStatusRepresentationFactory; import io.airlift.airship.shared.UpgradeVersions; import io.airlift.configuration.ConfigurationFactory; import io.airlift.configuration.ConfigurationModule; import io.airlift.event.client.EventModule; import io.airlift.http.client.HttpClient; import io.airlift.http.client.Request; import io.airlift.http.client.StatusResponseHandler.StatusResponse; import io.airlift.http.client.jetty.JettyHttpClient; import io.airlift.http.server.testing.TestingHttpServer; import io.airlift.http.server.testing.TestingHttpServerModule; import io.airlift.jaxrs.JaxrsModule; import io.airlift.json.JsonCodec; import io.airlift.json.JsonModule; import io.airlift.node.testing.TestingNodeModule; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import javax.inject.Singleton; import javax.ws.rs.core.Response.Status; import java.net.URI; import java.util.List; import java.util.Map; import java.util.UUID; import static com.google.common.base.Charsets.UTF_8; import static com.google.common.net.HttpHeaders.CONTENT_TYPE; import static com.google.inject.Scopes.SINGLETON; import static io.airlift.airship.coordinator.CoordinatorSlotResource.MIN_PREFIX_SIZE; import static io.airlift.airship.coordinator.TestingMavenRepository.MOCK_REPO; import static io.airlift.airship.shared.AgentLifecycleState.ONLINE; import static io.airlift.airship.shared.AssignmentHelper.APPLE_ASSIGNMENT; import static io.airlift.airship.shared.AssignmentHelper.BANANA_ASSIGNMENT; import static io.airlift.airship.shared.ExtraAssertions.assertEqualsNoOrder; import static io.airlift.airship.shared.HttpUriBuilder.uriBuilderFrom; import static io.airlift.airship.shared.SlotLifecycleState.RUNNING; import static io.airlift.airship.shared.SlotLifecycleState.STOPPED; import static io.airlift.airship.shared.SlotLifecycleState.TERMINATED; import static io.airlift.airship.shared.SlotStatus.createSlotStatus; import static io.airlift.airship.shared.Strings.shortestUniquePrefix; import static io.airlift.http.client.JsonBodyGenerator.jsonBodyGenerator; import static io.airlift.http.client.JsonResponseHandler.createJsonResponseHandler; import static io.airlift.http.client.StaticBodyGenerator.createStaticBodyGenerator; import static io.airlift.http.client.StatusResponseHandler.createStatusResponseHandler; import static io.airlift.json.JsonCodec.jsonCodec; import static io.airlift.json.JsonCodec.listJsonCodec; import static io.airlift.testing.Closeables.closeQuietly; import static java.util.Arrays.asList; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class TestCoordinatorServer { private HttpClient httpClient; private TestingHttpServer server; private Coordinator coordinator; private MockProvisioner provisioner; private InMemoryStateManager stateManager; private Repository repository; private final JsonCodec<List<CoordinatorStatusRepresentation>> coordinatorStatusesCodec = listJsonCodec(CoordinatorStatusRepresentation.class); private final JsonCodec<List<AgentStatusRepresentation>> agentStatusesCodec = listJsonCodec(AgentStatusRepresentation.class); private final JsonCodec<List<SlotStatusRepresentation>> slotStatusesCodec = listJsonCodec(SlotStatusRepresentation.class); private final JsonCodec<CoordinatorProvisioningRepresentation> coordinatorProvisioningCodec = jsonCodec(CoordinatorProvisioningRepresentation.class); private final JsonCodec<AgentProvisioningRepresentation> agentProvisioningCodec = jsonCodec(AgentProvisioningRepresentation.class); private final JsonCodec<UpgradeVersions> upgradeVersionsCodec = jsonCodec(UpgradeVersions.class); private String agentId; private UUID apple1SotId; private UUID apple2SlotId; private UUID bananaSlotId; private SlotStatusRepresentationFactory slotStatusRepresentationFactory; @BeforeClass public void startServer() throws Exception { Map<String, String> properties = ImmutableMap.<String, String>builder() .put("airship.version", "123") .put("node.id", "this-coordinator-instance-id") .put("node.location", "/test/location") .put("coordinator.binary-repo", "http://localhost:9999/") .put("coordinator.default-group-id", "prod") .put("coordinator.agent.default-config", "@agent.config") .put("coordinator.aws.access-key", "my-access-key") .put("coordinator.aws.secret-key", "my-secret-key") .put("coordinator.aws.agent.ami", "ami-0123abcd") .put("coordinator.aws.agent.keypair", "keypair") .put("coordinator.aws.agent.security-group", "default") .put("coordinator.aws.agent.default-instance-type", "t1.micro") .build(); Injector injector = Guice.createInjector(new TestingHttpServerModule(), new TestingNodeModule(), new JsonModule(), new JaxrsModule(), new EventModule(), Modules.override(new StaticProvisionerModule()).with(new Module() { @Override public void configure(Binder binder) { binder.bind(StateManager.class).to(InMemoryStateManager.class).in(SINGLETON); binder.bind(MockProvisioner.class).in(SINGLETON); binder.bind(Provisioner.class).to(Key.get(MockProvisioner.class)).in(SINGLETON); } }), Modules.override(new CoordinatorMainModule()).with(new Module() { public void configure(Binder binder) { binder.bind(Repository.class).toInstance(MOCK_REPO); binder.bind(ServiceInventory.class).to(MockServiceInventory.class).in(Scopes.SINGLETON); } @Provides @Singleton public RemoteCoordinatorFactory getRemoteCoordinatorFactory(MockProvisioner provisioner) { return provisioner.getCoordinatorFactory(); } @Provides @Singleton public RemoteAgentFactory getRemoteAgentFactory(MockProvisioner provisioner) { return provisioner.getAgentFactory(); } }), new ConfigurationModule(new ConfigurationFactory(properties))); server = injector.getInstance(TestingHttpServer.class); coordinator = injector.getInstance(Coordinator.class); stateManager = (InMemoryStateManager) injector.getInstance(StateManager.class); provisioner = (MockProvisioner) injector.getInstance(Provisioner.class); repository = injector.getInstance(Repository.class); server.start(); httpClient = new JettyHttpClient(); } @BeforeMethod public void resetState() { provisioner.clearCoordinators(); coordinator.updateAllCoordinatorsAndWait(); assertEquals(coordinator.getCoordinators().size(), 1); provisioner.clearAgents(); coordinator.updateAllAgentsAndWait(); assertTrue(coordinator.getAgents().isEmpty()); stateManager.clearAll(); assertTrue(coordinator.getAllSlotStatus().isEmpty()); } private void initializeOneAgent() { apple1SotId = UUID.randomUUID(); SlotStatus appleSlotStatus1 = createSlotStatus(apple1SotId, URI.create("fake://appleServer1/v1/agent/slot/apple1"), URI.create("fake://appleServer1/v1/agent/slot/apple1"), "instance", "/location", STOPPED, APPLE_ASSIGNMENT, "/apple1", ImmutableMap.<String, Integer>of()); apple2SlotId = UUID.randomUUID(); SlotStatus appleSlotStatus2 = createSlotStatus(apple2SlotId, URI.create("fake://appleServer2/v1/agent/slot/apple1"), URI.create("fake://appleServer2/v1/agent/slot/apple1"), "instance", "/location", STOPPED, APPLE_ASSIGNMENT, "/apple2", ImmutableMap.<String, Integer>of()); bananaSlotId = UUID.randomUUID(); SlotStatus bananaSlotStatus = createSlotStatus(bananaSlotId, URI.create("fake://bananaServer/v1/agent/slot/banana"), URI.create("fake://bananaServer/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)); provisioner.addAgents(agentStatus); coordinator.updateAllAgentsAndWait(); stateManager.clearAll(); slotStatusRepresentationFactory = new SlotStatusRepresentationFactory(ImmutableList.of(appleSlotStatus1, appleSlotStatus2, bananaSlotStatus), repository); } @AfterClass public void stopServer() throws Exception { closeQuietly(httpClient); if (server != null) { server.stop(); } } @Test public void testGetAllCoordinatorsSingle() throws Exception { // add a coordinator directly to the provisioner String coordinatorId = UUID.randomUUID().toString(); String instanceId = "instance-id"; URI internalUri = URI.create("fake://coordinator/" + instanceId + "/internal"); URI externalUri = URI.create("fake://coordinator/" + instanceId + "/external"); String location = "/unknown/location"; String instanceType = "instance.type"; CoordinatorStatus status = new CoordinatorStatus(coordinatorId, CoordinatorLifecycleState.ONLINE, instanceId, internalUri, externalUri, location, instanceType); provisioner.addCoordinators(status); coordinator.updateAllCoordinatorsAndWait(); // verify coordinator appears Request request = Request.Builder.prepareGet() .setUri(coordinatorUriBuilder().appendPath("/v1/admin/coordinator").build()) .build(); List<CoordinatorStatusRepresentation> coordinators = httpClient.execute(request, createJsonResponseHandler(coordinatorStatusesCodec, Status.OK.getStatusCode())); CoordinatorStatusRepresentation actual = getNonMainCoordinator(coordinators); assertEquals(actual.getCoordinatorId(), coordinatorId); assertEquals(actual.getState(), CoordinatorLifecycleState.ONLINE); assertEquals(actual.getInstanceId(), instanceId); assertEquals(actual.getLocation(), location); assertEquals(actual.getInstanceType(), instanceType); assertEquals(actual.getSelf(), internalUri); assertEquals(actual.getExternalUri(), externalUri); } @Test public void testCoordinatorProvision() throws Exception { // provision the coordinator and verify String instanceType = "instance-type"; CoordinatorProvisioningRepresentation coordinatorProvisioningRepresentation = new CoordinatorProvisioningRepresentation("coordinator:config:1", 1, instanceType, null, null, null, null, null); Request request = Request.Builder.preparePost() .setUri(coordinatorUriBuilder().appendPath("/v1/admin/coordinator").build()) .setHeader(CONTENT_TYPE, APPLICATION_JSON) .setBodyGenerator(jsonBodyGenerator(coordinatorProvisioningCodec, coordinatorProvisioningRepresentation)) .build(); List<CoordinatorStatusRepresentation> coordinators = httpClient.execute(request, createJsonResponseHandler(coordinatorStatusesCodec, Status.OK.getStatusCode())); assertEquals(coordinators.size(), 1); String instanceId = coordinators.get(0).getInstanceId(); assertNotNull(instanceId); String location = coordinators.get(0).getLocation(); assertNotNull(location); assertEquals(coordinators.get(0).getInstanceType(), instanceType); assertNull(coordinators.get(0).getCoordinatorId()); assertNull(coordinators.get(0).getSelf()); assertNull(coordinators.get(0).getExternalUri()); assertEquals(coordinators.get(0).getState(), CoordinatorLifecycleState.PROVISIONING); // start the coordinator and verify CoordinatorStatus expectedCoordinatorStatus = provisioner.startCoordinator(instanceId); coordinator.updateAllCoordinatorsAndWait(); assertEquals(coordinator.getCoordinators().size(), 2); assertEquals(coordinator.getCoordinator(instanceId).getInstanceId(), instanceId); assertEquals(coordinator.getCoordinator(instanceId).getInstanceType(), instanceType); assertEquals(coordinator.getCoordinator(instanceId).getLocation(), location); assertEquals(coordinator.getCoordinator(instanceId).getCoordinatorId(), expectedCoordinatorStatus.getCoordinatorId()); assertEquals(coordinator.getCoordinator(instanceId).getInternalUri(), expectedCoordinatorStatus.getInternalUri()); assertEquals(coordinator.getCoordinator(instanceId).getExternalUri(), expectedCoordinatorStatus.getExternalUri()); assertEquals(coordinator.getCoordinator(instanceId).getState(), CoordinatorLifecycleState.ONLINE); request = Request.Builder.prepareGet() .setUri(coordinatorUriBuilder().appendPath("/v1/admin/coordinator").build()) .build(); coordinators = httpClient.execute(request, createJsonResponseHandler(coordinatorStatusesCodec, Status.OK.getStatusCode())); CoordinatorStatusRepresentation actual = getNonMainCoordinator(coordinators); assertEquals(actual.getInstanceId(), instanceId); assertEquals(actual.getInstanceType(), instanceType); assertEquals(actual.getLocation(), location); assertEquals(actual.getCoordinatorId(), expectedCoordinatorStatus.getCoordinatorId()); assertEquals(actual.getSelf(), expectedCoordinatorStatus.getInternalUri()); assertEquals(actual.getExternalUri(), expectedCoordinatorStatus.getExternalUri()); assertEquals(actual.getState(), CoordinatorLifecycleState.ONLINE); } private CoordinatorStatusRepresentation getNonMainCoordinator(List<CoordinatorStatusRepresentation> coordinators) { assertEquals(coordinators.size(), 2); CoordinatorStatusRepresentation actual; if (coordinators.get(0).getInstanceId().equals(coordinator.status().getInstanceId())) { actual = coordinators.get(1); } else { actual = coordinators.get(0); assertEquals(coordinators.get(1).getInstanceId(), coordinator.status().getInstanceId()); } return actual; } @Test public void testGetAllAgentsEmpty() { Request request = Request.Builder.prepareGet() .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build()) .build(); List<AgentStatusRepresentation> actual = httpClient.execute(request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode())); assertEquals(actual.size(), 0); } @Test public void testGetAllAgentsSingle() throws Exception { String agentId = UUID.randomUUID().toString(); URI internalUri = URI.create("fake://agent/" + agentId + "/internal"); URI externalUri = URI.create("fake://agent/" + agentId + "/external"); String instanceId = "instance-id"; String location = "/unknown/location"; String instanceType = "instance.type"; Map<String, Integer> resources = ImmutableMap.of("cpu", 8, "memory", 1024); AgentStatus status = new AgentStatus(agentId, AgentLifecycleState.ONLINE, instanceId, internalUri, externalUri, location, instanceType, ImmutableList.<SlotStatus>of(), resources); // add the agent provisioner.addAgents(status); coordinator.updateAllAgentsAndWait(); Request request = Request.Builder.prepareGet() .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build()) .build(); List<AgentStatusRepresentation> agents = httpClient.execute(request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode())); assertEquals(agents.size(), 1); AgentStatusRepresentation actual = agents.get(0); assertEquals(actual.getAgentId(), agentId); assertEquals(actual.getState(), AgentLifecycleState.ONLINE); assertEquals(actual.getInstanceId(), instanceId); assertEquals(actual.getLocation(), location); assertEquals(actual.getInstanceType(), instanceType); assertEquals(actual.getSelf(), internalUri); assertEquals(actual.getExternalUri(), externalUri); assertEquals(actual.getResources(), resources); } @Test public void testAgentProvision() throws Exception { // provision the agent and verify String instanceType = "instance-type"; AgentProvisioningRepresentation agentProvisioningRepresentation = new AgentProvisioningRepresentation("agent:config:1", 1, instanceType, null, null, null, null, null); Request request = Request.Builder.preparePost() .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build()) .setHeader(CONTENT_TYPE, APPLICATION_JSON) .setBodyGenerator(jsonBodyGenerator(agentProvisioningCodec, agentProvisioningRepresentation)) .build(); List<AgentStatusRepresentation> agents = httpClient.execute(request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode())); assertEquals(agents.size(), 1); String instanceId = agents.get(0).getInstanceId(); assertNotNull(instanceId); String location = agents.get(0).getLocation(); assertNotNull(location); assertEquals(agents.get(0).getInstanceType(), instanceType); assertNull(agents.get(0).getAgentId()); assertNull(agents.get(0).getSelf()); assertNull(agents.get(0).getExternalUri()); assertEquals(agents.get(0).getState(), AgentLifecycleState.PROVISIONING); // start the agent and verify AgentStatus expectedAgentStatus = provisioner.startAgent(instanceId); coordinator.updateAllAgentsAndWait(); assertEquals(coordinator.getAgents().size(), 1); assertEquals(coordinator.getAgent(instanceId).getInstanceId(), instanceId); assertEquals(coordinator.getAgent(instanceId).getInstanceType(), instanceType); assertEquals(coordinator.getAgent(instanceId).getLocation(), location); assertEquals(coordinator.getAgent(instanceId).getAgentId(), expectedAgentStatus.getAgentId()); assertEquals(coordinator.getAgent(instanceId).getInternalUri(), expectedAgentStatus.getInternalUri()); assertEquals(coordinator.getAgent(instanceId).getExternalUri(), expectedAgentStatus.getExternalUri()); assertEquals(coordinator.getAgent(instanceId).getState(), AgentLifecycleState.ONLINE); request = Request.Builder.prepareGet() .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build()) .build(); agents = httpClient.execute(request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode())); assertEquals(agents.size(), 1); AgentStatusRepresentation actual = agents.get(0); assertEquals(actual.getInstanceId(), instanceId); assertEquals(actual.getInstanceType(), instanceType); assertEquals(actual.getLocation(), location); assertEquals(actual.getAgentId(), expectedAgentStatus.getAgentId()); assertEquals(actual.getSelf(), expectedAgentStatus.getInternalUri()); assertEquals(actual.getExternalUri(), expectedAgentStatus.getExternalUri()); assertEquals(actual.getState(), AgentLifecycleState.ONLINE); } @Test public void testGetAllSlots() throws Exception { initializeOneAgent(); Request request = Request.Builder.prepareGet() .setUri(coordinatorUriBuilder().appendPath("/v1/slot").addParameter("name", "*").build()) .build(); List<SlotStatusRepresentation> actual = httpClient.execute(request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode())); AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId); int prefixSize = shortestUniquePrefix(asList( agentStatus.getSlotStatus(apple1SotId).getId().toString(), agentStatus.getSlotStatus(apple2SlotId).getId().toString(), agentStatus.getSlotStatus(bananaSlotId).getId().toString()), MIN_PREFIX_SIZE); assertEqualsNoOrder(actual, ImmutableList.of( SlotStatusRepresentation.from(agentStatus.getSlotStatus(apple1SotId), prefixSize, MOCK_REPO), SlotStatusRepresentation.from(agentStatus.getSlotStatus(apple2SlotId), prefixSize, MOCK_REPO), SlotStatusRepresentation.from(agentStatus.getSlotStatus(bananaSlotId), prefixSize, MOCK_REPO))); } @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); } @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); } @Test public void testStart() throws Exception { initializeOneAgent(); Request request = Request.Builder.preparePut() .setUri(coordinatorUriBuilder().appendPath("/v1/slot/lifecycle").addParameter("binary", "apple:*").build()) .setBodyGenerator(createStaticBodyGenerator("running", 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(), RUNNING); assertEquals(apple2Status.getState(), RUNNING); assertEquals(bananaStatus.getState(), STOPPED); } @Test public void testRestart() throws Exception { initializeOneAgent(); Request request = Request.Builder.preparePut() .setUri(coordinatorUriBuilder().appendPath("/v1/slot/lifecycle").addParameter("binary", "apple:*").build()) .setBodyGenerator(createStaticBodyGenerator("restarting", 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(), RUNNING); assertEquals(apple2Status.getState(), RUNNING); assertEquals(bananaStatus.getState(), STOPPED); } @Test public void testStop() 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("stopped", 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 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 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); } private HttpUriBuilder coordinatorUriBuilder() { return uriBuilderFrom(server.getBaseUrl()); } }