@POST @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public Response createDeploymentGroup(@Valid final DeploymentGroup deploymentGroup) { try { model.addDeploymentGroup(deploymentGroup); return Response.ok(CREATED_RESPONSE).build(); } catch (DeploymentGroupExistsException ignored) { final DeploymentGroup existing; try { existing = model.getDeploymentGroup(deploymentGroup.getName()); } catch (DeploymentGroupDoesNotExistException e) { // Edge condition: There's a race where someone can potentially remove the deployment-group // while this operation is in progress. This should be very rare. If it does happen, // return 500. return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } if (!Objects.equals(existing.getHostSelectors(), deploymentGroup.getHostSelectors())) { return Response.ok(DEPLOYMENT_GROUP_ALREADY_EXISTS_RESPONSE).build(); } return Response.ok(NOT_MODIFIED_RESPONSE).build(); } }
@Override void processItem(final String agent) { try { if (masterModel.isHostUp(agent)) { // Host UP -- nothing to do return; } final AgentInfo agentInfo = masterModel.getAgentInfo(agent); if (agentInfo == null) { return; } final long downSince = agentInfo.getStartTime() + agentInfo.getUptime(); final long downDurationMillis = clock.now().getMillis() - downSince; if (downDurationMillis >= timeoutMillis) { try { log.info("Reaping dead agent '{}' (DOWN for {} hours)", agent, DurationFormatUtils.formatDurationHMS(downDurationMillis)); masterModel.deregisterHost(agent); } catch (Exception e) { log.warn("Failed to reap agent '{}'", agent, e); } } } catch (Exception e) { log.warn("Failed to determine if agent '{}' should be reaped", agent, e); } } }
/** * Returns the current {@link Deployment} of {@code job} on {@code host} if it is deployed. * * @param host The host where the job is deployed. * @param jobId The ID of the job. * * @return The response. */ @GET @Path("/{host}/jobs/{job}") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public Optional<Deployment> jobGet(@PathParam("host") final String host, @PathParam("job") final JobId jobId) { if (!jobId.isFullyQualified()) { throw badRequest(); } return Optional.fromNullable(model.getDeployment(host, jobId)); }
@Override public void run(final boolean timeout) throws InterruptedException { final List<String> allHosts = masterModel.listHosts(); final Map<String, Map<String, String>> hostsToLabels = Maps.newHashMap(); // determine all hosts and their labels for (final String host : allHosts) { hostsToLabels.put(host, masterModel.getHostLabels(host)); } final HostMatcher hostMatcher = new HostMatcher(hostsToLabels); for (final DeploymentGroup dg : masterModel.getDeploymentGroups().values()) { final List<String> matchingHosts = hostMatcher.getMatchingHosts(dg); try { masterModel.updateDeploymentGroupHosts(dg.getName(), matchingHosts); } catch (Exception e) { log.warn("error processing hosts update for deployment group: {} - {}", dg.getName(), e); } } } }
@POST @Path("/{name}/rolling-update") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public Response rollingUpdate(@PathParam("name") @Valid final String name, @Valid final RollingUpdateRequest args) { try { final DeploymentGroup deploymentGroup = model.getDeploymentGroup(name); model.rollingUpdate(deploymentGroup, args.getJob(), args.getRolloutOptions()); return Response.ok(new RollingUpdateResponse(RollingUpdateResponse.Status.OK)).build(); } catch (DeploymentGroupDoesNotExistException e) { return Response.ok(new RollingUpdateResponse( RollingUpdateResponse.Status.DEPLOYMENT_GROUP_NOT_FOUND)).build(); } catch (JobDoesNotExistException e) { return Response.ok(new RollingUpdateResponse( RollingUpdateResponse.Status.JOB_NOT_FOUND)).build(); } }
public Response getDeploymentGroupStatus(@PathParam("name") @Valid final String name) { try { final DeploymentGroup deploymentGroup = model.getDeploymentGroup(name); final DeploymentGroupStatus deploymentGroupStatus = model.getDeploymentGroupStatus(name); final List<String> hosts = model.getDeploymentGroupHosts(name); final HostStatus hostStatus = model.getHostStatus(host); JobId deployedJobId = null; TaskStatus.State state = null;
@Override public void run(final boolean timeout) throws InterruptedException { final List<String> allHosts = masterModel.listHosts(); final Map<String, Map<String, String>> hostsToLabels = Maps.newHashMap(); // determine all hosts and their labels for (final String host : allHosts) { final HostStatus hostStatus = masterModel.getHostStatus(host); if (hostStatus != null) { hostsToLabels.put(host, hostStatus.getLabels()); } } final HostMatcher hostMatcher = new HostMatcher(hostsToLabels); for (final DeploymentGroup dg : masterModel.getDeploymentGroups().values()) { final List<String> matchingHosts = hostMatcher.getMatchingHosts(dg); try { masterModel.updateDeploymentGroupHosts(dg.getName(), matchingHosts); } catch (Exception e) { log.warn("error processing hosts update for deployment group: {} - {}", dg.getName(), e); } } } }
@Override public void run(final boolean timeout) throws InterruptedException { for (final DeploymentGroup dg : masterModel.getDeploymentGroups().values()) { try { masterModel.rollingUpdateStep(dg, DefaultRolloutPlanner.of(dg)); } catch (Exception e) { log.warn("error processing rolling update step for deployment group: {} - {}", dg.getName(), e); } } } }
/** * Returns various status information about the host. * * @param host The host id. * @param statusFilter An optional status filter. * * @return The host status. */ @GET @Path("{id}/status") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public Optional<HostStatus> hostStatus( @PathParam("id") final String host, @QueryParam("status") @DefaultValue("") final String statusFilter) { final HostStatus status = model.getHostStatus(host); final Optional<HostStatus> response; if (status != null && (isNullOrEmpty(statusFilter) || statusFilter.equals(status.getStatus().toString()))) { response = Optional.of(status); } else { response = Optional.absent(); } log.debug("hostStatus: host={}, statusFilter={}, returning: {}", host, statusFilter, response); return response; }
@Override protected void beforeIteration() { jobsInDeploymentGroups = masterModel.getDeploymentGroups() .values() .stream() .map(DeploymentGroup::getJobId) .collect(Collectors.toSet()); }
@GET @Path("/{name}") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public Response getDeploymentGroup(@PathParam("name") final String name) { try { return Response.ok(model.getDeploymentGroup(name)).build(); } catch (final DeploymentGroupDoesNotExistException e) { return Response.status(Response.Status.NOT_FOUND).build(); } }
/** * Deregisters the host from the cluster. Will delete just about everything the cluster knows * about it. * * @param host The host to deregister. * * @return The response. */ @DELETE @Path("{id}") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public HostDeregisterResponse delete(@PathParam("id") final String host) { try { model.deregisterHost(host); return new HostDeregisterResponse(HostDeregisterResponse.Status.OK, host); } catch (HostNotFoundException e) { throw notFound(new HostDeregisterResponse(HostDeregisterResponse.Status.NOT_FOUND, host)); } catch (HostStillInUseException e) { throw badRequest(new HostDeregisterResponse(HostDeregisterResponse.Status.JOBS_STILL_DEPLOYED, host)); } }
model.addJob(actualJob); } catch (JobExistsException e) { throw badRequest(new CreateJobResponse(JOB_ALREADY_EXISTS, ImmutableList.<String>of(),
model.deployJob(host, actualDeployment, token); return new JobDeployResponse(JobDeployResponse.Status.OK, host, jobId); } catch (JobAlreadyDeployedException e) {
public Response getDeploymentGroupStatus(@PathParam("name") @Valid final String name) { try { final DeploymentGroup deploymentGroup = model.getDeploymentGroup(name); final DeploymentGroupStatus deploymentGroupStatus = model.getDeploymentGroupStatus(name); final List<String> hosts = model.getDeploymentGroupHosts(name); final HostStatus hostStatus = model.getHostStatus(host); JobId deployedJobId = null; TaskStatus.State state = null;
@POST @Path("/{name}/rolling-update") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public Response rollingUpdate(@PathParam("name") @Valid final String name, @Valid final RollingUpdateRequest args) { try { final DeploymentGroup deploymentGroup = model.getDeploymentGroup(name); model.rollingUpdate(deploymentGroup, args.getJob(), args.getRolloutOptions()); return Response.ok(new RollingUpdateResponse(RollingUpdateResponse.Status.OK)).build(); } catch (DeploymentGroupDoesNotExistException e) { return Response.ok(new RollingUpdateResponse( RollingUpdateResponse.Status.DEPLOYMENT_GROUP_NOT_FOUND)).build(); } catch (JobDoesNotExistException e) { return Response.ok(new RollingUpdateResponse( RollingUpdateResponse.Status.JOB_NOT_FOUND)).build(); } }
/** * Returns various status information about the hosts. * * @param hosts The hosts. * @param statusFilter An optional status filter. * * @return The response. */ @POST @Path("/statuses") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public Map<String, HostStatus> hostStatuses( final List<String> hosts, @QueryParam("status") @DefaultValue("") final String statusFilter) { final Map<String, HostStatus> statuses = Maps.newHashMap(); for (final String host : hosts) { final HostStatus status = model.getHostStatus(host); if (status != null) { if (isNullOrEmpty(statusFilter) || statusFilter.equals(status.getStatus().toString())) { statuses.put(host, status); } } } return statuses; }
@GET @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public List<String> getDeploymentGroup() { final List<String> deploymentGroups = Lists.newArrayList(model.getDeploymentGroups().keySet()); Collections.sort(deploymentGroups); return deploymentGroups; }
@GET @Path("/{name}") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public Response getDeploymentGroup(@PathParam("name") final String name) { try { return Response.ok(model.getDeploymentGroup(name)).build(); } catch (final DeploymentGroupDoesNotExistException e) { return Response.status(Response.Status.NOT_FOUND).build(); } }
/** * Deregisters the host from the cluster. Will delete just about everything the cluster knows * about it. * @param host The host to deregister. * @return The response. */ @DELETE @Path("{id}") @Produces(APPLICATION_JSON) @Timed @ExceptionMetered public HostDeregisterResponse delete(@PathParam("id") final String host) { try { model.deregisterHost(host); return new HostDeregisterResponse(HostDeregisterResponse.Status.OK, host); } catch (HostNotFoundException e) { throw notFound(new HostDeregisterResponse(HostDeregisterResponse.Status.NOT_FOUND, host)); } catch (HostStillInUseException e) { throw badRequest(new HostDeregisterResponse(HostDeregisterResponse.Status.JOBS_STILL_DEPLOYED, host)); } }