diff options
30 files changed, 455 insertions, 382 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/DeploymentReference.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/DeploymentReference.java new file mode 100644 index 00000000000..7971a3d0e0e --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/DeploymentReference.java @@ -0,0 +1,20 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.application.v4.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.yahoo.vespa.hosted.controller.api.identifiers.EnvironmentId; +import com.yahoo.vespa.hosted.controller.api.identifiers.RegionId; + +import java.net.URI; + +/** + * @author jonmv + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class DeploymentReference { + public EnvironmentId environment; + public RegionId region; + + public URI url; + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/InstanceReference.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/InstanceReference.java index 6ac27d0bad9..271deb6fe35 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/InstanceReference.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/InstanceReference.java @@ -2,31 +2,20 @@ package com.yahoo.vespa.hosted.controller.api.application.v4.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.yahoo.vespa.hosted.controller.api.bcp.BcpStatus; -import com.yahoo.vespa.hosted.controller.api.identifiers.EnvironmentId; import com.yahoo.vespa.hosted.controller.api.identifiers.InstanceId; -import com.yahoo.vespa.hosted.controller.api.identifiers.RegionId; import java.net.URI; +import java.util.List; /** * @author mortent */ @JsonIgnoreProperties(ignoreUnknown = true) public class InstanceReference { - public EnvironmentId environment; - public RegionId region; + + public List<DeploymentReference> deployments; public InstanceId instance; - public BcpStatus bcpStatus; public URI url; - public static InstanceReference createInstanceReference(InstanceId instanceId, RegionId regionId, EnvironmentId environmentId, URI uri) { - InstanceReference instanceReference = new InstanceReference(); - instanceReference.instance = instanceId; - instanceReference.region = regionId; - instanceReference.environment = environmentId; - instanceReference.url = uri; - return instanceReference; - } } 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) ] } |