Search in sources :

Example 1 with DeploymentGroupStatusResponse

use of com.spotify.helios.common.protocol.DeploymentGroupStatusResponse in project helios by spotify.

the class RollingUpdateCommand 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, IOException {
    final String name = options.getString(nameArg.getDest());
    final long timeout = options.getLong(timeoutArg.getDest());
    final int parallelism = options.getInt(parallelismArg.getDest());
    final boolean async = options.getBoolean(asyncArg.getDest());
    final long rolloutTimeout = options.getLong(rolloutTimeoutArg.getDest());
    final boolean migrate = options.getBoolean(migrateArg.getDest());
    final boolean overlap = options.getBoolean(overlapArg.getDest());
    final String token = options.getString(tokenArg.getDest());
    checkArgument(timeout > 0, "Timeout must be greater than 0");
    checkArgument(parallelism > 0, "Parallelism must be greater than 0");
    checkArgument(rolloutTimeout > 0, "Rollout timeout must be greater than 0");
    final long startTime = timeSupplier.get();
    final RolloutOptions rolloutOptions = RolloutOptions.newBuilder().setTimeout(timeout).setParallelism(parallelism).setMigrate(migrate).setOverlap(overlap).setToken(token).build();
    final RollingUpdateResponse response = client.rollingUpdate(name, jobId, rolloutOptions).get();
    if (response.getStatus() != RollingUpdateResponse.Status.OK) {
        if (!json) {
            out.println("Failed: " + response);
        } else {
            out.println(response.toJsonString());
        }
        return 1;
    }
    if (!json) {
        out.println(format("Rolling update%s started: %s -> %s " + "(parallelism=%d, timeout=%d, overlap=%b, token=%s)%s", async ? " (async)" : "", name, jobId.toShortString(), parallelism, timeout, overlap, token, async ? "" : "\n"));
    }
    final Map<String, Object> jsonOutput = Maps.newHashMap();
    jsonOutput.put("parallelism", parallelism);
    jsonOutput.put("timeout", timeout);
    jsonOutput.put("overlap", overlap);
    jsonOutput.put("token", token);
    if (async) {
        if (json) {
            jsonOutput.put("status", response.getStatus());
            out.println(Json.asStringUnchecked(jsonOutput));
        }
        return 0;
    }
    String error = "";
    boolean failed = false;
    boolean timedOut = false;
    final Set<String> reported = Sets.newHashSet();
    while (true) {
        final DeploymentGroupStatusResponse status = client.deploymentGroupStatus(name).get();
        if (status == null) {
            failed = true;
            error = "Failed to fetch deployment-group status";
            break;
        }
        if (!jobId.equals(status.getDeploymentGroup().getJobId())) {
            // Another rolling-update was started, overriding this one -- exit
            failed = true;
            error = "Deployment-group job id changed during rolling-update";
            break;
        }
        if (!json) {
            for (final DeploymentGroupStatusResponse.HostStatus hostStatus : status.getHostStatuses()) {
                final JobId hostJobId = hostStatus.getJobId();
                final String host = hostStatus.getHost();
                final TaskStatus.State state = hostStatus.getState();
                final boolean done = hostJobId != null && hostJobId.equals(jobId) && state == TaskStatus.State.RUNNING;
                if (done && reported.add(host)) {
                    out.println(format("%s -> %s (%d/%d)", host, state, reported.size(), status.getHostStatuses().size()));
                }
            }
        }
        if (status.getStatus() != DeploymentGroupStatusResponse.Status.ROLLING_OUT) {
            if (status.getStatus() == DeploymentGroupStatusResponse.Status.FAILED) {
                failed = true;
                error = status.getError();
            }
            break;
        }
        if (timeSupplier.get() - startTime > TimeUnit.MINUTES.toMillis(rolloutTimeout)) {
            // Rollout timed out
            timedOut = true;
            break;
        }
        sleepFunction.sleep(POLL_INTERVAL_MILLIS);
    }
    final double duration = (timeSupplier.get() - startTime) / 1000.0;
    if (json) {
        if (failed) {
            jsonOutput.put("status", "FAILED");
            jsonOutput.put("error", error);
        } else if (timedOut) {
            jsonOutput.put("status", "TIMEOUT");
        } else {
            jsonOutput.put("status", "DONE");
        }
        jsonOutput.put("duration", duration);
        out.println(Json.asStringUnchecked(jsonOutput));
    } else {
        out.println();
        if (failed) {
            out.println(format("Failed: %s", error));
        } else if (timedOut) {
            out.println("Timed out! (rolling-update still in progress)");
        } else {
            out.println("Done.");
        }
        out.println(format("Duration: %.2f s", duration));
    }
    return (failed || timedOut) ? 1 : 0;
}
Also used : RolloutOptions(com.spotify.helios.common.descriptors.RolloutOptions) TaskStatus(com.spotify.helios.common.descriptors.TaskStatus) DeploymentGroupStatusResponse(com.spotify.helios.common.protocol.DeploymentGroupStatusResponse) RollingUpdateResponse(com.spotify.helios.common.protocol.RollingUpdateResponse) JobId(com.spotify.helios.common.descriptors.JobId)

Example 2 with DeploymentGroupStatusResponse

use of com.spotify.helios.common.protocol.DeploymentGroupStatusResponse in project helios by spotify.

the class DeploymentGroupStatusCommand method run0.

static int run0(final HeliosClient client, final PrintStream out, final boolean json, final String name, final boolean full) throws ExecutionException, InterruptedException {
    final DeploymentGroupStatusResponse status = client.deploymentGroupStatus(name).get();
    if (status == null) {
        if (json) {
            final Map<String, Object> output = Maps.newHashMap();
            output.put("status", "DEPLOYMENT_GROUP_NOT_FOUND");
            out.print(Json.asStringUnchecked(output));
        } else {
            out.printf("Unknown deployment group: %s%n", name);
        }
        return 1;
    }
    if (json) {
        out.println(Json.asPrettyStringUnchecked(status));
    } else {
        final JobId jobId = status.getDeploymentGroup().getJobId();
        final String error = status.getError();
        final List<HostSelector> hostSelectors = status.getDeploymentGroup().getHostSelectors();
        out.printf("Name: %s%n", name);
        out.printf("Job Id: %s%n", full ? jobId : (jobId == null ? null : jobId.toShortString()));
        out.printf("Status: %s%n", status.getStatus());
        out.printf("Host selectors:%n");
        for (final HostSelector hostSelector : hostSelectors) {
            out.printf("  %s%n", hostSelector.toPrettyString());
        }
        if (!Strings.isNullOrEmpty(error)) {
            out.printf("Error: %s%n", error);
        }
        out.printf("%n");
        printTable(out, jobId, status.getHostStatuses(), full);
    }
    return 0;
}
Also used : HostSelector(com.spotify.helios.common.descriptors.HostSelector) DeploymentGroupStatusResponse(com.spotify.helios.common.protocol.DeploymentGroupStatusResponse) JobId(com.spotify.helios.common.descriptors.JobId)

Example 3 with DeploymentGroupStatusResponse

use of com.spotify.helios.common.protocol.DeploymentGroupStatusResponse in project helios by spotify.

the class RollingUpdateCommand method runWithJob.

@Override
protected int runWithJob(final Namespace options, final HeliosClient client, final PrintStream out, final boolean json, final Job job, final BufferedReader stdin) throws ExecutionException, InterruptedException, IOException {
    final JobId jobId = job.getId();
    final String name = options.getString(nameArg.getDest());
    final Long timeout = options.getLong(timeoutArg.getDest());
    final Integer parallelism = options.getInt(parallelismArg.getDest());
    final boolean async = options.getBoolean(asyncArg.getDest());
    final long rolloutTimeout = options.getLong(rolloutTimeoutArg.getDest());
    final Boolean migrate = options.getBoolean(migrateArg.getDest());
    final Boolean overlap = options.getBoolean(overlapArg.getDest());
    final String token = options.getString(tokenArg.getDest());
    final Boolean ignoreFailures = options.getBoolean(ignoreFailuresArg.getDest());
    checkArgument(timeout == null || timeout > 0, "Timeout must be greater than 0");
    checkArgument(parallelism == null || parallelism > 0, "Parallelism must be greater than 0");
    checkArgument(rolloutTimeout > 0, "Rollout timeout must be greater than 0");
    final long startTime = timeSupplier.get();
    final RolloutOptions rolloutOptions = RolloutOptions.newBuilder().setTimeout(timeout).setParallelism(parallelism).setMigrate(migrate).setOverlap(overlap).setToken(token).setIgnoreFailures(ignoreFailures).build();
    final RollingUpdateResponse response = client.rollingUpdate(name, jobId, rolloutOptions).get();
    if (response.getStatus() != RollingUpdateResponse.Status.OK) {
        if (!json) {
            out.println("Failed: " + response);
        } else {
            out.println(response.toJsonString());
        }
        return 1;
    }
    final RolloutOptions optionsFromJob = 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());
    if (!json) {
        out.println(format("Rolling update%s started: %s -> %s " + "(parallelism=%d, timeout=%d, overlap=%b, token=%s, " + "ignoreFailures=%b, migrate=%b)%s", async ? " (async)" : "", name, jobId.toShortString(), actualParallelism, actualTimeout, actualOverlap, actualToken, actualIgnoreFailures, actualMigrate, async ? "" : "\n"));
    }
    final Map<String, Object> jsonOutput = Maps.newHashMap();
    jsonOutput.put("parallelism", actualParallelism);
    jsonOutput.put("timeout", actualTimeout);
    jsonOutput.put("overlap", actualOverlap);
    jsonOutput.put("token", actualToken);
    jsonOutput.put("ignoreFailures", actualIgnoreFailures);
    jsonOutput.put("migrate", actualMigrate);
    if (async) {
        if (json) {
            jsonOutput.put("status", response.getStatus());
            out.println(Json.asStringUnchecked(jsonOutput));
        }
        return 0;
    }
    String error = "";
    boolean failed = false;
    boolean timedOut = false;
    final Set<String> reported = Sets.newHashSet();
    while (true) {
        final DeploymentGroupStatusResponse status = client.deploymentGroupStatus(name).get();
        if (status == null) {
            failed = true;
            error = "Failed to fetch deployment-group status";
            break;
        }
        if (!jobId.equals(status.getDeploymentGroup().getJobId())) {
            // Another rolling-update was started, overriding this one -- exit
            failed = true;
            error = "Deployment-group job id changed during rolling-update";
            break;
        }
        if (!json) {
            for (final DeploymentGroupStatusResponse.HostStatus hostStatus : status.getHostStatuses()) {
                final JobId hostJobId = hostStatus.getJobId();
                final String host = hostStatus.getHost();
                final TaskStatus.State state = hostStatus.getState();
                final boolean done = hostJobId != null && hostJobId.equals(jobId) && state == TaskStatus.State.RUNNING;
                if (done && reported.add(host)) {
                    out.println(format("%s -> %s (%d/%d)", host, state, reported.size(), status.getHostStatuses().size()));
                }
            }
        }
        if (status.getStatus() != DeploymentGroupStatusResponse.Status.ROLLING_OUT) {
            if (status.getStatus() == DeploymentGroupStatusResponse.Status.FAILED) {
                failed = true;
                error = status.getError();
            }
            break;
        }
        if (timeSupplier.get() - startTime > TimeUnit.MINUTES.toMillis(rolloutTimeout)) {
            // Rollout timed out
            timedOut = true;
            break;
        }
        sleepFunction.sleep(POLL_INTERVAL_MILLIS);
    }
    final double duration = (timeSupplier.get() - startTime) / 1000.0;
    if (json) {
        if (failed) {
            jsonOutput.put("status", "FAILED");
            jsonOutput.put("error", error);
        } else if (timedOut) {
            jsonOutput.put("status", "TIMEOUT");
        } else {
            jsonOutput.put("status", "DONE");
        }
        jsonOutput.put("duration", duration);
        out.println(Json.asStringUnchecked(jsonOutput));
    } else {
        out.println();
        if (failed) {
            out.println(format("Failed: %s", error));
        } else if (timedOut) {
            out.println("Timed out! (rolling-update still in progress)");
        } else {
            out.println("Done.");
        }
        out.println(format("Duration: %.2f s", duration));
    }
    return (failed || timedOut) ? 1 : 0;
}
Also used : RolloutOptions(com.spotify.helios.common.descriptors.RolloutOptions) TaskStatus(com.spotify.helios.common.descriptors.TaskStatus) DeploymentGroupStatusResponse(com.spotify.helios.common.protocol.DeploymentGroupStatusResponse) RollingUpdateResponse(com.spotify.helios.common.protocol.RollingUpdateResponse) JobId(com.spotify.helios.common.descriptors.JobId)

Example 4 with DeploymentGroupStatusResponse

use of com.spotify.helios.common.protocol.DeploymentGroupStatusResponse in project helios by spotify.

the class DeploymentGroupStatusCommandTest method testDeploymentGroupStatusWithError.

@Test
public void testDeploymentGroupStatusWithError() throws Exception {
    final List<DeploymentGroupStatusResponse.HostStatus> hostStatuses = Lists.newArrayList();
    hostStatuses.add(new DeploymentGroupStatusResponse.HostStatus("host1", JOB_ID, TaskStatus.State.RUNNING));
    hostStatuses.add(new DeploymentGroupStatusResponse.HostStatus("host2", JOB_ID, TaskStatus.State.PULLING_IMAGE));
    hostStatuses.add(new DeploymentGroupStatusResponse.HostStatus("host3", null, null));
    final DeploymentGroupStatusResponse status = new DeploymentGroupStatusResponse(DEPLOYMENT_GROUP, DeploymentGroupStatusResponse.Status.ROLLING_OUT, "Oops!", hostStatuses, null);
    when(client.deploymentGroupStatus(GROUP_NAME)).thenReturn(Futures.immediateFuture(status));
    when(options.getString("name")).thenReturn(GROUP_NAME);
    final int ret = command.run(options, client, out, false, null);
    assertEquals(0, ret);
    final String output = baos.toString().replaceAll("\\s+", "");
    final String expected = format("Name: %s" + "Job Id: %s" + "Status: ROLLING_OUT" + "Host selectors:" + "  a = b" + "  foo = bar" + "Error: Oops!" + "HOST UP-TO-DATE JOB STATE" + "host1. X %s RUNNING" + "host2. X %s PULLING_IMAGE" + "host3. - -", GROUP_NAME, JOB_ID, JOB_ID, JOB_ID).replace(" ", "");
    assertEquals(expected, output);
}
Also used : DeploymentGroupStatusResponse(com.spotify.helios.common.protocol.DeploymentGroupStatusResponse) Matchers.anyString(org.mockito.Matchers.anyString) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Test(org.junit.Test)

Example 5 with DeploymentGroupStatusResponse

use of com.spotify.helios.common.protocol.DeploymentGroupStatusResponse in project helios by spotify.

the class DeploymentGroupStatusCommandTest method testDeploymentGroupNotFound.

@Test
public void testDeploymentGroupNotFound() throws Exception {
    final ListenableFuture<DeploymentGroupStatusResponse> nullFuture = Futures.immediateFuture(null);
    when(client.deploymentGroupStatus(anyString())).thenReturn(nullFuture);
    final String name = "non-existent-group";
    when(options.getString("name")).thenReturn(name);
    final int ret = command.run(options, client, out, false, null);
    assertEquals(1, ret);
    final String output = baos.toString();
    assertThat(output, containsString(format("Unknown deployment group: %s", name)));
}
Also used : DeploymentGroupStatusResponse(com.spotify.helios.common.protocol.DeploymentGroupStatusResponse) Matchers.anyString(org.mockito.Matchers.anyString) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Test(org.junit.Test)

Aggregations

DeploymentGroupStatusResponse (com.spotify.helios.common.protocol.DeploymentGroupStatusResponse)11 Test (org.junit.Test)7 CoreMatchers.containsString (org.hamcrest.CoreMatchers.containsString)5 Matchers.anyString (org.mockito.Matchers.anyString)5 JobId (com.spotify.helios.common.descriptors.JobId)4 TaskStatus (com.spotify.helios.common.descriptors.TaskStatus)3 DeploymentGroup (com.spotify.helios.common.descriptors.DeploymentGroup)2 RolloutOptions (com.spotify.helios.common.descriptors.RolloutOptions)2 RollingUpdateResponse (com.spotify.helios.common.protocol.RollingUpdateResponse)2 Map (java.util.Map)2 ExceptionMetered (com.codahale.metrics.annotation.ExceptionMetered)1 Timed (com.codahale.metrics.annotation.Timed)1 Deployment (com.spotify.helios.common.descriptors.Deployment)1 DeploymentGroupStatus (com.spotify.helios.common.descriptors.DeploymentGroupStatus)1 HostSelector (com.spotify.helios.common.descriptors.HostSelector)1 HostStatus (com.spotify.helios.common.descriptors.HostStatus)1 DeploymentGroupDoesNotExistException (com.spotify.helios.master.DeploymentGroupDoesNotExistException)1 GET (javax.ws.rs.GET)1 Path (javax.ws.rs.Path)1 Produces (javax.ws.rs.Produces)1