out.println(Json.asPrettyStringUnchecked(deploymentGroup)); } else { out.printf("Name: %s%n", deploymentGroup.getName()); out.printf("Host selectors:%n"); for (final HostSelector hostSelector : deploymentGroup.getHostSelectors()) { out.printf(" %s%n", hostSelector.toPrettyString()); out.printf("Job: %s%n", deploymentGroup.getJobId()); if (deploymentGroup.getRollingUpdateReason() != null) { out.printf("Rolling update reason: %s%n", deploymentGroup.getRollingUpdateReason()); final RolloutOptions rolloutOptions = deploymentGroup.getRolloutOptions(); if (rolloutOptions != null) { out.printf("Rollout options:%n");
final boolean quiet = options.getBoolean(quietArg.getDest()); final DeploymentGroup deploymentGroup = DeploymentGroup.newBuilder() .setName(name) .setHostSelectors(hostSelectors) out.println("Creating deployment group: " + deploymentGroup.toJsonString());
deploymentGroup.getName(), jobId, rolloutOptionsWithFallback); final DeploymentGroup updated = deploymentGroup.toBuilder() .setJobId(jobId) .setRolloutOptions(rolloutOptionsWithFallback) final ZooKeeperClient client = provider.get("rollingUpdate"); operations.add(set(Paths.configDeploymentGroup(updated.getName()), updated)); deploymentGroup.getName(), jobId, operations); deploymentGroup.getName(), jobId); } catch (final NoNodeException e) { throw new DeploymentGroupDoesNotExistException(deploymentGroup.getName()); } catch (final KeeperException e) { throw new HeliosRuntimeException( "rolling-update on deployment-group " + deploymentGroup.getName() + " failed", e);
public List<String> getMatchingHosts(final DeploymentGroup deploymentGroup) { final List<HostSelector> selectors = deploymentGroup.getHostSelectors(); if (selectors == null || selectors.isEmpty()) { log.error("skipping deployment group with no host selectors: " + deploymentGroup.getName()); return emptyList(); } return getMatchingHosts(selectors); }
private boolean isMigration(final Deployment deployment, final DeploymentGroup deploymentGroup) { return (deploymentGroup.getRolloutOptions() != null && TRUE.equals(deploymentGroup.getRolloutOptions().getMigrate()) && deployment.getJobId().equals(deploymentGroup.getJobId())); }
private boolean ownedByDeploymentGroup(final Deployment deployment, final DeploymentGroup deploymentGroup) { return Objects.equals(deployment.getDeploymentGroupName(), deploymentGroup.getName()); }
private RollingUpdateOp rollingUpdateDeploy(final ZooKeeperClient client, final RollingUpdateOpFactory opFactory, final DeploymentGroup deploymentGroup, final String host) { final Deployment deployment = Deployment.of(deploymentGroup.getJobId(), Goal.START, Deployment.EMTPY_DEPLOYER_USER, this.name, deploymentGroup.getName()); try { final String token = MoreObjects.firstNonNull( deploymentGroup.getRolloutOptions().getToken(), Job.EMPTY_TOKEN); return opFactory.nextTask(getDeployOperations(client, host, deployment, token)); } catch (JobDoesNotExistException e) { return opFactory.error(e, host, RollingUpdateError.JOB_NOT_FOUND); } catch (TokenVerificationException e) { return opFactory.error(e, host, RollingUpdateError.TOKEN_VERIFICATION_ERROR); } catch (HostNotFoundException e) { return opFactory.error(e, host, RollingUpdateError.HOST_NOT_FOUND); } catch (JobPortAllocationConflictException e) { return opFactory.error(e, host, RollingUpdateError.PORT_CONFLICT); } catch (JobAlreadyDeployedException e) { // Nothing to do return opFactory.nextTask(); } }
out.println(Json.asPrettyStringUnchecked(deploymentGroup)); } else { out.printf("Name: %s%n", deploymentGroup.getName()); out.printf("Host selectors:%n"); for (final HostSelector hostSelector : deploymentGroup.getHostSelectors()) { out.printf(" %s%n", hostSelector.toPrettyString()); out.printf("Job: %s%n", deploymentGroup.getJobId());
out.println(Json.asPrettyStringUnchecked(status)); } else { final JobId jobId = status.getDeploymentGroup().getJobId(); final String error = status.getError(); final List<HostSelector> hostSelectors = status.getDeploymentGroup().getHostSelectors();
if (deploymentGroup.getJobId() != null && updateOnHostChange(deploymentGroup, status)) { deploymentGroup = deploymentGroup.toBuilder() .setRollingUpdateReason(HOSTS_CHANGED) .build(); ops.add(set(Paths.configDeploymentGroup(deploymentGroup.getName()), deploymentGroup)); groupName, deploymentGroup.getJobId(), ops);
private boolean isRolloutTimedOut(final ZooKeeperClient client, final DeploymentGroup deploymentGroup) { final String groupName = deploymentGroup.getName(); final RolloutOptions defaultOptions = RolloutOptions.getDefault(); final long groupTimeoutSetting = deploymentGroup.getRolloutOptions() == null ? defaultOptions.getTimeout() : deploymentGroup.getRolloutOptions().withFallback(defaultOptions).getTimeout(); final long secondsSinceDeploy; try { final String statusPath = Paths.statusDeploymentGroupTasks(groupName); secondsSinceDeploy = MILLISECONDS.toSeconds( System.currentTimeMillis() - client.getNode(statusPath).getStat().getMtime()); } catch (KeeperException e) { // statusPath doesn't exist or some other ZK issue. probably this deployment group // was removed. log.warn("error determining deployment group modification time: name={}", groupName, e); return false; } if (secondsSinceDeploy > groupTimeoutSetting) { log.info("rolling-update on deployment-group name={} has timed out after " + "{} seconds (rolloutOptions.timeout={})", groupName, secondsSinceDeploy, groupTimeoutSetting); return true; } return false; }
private RollingUpdateOp rollingUpdateAwaitUndeployed(final ZooKeeperClient client, final RollingUpdateOpFactory opFactory, final DeploymentGroup deploymentGroup, final String host) { final TaskStatus taskStatus = getTaskStatus(client, host, deploymentGroup.getJobId()); if (taskStatus == null) { // The task status (i.e. /status/hosts/<host>/job/<job-id>) has been removed, indicating the // job has been undeployed. return opFactory.nextTask(); } if (isRolloutTimedOut(client, deploymentGroup)) { return opFactory.error("timed out while waiting for job undeployment", host, RollingUpdateError.TIMED_OUT_WAITING_FOR_JOB_TO_UNDEPLOY); } return opFactory.yield(); }
private boolean isIgnoreFailures() { return deploymentGroup.getRolloutOptions() != null && TRUE.equals(deploymentGroup.getRolloutOptions().getIgnoreFailures()); }
public Builder toBuilder() { final Builder builder = newBuilder(); return builder.setName(name) .setJobId(jobId) .setHostSelectors(hostSelectors) .setRolloutOptions(rolloutOptions) .setRollingUpdateReason(reason); }
public Map<String, Object> rollingUpdateStarted(final DeploymentGroup deploymentGroup) { final Map<String, Object> ev = createEvent("rollingUpdateStarted", deploymentGroup); ev.put("reason", deploymentGroup.getRollingUpdateReason()); return ev; }
@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 @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(); } }
final DeploymentGroup deploymentGroup, final String host) { final TaskStatus taskStatus = getTaskStatus(client, host, deploymentGroup.getJobId()); final JobId jobId = deploymentGroup.getJobId(); final Deployment deployment = getDeployment(host, deploymentGroup.getJobId()); if (deployment == null) { return opFactory.error( + "Perhaps it was manually undeployed?", host, RollingUpdateError.JOB_UNEXPECTEDLY_UNDEPLOYED); } else if (!Objects.equals(deployment.getDeploymentGroupName(), deploymentGroup.getName())) { return opFactory.error( "job was already deployed, either manually or by a different deployment group", host,
private RollingUpdateTaskResult rollingUpdateUndeploy(final DeploymentGroup deploymentGroup, final String host) { final ZooKeeperClient client = provider.get("rollingUpdateUndeploy"); final List<ZooKeeperOperation> operations = Lists.newArrayList(); for (final Deployment deployment : getTasks(client, host).values()) { final boolean isOwnedByDeploymentGroup = Objects.equals( deployment.getDeploymentGroupName(), deploymentGroup.getName()); final boolean isSameJob = deployment.getJobId().equals(deploymentGroup.getJobId()); if (isOwnedByDeploymentGroup || ( isSameJob && deploymentGroup.getRolloutOptions().getMigrate())) { if (isSameJob && isOwnedByDeploymentGroup && deployment.getGoal().equals(Goal.START)) { // The job we want deployed is already deployed and set to run, so just leave it. continue; } try { operations.addAll(getUndeployOperations(client, host, deployment.getJobId(), Job.EMPTY_TOKEN)); } catch (TokenVerificationException | HostNotFoundException e) { return RollingUpdateTaskResult.error(e, host); } catch (JobNotDeployedException e) { // probably somebody beat us to the punch of undeploying. that's fine. } } } return RollingUpdateTaskResult.of(operations); }