summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Marius Venstad <jonmv@users.noreply.github.com>2019-09-12 12:59:54 +0200
committerGitHub <noreply@github.com>2019-09-12 12:59:54 +0200
commit4c4072e53213f75c739bbfc152e884cab94bdf3c (patch)
tree2c50bf414541b679c664a4ef10f466d01593d5e3
parentcc8a4ee468a4a403d1be54260259b060851b35e6 (diff)
parent10cc1a0232d7f09116fb9eeaaa646c67ce3c29d5 (diff)
Merge pull request #10590 from vespa-engine/jvenstad/reflect-deployment-status-in-plugin-exit
Reflect deployment job status when plugin exists
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java22
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json1
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/us-east-3-log-without-first.json1
-rw-r--r--hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java15
-rw-r--r--hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentLog.java20
-rw-r--r--hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentResult.java2
-rw-r--r--vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/AbstractVespaMojo.java6
-rw-r--r--vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/DeployMojo.java20
8 files changed, 78 insertions, 9 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java
index 069b992290c..293f4f9a8e3 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java
@@ -26,6 +26,7 @@ import com.yahoo.vespa.hosted.controller.deployment.DeploymentSteps;
import com.yahoo.vespa.hosted.controller.deployment.JobController;
import com.yahoo.vespa.hosted.controller.deployment.Run;
import com.yahoo.vespa.hosted.controller.deployment.RunLog;
+import com.yahoo.vespa.hosted.controller.deployment.RunStatus;
import com.yahoo.vespa.hosted.controller.deployment.Step;
import com.yahoo.vespa.hosted.controller.deployment.Versions;
import com.yahoo.vespa.hosted.controller.restapi.MessageResponse;
@@ -325,7 +326,7 @@ class JobControllerApiHandlerHelper {
private static void runToSlime(Cursor runObject, Run run, URI baseUriForJobType) {
runObject.setLong("id", run.id().number());
- runObject.setString("status", run.status().name());
+ runObject.setString("status", nameOf(run.status()));
runObject.setLong("start", run.start().toEpochMilli());
run.end().ifPresent(instant -> runObject.setLong("end", instant.toEpochMilli()));
@@ -385,7 +386,10 @@ class JobControllerApiHandlerHelper {
Slime slime = new Slime();
Cursor detailsObject = slime.setObject();
- detailsObject.setBool("active", jobController.active(runId).isPresent());
+ Run run = jobController.run(runId)
+ .orElseThrow(() -> new IllegalStateException("Unknown run '" + runId + "'"));
+ detailsObject.setBool("active", ! run.hasEnded());
+ detailsObject.setString("status", nameOf(run.status()));
jobController.updateTestLog(runId);
RunLog runLog = (after == null ? jobController.details(runId) : jobController.details(runId, Long.parseLong(after)))
@@ -455,5 +459,19 @@ class JobControllerApiHandlerHelper {
return new SlimeJsonResponse(slime);
}
+ private static String nameOf(RunStatus status) {
+ switch (status) {
+ case running: return "running";
+ case aborted: return "aborted";
+ case error: return "error";
+ case testFailure: return "testFailure";
+ case outOfCapacity: return "outOfCapacity";
+ case installationFailed: return "installationFailed";
+ case deploymentFailed: return "deploymentFailed";
+ case success: return "success";
+ default: throw new IllegalArgumentException("Unexpected status '" + status + "'");
+ }
+ }
+
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json
index 98d4e2db612..10d7f3260c1 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/system-test-details.json
@@ -1,4 +1,5 @@
{
"active": true,
+ "status": "running",
"log": {}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/us-east-3-log-without-first.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/us-east-3-log-without-first.json
index 2891ea943f2..6d58392cb25 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/us-east-3-log-without-first.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/us-east-3-log-without-first.json
@@ -1,5 +1,6 @@
{
"active": false,
+ "status": "deploymentFailed",
"log": {
"deployTester": [
{
diff --git a/hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java b/hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java
index bcbcb99587d..c6c5c64bd9f 100644
--- a/hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java
+++ b/hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java
@@ -304,6 +304,7 @@ public abstract class ControllerHttpClient {
}));
return new DeploymentLog(entries,
rootObject.field("active").asBool(),
+ valueOf(rootObject.field("status").asString()),
rootObject.field("lastId").valid() ? OptionalLong.of(rootObject.field("lastId").asLong())
: OptionalLong.empty());
}
@@ -367,4 +368,18 @@ public abstract class ControllerHttpClient {
}
+ private static DeploymentLog.Status valueOf(String status) {
+ switch (status) {
+ case "running": return DeploymentLog.Status.running;
+ case "aborted": return DeploymentLog.Status.aborted;
+ case "error": return DeploymentLog.Status.error;
+ case "testFailure": return DeploymentLog.Status.testFailure;
+ case "outOfCapacity": return DeploymentLog.Status.outOfCapacity;
+ case "installationFailed": return DeploymentLog.Status.installationFailed;
+ case "deploymentFailed": return DeploymentLog.Status.deploymentFailed;
+ case "success": return DeploymentLog.Status.success;
+ default: throw new IllegalArgumentException("Unexpected status '" + status + "'");
+ }
+ }
+
}
diff --git a/hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentLog.java b/hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentLog.java
index f2da64e9403..a42072fffd8 100644
--- a/hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentLog.java
+++ b/hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentLog.java
@@ -16,11 +16,13 @@ public class DeploymentLog {
private final List<Entry> entries;
private final boolean active;
+ private final Status status;
private final OptionalLong last;
- public DeploymentLog(List<Entry> entries, boolean active, OptionalLong last) {
+ public DeploymentLog(List<Entry> entries, boolean active, Status status, OptionalLong last) {
this.entries = entries.stream().sorted(comparing(Entry::at)).collect(toUnmodifiableList());
this.active = active;
+ this.status = status;
this.last = last;
}
@@ -32,6 +34,10 @@ public class DeploymentLog {
return active;
}
+ public Status status() {
+ return status;
+ }
+
public OptionalLong last() {
return last;
}
@@ -63,4 +69,16 @@ public class DeploymentLog {
}
+
+ public enum Status {
+ running,
+ aborted,
+ error,
+ testFailure,
+ outOfCapacity,
+ installationFailed,
+ deploymentFailed,
+ success;
+ }
+
}
diff --git a/hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentResult.java b/hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentResult.java
index e78a7e926b4..34ce04b95fd 100644
--- a/hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentResult.java
+++ b/hosted-api/src/main/java/ai/vespa/hosted/api/DeploymentResult.java
@@ -1,8 +1,6 @@
package ai.vespa.hosted.api;
-import java.net.URI;
-
/**
* Contains information about the result of a {@link Deployment} against a {@link ControllerHttpClient}.
*
diff --git a/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/AbstractVespaMojo.java b/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/AbstractVespaMojo.java
index e59b94ead4a..bf8f6f83f53 100644
--- a/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/AbstractVespaMojo.java
+++ b/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/AbstractVespaMojo.java
@@ -4,6 +4,7 @@ import ai.vespa.hosted.api.ControllerHttpClient;
import com.yahoo.config.provision.ApplicationId;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
@@ -44,11 +45,14 @@ public abstract class AbstractVespaMojo extends AbstractMojo {
protected ControllerHttpClient controller;
@Override
- public final void execute() throws MojoExecutionException {
+ public final void execute() throws MojoExecutionException, MojoFailureException {
try {
setup();
doExecute();
}
+ catch (MojoFailureException | MojoExecutionException e) {
+ throw e;
+ }
catch (Exception e) {
throw new MojoExecutionException("Execution failed for application '" + id + "':", e);
}
diff --git a/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/DeployMojo.java b/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/DeployMojo.java
index 9ef31cafb1b..7deffd37a79 100644
--- a/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/DeployMojo.java
+++ b/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/DeployMojo.java
@@ -5,6 +5,8 @@ import ai.vespa.hosted.api.DeploymentLog;
import ai.vespa.hosted.api.DeploymentResult;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.zone.ZoneId;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
@@ -30,7 +32,7 @@ public class DeployMojo extends AbstractVespaDeploymentMojo {
private boolean follow;
@Override
- protected void doExecute() {
+ protected void doExecute() throws MojoFailureException, MojoExecutionException {
Deployment deployment = Deployment.ofPackage(Paths.get(firstNonBlank(applicationZip,
projectPathOf("target", "application.zip"))));
if (vespaVersion != null) deployment = deployment.atVersion(vespaVersion);
@@ -42,10 +44,11 @@ public class DeployMojo extends AbstractVespaDeploymentMojo {
if (follow) tailLogs(id, zone, result.run());
}
- private void tailLogs(ApplicationId id, ZoneId zone, long run) {
+ private void tailLogs(ApplicationId id, ZoneId zone, long run) throws MojoFailureException, MojoExecutionException {
long last = -1;
+ DeploymentLog log;
while (true) {
- DeploymentLog log = controller.deploymentLog(id, zone, run, last);
+ log = controller.deploymentLog(id, zone, run, last);
for (DeploymentLog.Entry entry : log.entries())
print(entry);
last = log.last().orElse(last);
@@ -61,6 +64,17 @@ public class DeployMojo extends AbstractVespaDeploymentMojo {
break;
}
}
+ switch (log.status()) {
+ case success: return;
+ case error: throw new MojoExecutionException("Unexpected error during deployment; see log for details");
+ case aborted: throw new MojoFailureException("Deployment was aborted, probably by a newer deployment");
+ case outOfCapacity: throw new MojoFailureException("No capacity left in zone; please contact the Vespa team");
+ case deploymentFailed: throw new MojoFailureException("Deployment failed; see log for details");
+ case installationFailed: throw new MojoFailureException("Installation failed; see Vespa log for details");
+ case running: throw new MojoFailureException("Deployment not completed");
+ case testFailure: throw new IllegalStateException("Unexpected status; tests are not run for manual deployments");
+ default: throw new IllegalArgumentException("Unexpected status '" + log.status() + "'");
+ }
}
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneOffset.UTC);