summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationVersion.java52
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java27
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java20
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java21
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java17
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelper.java13
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalDeploymentTester.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java12
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java7
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializerTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/run-status.json2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java4
14 files changed, 140 insertions, 51 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationVersion.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationVersion.java
index 1c8b861ba51..b1dad7d814e 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationVersion.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationVersion.java
@@ -1,6 +1,9 @@
// 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.integration.deployment;
+import com.yahoo.component.Version;
+
+import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalLong;
@@ -17,7 +20,8 @@ public class ApplicationVersion implements Comparable<ApplicationVersion> {
* Used in cases where application version cannot be determined, such as manual deployments (e.g. in dev
* environment)
*/
- public static final ApplicationVersion unknown = new ApplicationVersion(Optional.empty(), OptionalLong.empty(), Optional.empty());
+ public static final ApplicationVersion unknown = new ApplicationVersion(Optional.empty(), OptionalLong.empty(),
+ Optional.empty(), Optional.empty(), Optional.empty());
// This never changes and is only used to create a valid semantic version number, as required by application bundles
private static final String majorVersion = "1.0";
@@ -25,33 +29,53 @@ public class ApplicationVersion implements Comparable<ApplicationVersion> {
private final Optional<SourceRevision> source;
private final Optional<String> authorEmail;
private final OptionalLong buildNumber;
+ private final Optional<Version> compileVersion;
+ private final Optional<Instant> buildTime;
- private ApplicationVersion(Optional<SourceRevision> source, OptionalLong buildNumber, Optional<String> authorEmail) {
+ private ApplicationVersion(Optional<SourceRevision> source, OptionalLong buildNumber, Optional<String> authorEmail,
+ Optional<Version> compileVersion, Optional<Instant> buildTime) {
Objects.requireNonNull(source, "source cannot be null");
Objects.requireNonNull(buildNumber, "buildNumber cannot be null");
Objects.requireNonNull(authorEmail, "author cannot be null");
if (source.isPresent() != buildNumber.isPresent()) {
throw new IllegalArgumentException("both buildNumber and source must be set together");
}
+ if (compileVersion.isPresent() != buildTime.isPresent()) {
+ throw new IllegalArgumentException("both compileVersion and buildTime must be set together");
+ }
if (buildNumber.isPresent() && buildNumber.getAsLong() <= 0) {
throw new IllegalArgumentException("buildNumber must be > 0");
}
if (authorEmail.isPresent() && ! authorEmail.get().matches("[^@]+@[^@]+")) {
throw new IllegalArgumentException("Invalid author email '" + authorEmail.get() + "'.");
}
+ if (compileVersion.isPresent() && compileVersion.get().equals(Version.emptyVersion)) {
+ throw new IllegalArgumentException("The empty version is not a legal compile version.");
+ }
this.source = source;
this.buildNumber = buildNumber;
this.authorEmail = authorEmail;
+ this.compileVersion = compileVersion;
+ this.buildTime = buildTime;
}
/** Create an application package version from a completed build, without an author email */
public static ApplicationVersion from(SourceRevision source, long buildNumber) {
- return new ApplicationVersion(Optional.of(source), OptionalLong.of(buildNumber), Optional.empty());
+ return new ApplicationVersion(Optional.of(source), OptionalLong.of(buildNumber), Optional.empty(),
+ Optional.empty(), Optional.empty());
}
- /** Create an application package version from a completed build, with an author email */
+ /** Creates an version from a completed build and an author email. */
public static ApplicationVersion from(SourceRevision source, long buildNumber, String authorEmail) {
- return new ApplicationVersion(Optional.of(source), OptionalLong.of(buildNumber), Optional.of(authorEmail));
+ return new ApplicationVersion(Optional.of(source), OptionalLong.of(buildNumber),
+ Optional.of(authorEmail), Optional.empty(), Optional.empty());
+ }
+
+ /** Creates an version from a completed build, an author email, and build meta data. */
+ public static ApplicationVersion from(SourceRevision source, long buildNumber, String authorEmail,
+ Version compileVersion, Instant buildTime) {
+ return new ApplicationVersion(Optional.of(source), OptionalLong.of(buildNumber), Optional.of(authorEmail),
+ Optional.of(compileVersion), Optional.of(buildTime));
}
/** Returns an unique identifier for this version or "unknown" if version is not known */
@@ -74,6 +98,12 @@ public class ApplicationVersion implements Comparable<ApplicationVersion> {
/** Returns the email of the author of commit of this version, if known */
public Optional<String> authorEmail() { return authorEmail; }
+ /** Returns the Vespa version this package was compiled against, if known. */
+ public Optional<Version> compileVersion() { return compileVersion; }
+
+ /** Returns the time this package was built, if known. */
+ public Optional<Instant> buildTime() { return buildTime; }
+
/** Returns whether this is unknown */
public boolean isUnknown() {
return this.equals(unknown);
@@ -86,19 +116,23 @@ public class ApplicationVersion implements Comparable<ApplicationVersion> {
ApplicationVersion that = (ApplicationVersion) o;
return Objects.equals(source, that.source) &&
Objects.equals(authorEmail, that.authorEmail) &&
- Objects.equals(buildNumber, that.buildNumber);
+ Objects.equals(buildNumber, that.buildNumber) &&
+ Objects.equals(compileVersion, that.compileVersion) &&
+ Objects.equals(buildTime, that.buildTime);
}
@Override
public int hashCode() {
- return Objects.hash(source, authorEmail, buildNumber);
+ return Objects.hash(source, authorEmail, buildNumber, compileVersion, buildTime);
}
@Override
public String toString() {
- return "Application package version: " + id()
+ return "Application package version: " + id()
+ source.map(s -> ", " + s.toString()).orElse("")
- + authorEmail.map(e -> ", " + e).orElse("");
+ + authorEmail.map(e -> ", by " + e).orElse("")
+ + compileVersion.map(v -> ", built against " + v).orElse("")
+ + buildTime.map(t -> " at " + t).orElse("") ;
}
/** Abbreviate given commit hash to 9 characters */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java
index 40e2e4a92d1..a0b4a888727 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java
@@ -1,14 +1,19 @@
// 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.application;
+import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.application.api.ValidationOverrides;
+import com.yahoo.slime.Inspector;
+import com.yahoo.slime.Slime;
+import com.yahoo.vespa.config.SlimeUtils;
import org.apache.commons.codec.digest.DigestUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
@@ -27,10 +32,12 @@ public class ApplicationPackage {
private final byte[] zippedContent;
private final DeploymentSpec deploymentSpec;
private final ValidationOverrides validationOverrides;
+ private final Optional<Version> compileVersion;
+ private final Optional<Instant> buildTime;
/**
* Creates an application package from its zipped content.
- * This <b>assigns ownership</b> of the given byte array to this class:
+ * This <b>assigns ownership</b> of the given byte array to this class;
* it must not be further changed by the caller.
*/
public ApplicationPackage(byte[] zippedContent) {
@@ -38,6 +45,10 @@ public class ApplicationPackage {
this.contentHash = DigestUtils.shaHex(zippedContent);
this.deploymentSpec = extractFile("deployment.xml", zippedContent).map(DeploymentSpec::fromXml).orElse(DeploymentSpec.empty);
this.validationOverrides = extractFile("validation-overrides.xml", zippedContent).map(ValidationOverrides::fromXml).orElse(ValidationOverrides.empty);
+ Optional<Inspector> buildMetaObject = extractFileBytes("build-meta.json", zippedContent)
+ .map(SlimeUtils::jsonToSlime).map(Slime::get);
+ this.compileVersion = buildMetaObject.map(object -> Version.fromString(object.field("compileVersion").asString()));
+ this.buildTime = buildMetaObject.map(object -> Instant.ofEpochMilli(object.field("buildTime").asLong()));
}
/** Returns a hash of the content of this package */
@@ -58,12 +69,18 @@ public class ApplicationPackage {
*/
public ValidationOverrides validationOverrides() { return validationOverrides; }
- private static Optional<Reader> extractFile(String fileName, byte[] zippedContent) {
+ /** Returns the platform version which package was compiled against, if known. */
+ public Optional<Version> compileVersion() { return compileVersion; }
+
+ /** Returns the time this package was built, if known. */
+ public Optional<Instant> buildTime() { return buildTime; }
+
+ private static Optional<byte[]> extractFileBytes(String fileName, byte[] zippedContent) {
try (ByteArrayInputStream stream = new ByteArrayInputStream(zippedContent)) {
ZipStreamReader reader = new ZipStreamReader(stream);
for (ZipStreamReader.ZipEntryWithContent entry : reader.entries())
if (entry.zipEntry().getName().equals(fileName) || entry.zipEntry().getName().equals("application/" + fileName)) // TODO: Remove application/ directory support
- return Optional.of(new InputStreamReader(new ByteArrayInputStream(entry.content())));
+ return Optional.of(entry.content());
return Optional.empty();
}
catch (IOException e) {
@@ -71,4 +88,8 @@ public class ApplicationPackage {
}
}
+ private static Optional<Reader> extractFile(String fileName, byte[] zippedContent) {
+ return extractFileBytes(fileName, zippedContent).map(ByteArrayInputStream::new).map(InputStreamReader::new);
+ }
+
}
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 5c56c7d2280..fcead86893a 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
@@ -10,25 +10,23 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
import com.yahoo.vespa.hosted.controller.api.integration.LogEntry;
import com.yahoo.vespa.hosted.controller.api.integration.RunDataStore;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.NoInstanceException;
+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.api.integration.deployment.RunId;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterCloud;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterId;
import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.vespa.hosted.controller.application.DeploymentJobs;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision;
import com.yahoo.vespa.hosted.controller.persistence.BufferedLogStore;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import java.net.URI;
-import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -41,7 +39,6 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import java.util.logging.Level;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.google.common.collect.ImmutableList.copyOf;
@@ -229,7 +226,7 @@ public class JobController {
* Accepts and stores a new application package and test jar pair under a generated application version key.
*/
public ApplicationVersion submit(ApplicationId id, SourceRevision revision, String authorEmail, long projectId,
- byte[] packageBytes, byte[] testPackageBytes) {
+ ApplicationPackage applicationPackage, byte[] testPackageBytes) {
AtomicReference<ApplicationVersion> version = new AtomicReference<>();
controller.applications().lockOrThrow(id, application -> {
if ( ! application.get().deploymentJobs().deployedInternally()) {
@@ -245,17 +242,22 @@ public class JobController {
}
long run = nextBuild(id);
- version.set(ApplicationVersion.from(revision, run, authorEmail));
+ if (applicationPackage.compileVersion().isPresent() && applicationPackage.buildTime().isPresent())
+ version.set(ApplicationVersion.from(revision, run, authorEmail,
+ applicationPackage.compileVersion().get(),
+ applicationPackage.buildTime().get()));
+ else
+ version.set(ApplicationVersion.from(revision, run, authorEmail));
controller.applications().applicationStore().put(id,
version.get(),
- packageBytes);
+ applicationPackage.zippedContent());
controller.applications().applicationStore().put(TesterId.of(id),
version.get(),
testPackageBytes);
prunePackages(id);
- controller.applications().storeWithUpdatedConfig(application.withBuiltInternally(true), new ApplicationPackage(packageBytes));
+ controller.applications().storeWithUpdatedConfig(application.withBuiltInternally(true), applicationPackage);
controller.applications().deploymentTrigger().notifyOfCompletion(DeploymentJobs.JobReport.ofSubmission(id, projectId, version.get()));
});
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 69ea36c7e3a..147b2edee3e 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
@@ -81,6 +81,8 @@ public class ApplicationSerializer {
private final String branchField = "branchField";
private final String commitField = "commitField";
private final String authorEmailField = "authorEmailField";
+ private final String compileVersionField = "compileVersion";
+ private final String buildTimeField = "buildTime";
private final String lastQueriedField = "lastQueried";
private final String lastWrittenField = "lastWritten";
private final String lastQueriesPerSecondField = "lastQueriesPerSecond";
@@ -231,6 +233,8 @@ public class ApplicationSerializer {
object.setLong(applicationBuildNumberField, applicationVersion.buildNumber().getAsLong());
toSlime(applicationVersion.source().get(), object.setObject(sourceRevisionField));
applicationVersion.authorEmail().ifPresent(email -> object.setString(authorEmailField, email));
+ applicationVersion.compileVersion().ifPresent(version -> object.setString(compileVersionField, version.toString()));
+ applicationVersion.buildTime().ifPresent(time -> object.setLong(buildTimeField, time.toEpochMilli()));
}
}
@@ -406,12 +410,21 @@ public class ApplicationSerializer {
if ( ! object.valid()) return ApplicationVersion.unknown;
OptionalLong applicationBuildNumber = optionalLong(object.field(applicationBuildNumberField));
Optional<SourceRevision> sourceRevision = sourceRevisionFromSlime(object.field(sourceRevisionField));
- if (!sourceRevision.isPresent() || !applicationBuildNumber.isPresent()) {
+ if ( ! sourceRevision.isPresent() || ! applicationBuildNumber.isPresent()) {
return ApplicationVersion.unknown;
}
- return object.field(authorEmailField).valid()
- ? ApplicationVersion.from(sourceRevision.get(), applicationBuildNumber.getAsLong(), object.field(authorEmailField).asString())
- : ApplicationVersion.from(sourceRevision.get(), applicationBuildNumber.getAsLong());
+ Optional<String> authorEmail = optionalString(object.field(authorEmailField));
+ Optional<Version> compileVersion = optionalString(object.field(compileVersionField)).map(Version::fromString);
+ Optional<Instant> buildTime = optionalInstant(object.field(buildTimeField));
+
+ if ( ! authorEmail.isPresent())
+ return ApplicationVersion.from(sourceRevision.get(), applicationBuildNumber.getAsLong());
+
+ if ( ! compileVersion.isPresent() || ! buildTime.isPresent())
+ return ApplicationVersion.from(sourceRevision.get(), applicationBuildNumber.getAsLong(), authorEmail.get());
+
+ return ApplicationVersion.from(sourceRevision.get(), applicationBuildNumber.getAsLong(), authorEmail.get(),
+ compileVersion.get(), buildTime.get());
}
private Optional<SourceRevision> sourceRevisionFromSlime(Inspector object) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java
index ef91a2e5a15..32c92e6f135 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java
@@ -68,6 +68,8 @@ class RunSerializer {
private static final String branchField = "branch";
private static final String commitField = "commit";
private static final String authorEmailField = "authorEmail";
+ private static final String compileVersionField = "compileVersion";
+ private static final String buildTimeField = "buildTime";
private static final String buildField = "build";
private static final String sourceField = "source";
private static final String lastTestRecordField = "lastTestRecord";
@@ -123,9 +125,16 @@ class RunSerializer {
versionObject.field(branchField).asString(),
versionObject.field(commitField).asString());
long buildNumber = versionObject.field(buildField).asLong();
- return versionObject.field(authorEmailField).valid()
- ? ApplicationVersion.from(revision, buildNumber, versionObject.field(authorEmailField).asString())
- : ApplicationVersion.from(revision, buildNumber);
+
+ if ( ! versionObject.field(authorEmailField).valid())
+ return ApplicationVersion.from(revision, buildNumber);
+
+ if ( ! versionObject.field(compileVersionField).valid() || ! versionObject.field(buildTimeField).valid())
+ return ApplicationVersion.from(revision, buildNumber, versionObject.field(authorEmailField).asString());
+
+ return ApplicationVersion.from(revision, buildNumber, versionObject.field(authorEmailField).asString(),
+ Version.fromString(versionObject.field(compileVersionField).asString()),
+ Instant.ofEpochMilli(versionObject.field(buildTimeField).asLong()));
}
Slime toSlime(Iterable<Run> runs) {
@@ -173,6 +182,8 @@ class RunSerializer {
versionsObject.setLong(buildField, applicationVersion.buildNumber()
.orElseThrow(() -> new IllegalArgumentException("Build number must be present in application version.")));
applicationVersion.authorEmail().ifPresent(email -> versionsObject.setString(authorEmailField, email));
+ applicationVersion.compileVersion().ifPresent(version -> versionsObject.setString(compileVersionField, version.toString()));
+ applicationVersion.buildTime().ifPresent(time -> versionsObject.setLong(buildTimeField, time.toEpochMilli()));
}
static String valueOf(Step step) {
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 8f8a3ad7f55..56e1e746d04 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
@@ -1321,9 +1321,9 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
String authorEmail = submitOptions.field("authorEmail").asString();
long projectId = Math.max(1, submitOptions.field("projectId").asLong());
- byte[] applicationZip = dataParts.get(EnvironmentResource.APPLICATION_ZIP);
+ ApplicationPackage applicationPackage = new ApplicationPackage(dataParts.get(EnvironmentResource.APPLICATION_ZIP));
controller.applications().verifyApplicationIdentityConfiguration(TenantName.from(tenant),
- new ApplicationPackage(applicationZip),
+ applicationPackage,
Optional.of(getUserPrincipal(request).getIdentity()));
return JobControllerApiHandlerHelper.submitResponse(controller.jobController(),
@@ -1332,7 +1332,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
sourceRevision,
authorEmail,
projectId,
- applicationZip,
+ applicationPackage,
dataParts.get(EnvironmentResource.APPLICATION_TEST_ZIP));
}
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 a3dc3f1e706..7d49ffe8139 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
@@ -16,6 +16,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
+import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.application.Change;
import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
@@ -27,6 +28,7 @@ import com.yahoo.vespa.hosted.controller.deployment.RunLog;
import com.yahoo.vespa.hosted.controller.deployment.Run;
import com.yahoo.vespa.hosted.controller.deployment.Step;
import com.yahoo.vespa.hosted.controller.deployment.Versions;
+import com.yahoo.vespa.hosted.controller.restapi.MessageResponse;
import com.yahoo.vespa.hosted.controller.restapi.SlimeJsonResponse;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
@@ -398,19 +400,16 @@ class JobControllerApiHandlerHelper {
* @return Response with the new application version
*/
static HttpResponse submitResponse(JobController jobController, String tenant, String application,
- SourceRevision sourceRevision, String authorEmail,
- long projectId, byte[] appPackage, byte[] testPackage) {
+ SourceRevision sourceRevision, String authorEmail, long projectId,
+ ApplicationPackage applicationPackage, byte[] testPackage) {
ApplicationVersion version = jobController.submit(ApplicationId.from(tenant, application, "default"),
sourceRevision,
authorEmail,
projectId,
- appPackage,
+ applicationPackage,
testPackage);
- Slime slime = new Slime();
- Cursor responseObject = slime.setObject();
- responseObject.setString("version", version.id());
- return new SlimeJsonResponse(slime);
+ return new MessageResponse(version.toString());
}
/** Aborts any job of the given type. */
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 b7a881c672e..1199f0229b6 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
@@ -155,7 +155,8 @@ public class ControllerTest {
.region("deep-space-9")
.build();
try {
- tester.controller().jobController().submit(app1.id(), BuildJob.defaultSourceRevision, "a@b", 2, applicationPackage.zippedContent(), new byte[0]);
+ tester.controller().jobController().submit(app1.id(), BuildJob.defaultSourceRevision, "a@b",
+ 2, applicationPackage, new byte[0]);
fail("Expected exception due to illegal deployment spec.");
}
catch (IllegalArgumentException e) {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalDeploymentTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalDeploymentTester.java
index 80cbbfa2c30..35e7aea5efe 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalDeploymentTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalDeploymentTester.java
@@ -89,7 +89,7 @@ public class InternalDeploymentTester {
* Submits a new application, and returns the version of the new submission.
*/
public ApplicationVersion newSubmission() {
- ApplicationVersion version = jobs.submit(appId, BuildJob.defaultSourceRevision, "a@b", 2, applicationPackage.zippedContent(), new byte[0]);
+ ApplicationVersion version = jobs.submit(appId, BuildJob.defaultSourceRevision, "a@b", 2, applicationPackage, new byte[0]);
tester.applicationStore().put(appId, version, applicationPackage.zippedContent());
tester.applicationStore().put(testerId, version, new byte[0]);
return version;
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java
index 7e6e892891a..8ebb8c108c0 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java
@@ -7,6 +7,7 @@ import com.yahoo.vespa.athenz.api.OktaAccessToken;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision;
+import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester;
import com.yahoo.vespa.hosted.controller.deployment.JobController;
import com.yahoo.vespa.hosted.controller.deployment.Run;
@@ -64,6 +65,7 @@ import static org.junit.Assert.fail;
*/
public class JobRunnerTest {
+ private static final ApplicationPackage applicationPackage = new ApplicationPackage(new byte[0]);
private static final Versions versions = new Versions(Version.fromString("1.2.3"),
ApplicationVersion.from(new SourceRevision("repo",
"branch",
@@ -82,7 +84,7 @@ public class JobRunnerTest {
phasedExecutor(phaser), stepRunner);
ApplicationId id = tester.createApplication("real", "tenant", 1, 1L).id();
- jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, new byte[0], new byte[0]);
+ jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, applicationPackage, new byte[0]);
jobs.start(id, systemTest, versions);
try {
@@ -113,7 +115,7 @@ public class JobRunnerTest {
inThreadExecutor(), mappedRunner(outcomes));
ApplicationId id = tester.createApplication("real", "tenant", 1, 1L).id();
- jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, new byte[0], new byte[0]);
+ jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, applicationPackage, new byte[0]);
Supplier<Run> run = () -> jobs.last(id, systemTest).get();
jobs.start(id, systemTest, versions);
@@ -197,7 +199,7 @@ public class JobRunnerTest {
Executors.newFixedThreadPool(32), waitingRunner(barrier));
ApplicationId id = tester.createApplication("real", "tenant", 1, 1L).id();
- jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, new byte[0], new byte[0]);
+ jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, applicationPackage, new byte[0]);
RunId runId = new RunId(id, systemTest, 1);
jobs.start(id, systemTest, versions);
@@ -233,7 +235,7 @@ public class JobRunnerTest {
inThreadExecutor(), (id, step) -> Optional.of(running));
ApplicationId id = tester.createApplication("real", "tenant", 1, 1L).id();
- jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, new byte[0], new byte[0]);
+ jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, applicationPackage, new byte[0]);
for (int i = 0; i < jobs.historyLength(); i++) {
jobs.start(id, systemTest, versions);
@@ -261,7 +263,7 @@ public class JobRunnerTest {
inThreadExecutor(), mappedRunner(outcomes));
ApplicationId id = tester.createApplication("real", "tenant", 1, 1L).id();
- jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, new byte[0], new byte[0]);
+ jobs.submit(id, versions.targetApplication().source().get(), "a@b", 2, applicationPackage, new byte[0]);
jobs.start(id, systemTest, versions);
tester.clock().advance(JobRunner.jobTimeout.plus(Duration.ofSeconds(1)));
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 774caea97b0..0b337eb5380 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
@@ -10,11 +10,12 @@ import com.yahoo.config.provision.HostName;
import com.yahoo.vespa.config.SlimeUtils;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.api.integration.MetricsService;
+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.api.integration.deployment.SourceRevision;
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.api.integration.zone.ZoneId;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.application.Change;
import com.yahoo.vespa.hosted.controller.application.ClusterInfo;
import com.yahoo.vespa.hosted.controller.application.ClusterUtilization;
@@ -25,7 +26,6 @@ import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobError;
import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
import com.yahoo.vespa.hosted.controller.application.RotationStatus;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision;
import com.yahoo.vespa.hosted.controller.rotation.RotationId;
import org.junit.Test;
@@ -70,7 +70,8 @@ public class ApplicationSerializerTest {
List<Deployment> deployments = new ArrayList<>();
ApplicationVersion applicationVersion1 = ApplicationVersion.from(new SourceRevision("repo1", "branch1", "commit1"), 31);
ApplicationVersion applicationVersion2 = ApplicationVersion
- .from(new SourceRevision("repo1", "branch1", "commit1"), 32, "a@b");
+ .from(new SourceRevision("repo1", "branch1", "commit1"), 32, "a@b",
+ Version.fromString("6.3.1"), Instant.ofEpochMilli(496));
Instant activityAt = Instant.parse("2018-06-01T10:15:30.00Z");
deployments.add(new Deployment(zone1, applicationVersion1, Version.fromString("1.2.3"), Instant.ofEpochMilli(3))); // One deployment without cluster info and utils
deployments.add(new Deployment(zone2, applicationVersion2, Version.fromString("1.2.3"), Instant.ofEpochMilli(5),
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializerTest.java
index d6334a9ea86..03b432588bd 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializerTest.java
@@ -19,6 +19,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.Optional;
@@ -78,7 +79,9 @@ public class RunSerializerTest {
"master",
"f00bad"),
123,
- "a@b"),
+ "a@b",
+ Version.fromString("6.3.1"),
+ Instant.ofEpochMilli(100)),
run.versions().targetApplication());
assertEquals(new Version(1, 2, 2), run.versions().sourcePlatform().get());
assertEquals(ApplicationVersion.from(new SourceRevision("git@github.com:user/repo.git",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/run-status.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/run-status.json
index 75bbea6861d..cda3834d47d 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/run-status.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/run-status.json
@@ -26,6 +26,8 @@
"commit": "f00bad",
"build": 123,
"authorEmail": "a@b",
+ "compileVersion": "6.3.1",
+ "buildTime": 100,
"source": {
"platform": "1.2.2",
"repository": "git@github.com:user/repo.git",
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 fd3b30a76c9..eaf78eda593 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
@@ -455,7 +455,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/submit", POST)
.screwdriverIdentity(SCREWDRIVER_ID)
.data(createApplicationSubmissionData(applicationPackage)),
- "{\"version\":\"1.0.43-d00d\"}");
+ "{\"message\":\"Application package version: 1.0.43-d00d, source revision of repository 'repo', branch 'master' with commit 'd00d', by a@b\"}");
// Second attempt has a service under a different domain than the tenant of the application, and fails.
ApplicationPackage packageWithServiceForWrongDomain = new ApplicationPackageBuilder()
@@ -477,7 +477,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/submit", POST)
.screwdriverIdentity(SCREWDRIVER_ID)
.data(createApplicationSubmissionData(packageWithService)),
- "{\"version\":\"1.0.44-d00d\"}");
+ "{\"message\":\"Application package version: 1.0.44-d00d, source revision of repository 'repo', branch 'master' with commit 'd00d', by a@b\"}");
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/default/badge", GET)
.userIdentity(USER_ID),