/** * Return a new RolloutOptions instance by merging this instance with another one. * @throws NullPointerException if any attribute in both instances are null. */ public RolloutOptions withFallback(final RolloutOptions that) { return RolloutOptions.newBuilder() .setTimeout(firstNonNull(timeout, that.timeout)) .setParallelism(firstNonNull(parallelism, that.parallelism)) .setMigrate(firstNonNull(migrate, that.migrate)) .setOverlap(firstNonNull(overlap, that.overlap)) .setToken(firstNonNull(token, that.token)) .setIgnoreFailures(firstNonNull(ignoreFailures, that.ignoreFailures)) .build(); }
private static String formatRolloutOptions(final RolloutOptions options) { if (options == null) { return ""; } final List<String> output = new ArrayList<>(); output.add(String.format("timeout: %d", options.getTimeout())); output.add(String.format("parallelism: %d", options.getParallelism())); output.add(String.format("migrate: %s", options.getMigrate())); output.add(String.format("overlap: %s", options.getOverlap())); output.add(String.format("token: %s", options.getToken())); output.add(String.format("ignoreFailures: %s", options.getIgnoreFailures())); return Joiner.on(", ").join(output); }
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; }
/** * Returns a {@link RolloutOptions} instance that will replace null attributes in options with * values from two tiers of fallbacks. First fallback to job then * {@link RolloutOptions#getDefault()}. */ static RolloutOptions rolloutOptionsWithFallback(final RolloutOptions options, final Job job) { return options.withFallback( job.getRolloutOptions() == null ? RolloutOptions.getDefault() : job.getRolloutOptions().withFallback(RolloutOptions.getDefault())); }
@Override public List<RolloutTask> plan(final List<String> hosts) { // generate the rollout tasks final List<RolloutTask> rolloutTasks = Lists.newArrayList(); final int parallelism = deploymentGroup.getRolloutOptions() != null && deploymentGroup.getRolloutOptions().getParallelism() != null ? deploymentGroup.getRolloutOptions().getParallelism() : 1; final boolean overlap = deploymentGroup.getRolloutOptions() != null && TRUE.equals(deploymentGroup.getRolloutOptions().getOverlap()); for (final List<String> partition : Lists.partition(hosts, parallelism)) { rolloutTasks.addAll(overlap ? rolloutTasksWithOverlap(partition) : rolloutTasks(partition)); } return ImmutableList.copyOf(rolloutTasks); }
final RolloutOptions rolloutOptions = RolloutOptions.newBuilder() .setTimeout(timeout) .setParallelism(parallelism) MoreObjects.firstNonNull(job.getRolloutOptions(), RolloutOptions.getDefault()); final Integer actualParallelism = nullableWithFallback(parallelism, optionsFromJob.getParallelism()); final Long actualTimeout = nullableWithFallback(timeout, optionsFromJob.getTimeout()); final Boolean actualOverlap = nullableWithFallback(overlap, optionsFromJob.getOverlap()); final String actualToken = nullableWithFallback(token, optionsFromJob.getToken()); final Boolean actualIgnoreFailures = nullableWithFallback(ignoreFailures, optionsFromJob.getIgnoreFailures()); final Boolean actualMigrate = nullableWithFallback(migrate, optionsFromJob.getMigrate());
@Override public List<RolloutTask> plan(final List<String> hosts) { // generate the rollout tasks final List<RolloutTask> rolloutTasks = Lists.newArrayList(); final int parallelism = deploymentGroup.getRolloutOptions() != null && deploymentGroup.getRolloutOptions().getParallelism() != null ? deploymentGroup.getRolloutOptions().getParallelism() : 1; Lists.partition(hosts, parallelism) .forEach(partition -> rolloutTasks.addAll(rolloutTasks(partition))); return ImmutableList.copyOf(rolloutTasks); }
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 isRolloutTimedOut(final DeploymentGroup deploymentGroup, final ZooKeeperClient client) { try { final String statusPath = Paths.statusDeploymentGroup(deploymentGroup.getName()); final long secondsSinceDeploy = MILLISECONDS.toSeconds( System.currentTimeMillis() - client.getNode(statusPath).getStat().getMtime()); return secondsSinceDeploy > deploymentGroup.getRolloutOptions().getTimeout(); } 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: {} - {}", deploymentGroup.getName(), e); return false; } }
private RollingUpdateOp rollingUpdateUndeploy(final ZooKeeperClient client, final RollingUpdateOpFactory opFactory, final DeploymentGroup deploymentGroup, final String host, final boolean skipRedundantUndeploys) { final List<ZooKeeperOperation> operations = Lists.newArrayList(); for (final Deployment deployment : getTasks(client, host).values()) { if (!ownedByDeploymentGroup(deployment, deploymentGroup) && !isMigration(deployment, deploymentGroup)) { continue; } if (skipRedundantUndeploys && redundantUndeployment(deployment, deploymentGroup)) { continue; } try { final String token = MoreObjects.firstNonNull( deploymentGroup.getRolloutOptions().getToken(), Job.EMPTY_TOKEN); operations.addAll(getUndeployOperations(client, host, deployment.getJobId(), token)); log.debug("planned undeploy operations for job={}", deployment.getJobId()); } 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 (JobNotDeployedException e) { // probably somebody beat us to the punch of undeploying. that's fine. } } return opFactory.nextTask(operations); }
private boolean isIgnoreFailures() { return deploymentGroup.getRolloutOptions() != null && TRUE.equals(deploymentGroup.getRolloutOptions().getIgnoreFailures()); }
@Override public List<RolloutTask> plan(final Map<String, HostStatus> hostsAndStatuses) { // we only care about hosts that are UP final List<String> hosts = Lists.newArrayList(); for (final Map.Entry<String, HostStatus> entry : hostsAndStatuses.entrySet()) { if (entry.getValue().getStatus().equals(HostStatus.Status.UP)) { hosts.add(entry.getKey()); } } // generate the rollout tasks final List<RolloutTask> rolloutTasks = Lists.newArrayList(); final int parallelism = deploymentGroup.getRolloutOptions() != null ? deploymentGroup.getRolloutOptions().getParallelism() : 1; for (final List<String> partition : Lists.partition(hosts, parallelism)) { for (final String host : partition) { rolloutTasks.add(RolloutTask.of(RolloutTask.Action.UNDEPLOY_OLD_JOBS, host)); rolloutTasks.add(RolloutTask.of(RolloutTask.Action.DEPLOY_NEW_JOB, host)); } for (final String host : partition) { rolloutTasks.add(RolloutTask.of(RolloutTask.Action.AWAIT_RUNNING, host)); } } return ImmutableList.copyOf(rolloutTasks); } }
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); }
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(); } }
if (rolloutOptions != null) { out.printf("Rollout options:%n"); out.printf(" Migrate: %s%n", rolloutOptions.getMigrate()); out.printf(" Overlap: %s%n", rolloutOptions.getOverlap()); out.printf(" Parallelism: %d%n", rolloutOptions.getParallelism()); out.printf(" Timeout: %d%n", rolloutOptions.getTimeout()); if (!isNullOrEmpty(rolloutOptions.getToken())) { out.printf(" Token: %s%n", rolloutOptions.getToken()); out.printf(" Ignore failures: %b%n", rolloutOptions.getIgnoreFailures());
.setVolumes(emptyMap()) .setExpires(null) .setRolloutOptions(RolloutOptions.newBuilder().build()) .build(); .setVolumes(emptyMap()) .setExpires(null) .setRolloutOptions(RolloutOptions.newBuilder().build()) .build(); final JobId secondJobId = createJob(job2);
final RolloutOptions rolloutOptions = RolloutOptions.newBuilder() .setTimeout(timeout) .setParallelism(parallelism)