@JsonCreator public SingularityTaskShellCommandRequest(@JsonProperty("taskId") SingularityTaskId taskId, @JsonProperty("user") Optional<String> user, @JsonProperty("timestamp") long timestamp, @JsonProperty("shellCommand") SingularityShellCommand shellCommand) { this.taskId = taskId; this.user = user; this.timestamp = timestamp; this.shellCommand = shellCommand; this.id = new SingularityTaskShellCommandRequestId(taskId, shellCommand.getName(), timestamp); }
public void checkValidShellCommand(final SingularityShellCommand shellCommand) { Optional<ShellCommandDescriptor> commandDescriptor = Iterables.tryFind(uiConfiguration.getShellCommands(), new Predicate<ShellCommandDescriptor>() { @Override public boolean apply(ShellCommandDescriptor input) { return input.getName().equals(shellCommand.getName()); } }); if (!commandDescriptor.isPresent()) { throw WebExceptions.badRequest("Shell command %s not in %s", shellCommand.getName(), uiConfiguration.getShellCommands()); } Set<String> options = Sets.newHashSetWithExpectedSize(commandDescriptor.get().getOptions().size()); for (ShellCommandOptionDescriptor option : commandDescriptor.get().getOptions()) { options.add(option.getName()); } if (shellCommand.getOptions().isPresent()) { for (String option : shellCommand.getOptions().get()) { if (!options.contains(option)) { throw WebExceptions.badRequest("Shell command %s does not have option %s (%s)", shellCommand.getName(), option, options); } } } } }
public void start() { List<String> command = null; try { command = buildCommand(); } catch (InvalidShellCommandException isce) { shellCommandUpdater.sendUpdate(UpdateType.INVALID, Optional.of(isce.getMessage()), Optional.<String>absent()); return; } final String outputFilename = executorConfiguration.getShellCommandOutFile() .replace("{NAME}", shellRequest.getShellCommand().getLogfileName().or(convertCommandNameToLogfileName(shellRequest.getShellCommand().getName()))) .replace("{TIMESTAMP}", Long.toString(shellRequest.getTimestamp())); shellCommandUpdater.sendUpdate(UpdateType.ACKED, Optional.of(Joiner.on(" ").join(command)), Optional.of(outputFilename)); final File outputFile = MesosUtils.getTaskDirectoryPath(getTask().getTaskId()).resolve(outputFilename).toFile(); Map<String, String> additionalEnv = new HashMap<>(); additionalEnv.put("TASK_SANDBOX_DIR", MesosUtils.getTaskDirectoryPath(getTask().getTaskId()).toString()); SingularityExecutorShellCommandRunnerCallable callable = new SingularityExecutorShellCommandRunnerCallable(task.getLog(), shellCommandUpdater, buildProcessBuilder(command, outputFile, additionalEnv), outputFile); ListenableFuture<Integer> shellFuture = shellCommandExecutorService.submit(callable); Futures.addCallback(shellFuture, new FutureCallback<Integer>() { @Override public void onSuccess(Integer result) { task.getLog().info("ShellRequest {} finished with {}", shellRequest, result); shellCommandUpdater.sendUpdate(UpdateType.FINISHED, Optional.of(String.format("Finished with code %s", result)), Optional.<String>absent()); } @Override public void onFailure(Throwable t) { task.getLog().warn("ShellRequest {} failed", shellRequest, t); shellCommandUpdater.sendUpdate(UpdateType.FAILED, Optional.of(String.format("Failed - %s (%s)", t.getClass().getSimpleName(), t.getMessage())), Optional.<String>absent()); } }); }
@Test public void testRunCommandBeforeBounceKill() { setShellCommandsConfiguration(); initRequest(); initFirstDeploy(); launchTask(request, firstDeploy, 1, TaskState.TASK_RUNNING); requestResource.bounce(requestId, Optional.of(new SingularityBounceRequest(Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), Optional.of(new SingularityShellCommand("d1", Optional.of(Arrays.asList("o1", "o2")), user, Optional.absent())))), singularityUser); 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()); }
taskResource.runShellCommand(singularityUser, task.getTaskId().getId(), new SingularityShellCommand("test-cmd", Optional.of(Arrays.asList("one", "two")), user, Optional.absent())); } catch (WebApplicationException exception) { assertEquals(400, exception.getResponse().getStatus()); taskResource.runShellCommand(singularityUser, task.getTaskId().getId(), new SingularityShellCommand("d1", Optional.of(Arrays.asList("one", "two")), user, Optional.absent())); } catch (WebApplicationException exception) { assertEquals(400, exception.getResponse().getStatus()); SingularityTaskShellCommandRequest firstShellRequest = taskResource.runShellCommand(singularityUser, task.getTaskId().getId(), new SingularityShellCommand("d1", Optional.of(Arrays.asList("o1", "o2")), user, Optional.absent())); SingularityTaskShellCommandRequest secondShellRequest = taskResource.runShellCommand(singularityUser, task.getTaskId().getId(), new SingularityShellCommand("d2", Optional.<List<String>> absent(), user, Optional.absent()));
@Override public boolean apply(ShellCommandDescriptor input) { return input.getName().equals(shellCommand.getName()); } });
throw new InvalidShellCommandException(String.format( "\"%s\" command not found. If this command was added or modified after the task launched, then the task must be restarted to find it. Currently available commands are: %s", shellRequest.getShellCommand().getName(), executorConfiguration.getShellCommands().stream().map(SingularityExecutorShellCommandDescriptor::getName).collect(Collectors.toList()))); if (shellRequest.getShellCommand().getOptions().isPresent()) { for (SingularityExecutorShellCommandOptionDescriptor option : shellCommandDescriptor.getOptions()) { if (shellRequest.getShellCommand().getOptions().get().contains(option.getName())) { command.add(option.getFlag());
@Test public void testRunCommandBeforeBounceKill() { setShellCommandsConfiguration(); initRequest(); initFirstDeploy(); launchTask(request, firstDeploy, 1, TaskState.TASK_RUNNING); requestResource.bounce(requestId, Optional.of(new SingularityBounceRequest(Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), Optional.of(new SingularityShellCommand("d1", Optional.of(Arrays.asList("o1", "o2")), user, Optional.absent())))), singularityUser); 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()); }
@Override public boolean apply(SingularityExecutorShellCommandDescriptor input) { return input.getName().equals(shellRequest.getShellCommand().getName()); }
public void checkValidShellCommand(final SingularityShellCommand shellCommand) { Optional<ShellCommandDescriptor> commandDescriptor = Iterables.tryFind(uiConfiguration.getShellCommands(), new Predicate<ShellCommandDescriptor>() { @Override public boolean apply(ShellCommandDescriptor input) { return input.getName().equals(shellCommand.getName()); } }); if (!commandDescriptor.isPresent()) { throw WebExceptions.badRequest("Shell command %s not in %s", shellCommand.getName(), uiConfiguration.getShellCommands()); } Set<String> options = Sets.newHashSetWithExpectedSize(commandDescriptor.get().getOptions().size()); for (ShellCommandOptionDescriptor option : commandDescriptor.get().getOptions()) { options.add(option.getName()); } if (shellCommand.getOptions().isPresent()) { for (String option : shellCommand.getOptions().get()) { if (!options.contains(option)) { throw WebExceptions.badRequest("Shell command %s does not have option %s (%s)", shellCommand.getName(), option, options); } } } } }
taskResource.runShellCommand(singularityUser, task.getTaskId().getId(), new SingularityShellCommand("test-cmd", Optional.of(Arrays.asList("one", "two")), user, Optional.absent())); } catch (WebApplicationException exception) { assertEquals(400, exception.getResponse().getStatus()); taskResource.runShellCommand(singularityUser, task.getTaskId().getId(), new SingularityShellCommand("d1", Optional.of(Arrays.asList("one", "two")), user, Optional.absent())); } catch (WebApplicationException exception) { assertEquals(400, exception.getResponse().getStatus()); SingularityTaskShellCommandRequest firstShellRequest = taskResource.runShellCommand(singularityUser, task.getTaskId().getId(), new SingularityShellCommand("d1", Optional.of(Arrays.asList("o1", "o2")), user, Optional.absent())); SingularityTaskShellCommandRequest secondShellRequest = taskResource.runShellCommand(singularityUser, task.getTaskId().getId(), new SingularityShellCommand("d2", Optional.<List<String>> absent(), user, Optional.absent()));
public Collection<SingularityTaskShellCommandUpdate> getShellCommandUpdates(SingularityTaskShellCommandRequest shellCommandRequest) { final Function<String, String> requestUri = (host) -> String.format(SHELL_COMMAND_UPDATES_FORMAT, getApiBase(host), shellCommandRequest.getTaskId(), shellCommandRequest.getShellCommand().getName(), shellCommandRequest.getTimestamp()); return getCollection(requestUri, "get shell command update history", SHELL_COMMAND_UPDATES); }
@POST @Path("/task/{taskId}/command") @Operation( summary = "Run a configured shell command against the given task", responses = { @ApiResponse(responseCode = "400", description = "Given shell command option doesn't exist"), @ApiResponse(responseCode = "403", description = "Given shell command doesn't exist") } ) @Consumes({ MediaType.APPLICATION_JSON }) public SingularityTaskShellCommandRequest runShellCommand( @Parameter(hidden = true) @Auth SingularityUser user, @Parameter(required = true, description = "Id of the task")@PathParam("taskId") String taskId, @RequestBody(required = true, description = "Object describing the command to be run") final SingularityShellCommand shellCommand) { SingularityTaskId taskIdObj = getTaskIdFromStr(taskId); authorizationHelper.checkForAuthorizationByTaskId(taskId, user, SingularityAuthorizationScope.WRITE); validator.checkActionEnabled(SingularityAction.RUN_SHELL_COMMAND); if (!taskManager.isActiveTask(taskId)) { throw WebExceptions.badRequest("%s is not an active task, can't run %s on it", taskId, shellCommand.getName()); } return startShellCommand(taskIdObj, shellCommand, user); }
@Override public boolean apply(ShellCommandDescriptor input) { return input.getName().equals(shellCommand.getName()); } });
@POST @Path("/task/{taskId}/command") @Operation( summary = "Run a configured shell command against the given task", responses = { @ApiResponse(responseCode = "400", description = "Given shell command option doesn't exist"), @ApiResponse(responseCode = "403", description = "Given shell command doesn't exist") } ) @Consumes({ MediaType.APPLICATION_JSON }) public SingularityTaskShellCommandRequest runShellCommand( @Parameter(hidden = true) @Auth SingularityUser user, @Parameter(required = true, description = "Id of the task")@PathParam("taskId") String taskId, @RequestBody(required = true, description = "Object describing the command to be run") final SingularityShellCommand shellCommand) { SingularityTaskId taskIdObj = getTaskIdFromStr(taskId); authorizationHelper.checkForAuthorizationByTaskId(taskId, user, SingularityAuthorizationScope.WRITE); validator.checkActionEnabled(SingularityAction.RUN_SHELL_COMMAND); if (!taskManager.isActiveTask(taskId)) { throw WebExceptions.badRequest("%s is not an active task, can't run %s on it", taskId, shellCommand.getName()); } return startShellCommand(taskIdObj, shellCommand, user); }