summaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorJon Marius Venstad <jvenstad@yahoo-inc.com>2018-08-30 10:55:42 +0200
committerJon Marius Venstad <jvenstad@yahoo-inc.com>2018-08-30 10:55:42 +0200
commitc85e6cf73addb51a364836a09759afa6b7786820 (patch)
tree9e0595154a9530b84000b6ab156275c41f8a0175 /controller-server
parentcf4898674735a733d8af4b1b2f96202c81062d21 (diff)
Change the response for the new deployment view
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java31
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java327
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java16
3 files changed, 291 insertions, 83 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index b8d4cc48dce..07286fda90b 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -64,8 +64,6 @@ import com.yahoo.vespa.hosted.controller.application.DeploymentJobs;
import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
import com.yahoo.vespa.hosted.controller.application.SourceRevision;
-import com.yahoo.vespa.hosted.controller.deployment.DeploymentSteps;
-import com.yahoo.vespa.hosted.controller.deployment.Run;
import com.yahoo.vespa.hosted.controller.restapi.ErrorResponse;
import com.yahoo.vespa.hosted.controller.restapi.MessageResponse;
import com.yahoo.restapi.Path;
@@ -91,7 +89,6 @@ import java.security.Principal;
import java.time.DayOfWeek;
import java.time.Duration;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -172,7 +169,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
if (path.matches("/application/v4/tenant/{tenant}")) return tenant(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/application")) return applications(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}")) return application(path.get("tenant"), path.get("application"), request);
- if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job")) return JobControllerApiHandlerHelper.jobTypeResponse(jobTypes(path), latestRuns(path), request.getUri());
+ if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job")) return JobControllerApiHandlerHelper.jobTypeResponse(controller, appIdFromPath(path), request.getUri());
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job/{jobtype}")) return JobControllerApiHandlerHelper.runResponse(controller.jobController().runs(appIdFromPath(path), jobTypeFromPath(path)), request.getUri());
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job/{jobtype}/run/{number}")) return JobControllerApiHandlerHelper.runDetailsResponse(controller.jobController(), runIdFromPath(path), request.getProperty("after"));
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}")) return deployment(path.get("tenant"), path.get("application"), path.get("instance"), path.get("environment"), path.get("region"), request);
@@ -1211,39 +1208,19 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
message + ": No NToken provided"));
}
- private ApplicationId appIdFromPath(Path path) {
+ private static ApplicationId appIdFromPath(Path path) {
return ApplicationId.from(path.get("tenant"), path.get("application"), path.get("instance"));
}
- private JobType jobTypeFromPath(Path path) {
+ private static JobType jobTypeFromPath(Path path) {
return JobType.fromJobName(path.get("jobtype"));
}
- private RunId runIdFromPath(Path path) {
+ private static RunId runIdFromPath(Path path) {
long number = Long.parseLong(path.get("number"));
return new RunId(appIdFromPath(path), jobTypeFromPath(path), number);
}
- private List<JobType> jobTypes(Path path) {
- ApplicationId appId = appIdFromPath(path);
- DeploymentSpec deploymentSpec = controller.applications().get(appId).get().deploymentSpec();
- DeploymentSteps deploymentSteps = new DeploymentSteps(deploymentSpec, controller::system);
- return deploymentSteps.jobs();
- }
-
- private Map<JobType, Run> latestRuns(Path path) {
- Map<JobType, Run> jobMap = new HashMap<>();
- ApplicationId appId = appIdFromPath(path);
- controller.jobController().jobs(appId)
- .forEach(jobType -> jobMap.put(jobType, controller.jobController()
- .last(appId, jobType)
- .orElseThrow(() -> new RuntimeException(String.format("Job %s for application %s appears in " +
- "the list of previously ran jobs, but no status of the last execution found",
- jobType.jobName(), appId.toShortString())))));
-
- return jobMap;
- }
-
private HttpResponse submit(String tenant, String application, HttpRequest request) {
Map<String, byte[]> dataParts = new MultipartParser().parse(request);
Inspector submitOptions = SlimeUtils.jsonToSlime(dataParts.get(EnvironmentResource.SUBMIT_OPTIONS)).get();
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 27810306fa7..b883d4b7fa6 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
@@ -1,25 +1,56 @@
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.DeploymentSpec;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.slime.Cursor;
import com.yahoo.slime.Slime;
+import com.yahoo.vespa.hosted.controller.Application;
+import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.NotExistsException;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
+import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.application.ApplicationVersion;
+import com.yahoo.vespa.hosted.controller.application.Change;
+import com.yahoo.vespa.hosted.controller.application.Deployment;
+import com.yahoo.vespa.hosted.controller.application.JobStatus;
import com.yahoo.vespa.hosted.controller.application.SourceRevision;
+import com.yahoo.vespa.hosted.controller.deployment.DeploymentSteps;
import com.yahoo.vespa.hosted.controller.deployment.JobController;
import com.yahoo.vespa.hosted.controller.api.integration.LogEntry;
import com.yahoo.vespa.hosted.controller.deployment.RunLog;
import com.yahoo.vespa.hosted.controller.deployment.Run;
import com.yahoo.vespa.hosted.controller.deployment.Step;
+import com.yahoo.vespa.hosted.controller.deployment.Versions;
import com.yahoo.vespa.hosted.controller.restapi.SlimeJsonResponse;
+import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
import java.net.URI;
+import java.util.ArrayDeque;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static com.yahoo.config.application.api.DeploymentSpec.UpgradePolicy.conservative;
+import static com.yahoo.config.application.api.DeploymentSpec.UpgradePolicy.defaultPolicy;
+import static com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType.component;
+import static com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType.stagingTest;
+import static com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType.systemTest;
+import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.unfinished;
+import static com.yahoo.vespa.hosted.controller.deployment.Step.deployReal;
+import static com.yahoo.vespa.hosted.controller.versions.VespaVersion.Confidence.broken;
+import static com.yahoo.vespa.hosted.controller.versions.VespaVersion.Confidence.high;
+import static com.yahoo.vespa.hosted.controller.versions.VespaVersion.Confidence.normal;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
/**
* Implements the REST API for the job controller delegated from the Application API.
@@ -32,71 +63,276 @@ class JobControllerApiHandlerHelper {
/**
* @return Response with all job types that have recorded runs for the application _and_ the status for the last run of that type
*/
- static HttpResponse jobTypeResponse(List<JobType> sortedJobs, Map<JobType, Run> lastRun, URI baseUriForJobs) {
+ static HttpResponse jobTypeResponse(Controller controller, ApplicationId id, URI baseUriForJobs) {
+ Application application = controller.applications().require(id);
+ Change change = application.changeAt(controller.clock().instant());
+ DeploymentSteps steps = new DeploymentSteps(application.deploymentSpec(), controller::system);
+
+ // 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, application, type))
+ .collect(Collectors.toMap(type -> type,
+ type -> Versions.from(change,
+ application,
+ Optional.ofNullable(application.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))
+ .filter(Optional::isPresent).map(Optional::get)
+ .filter(run -> ! run.hasEnded())
+ .collect(toMap(run -> run.id().type(),
+ run -> run));
+
Slime slime = new Slime();
Cursor responseObject = slime.setObject();
- Cursor jobArray = responseObject.setArray("jobs");
- sortedJobs.forEach(jobType ->
- jobTypeToSlime(jobArray.addObject(), jobType, Optional.ofNullable(lastRun.get(jobType)), baseUriForJobs));
+ Cursor lastVersionsObject = responseObject.setObject("lastVersions");
+ Cursor lastPlatformObject = lastVersionsObject.setObject("platform");
+ VespaVersion lastVespa = controller.versionStatus().version(controller.systemVersion());
+ VespaVersion.Confidence targetConfidence = application.deploymentSpec().upgradePolicy() == defaultPolicy ? normal
+ : application.deploymentSpec().upgradePolicy() == conservative ? high
+ : broken;
+ for (VespaVersion version : controller.versionStatus().versions())
+ if ( ! version.versionNumber().isAfter(controller.systemVersion())
+ && version.confidence().equalOrHigherThan(targetConfidence))
+ lastVespa = version;
+
+ Version lastPlatform = lastVespa.versionNumber();
+ lastPlatformObject.setString("version", lastPlatform.toString());
+ lastPlatformObject.setLong("at", lastVespa.committedAt().toEpochMilli());
+ long completed = steps.productionJobs().stream().filter(type -> controller.applications().deploymentTrigger().isComplete(Change.of(lastPlatform), application, type)).count();
+ if (Optional.of(lastPlatform).equals(change.platform()))
+ lastPlatformObject.setString("deploying", completed + " of " + steps.productionJobs().size());
+ else if (completed == steps.productionJobs().size())
+ lastPlatformObject.setString("completed", completed + " of " + steps.productionJobs().size());
+ else if ( ! application.deploymentSpec().canUpgradeAt(controller.clock().instant())) {
+ Optional<String> blocked = application.deploymentSpec().changeBlocker().stream()
+ .filter(blocker -> blocker.blocksVersions())
+ .filter(blocker -> blocker.window().includes(controller.clock().instant()))
+ .findAny().map(blocker -> blocker.window().toString());
+ if (blocked.isPresent())
+ lastPlatformObject.setString("blocked", blocked.get());
+ else
+ lastPlatformObject.setString("pending", ""); // What to put here?
+ }
+
+ Cursor lastApplicationObject = lastVersionsObject.setObject("application");
+ ApplicationVersion lastApplication = application.deploymentJobs().statusOf(component).flatMap(JobStatus::lastSuccess).get().application();
+ applicationVersionToSlime(lastApplicationObject.setObject("version"), lastApplication);
+ lastApplicationObject.setLong("at", application.deploymentJobs().statusOf(component).flatMap(JobStatus::lastSuccess).get().at().toEpochMilli());
+ completed = steps.productionJobs().stream().filter(type -> controller.applications().deploymentTrigger().isComplete(Change.of(lastApplication), application, 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");
+ else if ( ! application.deploymentSpec().canChangeRevisionAt(controller.clock().instant())) {
+ Optional<String> blocked = application.deploymentSpec().changeBlocker().stream()
+ .filter(blocker -> blocker.blocksRevisions())
+ .filter(blocker -> blocker.window().includes(controller.clock().instant()))
+ .findAny().map(blocker -> blocker.window().toString());
+ if (blocked.isPresent())
+ lastApplicationObject.setString("blocked", blocked.get());
+ else
+ lastApplicationObject.setString("pending", "Waiting for current deployment to complete");
+ }
+
+ if (change.isPresent()) {
+ Cursor deployingObject = responseObject.setObject("deploying");
+ change.platform().ifPresent(version -> deployingObject.setString("platform", version.toString()));
+ change.application().ifPresent(version -> applicationVersionToSlime(deployingObject.setObject("application"), version));
+ }
+
+ Cursor deploymentsArray = responseObject.setArray("deployments");
+ steps.production().forEach(step -> {
+ Cursor deploymentsObject = deploymentsArray.addObject();
+ steps.toJobs(step).forEach(type -> {
+ ZoneId zone = type.zone(controller.system());
+ Deployment deployment = application.deployments().get(zone);
+ if (deployment != null)
+ deploymentToSlime(deploymentsObject.setObject(zone.region().value()),
+ application,
+ change,
+ pendingProduction,
+ running,
+ type,
+ deployment);
+ });
+ });
+
+ Cursor jobsObject = responseObject.setObject("jobs");
+ steps.jobs().forEach(type -> {
+ jobTypeToSlime(jobsObject.setObject(type.jobName()),
+ controller,
+ application,
+ type,
+ steps,
+ pendingProduction,
+ running,
+ baseUriForJobs.resolve(type.jobName()));
+ });
return new SlimeJsonResponse(slime);
}
- private static void jobTypeToSlime(Cursor cursor, JobType jobType, Optional<Run> lastRun, URI baseUriForJobs) {
- Cursor jobObject = cursor.setObject(jobType.jobName());
+ private static void deploymentToSlime(Cursor deploymentObject, Application application, Change change,
+ Map<JobType, Versions> pendingProduction, Map<JobType, Run> running,
+ JobType type, Deployment deployment) {
+ deploymentObject.setLong("at", deployment.at().toEpochMilli());
+ deploymentObject.setString("platform", deployment.version().toString());
+ applicationVersionToSlime(deploymentObject.setObject("application"), deployment.applicationVersion());
+ deploymentObject.setBool("verified", application.deploymentJobs().statusOf(type)
+ .flatMap(JobStatus::lastSuccess)
+ .filter(run -> run.platform().equals(deployment.version())
+ && run.application().equals(deployment.applicationVersion()))
+ .isPresent());
+ if (running.containsKey(type))
+ deploymentObject.setString("status", running.get(type).steps().get(deployReal) == unfinished ? "deploying" : "verifying");
+ else if (change.isPresent())
+ deploymentObject.setString("status", pendingProduction.containsKey(type) ? "pending" : "completed");
+ }
- // Url that are specific to the jobtype
- String jobTypePath = baseUriForJobs.getPath() + "/" + jobType.jobName();
- URI baseUriForJobType = baseUriForJobs.resolve(jobTypePath);
- jobObject.setString("url", baseUriForJobType.toString());
+ private static void jobTypeToSlime(Cursor jobObject, Controller controller, Application application, JobType type, DeploymentSteps steps,
+ Map<JobType, Versions> pendingProduction, Map<JobType, Run> running, URI baseUriForJob) {
+ int runs = 0;
+ Cursor runArray = jobObject.setArray("runs");
+ if (type.isTest()) {
+ Deque<List<JobType>> pending = new ArrayDeque<>();
+ pendingProduction.entrySet().stream()
+ .filter(typeVersions -> ! controller.applications().deploymentTrigger().testedIn(application, type, typeVersions.getValue()))
+ .filter(typeVersions -> ! controller.applications().deploymentTrigger().alreadyTriggered(application, typeVersions.getValue()))
+ .collect(groupingBy(Map.Entry::getValue,
+ LinkedHashMap::new,
+ Collectors.mapping(Map.Entry::getKey, toList())))
+ .forEach((versions, types) -> pending.addFirst(types));
+ for (List<JobType> productionTypes : pending) {
+ Versions versions = pendingProduction.get(productionTypes.get(0));
+ runs++;
+ Cursor runObject = runArray.addObject();
+ runObject.setString("status", "pending");
+ versionsToSlime(runObject, versions);
+ if ( ! controller.applications().deploymentTrigger().triggerAt(controller.clock().instant(), type, versions, application))
+ runObject.setObject("tasks").setString("cooldown", "failed");
+ else
+ runObject.setObject("tasks").setString("capacity", "running");
- // Add the last run for the jobtype if present
- lastRun.ifPresent(run -> {
- Cursor lastObject = jobObject.setObject("last");
- runToSlime(lastObject, run, baseUriForJobType);
- });
+ runObject.setString("reason", "Testing for " + Joiner.on(", ").join(productionTypes));
+ }
+ }
+ else if ( pendingProduction.containsKey(type)
+ && ! running.containsKey(type)) {
+ Versions versions = pendingProduction.get(type);
+ runs++;
+ Cursor runObject = runArray.addObject();
+ runObject.setString("status", "pending");
+ versionsToSlime(runObject, pendingProduction.get(type));
+ Cursor pendingObject = runObject.setObject("tasks");
+ if ( ! controller.applications().deploymentTrigger().triggerAt(controller.clock().instant(), type, versions, application))
+ pendingObject.setString("cooldown", "failed");
+ else {
+ int pending = 0;
+ if ( ! controller.applications().deploymentTrigger().alreadyTriggered(application, versions)) {
+ if ( ! controller.applications().deploymentTrigger().testedIn(application, systemTest, versions)) {
+ pending++;
+ pendingObject.setString(systemTest.jobName(), statusOf(controller, application.id(), systemTest, versions));
+ }
+ if ( ! controller.applications().deploymentTrigger().testedIn(application, stagingTest, versions)) {
+ pending++;
+ pendingObject.setString(stagingTest.jobName(), statusOf(controller, application.id(), stagingTest, versions));
+ }
+ }
+ steps: for (DeploymentSpec.Step step : steps.production()) {
+ if (steps.toJobs(step).contains(type))
+ break;
+ for (JobType stepType : steps.toJobs(step)) {
+ if (pendingProduction.containsKey(stepType)) {
+ pendingObject.setString(stepType.jobName(), statusOf(controller, application.id(), stepType, versions));
+ if (++pending == 3)
+ break steps;
+ }
+ }
+ }
+ if (pending == 0)
+ pendingObject.setString("delay", "running");
+ }
+ }
+
+ controller.jobController().runs(application.id(), type).values().stream()
+ .sorted(Comparator.comparing(run -> -run.id().number()))
+ .limit(Math.max(0, 10 - runs))
+ .forEach(run -> runToSlime(runArray.addObject(), run, baseUriForJob, true));
+
+ jobObject.setString("url", baseUriForJob.toString());
}
- /**
- * @return Response with the runs for a specific jobtype
- */
- static HttpResponse runResponse(Map<RunId, Run> runs, URI baseUriForJobType) {
- Slime slime = new Slime();
- Cursor cursor = slime.setObject();
+ private static String statusOf(Controller controller, ApplicationId id, JobType type, Versions versions) {
+ return controller.jobController().last(id, type)
+ .filter(run -> versions.targetsMatch(versions))
+ .filter(run -> type == systemTest || versions.sourcesMatchIfPresent(versions))
+ .map(JobControllerApiHandlerHelper::taskStatusOf)
+ .orElse("pending");
+ }
- runs.forEach((runid, run) -> runToSlime(cursor.setObject(Long.toString(runid.number())), run, baseUriForJobType));
+ private static String taskStatusOf(Run run) {
+ switch (run.status()) {
+ case running: return "running";
+ case success: return "succeeded";
+ default: return "failed";
+ }
+ }
- return new SlimeJsonResponse(slime);
+ private static void runToSlime(Cursor runObject, Run run, URI baseUriForJobType, boolean summarize) {
+ runObject.setLong("id", run.id().number());
+ runObject.setString("status", run.status().name());
+ runObject.setLong("start", run.start().toEpochMilli());
+ run.end().ifPresent(instant -> runObject.setLong("end", instant.toEpochMilli()));
+
+ versionsToSlime(runObject, run.versions());
+
+ if ( ! summarize) {
+ Cursor stepsObject = runObject.setObject("steps");
+ run.steps().forEach((step, status) -> stepsObject.setString(step.name(), status.name()));
+ }
+ Cursor tasksObject = runObject.setObject("tasks");
+ taskStatus(deployReal, run).ifPresent(status -> tasksObject.setString("deploy", status));
+ taskStatus(Step.installReal, run).ifPresent(status -> tasksObject.setString("install", status));
+ taskStatus(Step.endTests, run).ifPresent(status -> tasksObject.setString("test", status));
+
+ runObject.setString("log", baseUriForJobType.resolve("run/" + run.id().number()).toString());
}
- private static void runToSlime(Cursor cursor, Run run, URI baseUriForJobType) {
- cursor.setString("status", run.status().name());
- run.end().ifPresent(instant -> cursor.setString("end", instant.toString()));
+ /** Returns the status of the task represented by the given step, if it has started. */
+ private static Optional<String> taskStatus(Step step, Run run) {
+ return run.readySteps().contains(step) ? Optional.of("running")
+ : run.steps().get(step) != unfinished ? Optional.of(run.steps().get(step).name())
+ : Optional.empty();
+ }
- Cursor stepsArray = cursor.setArray("steps");
- run.steps().forEach((step, status) -> {
- Cursor stepObject = stepsArray.addObject();
- stepObject.setString(step.name(), status.name());
- });
+ /** Returns a response with the runs for the given job type. */
+ static HttpResponse runResponse(Map<RunId, Run> runs, URI baseUriForJobType) {
+ Slime slime = new Slime();
+ Cursor cursor = slime.setObject();
- cursor.setString("start", run.start().toString());
- cursor.setLong("id", run.id().number());
- String logsPath = baseUriForJobType.getPath() + "/run/" + run.id().number();
- cursor.setString("logs", baseUriForJobType.resolve(logsPath).toString());
+ runs.forEach((runid, run) -> runToSlime(cursor.setObject(Long.toString(runid.number())), run, baseUriForJobType, false));
- cursor.setString("wantedPlatform", run.versions().targetPlatform().toString());
- applicationVersionToSlime(cursor.setObject("wantedApplication"), run.versions().targetApplication());
- run.versions().sourcePlatform().ifPresent(version -> cursor.setString("currentPlatform", version.toString()));
- run.versions().sourceApplication().ifPresent(version -> applicationVersionToSlime(cursor.setObject("currentApplication"), version));
+ return new SlimeJsonResponse(slime);
+ }
+ private static void versionsToSlime(Cursor runObject, Versions versions) {
+ runObject.setString("wantedPlatform", versions.targetPlatform().toString());
+ applicationVersionToSlime(runObject.setObject("wantedApplication"), versions.targetApplication());
+ versions.sourcePlatform().ifPresent(version -> runObject.setString("currentPlatform", version.toString()));
+ versions.sourceApplication().ifPresent(version -> applicationVersionToSlime(runObject.setObject("currentApplication"), version));
}
- private static void applicationVersionToSlime(Cursor cursor, ApplicationVersion version) {
- cursor.setString("id", version.id());
- cursor.setLong("build", version.buildNumber().get());
- cursor.setString("repository", version.source().get().repository());
- cursor.setString("branch", version.source().get().branch());
- cursor.setString("commit", version.source().get().commit());
+ private static void applicationVersionToSlime(Cursor versionObject, ApplicationVersion version) {
+ versionObject.setString("id", version.id());
+ versionObject.setLong("build", version.buildNumber().get());
+ versionObject.setString("repository", version.source().get().repository());
+ versionObject.setString("branch", version.source().get().branch());
+ versionObject.setString("commit", version.source().get().commit());
}
/**
@@ -149,5 +385,6 @@ class JobControllerApiHandlerHelper {
responseObject.setString("version", version.id());
return new SlimeJsonResponse(slime);
}
+
}
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 3536a2f7f73..b59adba71a9 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
@@ -36,7 +36,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.logging.Level;
import static org.junit.Assert.fail;
@@ -56,18 +55,12 @@ public class JobControllerApiHandlerHelperTest {
@Test
public void jobTypeResponse() {
- Map<JobType, Run> jobMap = new HashMap<>();
- List<JobType> jobList = new ArrayList<>();
- jobMap.put(JobType.systemTest, createRun(JobType.systemTest, 1, 30, lastStep, Optional.of(RunStatus.running)));
- jobList.add(JobType.systemTest);
- jobMap.put(JobType.productionApNortheast1, createRun(JobType.productionApNortheast1, 1, 60, lastStep, Optional.of(RunStatus.running)));
- jobList.add(JobType.productionApNortheast1);
- jobMap.put(JobType.productionUsWest1, createRun(JobType.productionUsWest1, 1, 60, Step.startTests, Optional.of(RunStatus.error)));
- jobList.add(JobType.productionUsWest1);
+ ControllerTester tester = new ControllerTester();
+
- URI jobUrl = URI.create("https://domain.tld/application/v4/tenant/sometenant/application/someapp/instance/usuallydefault/job");
- HttpResponse response = JobControllerApiHandlerHelper.jobTypeResponse(jobList, jobMap, jobUrl);
+ URI jobUrl = URI.create("https://domain.tld/application/v4/tenant/sometenant/application/someapp/instance/usuallydefault/job");
+ HttpResponse response = JobControllerApiHandlerHelper.jobTypeResponse(tester.controller(), appId, jobUrl);
assertFile(response, "job/job-type-response.json");
}
@@ -174,4 +167,5 @@ public class JobControllerApiHandlerHelperTest {
throw new RuntimeException(e);
}
}
+
}