use of com.spotify.helios.common.descriptors.JobId in project helios by spotify.
the class HostListCommand method run.
@Override
int run(final Namespace options, final HeliosClient client, final PrintStream out, final boolean json, final BufferedReader stdin) throws ExecutionException, InterruptedException {
final String pattern = options.getString(patternArg.getDest());
final List<String> selectorArgValue = options.getList(hostSelectorsArg.getDest());
final Set<String> selectors = ImmutableSet.copyOf(selectorArgValue);
final List<String> hosts;
if (pattern.isEmpty() && selectors.isEmpty()) {
hosts = client.listHosts().get();
} else if (!pattern.isEmpty() && selectors.isEmpty()) {
hosts = client.listHosts(pattern).get();
} else if (pattern.isEmpty() && !selectors.isEmpty()) {
hosts = client.listHosts(selectors).get();
} else {
hosts = client.listHosts(pattern, selectors).get();
}
final Map<String, String> queryParams = Maps.newHashMap();
final String statusFilter = options.getString(statusArg.getDest());
if (!isNullOrEmpty(statusFilter)) {
try {
HostStatus.Status.valueOf(statusFilter);
queryParams.put("status", statusFilter);
} catch (IllegalArgumentException ignored) {
throw new IllegalArgumentException("Invalid status. Valid statuses are: " + statusChoicesString);
}
}
final boolean full = options.getBoolean(fullArg.getDest());
final boolean quiet = options.getBoolean(quietArg.getDest());
if (hosts.isEmpty()) {
if (json) {
out.println("{ }");
} else if (!quiet && !isNullOrEmpty(pattern)) {
out.printf("host pattern %s matched no hosts%n", pattern);
}
return 1;
}
final List<String> sortedHosts = natural().sortedCopy(hosts);
if (quiet) {
if (json) {
out.println(Json.asPrettyStringUnchecked(sortedHosts));
} else {
for (final String host : sortedHosts) {
out.println(formatHostname(full, host));
}
}
} else {
final Map<String, HostStatus> statuses = client.hostStatuses(hosts, queryParams).get();
if (json) {
final Map<String, HostStatus> sorted = Maps.newTreeMap();
sorted.putAll(statuses);
out.println(Json.asPrettyStringUnchecked(sorted));
} else {
final Table table = table(out);
table.row("HOST", "STATUS", "DEPLOYED", "RUNNING", "CPUS", "MEM", "LOAD AVG", "MEM USAGE", "OS", "HELIOS", "DOCKER", "LABELS");
for (final Map.Entry<String, HostStatus> e : statuses.entrySet()) {
final String host = e.getKey();
final HostStatus s = e.getValue();
if (s == null) {
continue;
}
final Set<TaskStatus> runningDeployedJobs = Sets.newHashSet();
for (final JobId jobId : s.getJobs().keySet()) {
final TaskStatus taskStatus = s.getStatuses().get(jobId);
if (taskStatus == null) {
continue;
}
if (taskStatus.getState() == TaskStatus.State.RUNNING) {
runningDeployedJobs.add(taskStatus);
}
}
final HostInfo hi = s.getHostInfo();
final String memUsage;
final String cpus;
final String mem;
final String loadAvg;
final String os;
final String docker;
if (hi != null) {
final long free = hi.getMemoryFreeBytes();
final long total = hi.getMemoryTotalBytes();
memUsage = format("%.2f", (float) (total - free) / total);
cpus = String.valueOf(hi.getCpus());
mem = hi.getMemoryTotalBytes() / (1024 * 1024 * 1024) + " gb";
loadAvg = format("%.2f", hi.getLoadAvg());
os = hi.getOsName() + " " + hi.getOsVersion();
final DockerVersion dv = hi.getDockerVersion();
docker = (dv != null) ? format("%s (%s)", dv.getVersion(), dv.getApiVersion()) : "";
} else {
memUsage = cpus = mem = loadAvg = os = docker = "";
}
final String version;
if (s.getAgentInfo() != null) {
version = Optional.fromNullable(s.getAgentInfo().getVersion()).or("");
} else {
version = "";
}
String status = s.getStatus() == UP ? "Up" : "Down";
if (s.getAgentInfo() != null) {
final long startTime = s.getAgentInfo().getStartTime();
final long upTime = s.getAgentInfo().getUptime();
if (s.getStatus() == UP) {
status += " " + humanDuration(currentTimeMillis() - startTime);
} else {
status += " " + humanDuration(currentTimeMillis() - startTime - upTime);
}
}
final String hostLabels = Joiner.on(", ").withKeyValueSeparator("=").join(s.getLabels());
table.row(formatHostname(full, host), status, s.getJobs().size(), runningDeployedJobs.size(), cpus, mem, loadAvg, memUsage, os, version, docker, hostLabels);
}
table.print();
}
}
return 0;
}
use of com.spotify.helios.common.descriptors.JobId in project helios by spotify.
the class JobHistoryCommand method run.
@Override
int run(final Namespace options, final HeliosClient client, final PrintStream out, final boolean json, final BufferedReader stdin) throws ExecutionException, InterruptedException {
final String jobIdString = options.getString(jobIdArg.getDest());
final Map<JobId, Job> jobs = client.jobs(jobIdString).get();
if (jobs.size() == 0) {
out.printf("Unknown job: %s%n", jobIdString);
return 1;
} else if (jobs.size() > 1) {
out.printf("Ambiguous job id: %s%n", jobIdString);
return 1;
}
final JobId jobId = getLast(jobs.keySet());
final TaskStatusEvents result = client.jobHistory(jobId).get();
if (json) {
out.println(Json.asPrettyStringUnchecked(result));
return 0;
}
final Table table = table(out);
table.row("HOST", "TIMESTAMP", "STATE", "THROTTLED", "CONTAINERID");
final List<TaskStatusEvent> events = result.getEvents();
final DateTimeFormatter format = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss.SSS");
for (final TaskStatusEvent event : events) {
final String host = checkNotNull(event.getHost());
final long timestamp = checkNotNull(event.getTimestamp());
final TaskStatus status = checkNotNull(event.getStatus());
final State state = checkNotNull(status.getState());
String containerId = status.getContainerId();
containerId = containerId == null ? "<none>" : containerId;
table.row(host, format.print(timestamp), state, status.getThrottled(), containerId);
}
table.print();
return 0;
}
use of com.spotify.helios.common.descriptors.JobId in project helios by spotify.
the class JobInspectCommand method runWithJobId.
@Override
protected int runWithJobId(final Namespace options, final HeliosClient client, final PrintStream out, final boolean json, final JobId jobId, final BufferedReader stdin) throws ExecutionException, InterruptedException {
final Map<JobId, Job> jobs = client.jobs(jobId.toString()).get();
if (jobs.size() == 0) {
out.printf("Unknown job: %s%n", jobId);
return 1;
}
final Job job = Iterables.getOnlyElement(jobs.values());
if (json) {
out.println(Json.asPrettyStringUnchecked(job));
} else {
out.printf("Id: %s%n", job.getId());
out.printf("Image: %s%n", job.getImage());
out.printf("Created: %s%n", job.getCreated() == null ? "" : DATE_FORMATTER.format(new Date(job.getCreated())));
out.printf("Expires: %s%n", job.getExpires() == null ? "never" : DATE_FORMATTER.format(job.getExpires()));
out.printf("Hostname: %s%n", job.getHostname());
out.printf("Command: %s%n", quote(job.getCommand()));
printMap(out, "Env: ", QUOTE, job.getEnv());
out.printf("Health check: %s%n", formatHealthCheck(job.getHealthCheck()));
out.printf("Grace period (seconds): %s%n", job.getGracePeriod());
out.printf("Time to wait before kill (seconds): %s%n", job.getSecondsToWaitBeforeKill());
printMap(out, "Metadata: ", QUOTE, job.getMetadata());
printMap(out, "Ports: ", FORMAT_PORTMAPPING, job.getPorts());
printMap(out, "Reg: ", FORMAT_SERVICE_PORTS, job.getRegistration());
out.printf("Security options: %s%n", job.getSecurityOpt());
out.printf("Network mode: %s%n", job.getNetworkMode());
out.printf("Token: %s%n", job.getToken());
printVolumes(out, job.getVolumes());
out.printf("Add capabilities: %s%n", Joiner.on(", ").join(job.getAddCapabilities()));
out.printf("Drop capabilities: %s%n", Joiner.on(", ").join(job.getDropCapabilities()));
}
return 0;
}
use of com.spotify.helios.common.descriptors.JobId in project helios by spotify.
the class Jobs method undeploy.
/**
* Undeploy the job from all specified hosts, and delete the job. Any failures will be ignored,
* and we will keep trying each host. A list of errors encountered along the way will be returned
* to the caller.
* @param client the HeliosClient to use
* @param job the job to undeploy and delete
* @param hosts the hosts to undeploy from
* @param errors errors encountered during the undeploy will be added to this list
* @return the list of errors
*/
static List<AssertionError> undeploy(final HeliosClient client, final Job job, final List<String> hosts, final List<AssertionError> errors) {
final JobId id = job.getId();
for (final String host : hosts) {
log.info("Undeploying {} from {}", getJobDescription(job), host);
final JobUndeployResponse response;
try {
response = get(client.undeploy(id, host));
if (response.getStatus() != JobUndeployResponse.Status.OK && response.getStatus() != JobUndeployResponse.Status.JOB_NOT_FOUND) {
errors.add(new AssertionError(format("Failed to undeploy job %s - %s", id, response)));
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
errors.add(new AssertionError(e));
}
}
try {
log.debug("Deleting job {}", id);
final JobDeleteResponse response = get(client.deleteJob(id));
if (response.getStatus() != JobDeleteResponse.Status.OK && response.getStatus() != JobDeleteResponse.Status.JOB_NOT_FOUND) {
errors.add(new AssertionError(format("Failed to delete job %s - %s", id.toString(), response.toString())));
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
errors.add(new AssertionError(e));
}
return errors;
}
use of com.spotify.helios.common.descriptors.JobId in project helios by spotify.
the class TemporaryJobs method removeOldJobs.
/**
* Undeploys and deletes jobs leftover from previous runs of TemporaryJobs. This would happen if
* the test was terminated before the cleanup code was called. This method will iterate over each
* file in the specified directory. Each filename is the prefix that was used for job names
* during previous runs. The method will undeploy and delete any jobs that have a matching
* prefix, and the delete the file. If the file is locked, it is currently in use, and will be
* skipped.
*/
private void removeOldJobs() throws ExecutionException, InterruptedException, IOException {
// is used as a @Rule in a test class with many test methods
if (removedOldJobs) {
return;
}
final File[] files = prefixDirectory.toFile().listFiles();
if (files == null || files.length == 0) {
return;
}
log.info("Removing old temporary jobs");
final Map<JobId, Job> jobs = client.jobs().get();
// Iterate over all files in the directory
for (final File file : files) {
// directories. We don't expect any, but skip them just in case.
if (file.getName().endsWith(".tmp") || file.isDirectory()) {
continue;
}
// used by another process. In either case, skip over it.
try (JobPrefixFile prefixFile = JobPrefixFile.tryFromExistingFile(file.toPath())) {
if (prefixFile == null) {
log.debug("Unable to create JobPrefixFile for {}", file.getPath());
continue;
}
boolean jobRemovalFailed = false;
// Iterate over jobs, looking for ones with a matching prefix.
for (final Map.Entry<JobId, Job> entry : jobs.entrySet()) {
final JobId jobId = entry.getKey();
// Skip over job if the id doesn't start with current filename.
if (!jobId.getName().startsWith(prefixFile.prefix())) {
continue;
}
// Get list of all hosts where this job is deployed, and undeploy
final JobStatus status = client.jobStatus(entry.getKey()).get();
final List<String> hosts = ImmutableList.copyOf(status.getDeployments().keySet());
final List<AssertionError> errors = undeploy(client, entry.getValue(), hosts, new ArrayList<AssertionError>());
// Set flag indicating if any errors occur
if (!errors.isEmpty()) {
jobRemovalFailed = true;
}
}
// leave it there so we can try again next time.
if (!jobRemovalFailed) {
prefixFile.delete();
}
} catch (NoSuchFileException e) {
log.debug("File {} already processed by somebody else.", file.getPath());
} catch (Exception e) {
// log exception and continue on to next file
log.warn("Exception processing file {}", file.getPath(), e);
}
}
removedOldJobs = true;
}
Aggregations