package io.airlift.airship.coordinator; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; 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.MockUriInfo; import io.airlift.airship.shared.SlotStatus; import io.airlift.units.Duration; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import javax.ws.rs.core.Response; import java.net.URI; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; import static io.airlift.airship.shared.ExtraAssertions.assertEqualsNoOrder; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; public class TestAdminResource { private AdminResource resource; private Coordinator coordinator; private TestingMavenRepository repository; private MockProvisioner provisioner; private CoordinatorStatus coordinatorStatus; @BeforeMethod public void setUp() throws Exception { coordinatorStatus = new CoordinatorStatus(UUID.randomUUID().toString(), CoordinatorLifecycleState.ONLINE, "this-coordinator-instance-id", URI.create("fake://coordinator/internal"), URI.create("fake://coordinator/external"), "/test/location", "this-coordinator-instance-type"); repository = new TestingMavenRepository(); provisioner = new MockProvisioner(); coordinator = new Coordinator(coordinatorStatus, provisioner.getCoordinatorFactory(), provisioner.getAgentFactory(), repository, provisioner, new InMemoryStateManager(), new MockServiceInventory(), new Duration(1, TimeUnit.DAYS), false); resource = new AdminResource(coordinator, repository); } @AfterMethod public void tearDown() throws Exception { repository.destroy(); } @Test public void testGetCoordinatorsDefault() { URI requestUri = URI.create("http://localhost/v1/admin/coordinator"); Response response = resource.getAllCoordinators(MockUriInfo.from(requestUri)); assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); assertNull(response.getMetadata().get("Content-Type")); // content type is set by jersey based on @Produces Iterable<CoordinatorStatusRepresentation> coordinators = (Iterable<CoordinatorStatusRepresentation>) response.getEntity(); assertEquals(Iterables.size(coordinators), 1); CoordinatorStatusRepresentation actual = coordinators.iterator().next(); assertEquals(actual.getCoordinatorId(), coordinatorStatus.getCoordinatorId()); assertEquals(actual.getState(), CoordinatorLifecycleState.ONLINE); assertEquals(actual.getInstanceId(), coordinatorStatus.getInstanceId()); assertEquals(actual.getLocation(), coordinatorStatus.getLocation()); assertEquals(actual.getInstanceType(), coordinatorStatus.getInstanceType()); assertEquals(actual.getSelf(), coordinatorStatus.getInternalUri()); assertEquals(actual.getExternalUri(), coordinatorStatus.getExternalUri()); } @Test public void testGetAllCoordinatorsSingle() throws Exception { 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); // add the coordinator provisioner.addCoordinators(status); coordinator.updateAllCoordinatorsAndWait(); URI requestUri = URI.create("http://localhost/v1/admin/coordinator"); Response response = resource.getAllCoordinators(MockUriInfo.from(requestUri)); assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); assertNull(response.getMetadata().get("Content-Type")); // content type is set by jersey based on @Produces // locate the new coordinator List<CoordinatorStatusRepresentation> coordinators = ImmutableList.copyOf((Iterable<CoordinatorStatusRepresentation>) response.getEntity()); 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); } private CoordinatorStatusRepresentation getNonMainCoordinator(List<CoordinatorStatusRepresentation> coordinators) { assertEquals(coordinators.size(), 2); CoordinatorStatusRepresentation actual; if (coordinators.get(0).getInstanceId().equals(coordinatorStatus.getInstanceId())) { actual = coordinators.get(1); } else { actual = coordinators.get(0); assertEquals(coordinators.get(1).getInstanceId(), coordinatorStatus.getInstanceId()); } return actual; } @Test public void testCoordinatorProvision() throws Exception { // provision the coordinator and verify String instanceType = "instance-type"; URI requestUri = URI.create("http://localhost/v1/admin/coordinator"); Response response = resource.provisionCoordinator( new CoordinatorProvisioningRepresentation("coordinator:config:1", 1, instanceType, null, null, null, null, null), MockUriInfo.from(requestUri) ); assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); assertNull(response.getMetadata().get("Content-Type")); // content type is set by jersey based on @Produces List<CoordinatorStatusRepresentation> coordinators = ImmutableList.copyOf((Iterable<CoordinatorStatusRepresentation>) response.getEntity()); 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 coordinatorStatus = 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(), coordinatorStatus.getCoordinatorId()); assertEquals(coordinator.getCoordinator(instanceId).getInternalUri(), coordinatorStatus.getInternalUri()); assertEquals(coordinator.getCoordinator(instanceId).getExternalUri(), coordinatorStatus.getExternalUri()); assertEquals(coordinator.getCoordinator(instanceId).getState(), CoordinatorLifecycleState.ONLINE); requestUri = URI.create("http://localhost/v1/admin/coordinator"); response = resource.getAllCoordinators(MockUriInfo.from(requestUri)); assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); assertNull(response.getMetadata().get("Content-Type")); // content type is set by jersey based on @Produces coordinators = ImmutableList.copyOf((Iterable<CoordinatorStatusRepresentation>) response.getEntity()); CoordinatorStatusRepresentation actual = getNonMainCoordinator(coordinators); assertEquals(actual.getInstanceId(), instanceId); assertEquals(actual.getInstanceType(), instanceType); assertEquals(actual.getLocation(), location); assertEquals(actual.getCoordinatorId(), coordinatorStatus.getCoordinatorId()); assertEquals(actual.getSelf(), coordinatorStatus.getInternalUri()); assertEquals(actual.getExternalUri(), coordinatorStatus.getExternalUri()); assertEquals(actual.getState(), CoordinatorLifecycleState.ONLINE); } @Test public void testGetAllAgentsEmpty() { URI requestUri = URI.create("http://localhost/v1/admin/agent"); Response response = resource.getAllAgents(MockUriInfo.from(requestUri)); assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); assertEqualsNoOrder((Iterable<?>) response.getEntity(), ImmutableList.of()); assertNull(response.getMetadata().get("Content-Type")); // content type is set by jersey based on @Produces } @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(); URI requestUri = URI.create("http://localhost/v1/admin/agent"); Response response = resource.getAllAgents(MockUriInfo.from(requestUri)); assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); assertNull(response.getMetadata().get("Content-Type")); // content type is set by jersey based on @Produces Iterable<AgentStatusRepresentation> agents = (Iterable<AgentStatusRepresentation>) response.getEntity(); assertEquals(Iterables.size(agents), 1); AgentStatusRepresentation actual = agents.iterator().next(); 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"; URI requestUri = URI.create("http://localhost/v1/admin/agent"); Response response = resource.provisionAgent( new AgentProvisioningRepresentation("agent:config:1", 1, instanceType, null, null, null, null, null), MockUriInfo.from(requestUri) ); assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); assertNull(response.getMetadata().get("Content-Type")); // content type is set by jersey based on @Produces List<AgentStatusRepresentation> agents = ImmutableList.copyOf((Iterable<AgentStatusRepresentation>) response.getEntity()); 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); requestUri = URI.create("http://localhost/v1/admin/agent"); response = resource.getAllAgents(MockUriInfo.from(requestUri)); assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); assertNull(response.getMetadata().get("Content-Type")); // content type is set by jersey based on @Produces agents = ImmutableList.copyOf((Iterable<AgentStatusRepresentation>) response.getEntity()); assertEquals(agents.size(), 1); AgentStatusRepresentation actual = agents.iterator().next(); 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); } }