summaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorJon Marius Venstad <jonmv@users.noreply.github.com>2019-10-08 14:30:28 +0200
committerGitHub <noreply@github.com>2019-10-08 14:30:28 +0200
commit1be5a1edc8d308a6be8c4b43a72ce395fec04359 (patch)
treea97eb7fc9e1488f5dd5e896a9be06f1d69b0f1b4 /controller-server
parentc8ea72faa033f846292aab8d166fe96626a8198a (diff)
parentd9e221b7895959ba6895c9d48489ebba91badb35 (diff)
Merge pull request #10911 from vespa-engine/jvenstad/application-response-with-proper-instances
Explicit latest application versions and aggregate over instance in application response
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java20
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedApplication.java47
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java74
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java13
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java21
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java16
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java161
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/complete-application.json8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java32
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-list.json3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2-with-patches.json102
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2.json95
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-list.json3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference-2.json (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference-2.json)0
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference-default.json (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference-default.json)0
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference.json (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference.json)0
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-with-routing-policy.json (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-with-routing-policy.json)43
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-without-change-multiple-deployments.json (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-without-change-multiple-deployments.json)44
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance.json (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application.json)42
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance1-metering.json (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-metering.json)0
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance1-recursive.json (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-recursive.json)42
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/jobs.json6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview.json2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/tenant1-recursive.json2
28 files changed, 432 insertions, 368 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java
index c83f366cb67..7842c3891a6 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java
@@ -43,6 +43,7 @@ public class Application {
private final Instant createdAt;
private final DeploymentSpec deploymentSpec;
private final ValidationOverrides validationOverrides;
+ private final Optional<ApplicationVersion> latestVersion;
private final OptionalLong projectId;
private final boolean internal;
private final Change change;
@@ -59,14 +60,14 @@ public class Application {
public Application(TenantAndApplicationId id, Instant now) {
this(id, now, DeploymentSpec.empty, ValidationOverrides.empty, Change.empty(), Change.empty(),
Optional.empty(), Optional.empty(), Optional.empty(), OptionalInt.empty(),
- new ApplicationMetrics(0, 0), Set.of(), OptionalLong.empty(), false, List.of());
+ new ApplicationMetrics(0, 0), Set.of(), OptionalLong.empty(), false, Optional.empty(), List.of());
}
// DO NOT USE! For serialization purposes, only.
public Application(TenantAndApplicationId id, Instant createdAt, DeploymentSpec deploymentSpec, ValidationOverrides validationOverrides,
Change change, Change outstandingChange, Optional<IssueId> deploymentIssueId, Optional<IssueId> ownershipIssueId, Optional<User> owner,
- OptionalInt majorVersion, ApplicationMetrics metrics, Set<PublicKey> deployKeys,
- OptionalLong projectId, boolean internal, Collection<Instance> instances) {
+ OptionalInt majorVersion, ApplicationMetrics metrics, Set<PublicKey> deployKeys, OptionalLong projectId,
+ boolean internal, Optional<ApplicationVersion> latestVersion, Collection<Instance> instances) {
this.id = Objects.requireNonNull(id, "id cannot be null");
this.createdAt = Objects.requireNonNull(createdAt, "instant of creation cannot be null");
this.deploymentSpec = Objects.requireNonNull(deploymentSpec, "deploymentSpec cannot be null");
@@ -81,6 +82,7 @@ public class Application {
this.deployKeys = Objects.requireNonNull(deployKeys, "deployKeys cannot be null");
this.projectId = Objects.requireNonNull(projectId, "projectId cannot be null");
this.internal = internal;
+ this.latestVersion = requireNotUnknown(latestVersion);
this.instances = ImmutableSortedMap.copyOf(instances.stream().collect(Collectors.toMap(Instance::name, Function.identity())));
}
@@ -97,6 +99,9 @@ public class Application {
/** Returns the project id of this application, if it has any. */
public OptionalLong projectId() { return projectId; }
+ /** Returns the last submitted version of this application. */
+ public Optional<ApplicationVersion> latestVersion() { return latestVersion; }
+
/** Returns whether this application is run on the internal deployment pipeline. */
// TODO jonmv: Remove, as will be always true.
public boolean internal() { return internal; }
@@ -194,6 +199,15 @@ public class Application {
/** Returns the set of deploy keys for this application. */
public Set<PublicKey> deployKeys() { return deployKeys; }
+ private static Optional<ApplicationVersion> requireNotUnknown(Optional<ApplicationVersion> latestVersion) {
+ Objects.requireNonNull(latestVersion, "latestVersion cannot be null");
+ latestVersion.ifPresent(version -> {
+ if (version.isUnknown())
+ throw new IllegalArgumentException("latstVersion cannot be unknown");
+ });
+ return latestVersion;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedApplication.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedApplication.java
index 19921595dc2..46d1d436521 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedApplication.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedApplication.java
@@ -5,6 +5,7 @@ import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.vespa.curator.Lock;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.api.integration.organization.IssueId;
import com.yahoo.vespa.hosted.controller.api.integration.organization.User;
import com.yahoo.vespa.hosted.controller.application.Change;
@@ -45,6 +46,7 @@ public class LockedApplication {
private final Set<PublicKey> deployKeys;
private final OptionalLong projectId;
private final boolean internal;
+ private final Optional<ApplicationVersion> latestVersion;
private final Map<InstanceName, Instance> instances;
/**
@@ -58,14 +60,14 @@ public class LockedApplication {
application.deploymentSpec(), application.validationOverrides(), application.change(),
application.outstandingChange(), application.deploymentIssueId(), application.ownershipIssueId(),
application.owner(), application.majorVersion(), application.metrics(), application.deployKeys(),
- application.projectId(), application.internal(), application.instances());
+ application.projectId(), application.internal(), application.latestVersion(), application.instances());
}
private LockedApplication(Lock lock, TenantAndApplicationId id, Instant createdAt, DeploymentSpec deploymentSpec,
ValidationOverrides validationOverrides, Change change, Change outstandingChange,
Optional<IssueId> deploymentIssueId, Optional<IssueId> ownershipIssueId, Optional<User> owner,
OptionalInt majorVersion, ApplicationMetrics metrics, Set<PublicKey> deployKeys,
- OptionalLong projectId, boolean internal,
+ OptionalLong projectId, boolean internal, Optional<ApplicationVersion> latestVersion,
Map<InstanceName, Instance> instances) {
this.lock = lock;
this.id = id;
@@ -82,6 +84,7 @@ public class LockedApplication {
this.deployKeys = deployKeys;
this.projectId = projectId;
this.internal = internal;
+ this.latestVersion = latestVersion;
this.instances = Map.copyOf(instances);
}
@@ -89,7 +92,7 @@ public class LockedApplication {
public Application get() {
return new Application(id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances.values());
+ projectId, internal, latestVersion, instances.values());
}
public LockedApplication withNewInstance(InstanceName instance) {
@@ -97,7 +100,7 @@ public class LockedApplication {
instances.put(instance, new Instance(id.instance(instance)));
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication with(InstanceName instance, UnaryOperator<Instance> modification) {
@@ -105,7 +108,7 @@ public class LockedApplication {
instances.put(instance, modification.apply(instances.get(instance)));
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication without(InstanceName instance) {
@@ -113,61 +116,67 @@ public class LockedApplication {
instances.remove(instance);
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
+ }
+
+ public LockedApplication withNewSubmission(ApplicationVersion latestVersion) {
+ return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
+ deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
+ projectId, internal, Optional.of(latestVersion), instances);
}
public LockedApplication withBuiltInternally(boolean builtInternally) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, builtInternally, instances);
+ projectId, builtInternally, latestVersion, instances);
}
public LockedApplication withProjectId(OptionalLong projectId) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication withDeploymentIssueId(IssueId issueId) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
Optional.ofNullable(issueId), ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication with(DeploymentSpec deploymentSpec) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication with(ValidationOverrides validationOverrides) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication withChange(Change change) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication withOutstandingChange(Change outstandingChange) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication withOwnershipIssueId(IssueId issueId) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, Optional.of(issueId), owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication withOwner(User owner) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, Optional.of(owner), majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
/** Set a major version for this, or set to null to remove any major version override */
@@ -175,13 +184,13 @@ public class LockedApplication {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner,
majorVersion == null ? OptionalInt.empty() : OptionalInt.of(majorVersion),
- metrics, deployKeys, projectId, internal, instances);
+ metrics, deployKeys, projectId, internal, latestVersion, instances);
}
public LockedApplication with(ApplicationMetrics metrics) {
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, deployKeys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication withDeployKey(PublicKey pemDeployKey) {
@@ -189,7 +198,7 @@ public class LockedApplication {
keys.add(pemDeployKey);
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, keys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
public LockedApplication withoutDeployKey(PublicKey pemDeployKey) {
@@ -197,7 +206,7 @@ public class LockedApplication {
keys.remove(pemDeployKey);
return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, change, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics, keys,
- projectId, internal, instances);
+ projectId, internal, latestVersion, instances);
}
@Override
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
index 3df889d7a88..f4ec1d26d8e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
@@ -98,6 +98,32 @@ public class DeploymentTrigger {
return new DeploymentSteps(spec, controller::system);
}
+ public void notifyOfSubmission(TenantAndApplicationId id, ApplicationVersion version, long projectId) {
+ if (applications().getApplication(id).isEmpty()) {
+ log.log(LogLevel.WARNING, "Ignoring submission from project '" + projectId +
+ "': Unknown application '" + id + "'");
+ return;
+ }
+
+ applications().lockApplicationOrThrow(id, application -> {
+ if (acceptNewApplicationVersion(application.get())) {
+ application = application.withChange(application.get().change().with(version))
+ .withOutstandingChange(Change.empty());
+ if (application.get().internal())
+ for (Run run : jobs.active())
+ if ( ! run.id().type().environment().isManuallyDeployed()
+ && TenantAndApplicationId.from(run.id().application()).equals(id))
+ jobs.abort(run.id());
+ }
+ else
+ application = application.withOutstandingChange(Change.of(version));
+
+ application = application.withProjectId(OptionalLong.of(projectId));
+ application = application.withNewSubmission(version);
+ applications().store(application.withChange(remainingChange(application.get())));
+ });
+ }
+
/**
* Records information when a job completes (successfully or not). This information is used when deciding what to
* trigger next.
@@ -116,40 +142,24 @@ public class DeploymentTrigger {
}
applications().lockApplicationOrThrow(TenantAndApplicationId.from(report.applicationId()), application -> {
- JobRun triggering;
- // TODO jonmv: Remove this, and replace with a simple application version counter.
if (report.jobType() == component) {
- ApplicationVersion applicationVersion = report.version().get();
- triggering = JobRun.triggering(applications().oldestInstalledPlatform(TenantAndApplicationId.from(report.applicationId())),
- applicationVersion,
- Optional.empty(), Optional.empty(), "Application commit", clock.instant());
- if (report.success()) {
- if (acceptNewApplicationVersion(application.get())) {
- application = application.withChange(application.get().change().with(applicationVersion))
- .withOutstandingChange(Change.empty());
- if (application.get().internal())
- for (Run run : jobs.active())
- if (run.id().application().equals(report.applicationId()))
- jobs.abort(run.id());
- }
- else
- application = application.withOutstandingChange(Change.of(applicationVersion));
- }
- application = application.withProjectId(OptionalLong.of(report.projectId()));
- }
- else {
- Optional<JobStatus> status = application.get().require(report.applicationId().instance())
- .deploymentJobs().statusOf(report.jobType());
- triggering = status.filter(job -> job.lastTriggered().isPresent()
- && job.lastCompleted()
- .map(completion -> ! completion.at().isAfter(job.lastTriggered().get().at()))
- .orElse(true))
- .orElseThrow(() -> new IllegalStateException("Notified of completion of " + report.jobType().jobName() + " for " +
- report.applicationId() + ", but that has not been triggered; last was " +
- status.flatMap(job -> job.lastTriggered().map(run -> run.at().toString()))
- .orElse("never")))
- .lastTriggered().get();
+ if (report.success())
+ notifyOfSubmission(application.get().id(), report.version().get(), report.projectId());
+
+ return;
}
+ JobRun triggering;
+ Optional<JobStatus> status = application.get().require(report.applicationId().instance())
+ .deploymentJobs().statusOf(report.jobType());
+ triggering = status.filter(job -> job.lastTriggered().isPresent()
+ && job.lastCompleted()
+ .map(completion -> ! completion.at().isAfter(job.lastTriggered().get().at()))
+ .orElse(true))
+ .orElseThrow(() -> new IllegalStateException("Notified of completion of " + report.jobType().jobName() + " for " +
+ report.applicationId() + ", but that has not been triggered; last was " +
+ status.flatMap(job -> job.lastTriggered().map(run -> run.at().toString()))
+ .orElse("never")))
+ .lastTriggered().get();
application = application.with(report.applicationId().instance(),
instance -> instance.withJobCompletion(report.jobType(),
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
index 54b5c339159..8c159644940 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
@@ -289,7 +289,9 @@ public class JobController {
if ( ! application.get().internal())
application = registered(application);
- long run = nextBuild(id);
+ long run = 1 + application.get().latestVersion()
+ .map(latestVersion -> latestVersion.buildNumber().getAsLong())
+ .orElse(0L);
if (applicationPackage.compileVersion().isPresent() && applicationPackage.buildTime().isPresent())
version.set(ApplicationVersion.from(revision, run, authorEmail,
applicationPackage.compileVersion().get(),
@@ -487,15 +489,6 @@ public class JobController {
.collect(Collectors.toSet());
}
- // TODO jvenstad: Find a more appropriate way of doing this, at least when this is the only build service.
- private long nextBuild(ApplicationId id) {
- return 1 + controller.applications().requireInstance(id).deploymentJobs()
- .statusOf(JobType.component)
- .flatMap(JobStatus::lastCompleted)
- .map(JobStatus.JobRun::id)
- .orElse(0L);
- }
-
private void prunePackages(ApplicationId id) {
controller.applications().lockApplicationIfPresent(TenantAndApplicationId.from(id), application -> {
application.get().require(id.instance()).productionDeployments().values().stream()
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java
index 361cc43da50..91594ed947c 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java
@@ -3,8 +3,10 @@ package com.yahoo.vespa.hosted.controller.maintenance;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.jdisc.Metric;
+import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.Instance;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.application.ApplicationList;
import com.yahoo.vespa.hosted.controller.application.Deployment;
@@ -70,10 +72,12 @@ public class MetricsReporter extends Maintainer {
}
private void reportDeploymentMetrics() {
- List<Instance> instances = ApplicationList.from(controller().applications().asList())
- .withProductionDeployment().asList().stream()
- .flatMap(application -> application.instances().values().stream())
- .collect(Collectors.toUnmodifiableList());
+ List<Application> applications = ApplicationList.from(controller().applications().asList())
+ .withProductionDeployment().asList().stream()
+ .collect(Collectors.toUnmodifiableList());
+ List<Instance> instances = applications.stream()
+ .flatMap(application -> application.instances().values().stream())
+ .collect(Collectors.toUnmodifiableList());
metric.set(DEPLOYMENT_FAIL_METRIC, deploymentFailRatio(instances) * 100, metric.createContext(Map.of()));
@@ -89,13 +93,12 @@ public class MetricsReporter extends Maintainer {
metric.set(DEPLOYMENT_WARNINGS, warnings, metric.createContext(dimensions(application)));
});
- for (Instance instance : instances)
- instance.deploymentJobs().statusOf(JobType.component)
- .flatMap(JobStatus::lastSuccess)
- .flatMap(run -> run.application().buildTime())
+ for (Application application : applications)
+ application.latestVersion()
+ .flatMap(ApplicationVersion::buildTime)
.ifPresent(buildTime -> metric.set(DEPLOYMENT_BUILD_AGE_SECONDS,
controller().clock().instant().getEpochSecond() - buildTime.getEpochSecond(),
- metric.createContext(dimensions(instance.id()))));
+ metric.createContext(dimensions(application.id().defaultInstance()))));
}
private void reportQueuedNameServiceRequests() {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java
index e67d5aea45d..d0af4b09a3b 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java
@@ -75,6 +75,7 @@ public class ApplicationSerializer {
private static final String instancesField = "instances";
private static final String deployingField = "deployingField";
private static final String projectIdField = "projectId";
+ private static final String latestVersionField = "latestVersion";
private static final String builtInternallyField = "builtInternally";
private static final String pinnedField = "pinned";
private static final String outstandingChangeField = "outstandingChangeField";
@@ -181,6 +182,7 @@ public class ApplicationSerializer {
root.setDouble(queryQualityField, application.metrics().queryServiceQuality());
root.setDouble(writeQualityField, application.metrics().writeServiceQuality());
deployKeysToSlime(application.deployKeys(), root.setArray(pemDeployKeysField));
+ application.latestVersion().ifPresent(version -> toSlime(version, root.setObject(latestVersionField)));
instancesToSlime(application, root.setArray(instancesField));
return slime;
}
@@ -360,11 +362,23 @@ public class ApplicationSerializer {
Set<PublicKey> deployKeys = deployKeysFromSlime(root.field(pemDeployKeysField));
List<Instance> instances = instancesFromSlime(id, deploymentSpec, root.field(instancesField));
OptionalLong projectId = Serializers.optionalLong(root.field(projectIdField));
+ Optional<ApplicationVersion> latestVersion = latestVersionFromSlimeWithFallback(root.field(latestVersionField), instances);
boolean builtInternally = root.field(builtInternallyField).asBool();
return new Application(id, createdAt, deploymentSpec, validationOverrides, deploying, outstandingChange,
deploymentIssueId, ownershipIssueId, owner, majorVersion, metrics,
- deployKeys, projectId, builtInternally, instances);
+ deployKeys, projectId, builtInternally, latestVersion, instances);
+ }
+
+ private Optional<ApplicationVersion> latestVersionFromSlimeWithFallback(Inspector latestVersionObject, List<Instance> instances) {
+ if (latestVersionObject.valid())
+ return Optional.of(applicationVersionFromSlime(latestVersionObject));
+
+ return instances.stream()
+ .flatMap(instance -> instance.deploymentJobs().statusOf(JobType.component).stream())
+ .flatMap(status -> status.lastSuccess().stream())
+ .map(JobStatus.JobRun::application)
+ .findFirst();
}
private List<Instance> instancesFromSlime(TenantAndApplicationId id, DeploymentSpec deploymentSpec, Inspector field) {
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 c36ffd384a8..e4ee858ab4c 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
@@ -203,12 +203,12 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
if (path.matches("/application/v4/tenant/{tenant}/cost")) return tenantCost(path.get("tenant"), request);
if (path.matches("/application/v4/tenant/{tenant}/cost/{month}")) return tenantCost(path.get("tenant"), path.get("month"), request);
if (path.matches("/application/v4/tenant/{tenant}/application")) return applications(path.get("tenant"), Optional.empty(), request);
- if (path.matches("/application/v4/tenant/{tenant}/application/{application}")) return application(path.get("tenant"), path.get("application"), "default", 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}/deploying")) return deploying(path.get("tenant"), path.get("application"), "default", request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying/pin")) return deploying(path.get("tenant"), path.get("application"), "default", request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/metering")) return metering(path.get("tenant"), path.get("application"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance")) return applications(path.get("tenant"), Optional.of(path.get("application")), request);
- if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}")) return application(path.get("tenant"), path.get("application"), path.get("instance"), request);
+ if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}")) return instance(path.get("tenant"), path.get("application"), path.get("instance"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/deploying")) return deploying(path.get("tenant"), path.get("application"), path.get("instance"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/deploying/pin")) return deploying(path.get("tenant"), path.get("application"), path.get("instance"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job")) return JobControllerApiHandlerHelper.jobTypeResponse(controller, appIdFromPath(path), request.getUri());
@@ -409,10 +409,16 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
return new SlimeJsonResponse(slime);
}
- private HttpResponse application(String tenantName, String applicationName, String instanceName, HttpRequest request) {
+ private HttpResponse application(String tenantName, String applicationName, HttpRequest request) {
+ Slime slime = new Slime();
+ toSlime(slime.setObject(), getApplication(tenantName, applicationName), request);
+ return new SlimeJsonResponse(slime);
+ }
+
+ private HttpResponse instance(String tenantName, String applicationName, String instanceName, HttpRequest request) {
Slime slime = new Slime();
toSlime(slime.setObject(), getInstance(tenantName, applicationName, instanceName),
- getApplication(tenantName, applicationName, instanceName), request);
+ getApplication(tenantName, applicationName), request);
return new SlimeJsonResponse(slime);
}
@@ -509,8 +515,8 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
return new MessageResponse(messageBuilder.toString());
}
- private Application getApplication(String tenantName, String applicationName, String instanceName) {
- ApplicationId applicationId = ApplicationId.from(tenantName, applicationName, instanceName);
+ private Application getApplication(String tenantName, String applicationName) {
+ TenantAndApplicationId applicationId = TenantAndApplicationId.from(tenantName, applicationName);
return controller.applications().getApplication(applicationId)
.orElseThrow(() -> new NotExistsException(applicationId + " not found"));
}
@@ -605,6 +611,138 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
return new MessageResponse(type.jobName() + " for " + id + " paused for " + DeploymentTrigger.maxPause);
}
+ private void toSlime(Cursor object, Application application, HttpRequest request) {
+ object.setString("tenant", application.id().tenant().value());
+ object.setString("application", application.id().application().value());
+ object.setString("deployments", withPath("/application/v4" +
+ "/tenant/" + application.id().tenant().value() +
+ "/application/" + application.id().application().value() +
+ "/job/",
+ request.getUri()).toString());
+
+ application.latestVersion().ifPresent(version -> toSlime(version, object.setObject("latestVersion")));
+
+ application.projectId().ifPresent(id -> object.setLong("projectId", id));
+
+ // Currently deploying change
+ if ( ! application.change().isEmpty())
+ toSlime(object.setObject("deploying"), application.change());
+
+ // Outstanding change
+ if ( ! application.outstandingChange().isEmpty())
+ toSlime(object.setObject("outstandingChange"), application.outstandingChange());
+
+ // Compile version. The version that should be used when building an application
+ object.setString("compileVersion", compileVersion(application.id()).toFullString());
+
+ application.majorVersion().ifPresent(majorVersion -> object.setLong("majorVersion", majorVersion));
+
+ Cursor instancesArray = object.setArray("instances");
+ for (Instance instance : application.instances().values())
+ toSlime(instancesArray.addObject(), instance, application.deploymentSpec(), request);
+
+ application.deployKeys().stream().map(KeyUtils::toPem).forEach(object.setArray("pemDeployKeys")::addString);
+
+ // Metrics
+ Cursor metricsObject = object.setObject("metrics");
+ metricsObject.setDouble("queryServiceQuality", application.metrics().queryServiceQuality());
+ metricsObject.setDouble("writeServiceQuality", application.metrics().writeServiceQuality());
+
+ // Activity
+ Cursor activity = object.setObject("activity");
+ application.activity().lastQueried().ifPresent(instant -> activity.setLong("lastQueried", instant.toEpochMilli()));
+ application.activity().lastWritten().ifPresent(instant -> activity.setLong("lastWritten", instant.toEpochMilli()));
+ application.activity().lastQueriesPerSecond().ifPresent(value -> activity.setDouble("lastQueriesPerSecond", value));
+ application.activity().lastWritesPerSecond().ifPresent(value -> activity.setDouble("lastWritesPerSecond", value));
+
+ application.ownershipIssueId().ifPresent(issueId -> object.setString("ownershipIssueId", issueId.value()));
+ application.owner().ifPresent(owner -> object.setString("owner", owner.username()));
+ application.deploymentIssueId().ifPresent(issueId -> object.setString("deploymentIssueId", issueId.value()));
+ }
+
+ private void toSlime(Cursor object, Instance instance, DeploymentSpec deploymentSpec, HttpRequest request) {
+ object.setString("instance", instance.name().value());
+ // Jobs sorted according to deployment spec
+ List<JobStatus> jobStatus = controller.applications().deploymentTrigger()
+ .steps(deploymentSpec)
+ .sortedJobs(instance.deploymentJobs().jobStatus().values());
+
+
+ Cursor deploymentJobsArray = object.setArray("deploymentJobs");
+ for (JobStatus job : jobStatus) {
+ Cursor jobObject = deploymentJobsArray.addObject();
+ jobObject.setString("type", job.type().jobName());
+ jobObject.setBool("success", job.isSuccess());
+ job.lastTriggered().ifPresent(jobRun -> toSlime(jobRun, jobObject.setObject("lastTriggered")));
+ job.lastCompleted().ifPresent(jobRun -> toSlime(jobRun, jobObject.setObject("lastCompleted")));
+ job.firstFailing().ifPresent(jobRun -> toSlime(jobRun, jobObject.setObject("firstFailing")));
+ job.lastSuccess().ifPresent(jobRun -> toSlime(jobRun, jobObject.setObject("lastSuccess")));
+ }
+
+ // Change blockers
+ Cursor changeBlockers = object.setArray("changeBlockers");
+ deploymentSpec.changeBlocker().forEach(changeBlocker -> {
+ Cursor changeBlockerObject = changeBlockers.addObject();
+ changeBlockerObject.setBool("versions", changeBlocker.blocksVersions());
+ changeBlockerObject.setBool("revisions", changeBlocker.blocksRevisions());
+ changeBlockerObject.setString("timeZone", changeBlocker.window().zone().getId());
+ Cursor days = changeBlockerObject.setArray("days");
+ changeBlocker.window().days().stream().map(DayOfWeek::getValue).forEach(days::addLong);
+ Cursor hours = changeBlockerObject.setArray("hours");
+ changeBlocker.window().hours().forEach(hours::addLong);
+ });
+
+ // Rotation
+ Cursor globalRotationsArray = object.setArray("globalRotations");
+ instance.endpointsIn(controller.system())
+ .scope(Endpoint.Scope.global)
+ .legacy(false) // Hide legacy names
+ .asList().stream()
+ .map(Endpoint::url)
+ .map(URI::toString)
+ .forEach(globalRotationsArray::addString);
+
+ instance.rotations().stream()
+ .map(AssignedRotation::rotationId)
+ .findFirst()
+ .ifPresent(rotation -> object.setString("rotationId", rotation.asString()));
+
+ // Per-cluster rotations
+ Set<RoutingPolicy> routingPolicies = controller.applications().routingPolicies().get(instance.id());
+ for (RoutingPolicy policy : routingPolicies) {
+ policy.rotationEndpointsIn(controller.system()).asList().stream()
+ .map(Endpoint::url)
+ .map(URI::toString)
+ .forEach(globalRotationsArray::addString);
+ }
+
+ // Deployments sorted according to deployment spec
+ List<Deployment> deployments = controller.applications().deploymentTrigger()
+ .steps(deploymentSpec)
+ .sortedDeployments(instance.deployments().values());
+
+ Cursor deploymentsArray = object.setArray("deployments");
+ for (Deployment deployment : deployments) {
+ Cursor deploymentObject = deploymentsArray.addObject();
+
+ // Rotation status for this deployment
+ if (deployment.zone().environment() == Environment.prod && ! instance.rotations().isEmpty())
+ toSlime(instance.rotations(), instance.rotationStatus(), deployment, deploymentObject);
+
+ if (recurseOverDeployments(request)) // List full deployment information when recursive.
+ toSlime(deploymentObject, new DeploymentId(instance.id(), deployment.zone()), deployment, request);
+ else {
+ deploymentObject.setString("environment", deployment.zone().environment().value());
+ deploymentObject.setString("region", deployment.zone().region().value());
+ deploymentObject.setString("url", withPath(request.getUri().getPath() +
+ "/instance/" + instance.name().value() +
+ "/environment/" + deployment.zone().environment().value() +
+ "/region/" + deployment.zone().region().value(),
+ request.getUri()).toString());
+ }
+ }
+ }
+
private void toSlime(Cursor object, Instance instance, Application application, HttpRequest request) {
object.setString("tenant", instance.id().tenant().value());
object.setString("application", instance.id().application().value());
@@ -615,10 +753,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
"/instance/" + instance.id().instance().value() + "/job/",
request.getUri()).toString());
- instance.deploymentJobs().statusOf(JobType.component)
- .flatMap(JobStatus::lastSuccess)
- .map(run -> run.application().source())
- .ifPresent(source -> sourceRevisionToSlime(source, object.setObject("source")));
+ application.latestVersion().ifPresent(version -> sourceRevisionToSlime(version.source(), object.setObject("source")));
application.projectId().ifPresent(id -> object.setLong("projectId", id));
@@ -723,8 +858,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
deploymentObject.setString("instance", instance.id().instance().value()); // pointless
deploymentObject.setString("url", withPath(request.getUri().getPath() +
"/environment/" + deployment.zone().environment().value() +
- "/region/" + deployment.zone().region().value() +
- ( request.getUri().getPath().contains("/instance/") ? "" : "/instance/" + instance.id().instance().value()),
+ "/region/" + deployment.zone().region().value(),
request.getUri()).toString());
}
}
@@ -836,7 +970,8 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
}
private void toSlime(ApplicationVersion applicationVersion, Cursor object) {
- if (!applicationVersion.isUnknown()) {
+ if ( ! applicationVersion.isUnknown()) {
+ object.setLong("buildNumber", applicationVersion.buildNumber().getAsLong());
object.setString("hash", applicationVersion.id());
sourceRevisionToSlime(applicationVersion.source(), object.setObject("source"));
}
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 49015f16cce..7a511c62388 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
@@ -102,7 +102,7 @@ class JobControllerApiHandlerHelper {
Cursor responseObject = slime.setObject();
Cursor lastVersionsObject = responseObject.setObject("lastVersions");
- if (instance.deploymentJobs().statusOf(component).flatMap(JobStatus::lastSuccess).isPresent()) {
+ if (application.latestVersion().isPresent()) {
lastPlatformToSlime(lastVersionsObject.setObject("platform"), controller, application, instance, change, steps);
lastApplicationToSlime(lastVersionsObject.setObject("application"), application, instance, change, steps, controller);
}
@@ -192,9 +192,9 @@ class JobControllerApiHandlerHelper {
private static void lastApplicationToSlime(Cursor lastApplicationObject, Application application, Instance instance, Change change, DeploymentSteps steps, Controller controller) {
long completed;
- ApplicationVersion lastApplication = instance.deploymentJobs().statusOf(component).flatMap(JobStatus::lastSuccess).get().application();
+ ApplicationVersion lastApplication = application.latestVersion().get();
applicationVersionToSlime(lastApplicationObject.setObject("application"), lastApplication);
- lastApplicationObject.setLong("at", instance.deploymentJobs().statusOf(component).flatMap(JobStatus::lastSuccess).get().at().toEpochMilli());
+ lastApplicationObject.setLong("at", lastApplication.buildTime().get().toEpochMilli());
completed = steps.productionJobs().stream().filter(type -> controller.applications().deploymentTrigger().isComplete(Change.of(lastApplication), change, instance, type)).count();
if (Optional.of(lastApplication).equals(change.application()))
lastApplicationObject.setString("deploying", completed + " of " + steps.productionJobs().size() + " complete");
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
index e3682a78b7d..971b88c2daf 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
@@ -88,7 +88,7 @@ public class ControllerTest {
tester.application(app1.id()).change().application().get());
tester.deployAndNotify(instance.id(), Optional.of(applicationPackage), true, systemTest);
tester.deployAndNotify(instance.id(), Optional.of(applicationPackage), true, stagingTest);
- assertEquals(4, tester.defaultInstance(app1.id()).deploymentJobs().jobStatus().size());
+ assertEquals(3, tester.defaultInstance(app1.id()).deploymentJobs().jobStatus().size());
ApplicationVersion applicationVersion = tester.application(app1.id()).change().application().get();
assertFalse("Application version has been set during deployment", applicationVersion.isUnknown());
@@ -104,7 +104,7 @@ public class ControllerTest {
// production job (failing) after deployment
tester.deploy(productionUsWest1, instance.id(), applicationPackage);
tester.deployAndNotify(instance.id(), Optional.of(applicationPackage), false, productionUsWest1);
- assertEquals(4, tester.defaultInstance(app1.id()).deploymentJobs().jobStatus().size());
+ assertEquals(3, tester.defaultInstance(app1.id()).deploymentJobs().jobStatus().size());
JobStatus expectedJobStatus = JobStatus.initial(productionUsWest1)
.withTriggering(version1, applicationVersion, Optional.empty(), "", tester.clock().instant().truncatedTo(MILLIS)) // Triggered first without application version info
@@ -122,7 +122,7 @@ public class ControllerTest {
assertNotNull(tester.controller().tenants().get(TenantName.from("tenant1")));
assertNotNull(tester.defaultInstance(app1.id()));
- assertEquals(4, tester.defaultInstance(app1.id()).deploymentJobs().jobStatus().size());
+ assertEquals(3, tester.defaultInstance(app1.id()).deploymentJobs().jobStatus().size());
tester.clock().advance(Duration.ofHours(1));
@@ -152,7 +152,7 @@ public class ControllerTest {
app1.id().defaultInstance(), tester.controller());
tester.deployAndNotify(instance.id(), Optional.of(applicationPackage), true, productionUsEast3);
- assertEquals(5, tester.defaultInstance(app1.id()).deploymentJobs().jobStatus().size());
+ assertEquals(4, tester.defaultInstance(app1.id()).deploymentJobs().jobStatus().size());
// Production zone for which there is no JobType is not allowed.
applicationPackage = new ApplicationPackageBuilder()
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java
index d979f1753c4..1fd51a453fd 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java
@@ -592,7 +592,7 @@ public class UpgraderTest {
tester.jobCompletion(component).application(default2).nextBuildNumber().uploadArtifact(canaryPolicy).unsuccessful().submit();
tester.jobCompletion(component).application(default3).nextBuildNumber(2).uploadArtifact(canaryPolicy).unsuccessful().submit();
tester.upgradeSystem(version);
- assertEquals(VespaVersion.Confidence.normal, tester.controller().versionStatus().systemVersion().get().confidence());
+ assertEquals(VespaVersion.Confidence.high, tester.controller().versionStatus().systemVersion().get().confidence());
}
@Test
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java
index 447bce0a544..aa413aafcf9 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java
@@ -100,6 +100,11 @@ public class ApplicationSerializerTest {
List<JobStatus> statusList = new ArrayList<>();
+ JobStatus.JobRun componentJob = JobStatus.JobRun.triggering(Version.emptyVersion, applicationVersion1, empty(),
+ empty(), "New commit", Instant.ofEpochMilli(400))
+ .completion(100, Instant.ofEpochMilli(500));
+ statusList.add(JobStatus.initial(JobType.component)
+ .withCompletion(componentJob, empty()));
statusList.add(JobStatus.initial(JobType.systemTest)
.withTriggering(Version.fromString("5.6.7"), ApplicationVersion.unknown, empty(), "Test", Instant.ofEpochMilli(7))
.withCompletion(30, empty(), Instant.ofEpochMilli(8))
@@ -144,12 +149,15 @@ public class ApplicationSerializerTest {
Set.of(publicKey, otherPublicKey),
projectId,
true,
+ empty(),
instances);
Application serialized = APPLICATION_SERIALIZER.fromSlime(APPLICATION_SERIALIZER.toSlime(original));
assertEquals(original.id(), serialized.id());
assertEquals(original.createdAt(), serialized.createdAt());
+ assertEquals(applicationVersion1, serialized.latestVersion().get()); // TODO jonmv: remove once this is released
+ assertEquals(applicationVersion1, APPLICATION_SERIALIZER.fromSlime(APPLICATION_SERIALIZER.toSlime(serialized)).latestVersion().get());
assertEquals(original.deploymentSpec().xmlForm(), serialized.deploymentSpec().xmlForm());
assertEquals(original.validationOverrides().xmlForm(), serialized.validationOverrides().xmlForm());
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/complete-application.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/complete-application.json
index 1c660726d61..8bb17733544 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/complete-application.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/complete-application.json
@@ -360,6 +360,14 @@
"version": "6.174.156",
"upgrade": false,
"reason": "Application commit",
+ "revision": {
+ "applicationBuildNumber": 123,
+ "sourceRevision": {
+ "repositoryField": "git@git.host:user/repo.git",
+ "branchField": "origin/master",
+ "commitField": "49cd7bbb1ed9f4b922083cb042590b0885ffe22b"
+ }
+ },
"at": 1511217733555
}
},
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
index a13bdb3e547..a38b347ee10 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
@@ -224,17 +224,17 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(USER_ID)
.oktaAccessToken(OKTA_AT),
- new File("application-reference.json"));
+ new File("instance-reference.json"));
// GET a tenant
tester.assertResponse(request("/application/v4/tenant/tenant1", GET).userIdentity(USER_ID),
new File("tenant-with-application.json"));
// GET tenant applications
tester.assertResponse(request("/application/v4/tenant/tenant1/application/", GET).userIdentity(USER_ID),
- new File("application-list.json"));
+ new File("instance-list.json"));
// GET tenant applications (instances of "application1" only)
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/", GET).userIdentity(USER_ID),
- new File("application-list.json"));
+ new File("instance-list.json"));
addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR));
@@ -331,7 +331,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/default", POST)
.userIdentity(USER_ID)
.oktaAccessToken(OKTA_AT),
- new File("application-reference-2.json"));
+ new File("instance-reference-2.json"));
ApplicationId app2 = ApplicationId.from("tenant2", "application2", "default");
long screwdriverProjectId2 = 456;
@@ -413,7 +413,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// GET tenant application deployments
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", GET)
.userIdentity(USER_ID),
- new File("application.json"));
+ new File("instance.json"));
// GET an application deployment
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1", GET)
.userIdentity(USER_ID),
@@ -439,7 +439,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", GET)
.userIdentity(USER_ID)
.recursive("true"),
- new File("application1-recursive.json"));
+ new File("instance1-recursive.json"));
// GET nodes
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1/nodes", GET)
@@ -868,7 +868,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(USER_ID)
.oktaAccessToken(OKTA_AT),
- new File("application-reference.json"));
+ new File("instance-reference.json"));
// Grant deploy access
addScrewdriverUserToDeployRole(SCREWDRIVER_ID,
@@ -961,7 +961,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
setDeploymentMaintainedInfo(controllerTester);
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", GET)
.userIdentity(USER_ID),
- new File("application-without-change-multiple-deployments.json"));
+ new File("instance-without-change-multiple-deployments.json"));
}
@Test
@@ -983,7 +983,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/doesnotexist/application/doesnotexist/metering", GET)
.userIdentity(USER_ID)
.oktaAccessToken(OKTA_AT),
- new File("application1-metering.json"));
+ new File("instance1-metering.json"));
}
@Test
@@ -1068,7 +1068,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(USER_ID)
.oktaAccessToken(OKTA_AT),
- new File("application-reference.json"));
+ new File("instance-reference.json"));
// Create the same application again
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
@@ -1208,7 +1208,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(authorizedUser)
.oktaAccessToken(OKTA_AT),
- new File("application-reference.json"),
+ new File("instance-reference.json"),
200);
// Deploy to an authorized zone by a user tenant is disallowed
@@ -1229,7 +1229,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/default", POST)
.userIdentity(authorizedUser)
.oktaAccessToken(OKTA_AT),
- new File("application-reference-default.json"),
+ new File("instance-reference-default.json"),
200);
// Deleting the application when more than one instance is present is forbidden
@@ -1515,7 +1515,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// ... and assert it was recorded
JobStatus recordedStatus =
- tester.controller().applications().getInstance(app.id().defaultInstance()).get().deploymentJobs().jobStatus().get(JobType.component);
+ tester.controller().applications().getInstance(app.id().defaultInstance()).get().deploymentJobs().jobStatus().get(JobType.systemTest);
assertNotNull("Status was recorded", recordedStatus);
assertTrue(recordedStatus.isSuccess());
@@ -1574,9 +1574,9 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.controller().curator().writeRoutingPolicies(app.id().defaultInstance(), Set.of(policy));
// GET application
- tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", GET)
+ tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/default", GET)
.userIdentity(USER_ID),
- new File("application-with-routing-policy.json"));
+ new File("instance-with-routing-policy.json"));
// GET deployment
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default", GET)
@@ -1706,7 +1706,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(USER_ID)
.oktaAccessToken(OKTA_AT),
- new File("application-reference.json"));
+ new File("instance-reference.json"));
addScrewdriverUserToDeployRole(SCREWDRIVER_ID, ATHENZ_TENANT_DOMAIN,
new com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId("application1"));
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-list.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-list.json
deleted file mode 100644
index ecee1c8dbde..00000000000
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-list.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[
- @include(application-reference.json)
-] \ No newline at end of file
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2-with-patches.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2-with-patches.json
index 9d76654fbc0..ad86fa34cde 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2-with-patches.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2-with-patches.json
@@ -1,12 +1,15 @@
{
"tenant": "tenant2",
"application": "application2",
- "instance": "default",
- "deployments": "http://localhost:8080/application/v4/tenant/tenant2/application/application2/instance/default/job/",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
+ "deployments": "http://localhost:8080/application/v4/tenant/tenant2/application/application2/job/",
+ "latestVersion": {
+ "buildNumber": 42,
+ "hash": "1.0.42-commit1",
+ "source": {
+ "gitRepository": "repository1",
+ "gitBranch": "master",
+ "gitCommit": "commit1"
+ }
},
"projectId": 456,
"deploying": {
@@ -14,6 +17,7 @@
},
"outstandingChange": {
"revision": {
+ "buildNumber": 42,
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -22,66 +26,40 @@
}
}
},
- "deployedInternally": false,
- "deploymentJobs": [
- {
- "type": "component",
- "success": true,
- "lastCompleted": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- },
- "lastSuccess": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- }
- },
+ "compileVersion": "6.1.0",
+ "majorVersion": 7,
+ "instances": [
{
- "type": "system-test",
- "success": false,
- "lastTriggered": {
- "id": -1,
- "version": "7.0.0",
- "revision": {
- "hash": "1.0.42-commit1",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
+ "instance": "default",
+ "deploymentJobs": [
+ {
+ "type": "system-test",
+ "success": false,
+ "lastTriggered": {
+ "id": -1,
+ "version": "7.0.0",
+ "revision": {
+ "buildNumber": 42,
+ "hash": "1.0.42-commit1",
+ "source": {
+ "gitRepository": "repository1",
+ "gitBranch": "master",
+ "gitCommit": "commit1"
+ }
+ },
+ "reason": "Testing last changes outside prod",
+ "at": "(ignore)"
}
- },
- "reason": "Testing last changes outside prod",
- "at": "(ignore)"
- }
+ }
+ ],
+ "changeBlockers": [],
+ "globalRotations": [],
+ "deployments": []
}
],
- "changeBlockers": [],
- "compileVersion": "6.1.0",
- "majorVersion": 7,
- "globalRotations": [],
- "instances": [],
- "pemDeployKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuKVFA8dXk43kVfYKzkUqhEY2rDT9\nz/4jKSTHwbYR8wdsOSrJGVEUPbS2nguIJ64OJH7gFnxM6sxUVj+Nm2HlXw==\n-----END PUBLIC KEY-----\n",
- "pemDeployKeys": ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuKVFA8dXk43kVfYKzkUqhEY2rDT9\nz/4jKSTHwbYR8wdsOSrJGVEUPbS2nguIJ64OJH7gFnxM6sxUVj+Nm2HlXw==\n-----END PUBLIC KEY-----\n"],
+ "pemDeployKeys": [
+ "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuKVFA8dXk43kVfYKzkUqhEY2rDT9\nz/4jKSTHwbYR8wdsOSrJGVEUPbS2nguIJ64OJH7gFnxM6sxUVj+Nm2HlXw==\n-----END PUBLIC KEY-----\n"
+ ],
"metrics": {
"queryServiceQuality": 0.0,
"writeServiceQuality": 0.0
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2.json
index e53684d501a..6d89fa4ee20 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application2.json
@@ -1,12 +1,15 @@
{
"tenant": "tenant2",
"application": "application2",
- "instance": "default",
- "deployments": "http://localhost:8080/application/v4/tenant/tenant2/application/application2/instance/default/job/",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
+ "deployments": "http://localhost:8080/application/v4/tenant/tenant2/application/application2/job/",
+ "latestVersion": {
+ "buildNumber": 42,
+ "hash": "1.0.42-commit1",
+ "source": {
+ "gitRepository": "repository1",
+ "gitBranch": "master",
+ "gitCommit": "commit1"
+ }
},
"projectId": 456,
"deploying": {
@@ -14,6 +17,7 @@
},
"outstandingChange": {
"revision": {
+ "buildNumber": 42,
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -22,63 +26,36 @@
}
}
},
- "deployedInternally": false,
- "deploymentJobs": [
- {
- "type": "component",
- "success": true,
- "lastCompleted": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- },
- "lastSuccess": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- }
- },
+ "compileVersion": "6.1.0",
+ "instances": [
{
- "type": "system-test",
- "success": false,
- "lastTriggered": {
- "id": -1,
- "version": "7.0.0",
- "revision": {
- "hash": "1.0.42-commit1",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
+ "instance": "default",
+ "deploymentJobs": [
+ {
+ "type": "system-test",
+ "success": false,
+ "lastTriggered": {
+ "id": -1,
+ "version": "7.0.0",
+ "revision": {
+ "buildNumber": 42,
+ "hash": "1.0.42-commit1",
+ "source": {
+ "gitRepository": "repository1",
+ "gitBranch": "master",
+ "gitCommit": "commit1"
+ }
+ },
+ "reason": "Testing last changes outside prod",
+ "at": "(ignore)"
}
- },
- "reason": "Testing last changes outside prod",
- "at": "(ignore)"
- }
+ }
+ ],
+ "changeBlockers": [],
+ "globalRotations": [],
+ "deployments": []
}
],
- "changeBlockers": [],
- "compileVersion": "6.1.0",
- "globalRotations": [],
- "instances": [],
"pemDeployKeys": [],
"metrics": {
"queryServiceQuality": 0.0,
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-list.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-list.json
new file mode 100644
index 00000000000..024ca11dbe3
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-list.json
@@ -0,0 +1,3 @@
+[
+ @include(instance-reference.json)
+] \ No newline at end of file
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference-2.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference-2.json
index 0c9dc2ca1e7..0c9dc2ca1e7 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference-2.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference-2.json
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference-default.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference-default.json
index 7117cc22507..7117cc22507 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference-default.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference-default.json
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference.json
index 60243633614..60243633614 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-reference.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-reference.json
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-with-routing-policy.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-with-routing-policy.json
index 776bfbf3880..91356bc83bf 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-with-routing-policy.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-with-routing-policy.json
@@ -12,44 +12,13 @@
"deployedInternally": false,
"deploymentJobs": [
{
- "type": "component",
- "success": true,
- "lastCompleted": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "1.0.42-commit1",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- },
- "lastSuccess": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "1.0.42-commit1",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- }
- },
- {
"type": "system-test",
"success": true,
"lastTriggered": {
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -64,6 +33,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -78,6 +48,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -96,6 +67,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -110,6 +82,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -124,6 +97,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -142,6 +116,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -156,6 +131,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -170,6 +146,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "1.0.42-commit1",
"source": {
"gitRepository": "repository1",
@@ -192,7 +169,7 @@
"environment": "prod",
"region": "us-west-1",
"instance": "default",
- "url": "http://localhost:8080/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default"
+ "url": "http://localhost:8080/application/v4/tenant/tenant1/application/application1/instance/default/environment/prod/region/us-west-1"
}
],
"pemDeployKeys": [],
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-without-change-multiple-deployments.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-without-change-multiple-deployments.json
index 3579f64f6c9..bcda7992d81 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-without-change-multiple-deployments.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance-without-change-multiple-deployments.json
@@ -12,44 +12,13 @@
"deployedInternally": false,
"deploymentJobs": [
{
- "type": "component",
- "success": true,
- "lastCompleted": {
- "id": 101,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- },
- "lastSuccess": {
- "id": 101,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- }
- },
- {
"type": "system-test",
"success": true,
"lastTriggered": {
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -64,6 +33,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -78,6 +48,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -96,6 +67,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -110,6 +82,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -124,6 +97,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -142,6 +116,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -156,6 +131,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -170,6 +146,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -188,6 +165,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -202,6 +180,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -216,6 +195,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance.json
index 4469b7cb321..009d6c74dd1 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance.json
@@ -11,6 +11,7 @@
"projectId": 123,
"deploying": {
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -22,44 +23,13 @@
"deployedInternally": false,
"deploymentJobs": [
{
- "type": "component",
- "success": true,
- "lastCompleted": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- },
- "lastSuccess": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- }
- },
- {
"type": "system-test",
"success": true,
"lastTriggered": {
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -74,6 +44,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -88,6 +59,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -106,6 +78,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -120,6 +93,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -134,6 +108,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -152,6 +127,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -166,6 +142,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -180,6 +157,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-metering.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance1-metering.json
index 2e07a7e8a96..2e07a7e8a96 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-metering.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance1-metering.json
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-recursive.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance1-recursive.json
index 603404bffae..afa506d1e48 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application1-recursive.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/instance1-recursive.json
@@ -11,6 +11,7 @@
"projectId": 123,
"deploying": {
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -22,44 +23,13 @@
"deployedInternally": false,
"deploymentJobs": [
{
- "type": "component",
- "success": true,
- "lastCompleted": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- },
- "lastSuccess": {
- "id": 42,
- "version": "(ignore)",
- "revision": {
- "hash": "(ignore)",
- "source": {
- "gitRepository": "repository1",
- "gitBranch": "master",
- "gitCommit": "commit1"
- }
- },
- "reason": "Application commit",
- "at": "(ignore)"
- }
- },
- {
"type": "system-test",
"success": true,
"lastTriggered": {
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -74,6 +44,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -88,6 +59,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -106,6 +78,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -120,6 +93,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -134,6 +108,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -152,6 +127,7 @@
"id": -1,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -166,6 +142,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
@@ -180,6 +157,7 @@
"id": 42,
"version": "(ignore)",
"revision": {
+ "buildNumber": "(ignore)",
"hash": "(ignore)",
"source": {
"gitRepository": "repository1",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/jobs.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/jobs.json
index 990618f28bc..1a312f3c99c 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/jobs.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/jobs.json
@@ -132,7 +132,7 @@
"runs": [
{
"id": 1,
- "status": "aborted",
+ "status": "running",
"start": (ignore),
"wantedPlatform": "6.1",
"wantedApplication": {
@@ -143,7 +143,9 @@
"installReal": "unfinished",
"copyVespaLogs": "unfinished"
},
- "tasks": {},
+ "tasks": {
+ "deploy": "running"
+ },
"log": "http://localhost:8080/application/v4/tenant/tenant1/application/application1/instance/instance1/job/dev-us-east-1/run/1"
}
],
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview.json
index 9c9e1b5ec67..d1e9a004dd2 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview.json
@@ -15,7 +15,7 @@
"gitCommit": "commit1"
}
},
- "at": 2000,
+ "at": 1000,
"deploying": "0 of 3 complete"
}
},
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/tenant1-recursive.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/tenant1-recursive.json
index 309177e6285..16b963a190e 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/tenant1-recursive.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/tenant1-recursive.json
@@ -4,6 +4,6 @@
"athensDomain": "domain1",
"property": "property1",
"applications": [
- @include(application1-recursive.json)
+ @include(instance1-recursive.json)
]
}