package com.hubspot.singularity.mesos;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.WebApplicationException;
import org.apache.mesos.Protos.TaskState;
import org.junit.Assert;
import org.junit.Test;
import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.hubspot.singularity.SingularityShellCommand;
import com.hubspot.singularity.SingularityTask;
import com.hubspot.singularity.SingularityTaskCleanup;
import com.hubspot.singularity.SingularityTaskId;
import com.hubspot.singularity.SingularityTaskShellCommandRequest;
import com.hubspot.singularity.SingularityTaskShellCommandRequestId;
import com.hubspot.singularity.SingularityTaskShellCommandUpdate;
import com.hubspot.singularity.SingularityTaskShellCommandUpdate.UpdateType;
import com.hubspot.singularity.api.SingularityBounceRequest;
import com.hubspot.singularity.config.UIConfiguration;
import com.hubspot.singularity.config.shell.ShellCommandDescriptor;
import com.hubspot.singularity.config.shell.ShellCommandOptionDescriptor;
import com.hubspot.singularity.data.transcoders.Transcoder;
import com.hubspot.singularity.resources.TaskResource;
import com.hubspot.singularity.scheduler.SingularitySchedulerTestBase;
import com.hubspot.singularity.scheduler.SingularityTaskShellCommandDispatchPoller;
public class SingularityTaskShellCommandTest extends SingularitySchedulerTestBase {
@Inject
private TaskResource taskResource;
@Inject
private SingularityTaskShellCommandDispatchPoller dispatchPoller;
@Inject
private SingularityMesosScheduler mesosScheduler;
@Inject
private Transcoder<SingularityTaskShellCommandUpdate> updateTranscoder;
@Inject
private UIConfiguration uiConfiguration;
public SingularityTaskShellCommandTest() {
super(false);
}
@Test
public void testTaskShellCommandPersistence() {
initRequest();
initFirstDeploy();
SingularityTask task = launchTask(request, firstDeploy, 1, TaskState.TASK_RUNNING);
// test bad command first:
setShellCommandsConfiguration();
// bad shell cmd
try {
taskResource.runShellCommand(task.getTaskId().getId(), new SingularityShellCommand("test-cmd", Optional.of(Arrays.asList("one", "two")), user, Optional.<String>absent()));
} catch (WebApplicationException exception) {
assertEquals(400, exception.getResponse().getStatus());
}
// bad option
try {
taskResource.runShellCommand(task.getTaskId().getId(), new SingularityShellCommand("d1", Optional.of(Arrays.asList("one", "two")), user, Optional.<String>absent()));
} catch (WebApplicationException exception) {
assertEquals(400, exception.getResponse().getStatus());
}
SingularityTaskShellCommandRequest firstShellRequest = taskResource.runShellCommand(task.getTaskId().getId(), new SingularityShellCommand("d1", Optional.of(Arrays.asList("o1", "o2")), user, Optional.<String>absent()));
try {
Thread.sleep(3);
} catch (Exception e) {
}
SingularityTaskShellCommandRequest secondShellRequest = taskResource.runShellCommand(task.getTaskId().getId(), new SingularityShellCommand("d2", Optional.<List<String>> absent(), user, Optional.<String>absent()));
assertEquals(2, taskManager.getAllQueuedTaskShellCommandRequests().size());
dispatchPoller.runActionOnPoll();
assertEquals(0, taskManager.getAllQueuedTaskShellCommandRequests().size());
assertEquals(2, taskManager.getTaskShellCommandRequestsForTask(task.getTaskId()).size());
mesosScheduler.frameworkMessage(driver, task.getMesosTask().getExecutor().getExecutorId(), task.getMesosTask().getSlaveId(),
updateTranscoder.toBytes(
new SingularityTaskShellCommandUpdate(firstShellRequest.getId(), System.currentTimeMillis(), Optional.<String> of("hi"), Optional.<String>absent(), UpdateType.STARTED)));
mesosScheduler.frameworkMessage(driver, task.getMesosTask().getExecutor().getExecutorId(), task.getMesosTask().getSlaveId(),
updateTranscoder.toBytes(
new SingularityTaskShellCommandUpdate(new SingularityTaskShellCommandRequestId(task.getTaskId(), "wat", System.currentTimeMillis()), System.currentTimeMillis(), Optional.<String> of("hi"), Optional.<String>absent(), UpdateType.STARTED)));
mesosScheduler.frameworkMessage(driver, task.getMesosTask().getExecutor().getExecutorId(), task.getMesosTask().getSlaveId(),
updateTranscoder.toBytes(
new SingularityTaskShellCommandUpdate(new SingularityTaskShellCommandRequestId(new SingularityTaskId("makingitup", "did", System.currentTimeMillis(), 1, "host", "rack"), "wat", System.currentTimeMillis()), System.currentTimeMillis(), Optional.<String> of("hi"), Optional.<String>absent(), UpdateType.STARTED)));
assertEquals(true, taskManager.getTaskHistory(task.getTaskId()).get().getShellCommandHistory().get(1).getShellUpdates().get(0).getUpdateType() == UpdateType.STARTED);
assertEquals(1, taskManager.getTaskShellCommandUpdates(firstShellRequest.getId()).size());
assertEquals(0, taskManager.getTaskShellCommandUpdates(secondShellRequest.getId()).size());
}
@Test
public void testRunCommandBeforeBounceKill() {
setShellCommandsConfiguration();
initRequest();
initFirstDeploy();
launchTask(request, firstDeploy, 1, TaskState.TASK_RUNNING);
requestResource.bounce(requestId, Optional.of(new SingularityBounceRequest(Optional.<Boolean>absent(), Optional.<Boolean>absent(), Optional.<Long>absent(), Optional.<String>absent(), Optional.<String>absent(),
Optional.of(new SingularityShellCommand("d1", Optional.of(Arrays.asList("o1", "o2")), user, Optional.<String>absent())))));
cleaner.drainCleanupQueue();
List<SingularityTaskCleanup> taskCleanups = taskManager.getCleanupTasks();
Assert.assertTrue(taskCleanups.get(0).getRunBeforeKillId().isPresent());
SingularityTaskShellCommandRequestId shellCommandRequestId = taskCleanups.get(0).getRunBeforeKillId().get();
cleaner.drainCleanupQueue();
Assert.assertEquals(1, taskManager.getCleanupTaskIds().size());
launchTask(request, firstDeploy, 1, TaskState.TASK_RUNNING);
Assert.assertEquals(2, taskManager.getActiveTaskIdsForRequest(requestId).size());
cleaner.drainCleanupQueue();
Assert.assertEquals(2, taskManager.getActiveTaskIdsForRequest(requestId).size());
taskManager.saveTaskShellCommandUpdate(new SingularityTaskShellCommandUpdate(shellCommandRequestId, System.currentTimeMillis(), Optional.<String>absent(), Optional.<String>absent(), UpdateType.ACKED));
cleaner.drainCleanupQueue();
Assert.assertEquals(2, taskManager.getActiveTaskIdsForRequest(requestId).size());
taskManager.saveTaskShellCommandUpdate(new SingularityTaskShellCommandUpdate(shellCommandRequestId, System.currentTimeMillis(), Optional.<String>absent(), Optional.<String>absent(), UpdateType.FINISHED));
cleaner.drainCleanupQueue();
Assert.assertEquals(1, taskManager.getKilledTaskIdRecords().size());
}
private void setShellCommandsConfiguration() {
List<ShellCommandDescriptor> descriptors = new ArrayList<>();
ShellCommandDescriptor descriptor1 = new ShellCommandDescriptor();
descriptor1.setName("d1");
descriptor1.setOptions(Arrays.asList(new ShellCommandOptionDescriptor().setName("o1"), new ShellCommandOptionDescriptor().setName("o2")));
ShellCommandDescriptor descriptor2 = new ShellCommandDescriptor();
descriptor2.setName("d2");
descriptor2.setOptions(Collections.<ShellCommandOptionDescriptor> emptyList());
descriptors.add(descriptor1);
descriptors.add(descriptor2);
uiConfiguration.setShellCommands(descriptors);
}
}