package io.airlift.airship.cli;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ListMultimap;
import io.airlift.airship.cli.Airship.AirshipCommand;
import io.airlift.airship.cli.Airship.AirshipCommanderCommand;
import io.airlift.airship.coordinator.TestingMavenRepository;
import io.airlift.airship.shared.AgentStatusRepresentation;
import io.airlift.airship.shared.Assignment;
import io.airlift.airship.shared.CoordinatorStatusRepresentation;
import io.airlift.airship.shared.FileUtils;
import io.airlift.airship.shared.SlotLifecycleState;
import io.airlift.airship.shared.SlotStatusRepresentation;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
import java.util.List;
import java.util.UUID;
import static io.airlift.airship.shared.AssignmentHelper.APPLE_ASSIGNMENT;
import static io.airlift.airship.shared.AssignmentHelper.APPLE_ASSIGNMENT_2;
import static io.airlift.airship.shared.AssignmentHelper.BANANA_ASSIGNMENT;
import static io.airlift.airship.shared.AssignmentHelper.BANANA_ASSIGNMENT_EXACT;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
public class TestAirship
{
private File tempDir;
private Config config;
private TestingMavenRepository repo;
private MockInteractiveUser interactiveUser;
private MockOutputFormat outputFormat;
@BeforeMethod
public void setUp()
throws Exception
{
tempDir = FileUtils.createTempDir("airship");
config = new Config();
repo = new TestingMavenRepository();
interactiveUser = new MockInteractiveUser(true);
outputFormat = new MockOutputFormat();
}
@AfterMethod
public void tearDown()
throws Exception
{
FileUtils.deleteRecursively(tempDir);
repo.destroy();
}
@Test
public void testLocalModeHappyPath()
throws Exception
{
File targetRepo = repo.getTargetRepo();
execute("environment", "provision-local", "local", new File(tempDir, "env").getAbsolutePath(),
"--name", "monkey",
"--repository", targetRepo.toURI().toASCIIString()
);
execute("show");
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 0);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("agent", "show");
assertNull(outputFormat.slots);
assertNull(outputFormat.slots);
assertNull(outputFormat.coordinators);
assertEquals(outputFormat.agents.size(), 1);
AgentStatusRepresentation agent = outputFormat.agents.get(0);
execute("coordinator", "show");
assertNull(outputFormat.slots);
assertNull(outputFormat.slots);
assertEquals(outputFormat.coordinators.size(), 1);
assertNull(outputFormat.agents);
execute("install", APPLE_ASSIGNMENT.getConfig(), APPLE_ASSIGNMENT.getBinary());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
SlotStatusRepresentation slot = outputFormat.slots.get(0);
UUID slotId = slot.getId();
assertNotNull(slotId);
assertSlotStatus(slot, slotId, APPLE_ASSIGNMENT, SlotLifecycleState.STOPPED, agent);
assertNull(outputFormat.coordinators);
assertEquals(outputFormat.agents.size(), 1);
execute("start", "-c", APPLE_ASSIGNMENT.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT, SlotLifecycleState.RUNNING, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("reset-to-actual", "-c", APPLE_ASSIGNMENT.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT, SlotLifecycleState.RUNNING, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("stop", "-c", APPLE_ASSIGNMENT.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT, SlotLifecycleState.STOPPED, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("restart", "-c", APPLE_ASSIGNMENT.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT, SlotLifecycleState.RUNNING, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("upgrade", "-c", APPLE_ASSIGNMENT.getConfig(), "2.0", "@2.0");
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT_2, SlotLifecycleState.RUNNING, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("start", "-c", APPLE_ASSIGNMENT_2.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT_2, SlotLifecycleState.RUNNING, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("restart", "-c", APPLE_ASSIGNMENT_2.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT_2, SlotLifecycleState.RUNNING, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("kill", "-c", APPLE_ASSIGNMENT_2.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT_2, SlotLifecycleState.STOPPED, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("restart", "-c", APPLE_ASSIGNMENT_2.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT_2, SlotLifecycleState.RUNNING, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("terminate", "-c", APPLE_ASSIGNMENT_2.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT_2, SlotLifecycleState.RUNNING, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("stop", "-c", APPLE_ASSIGNMENT_2.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT_2, SlotLifecycleState.STOPPED, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("terminate", "-c", APPLE_ASSIGNMENT_2.getConfig());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
assertSlotStatus(outputFormat.slots.get(0), slotId, APPLE_ASSIGNMENT_2, SlotLifecycleState.TERMINATED, agent);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
execute("show");
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 0);
assertNull(outputFormat.coordinators);
assertNull(outputFormat.agents);
}
@Test
public void testSlotFilter()
throws Exception
{
File targetRepo = repo.getTargetRepo();
execute("environment", "provision-local", "local", new File(tempDir, "env").getAbsolutePath(),
"--name", "monkey",
"--repository", targetRepo.toURI().toASCIIString(),
"--allow-duplicate-installations"
);
execute("agent", "show");
assertNull(outputFormat.slots);
assertNull(outputFormat.slots);
assertNull(outputFormat.coordinators);
assertEquals(outputFormat.agents.size(), 1);
AgentStatusRepresentation agent = outputFormat.agents.get(0);
execute("install", APPLE_ASSIGNMENT.getConfig(), APPLE_ASSIGNMENT.getBinary());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
execute("install", APPLE_ASSIGNMENT.getConfig(), APPLE_ASSIGNMENT.getBinary());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
execute("install", APPLE_ASSIGNMENT_2.getConfig(), APPLE_ASSIGNMENT_2.getBinary());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
execute("install", APPLE_ASSIGNMENT_2.getConfig(), APPLE_ASSIGNMENT_2.getBinary());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
execute("install", BANANA_ASSIGNMENT.getConfig(), BANANA_ASSIGNMENT.getBinary());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
execute("install", BANANA_ASSIGNMENT.getConfig(), BANANA_ASSIGNMENT.getBinary());
assertNotNull(outputFormat.slots);
assertEquals(outputFormat.slots.size(), 1);
ListMultimap<Assignment, SlotStatusRepresentation> slots;
execute("show");
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
String appleSlotId = slots.get(APPLE_ASSIGNMENT).get(0).getId().toString();
String appleShortSlotId = slots.get(APPLE_ASSIGNMENT).get(0).getShortId();
String apple2SlotId = slots.get(APPLE_ASSIGNMENT_2).get(0).getId().toString();
String apple2ShortSlotId = slots.get(APPLE_ASSIGNMENT_2).get(0).getShortId();
String bananaSlotId = slots.get(BANANA_ASSIGNMENT_EXACT).get(0).getId().toString();
String bananaShortSlotId = slots.get(BANANA_ASSIGNMENT_EXACT).get(0).getShortId();
execute("show", "--all");
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("show", "-u", appleSlotId);
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 1);
assertEquals(slots.get(APPLE_ASSIGNMENT).get(0).getId().toString(), appleSlotId);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("show", "-U", appleSlotId);
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 1);
assertNotEquals(slots.get(APPLE_ASSIGNMENT).get(0).getId().toString(), appleSlotId);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("show", "-u", appleShortSlotId, "-u", apple2ShortSlotId, "-u", bananaShortSlotId);
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 1);
assertEquals(slots.get(APPLE_ASSIGNMENT).get(0).getId().toString(), appleSlotId);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 1);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).get(0).getId().toString(), apple2SlotId);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 1);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).get(0).getId().toString(), bananaSlotId);
execute("show", "-U", appleShortSlotId, "-U", apple2ShortSlotId, "-U", bananaShortSlotId);
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 1);
assertNotEquals(slots.get(APPLE_ASSIGNMENT).get(0).getId().toString(), appleSlotId);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 1);
assertNotEquals(slots.get(APPLE_ASSIGNMENT_2).get(0).getId().toString(), apple2SlotId);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 1);
assertNotEquals(slots.get(BANANA_ASSIGNMENT_EXACT).get(0).getId().toString(), bananaSlotId);
execute("show", "-u", appleSlotId, "-u", apple2SlotId, "-u", bananaSlotId);
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 1);
assertEquals(slots.get(APPLE_ASSIGNMENT).get(0).getId().toString(), appleSlotId);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 1);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).get(0).getId().toString(), apple2SlotId);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 1);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).get(0).getId().toString(), bananaSlotId);
execute("show", "-U", appleSlotId, "-U", apple2SlotId, "-U", bananaSlotId);
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 1);
assertNotEquals(slots.get(APPLE_ASSIGNMENT).get(0).getId().toString(), appleSlotId);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 1);
assertNotEquals(slots.get(APPLE_ASSIGNMENT_2).get(0).getId().toString(), apple2SlotId);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 1);
assertNotEquals(slots.get(BANANA_ASSIGNMENT_EXACT).get(0).getId().toString(), bananaSlotId);
execute("show", "-c", APPLE_ASSIGNMENT.getConfig());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("show", "-C", APPLE_ASSIGNMENT.getConfig());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("show", "-b", APPLE_ASSIGNMENT.getBinary());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("show", "-B", APPLE_ASSIGNMENT.getBinary());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("show", "-h", agent.getInternalHost());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("show", "-H", agent.getInternalHost());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("show", "-h", agent.getInternalIp());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("show", "-H", agent.getInternalIp());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("show", "-h", agent.getExternalHost());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("show", "-H", agent.getExternalHost());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("show", "-m", agent.getInstanceId());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("show", "-M", agent.getInstanceId());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("start", "-b", BANANA_ASSIGNMENT_EXACT.getBinary());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("start", "-B", BANANA_ASSIGNMENT_EXACT.getBinary());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("start", "-s", SlotLifecycleState.RUNNING.toString());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 2);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 2);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 2);
execute("start", "-S", SlotLifecycleState.RUNNING.toString());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
execute("start", "-s", SlotLifecycleState.STOPPED.toString());
slots = slotsByAssignment();
assertEquals(slots.get(APPLE_ASSIGNMENT).size(), 0);
assertEquals(slots.get(APPLE_ASSIGNMENT_2).size(), 0);
assertEquals(slots.get(BANANA_ASSIGNMENT_EXACT).size(), 0);
}
private ListMultimap<Assignment, SlotStatusRepresentation> slotsByAssignment()
{
assertNotNull(outputFormat.slots);
ArrayListMultimap<Assignment, SlotStatusRepresentation> slotsByAssignment = ArrayListMultimap.create();
for (SlotStatusRepresentation slot : outputFormat.slots) {
slotsByAssignment.put(new Assignment(slot.getBinary(), slot.getConfig()), slot);
}
return slotsByAssignment;
}
private void assertSlotStatus(SlotStatusRepresentation slot,
UUID expectedSlotId,
Assignment expectedAssignment,
SlotLifecycleState expectedState,
AgentStatusRepresentation expectedAgent)
{
assertEquals(slot.getId(), expectedSlotId);
if (expectedState != SlotLifecycleState.TERMINATED) {
assertEquals(slot.getBinary(), expectedAssignment.getBinary());
assertEquals(slot.getConfig(), expectedAssignment.getConfig());
assertTrue(slot.getInstallPath().startsWith(tempDir.getAbsolutePath()));
}
else {
assertNull(slot.getBinary());
assertNull(slot.getConfig());
assertNull(slot.getInstallPath());
}
assertEquals(slot.getStatus(), expectedState.toString());
assertEquals(slot.getInstanceId(), expectedAgent.getInstanceId());
assertTrue(slot.getLocation().startsWith(expectedAgent.getLocation()));
assertTrue(slot.getLocation().endsWith(slot.getShortLocation()));
assertTrue(slot.getSelf().toASCIIString().startsWith(expectedAgent.getSelf().toASCIIString()));
assertTrue(slot.getExternalUri().toASCIIString().startsWith(expectedAgent.getExternalUri().toASCIIString()));
}
private void execute(String... args)
throws Exception
{
outputFormat.clear();
AirshipCommand command = Airship.AIRSHIP_PARSER.parse(ImmutableList.<String>builder().add("--debug").add(args).build());
command.config = config;
if (command instanceof AirshipCommanderCommand) {
Airship.AirshipCommanderCommand airshipCommanderCommand = (Airship.AirshipCommanderCommand) command;
airshipCommanderCommand.execute("local", outputFormat, interactiveUser);
}
else {
command.execute();
}
}
private static class MockOutputFormat
implements OutputFormat
{
private List<CoordinatorStatusRepresentation> coordinators;
private List<AgentStatusRepresentation> agents;
private List<SlotStatusRepresentation> slots;
public void clear()
{
coordinators = null;
agents = null;
slots = null;
}
@Override
public void displayCoordinators(Iterable<CoordinatorStatusRepresentation> coordinators)
{
this.coordinators = ImmutableList.copyOf(coordinators);
}
@Override
public void displayAgents(Iterable<AgentStatusRepresentation> agents)
{
this.agents = ImmutableList.copyOf(agents);
}
@Override
public void displaySlots(Iterable<SlotStatusRepresentation> slots)
{
this.slots = ImmutableList.copyOf(slots);
}
}
private static class MockInteractiveUser
implements InteractiveUser
{
private boolean answer;
private MockInteractiveUser(boolean answer)
{
this.answer = answer;
}
@Override
public boolean ask(String question, boolean defaultValue)
{
return answer;
}
}
}