aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorJon Marius Venstad <venstad@gmail.com>2019-11-19 14:28:36 +0100
committerJon Marius Venstad <venstad@gmail.com>2019-11-19 14:28:36 +0100
commit7dd75c6e9454c810738cf0aad138cd1ecb2c091d (patch)
tree2eab66c41726e306494c00ec1500fecaa8a38097 /controller-server
parent35ca9e133e48e99b3d633f0376f82b8cc2bbdfc5 (diff)
Handle missing spec for instance to display jobs for
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java84
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview-user-instance.json62
3 files changed, 108 insertions, 40 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 ed9612a7343..63516d2e51a 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
@@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.controller.restapi.application;
import com.google.common.base.Joiner;
import com.yahoo.component.Version;
+import com.yahoo.config.application.api.DeploymentInstanceSpec;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.SystemName;
@@ -28,7 +29,6 @@ import com.yahoo.vespa.hosted.controller.deployment.JobController;
import com.yahoo.vespa.hosted.controller.deployment.JobList;
import com.yahoo.vespa.hosted.controller.deployment.JobStatus;
import com.yahoo.vespa.hosted.controller.deployment.Run;
-import com.yahoo.vespa.hosted.controller.deployment.RunList;
import com.yahoo.vespa.hosted.controller.deployment.RunLog;
import com.yahoo.vespa.hosted.controller.deployment.RunStatus;
import com.yahoo.vespa.hosted.controller.deployment.Step;
@@ -78,35 +78,38 @@ class JobControllerApiHandlerHelper {
Application application = controller.applications().requireApplication(TenantAndApplicationId.from(id));
Instance instance = application.require(id.instance());
Change change = application.change();
- DeploymentSteps steps = new DeploymentSteps(application.deploymentSpec().requireInstance(id.instance()), controller::system);
+ Optional<DeploymentInstanceSpec> spec = application.deploymentSpec().instance(id.instance());
+ Optional<DeploymentSteps> steps = spec.map(s -> new DeploymentSteps(s, controller::system));
+ List<JobType> productionJobs = steps.map(DeploymentSteps::productionJobs).orElse(List.of());
+ List<JobType> jobs = steps.map(DeploymentSteps::jobs).orElse(List.of());
Map<JobType, JobStatus> status = controller.jobController().deploymentStatus(application).instanceJobs(id.instance());
// The logic for pending runs imitates DeploymentTrigger logic; not good, but the trigger wiring must be re-written to reuse :S
Map<JobType, Versions> pendingProduction =
- steps.productionJobs().stream()
- .filter(type -> ! controller.applications().deploymentTrigger().isComplete(change, change, instance, type, status.get(type)))
- .collect(Collectors.toMap(type -> type,
- type -> Versions.from(change,
- application,
- Optional.ofNullable(instance.deployments().get(type.zone(controller.system()))),
- controller.systemVersion()),
- (v1, v2) -> { throw new IllegalStateException("Entries '" + v1 + "' and '" + v2 + "' have the same key!"); },
- LinkedHashMap::new));
-
- Map<JobType, Run> running = steps.jobs().stream()
- .map(type -> controller.jobController().last(id, type))
- .flatMap(Optional::stream)
- .filter(run -> ! run.hasEnded())
- .collect(toMap(run -> run.id().type(),
- run -> run));
+ productionJobs.stream()
+ .filter(type -> ! controller.applications().deploymentTrigger().isComplete(change, change, instance, type, status.get(type)))
+ .collect(Collectors.toMap(type -> type,
+ type -> Versions.from(change,
+ application,
+ Optional.ofNullable(instance.deployments().get(type.zone(controller.system()))),
+ controller.systemVersion()),
+ (v1, v2) -> { throw new IllegalStateException("Entries '" + v1 + "' and '" + v2 + "' have the same key!"); },
+ LinkedHashMap::new));
+
+ Map<JobType, Run> running = jobs.stream()
+ .map(type -> controller.jobController().last(id, type))
+ .flatMap(Optional::stream)
+ .filter(run -> ! run.hasEnded())
+ .collect(toMap(run -> run.id().type(),
+ run -> run));
Slime slime = new Slime();
Cursor responseObject = slime.setObject();
Cursor lastVersionsObject = responseObject.setObject("lastVersions");
if (application.latestVersion().isPresent()) {
- lastPlatformToSlime(lastVersionsObject.setObject("platform"), controller, application, instance, status, change, steps);
- lastApplicationToSlime(lastVersionsObject.setObject("application"), application, instance, status, change, steps, controller);
+ lastPlatformToSlime(lastVersionsObject.setObject("platform"), controller, application, instance, status, change, productionJobs, spec);
+ lastApplicationToSlime(lastVersionsObject.setObject("application"), application, instance, status, change, productionJobs, controller);
}
Cursor deployingObject = responseObject.setObject("deploying");
@@ -116,9 +119,9 @@ class JobControllerApiHandlerHelper {
}
Cursor deploymentsArray = responseObject.setArray("deployments");
- steps.production().forEach(step -> {
+ steps.ifPresent(deploymentSteps -> deploymentSteps.production().forEach(step -> {
Cursor deploymentsObject = deploymentsArray.addObject();
- steps.toJobs(step).forEach(type -> {
+ deploymentSteps.toJobs(step).forEach(type -> {
ZoneId zone = type.zone(controller.system());
Deployment deployment = instance.deployments().get(zone);
if (deployment != null)
@@ -131,21 +134,21 @@ class JobControllerApiHandlerHelper {
status.get(type),
deployment);
});
- });
+ }));
Cursor jobsObject = responseObject.setObject("jobs");
- steps.jobs().forEach(type -> {
+ steps.ifPresent(deploymentSteps -> deploymentSteps.jobs().forEach(type -> {
jobTypeToSlime(jobsObject.setObject(shortNameOf(type, controller.system())),
controller,
application,
instance,
status,
type,
- steps,
+ deploymentSteps,
pendingProduction,
running,
baseUriForJobs.resolve(baseUriForJobs.getPath() + "/" + type.jobName()).normalize());
- });
+ }));
Cursor devJobsObject = responseObject.setObject("devJobs");
for (JobType type : JobType.allIn(controller.system()))
@@ -163,11 +166,14 @@ class JobControllerApiHandlerHelper {
return new SlimeJsonResponse(slime);
}
- private static void lastPlatformToSlime(Cursor lastPlatformObject, Controller controller, Application application, Instance instance, Map<JobType, JobStatus> status, Change change, DeploymentSteps steps) {
+ private static void lastPlatformToSlime(Cursor lastPlatformObject, Controller controller, Application application,
+ Instance instance, Map<JobType, JobStatus> status, Change change,
+ List<JobType> productionJobs, Optional<DeploymentInstanceSpec> instanceSpec) {
VespaVersion lastVespa = controller.versionStatus().version(controller.systemVersion());
- VespaVersion.Confidence targetConfidence = Map.of(defaultPolicy, normal,
- conservative, high)
- .getOrDefault(application.deploymentSpec().requireInstance(instance.name()).upgradePolicy(), broken);
+ VespaVersion.Confidence targetConfidence = instanceSpec.map(spec -> Map.of(defaultPolicy, normal,
+ conservative, high)
+ .getOrDefault(spec.upgradePolicy(), broken))
+ .orElse(normal);
for (VespaVersion version : controller.versionStatus().versions())
if ( ! version.versionNumber().isAfter(controller.systemVersion())
&& version.confidence().equalOrHigherThan(targetConfidence))
@@ -176,11 +182,11 @@ class JobControllerApiHandlerHelper {
Version lastPlatform = lastVespa.versionNumber();
lastPlatformObject.setString("platform", lastPlatform.toString());
lastPlatformObject.setLong("at", lastVespa.committedAt().toEpochMilli());
- long completed = steps.productionJobs().stream().filter(type -> controller.applications().deploymentTrigger().isComplete(Change.of(lastPlatform), change, instance, type, status.get(type))).count();
+ long completed = productionJobs.stream().filter(type -> controller.applications().deploymentTrigger().isComplete(Change.of(lastPlatform), change, instance, type, status.get(type))).count();
if (Optional.of(lastPlatform).equals(change.platform()))
- lastPlatformObject.setString("deploying", completed + " of " + steps.productionJobs().size() + " complete");
- else if (completed == steps.productionJobs().size())
- lastPlatformObject.setString("completed", completed + " of " + steps.productionJobs().size() + " complete");
+ lastPlatformObject.setString("deploying", completed + " of " + productionJobs.size() + " complete");
+ else if (completed == productionJobs.size())
+ lastPlatformObject.setString("completed", completed + " of " + productionJobs.size() + " complete");
else if ( ! application.deploymentSpec().instances().stream()
.allMatch(spec -> spec.canUpgradeAt(controller.clock().instant()))) {
lastPlatformObject.setString("blocked", application.deploymentSpec().instances().stream()
@@ -196,16 +202,16 @@ class JobControllerApiHandlerHelper {
: "Waiting for " + application.change() + " to complete");
}
- private static void lastApplicationToSlime(Cursor lastApplicationObject, Application application, Instance instance, Map<JobType, JobStatus> status, Change change, DeploymentSteps steps, Controller controller) {
+ private static void lastApplicationToSlime(Cursor lastApplicationObject, Application application, Instance instance, Map<JobType, JobStatus> status, Change change, List<JobType> productionJobs, Controller controller) {
long completed;
ApplicationVersion lastApplication = application.latestVersion().get();
applicationVersionToSlime(lastApplicationObject.setObject("application"), lastApplication);
lastApplicationObject.setLong("at", lastApplication.buildTime().get().toEpochMilli());
- completed = steps.productionJobs().stream().filter(type -> controller.applications().deploymentTrigger().isComplete(Change.of(lastApplication), change, instance, type, status.get(type))).count();
+ completed = productionJobs.stream().filter(type -> controller.applications().deploymentTrigger().isComplete(Change.of(lastApplication), change, instance, type, status.get(type))).count();
if (Optional.of(lastApplication).equals(change.application()))
- lastApplicationObject.setString("deploying", completed + " of " + steps.productionJobs().size() + " complete");
- else if (completed == steps.productionJobs().size())
- lastApplicationObject.setString("completed", completed + " of " + steps.productionJobs().size() + " complete");
+ lastApplicationObject.setString("deploying", completed + " of " + productionJobs.size() + " complete");
+ else if (completed == productionJobs.size())
+ lastApplicationObject.setString("completed", completed + " of " + productionJobs.size() + " complete");
else if ( ! application.deploymentSpec().instances().stream()
.allMatch(spec -> spec.canChangeRevisionAt(controller.clock().instant()))) {
lastApplicationObject.setString("blocked", application.deploymentSpec().instances().stream()
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java
index 7ad39745c44..766e64d20d0 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java
@@ -122,7 +122,7 @@ public class JobControllerApiHandlerHelperTest {
var userApp = tester.newDeploymentContext(app.instanceId().tenant().value(), app.instanceId().application().value(), "user");
userApp.runJob(devAwsUsEast2a, applicationPackage);
assertResponse(JobControllerApiHandlerHelper.runResponse(tester.jobs().runs(userApp.instanceId(), devAwsUsEast2a), URI.create("https://some.url:43/root")), "dev-aws-us-east-2a-runs.json");
- assertResponse(JobControllerApiHandlerHelper.jobTypeResponse(tester.controller(), userApp.instanceId(), URI.create("https://some.url:43/root/")), "overview.json");
+ assertResponse(JobControllerApiHandlerHelper.jobTypeResponse(tester.controller(), userApp.instanceId(), URI.create("https://some.url:43/root/")), "overview-user-instance.json");
}
@Test
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview-user-instance.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview-user-instance.json
new file mode 100644
index 00000000000..1af3abeea91
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview-user-instance.json
@@ -0,0 +1,62 @@
+{
+ "devJobs": {
+ "dev-aws-us-east-2a": {
+ "runs": [
+ {
+ "wantedPlatform": "7.1",
+ "log": "https://some.url:43/root/dev-aws-us-east-2a/run/1",
+ "wantedApplication": {
+ "hash": "unknown"
+ },
+ "start": 102000,
+ "end": 102000,
+ "id": 1,
+ "steps": {
+ "deployReal": "succeeded",
+ "installReal": "succeeded",
+ "copyVespaLogs": "succeeded"
+ },
+ "tasks": {
+ "install": "succeeded",
+ "deploy": "succeeded"
+ },
+ "status": "success"
+ }
+ ],
+ "url": "https://some.url:43/root/dev-aws-us-east-2a"
+ }
+ },
+ "deployments": [],
+ "lastVersions": {
+ "application": {
+ "at": 1000,
+ "application": {
+ "build": 3,
+ "source": {
+ "gitRepository": "repository1",
+ "gitCommit": "commit1",
+ "gitBranch": "master"
+ },
+ "hash": "1.0.3-commit1"
+ },
+ "deploying": "0 of 0 complete"
+ },
+ "platform": {
+ "at": 0,
+ "completed": "0 of 0 complete",
+ "platform": "7.1"
+ }
+ },
+ "deploying": {
+ "application": {
+ "build": 3,
+ "source": {
+ "gitRepository": "repository1",
+ "gitCommit": "commit1",
+ "gitBranch": "master"
+ },
+ "hash": "1.0.3-commit1"
+ }
+ },
+ "jobs": {}
+}