diff options
author | jonmv <venstad@gmail.com> | 2023-09-08 12:37:16 +0200 |
---|---|---|
committer | jonmv <venstad@gmail.com> | 2023-09-08 12:37:16 +0200 |
commit | 5935d65540ab4f19e1ea9783ea2df3f7f1c1c807 (patch) | |
tree | 31634f52b72badee6eb0f322d968dcce99f414e7 /controller-server | |
parent | 4e14c5c0cec9150f35a93222368af174f911798d (diff) |
Store optional dependent job and change for each run (will be used for tests)
Diffstat (limited to 'controller-server')
7 files changed, 80 insertions, 15 deletions
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 81eaa17f95d..42044cf335a 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 @@ -405,7 +405,7 @@ public class DeploymentTrigger { private void abortIfOutdated(JobStatus job, List<DeploymentStatus.Job> jobs) { job.lastTriggered() - .filter(last -> ! last.hasEnded() && last.reason().isEmpty()) + .filter(last -> ! last.hasEnded() && last.reason().reason().isEmpty()) .ifPresent(last -> { if (jobs.stream().noneMatch(versions -> versions.versions().targetsMatch(last.versions()) && versions.versions().sourcesMatchIfPresent(last.versions()))) { 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 5ccb59e3ebc..589188bfc4f 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 @@ -36,6 +36,7 @@ import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId; import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage; import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackageDiff; import com.yahoo.vespa.hosted.controller.application.pkg.TestPackage; +import com.yahoo.vespa.hosted.controller.deployment.Run.Reason; import com.yahoo.vespa.hosted.controller.notification.Notification; import com.yahoo.vespa.hosted.controller.notification.Notification.Type; import com.yahoo.vespa.hosted.controller.notification.NotificationSource; @@ -717,7 +718,8 @@ public class JobController { throw new IllegalArgumentException("Cannot start " + type + " for " + id + "; it is already running!"); RunId newId = new RunId(id, type, last.map(run -> run.id().number()).orElse(0L) + 1); - curator.writeLastRun(Run.initial(newId, versions, isRedeployment, controller.clock().instant(), profile, reason)); + curator.writeLastRun(Run.initial(newId, versions, isRedeployment, controller.clock().instant(), profile, + new Reason(reason, Optional.empty(), Optional.empty()))); metric.jobStarted(newId.job()); }); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java index 0c5fb3fb3cb..12e04df4790 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java @@ -2,7 +2,9 @@ package com.yahoo.vespa.hosted.controller.deployment; import com.yahoo.config.provision.CloudAccount; +import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId; +import com.yahoo.vespa.hosted.controller.application.Change; import java.security.cert.X509Certificate; import java.time.Instant; @@ -44,13 +46,13 @@ public class Run { private final Optional<X509Certificate> testerCertificate; private final boolean dryRun; private final Optional<CloudAccount> cloudAccount; - private final Optional<String> reason; + private final Reason reason; // For deserialisation only -- do not use! public Run(RunId id, Map<Step, StepInfo> steps, Versions versions, boolean isRedeployment, Instant start, Optional<Instant> end, Optional<Instant> sleepUntil, RunStatus status, long lastTestRecord, Instant lastVespaLogTimestamp, Optional<Instant> noNodesDownSince, Optional<ConvergenceSummary> convergenceSummary, - Optional<X509Certificate> testerCertificate, boolean dryRun, Optional<CloudAccount> cloudAccount, Optional<String> reason) { + Optional<X509Certificate> testerCertificate, boolean dryRun, Optional<CloudAccount> cloudAccount, Reason reason) { this.id = id; this.steps = Collections.unmodifiableMap(new EnumMap<>(steps)); this.versions = versions; @@ -69,12 +71,12 @@ public class Run { this.reason = reason; } - public static Run initial(RunId id, Versions versions, boolean isRedeployment, Instant now, JobProfile profile, Optional<String> triggeredBy) { + public static Run initial(RunId id, Versions versions, boolean isRedeployment, Instant now, JobProfile profile, Reason reason) { EnumMap<Step, StepInfo> steps = new EnumMap<>(Step.class); profile.steps().forEach(step -> steps.put(step, StepInfo.initial(step))); return new Run(id, steps, requireNonNull(versions), isRedeployment, requireNonNull(now), Optional.empty(), Optional.empty(), running, -1, Instant.EPOCH, Optional.empty(), Optional.empty(), - Optional.empty(), profile == JobProfile.developmentDryRun, Optional.empty(), triggeredBy); + Optional.empty(), profile == JobProfile.developmentDryRun, Optional.empty(), reason); } /** Returns a new Run with the status of the given completed step set accordingly. */ @@ -278,7 +280,7 @@ public class Run { public Optional<CloudAccount> cloudAccount() { return cloudAccount; } /** The specific reason for triggering this run, if any. This should be empty for jobs triggered bvy deployment orchestration. */ - public Optional<String> reason() { + public Reason reason() { return reason; } @@ -342,4 +344,6 @@ public class Run { throw new IllegalStateException("This run ended at " + end.get() + " -- it can't be further modified!"); } + public record Reason(Optional<String> reason, Optional<JobId> dependent, Optional<Change> change) { } + } 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 73d0bf6cad6..b1ca6c63816 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 @@ -11,11 +11,14 @@ import com.yahoo.slime.Inspector; import com.yahoo.slime.ObjectTraverser; import com.yahoo.slime.Slime; import com.yahoo.slime.SlimeUtils; +import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RevisionId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId; +import com.yahoo.vespa.hosted.controller.application.Change; import com.yahoo.vespa.hosted.controller.deployment.ConvergenceSummary; import com.yahoo.vespa.hosted.controller.deployment.Run; +import com.yahoo.vespa.hosted.controller.deployment.Run.Reason; import com.yahoo.vespa.hosted.controller.deployment.RunStatus; import com.yahoo.vespa.hosted.controller.deployment.Step; import com.yahoo.vespa.hosted.controller.deployment.Step.Status; @@ -101,6 +104,8 @@ class RunSerializer { private static final String isDryRunField = "isDryRun"; private static final String cloudAccountField = "account"; private static final String reasonField = "reason"; + private static final String dependentField = "dependent"; + private static final String changeField = "change"; Run runFromSlime(Slime slime) { return runFromSlime(slime.get()); @@ -147,7 +152,7 @@ class RunSerializer { SlimeUtils.optionalString(runObject.field(testerCertificateField)).map(X509CertificateUtils::fromPem), runObject.field(isDryRunField).valid() && runObject.field(isDryRunField).asBool(), SlimeUtils.optionalString(runObject.field(cloudAccountField)).map(CloudAccount::from), - SlimeUtils.optionalString(runObject.field(reasonField))); + reasonFrom(runObject)); } private Versions versionsFromSlime(Inspector versionsObject, RunId id) { @@ -241,7 +246,7 @@ class RunSerializer { }); runObject.setBool(isDryRunField, run.isDryRun()); run.cloudAccount().ifPresent(account -> runObject.setString(cloudAccountField, account.value())); - run.reason().ifPresent(reason -> runObject.setString(reasonField, reason)); + toSlime(run.reason(), runObject); } private void toSlime(Version platformVersion, RevisionId revsion, Cursor versionsObject) { @@ -372,4 +377,42 @@ class RunSerializer { }; } + Reason reasonFrom(Inspector object) { + return new Reason(SlimeUtils.optionalString(object.field(reasonField)), + Optional.ofNullable(jobIdFrom(object.field(dependentField))), + Optional.ofNullable(toChange(object.field(changeField)))); + } + + void toSlime(Reason reason, Cursor object) { + reason.reason().ifPresent(value -> object.setString(reasonField, value)); + reason.dependent().ifPresent(dependent -> toSlime(dependent, object.setObject(dependentField))); + reason.change().ifPresent(change -> toSlime(change, object.setObject(changeField))); + } + + JobId jobIdFrom(Inspector object) { + if ( ! object.valid()) return null; + return new JobId(ApplicationId.fromSerializedForm(object.field(applicationField).asString()), + JobType.ofSerialized(object.field(jobTypeField).asString())); + } + + void toSlime(JobId jobId, Cursor object) { + object.setString(applicationField, jobId.application().serializedForm()); + object.setString(jobTypeField, jobId.type().serialized()); + } + + Change toChange(Inspector object) { + if ( ! object.valid()) return null; + Change change = Change.empty(); + if (object.field(platformVersionField).valid()) + change = change.with(Version.fromString(object.field(platformVersionField).asString())); + if (object.field(buildField).valid()) + change = change.with(RevisionId.forProduction(object.field(buildField).asLong())); + return change; + } + + void toSlime(Change change, Cursor object) { + change.platform().ifPresent(version -> object.setString(platformVersionField, version.toString())); + change.revision().ifPresent(revision -> object.setLong(buildField, revision.number())); + } + } 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 982e81d92b1..140cc142ceb 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 @@ -125,7 +125,7 @@ class JobControllerApiHandlerHelper { Run run = jobController.run(runId); detailsObject.setBool("active", ! run.hasEnded()); detailsObject.setString("status", nameOf(run.status())); - run.reason().ifPresent(reason -> detailsObject.setString("reason", reason)); + run.reason().reason().ifPresent(reason -> detailsObject.setString("reason", reason)); try { jobController.updateTestLog(runId); jobController.updateVespaLog(runId); @@ -498,7 +498,7 @@ class JobControllerApiHandlerHelper { runObject.setLong("start", run.start().toEpochMilli()); run.end().ifPresent(end -> runObject.setLong("end", end.toEpochMilli())); runObject.setString("status", nameOf(run.status())); - run.reason().ifPresent(reason -> runObject.setString("reason", reason)); + run.reason().reason().ifPresent(reason -> runObject.setString("reason", reason)); toSlime(runObject.setObject("versions"), run.versions(), application); Cursor runStepsArray = runObject.setArray("steps"); run.steps().forEach((step, info) -> { 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 cae5037ab6f..fc1a694e0f7 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 @@ -7,12 +7,15 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.CloudAccount; import com.yahoo.security.X509CertificateUtils; import com.yahoo.slime.SlimeUtils; +import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RevisionId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId; +import com.yahoo.vespa.hosted.controller.application.Change; import com.yahoo.vespa.hosted.controller.deployment.ConvergenceSummary; import com.yahoo.vespa.hosted.controller.deployment.DeploymentContext; import com.yahoo.vespa.hosted.controller.deployment.JobProfile; import com.yahoo.vespa.hosted.controller.deployment.Run; +import com.yahoo.vespa.hosted.controller.deployment.Run.Reason; import com.yahoo.vespa.hosted.controller.deployment.RunStatus; import com.yahoo.vespa.hosted.controller.deployment.Step; import com.yahoo.vespa.hosted.controller.deployment.StepInfo; @@ -82,11 +85,15 @@ public class RunSerializerTest { assertFalse(run.hasEnded()); assertEquals(running, run.status()); assertEquals(3, run.lastTestLogEntry()); - assertEquals(new Version(1, 2, 3), run.versions().targetPlatform()); + Version version1 = new Version(1, 2, 3); + assertEquals(version1, run.versions().targetPlatform()); RevisionId revision1 = RevisionId.forDevelopment(123, id.job()); RevisionId revision2 = RevisionId.forProduction(122); assertEquals(revision1, run.versions().targetRevision()); - assertEquals("because", run.reason().get()); + assertEquals(new Reason(Optional.of("because"), + Optional.of(new JobId(id.application(), id.type())), + Optional.of(Change.of(version1).with(revision2))), + run.reason()); assertEquals(new Version(1, 2, 2), run.versions().sourcePlatform().get()); assertEquals(revision2, run.versions().sourceRevision().get()); assertEquals(Optional.of(new ConvergenceSummary(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233)), @@ -145,7 +152,8 @@ public class RunSerializerTest { assertEquals(new String(SlimeUtils.toJsonBytes(serializer.toSlime(run).get(), false), UTF_8), new String(SlimeUtils.toJsonBytes(serializer.toSlime(phoenix).get(), false), UTF_8)); - Run initial = Run.initial(id, run.versions(), run.isRedeployment(), run.start(), JobProfile.production, Optional.empty()); + Run initial = Run.initial(id, run.versions(), run.isRedeployment(), run.start(), JobProfile.production, + new Reason(Optional.empty(), Optional.empty(), Optional.empty())); assertEquals(initial, serializer.runFromSlime(serializer.toSlime(initial))); } 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 1216bcefab6..618a7e66c5e 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 @@ -54,6 +54,14 @@ "deployedDirectly": false } }, - "reason": "because" + "reason": "because", + "dependent": { + "id": "tenant:application:default", + "type": "prod.us-east-3" + }, + "change": { + "platform": "1.2.3", + "build": 122 + } } ]
\ No newline at end of file |