aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorJon Marius Venstad <venstad@gmail.com>2019-11-08 21:24:01 +0100
committerJon Marius Venstad <venstad@gmail.com>2019-11-11 08:28:01 +0100
commit357e91af802db4697436cb22a9ff525476ba7d79 (patch)
tree4a399c8bc3f2b8624cf13a94480f42964da7ba94 /controller-server
parentaed640a862cb30fc3e3a4c224b9121dbd88684bf (diff)
Replace more JobStatus usages
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java20
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java32
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatusList.java82
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java9
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java20
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java76
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java2
11 files changed, 179 insertions, 75 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
index d28df826957..21a1b3c1eda 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
@@ -2,7 +2,6 @@
package com.yahoo.vespa.hosted.controller;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentInstanceSpec;
import com.yahoo.config.application.api.DeploymentSpec;
@@ -57,13 +56,13 @@ import com.yahoo.vespa.hosted.controller.application.Endpoint;
import com.yahoo.vespa.hosted.controller.application.EndpointId;
import com.yahoo.vespa.hosted.controller.application.JobList;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
-import com.yahoo.vespa.hosted.controller.application.JobStatus.JobRun;
import com.yahoo.vespa.hosted.controller.application.SystemApplication;
import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId;
import com.yahoo.vespa.hosted.controller.athenz.impl.AthenzFacade;
import com.yahoo.vespa.hosted.controller.concurrent.Once;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentTrigger;
import com.yahoo.vespa.hosted.controller.deployment.Run;
+import com.yahoo.vespa.hosted.controller.deployment.Versions;
import com.yahoo.vespa.hosted.controller.dns.NameServiceQueue.Priority;
import com.yahoo.vespa.hosted.controller.maintenance.RoutingPolicies;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
@@ -75,7 +74,6 @@ import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant;
import com.yahoo.vespa.hosted.controller.tenant.Tenant;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
import com.yahoo.vespa.hosted.rotation.config.RotationsConfig;
-import com.yahoo.yolean.Exceptions;
import java.net.URI;
import java.security.Principal;
@@ -379,16 +377,14 @@ public class ApplicationController {
else {
JobType jobType = JobType.from(controller.system(), zone)
.orElseThrow(() -> new IllegalArgumentException("No job is known for " + zone + "."));
- Optional<JobStatus> job = Optional.ofNullable(application.get().require(instance).deploymentJobs().jobStatus().get(jobType));
- if ( job.isEmpty()
- || job.get().lastTriggered().isEmpty()
- || job.get().lastCompleted().isPresent() && job.get().lastCompleted().get().at().isAfter(job.get().lastTriggered().get().at()))
+ var run = controller.jobController().last(instanceId, jobType);
+ if (run.map(Run::hasEnded).orElse(true))
return unexpectedDeployment(instanceId, zone);
- JobRun triggered = job.get().lastTriggered().get();
- platformVersion = preferOldestVersion ? triggered.sourcePlatform().orElse(triggered.platform())
- : triggered.platform();
- applicationVersion = preferOldestVersion ? triggered.sourceApplication().orElse(triggered.application())
- : triggered.application();
+ Versions versions = run.get().versions();
+ platformVersion = preferOldestVersion ? versions.sourcePlatform().orElse(versions.targetPlatform())
+ : versions.targetPlatform();
+ applicationVersion = preferOldestVersion ? versions.sourceApplication().orElse(versions.targetApplication())
+ : versions.targetApplication();
applicationPackage = getApplicationPackage(instanceId, applicationVersion);
applicationPackage = withTesterCertificate(applicationPackage, instanceId, jobType);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java
index 3fe8e9f52c3..99f5572ad60 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java
@@ -92,7 +92,7 @@ public class ApplicationList extends AbstractFilteringList<Application, Applicat
/** Returns the subset of applications which currently have failing jobs */
public ApplicationList failing() {
return matching(application -> application.instances().values().stream()
- .anyMatch(instance -> instance.deploymentJobs().hasFailures()));
+ .anyMatch(instance -> instance.deploymentJobs().hasFailures()));
}
/** Returns the subset of applications which have been failing an upgrade to the given version since the given instant */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
index 1582bc144f4..092677255f2 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
@@ -1,5 +1,6 @@
package com.yahoo.vespa.hosted.controller.deployment;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobId;
@@ -9,6 +10,10 @@ import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.toUnmodifiableList;
+
/**
* Status of the deployment jobs of an {@link Application}.
*
@@ -17,33 +22,38 @@ import java.util.stream.Collectors;
public class DeploymentStatus {
private final Application application;
- private final Map<JobId, JobStatus> jobs;
+ private final JobList jobs;
public DeploymentStatus(Application application, Map<JobId, JobStatus> jobs) {
this.application = Objects.requireNonNull(application);
- this.jobs = Map.copyOf(jobs);
+ this.jobs = JobList.from(jobs.values());
}
public Application application() {
return application;
}
- public Map<JobId, JobStatus> jobs() {
+ public JobList jobs() {
return jobs;
}
public boolean hasFailures() {
- return ! JobList.from(jobs.values())
- .failing()
- .not().withStatus(RunStatus.outOfCapacity)
- .isEmpty();
+ return ! jobs.failing()
+ .not().withStatus(RunStatus.outOfCapacity)
+ .isEmpty();
}
public Map<JobType, JobStatus> instanceJobs(InstanceName instance) {
- return jobs.entrySet().stream()
- .filter(entry -> entry.getKey().application().equals(application.id().instance(instance)))
- .collect(Collectors.toUnmodifiableMap(entry -> entry.getKey().type(),
- entry -> entry.getValue()));
+ return jobs.asList().stream()
+ .filter(job -> job.id().application().equals(application.id().instance(instance)))
+ .collect(Collectors.toUnmodifiableMap(job -> job.id().type(),
+ job -> job));
+ }
+
+ public Map<ApplicationId, JobList> instanceJobs() {
+ return jobs.asList().stream()
+ .collect(groupingBy(job -> job.id().application(),
+ collectingAndThen(toUnmodifiableList(), JobList::from)));
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatusList.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatusList.java
new file mode 100644
index 00000000000..779beab60d1
--- /dev/null
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatusList.java
@@ -0,0 +1,82 @@
+package com.yahoo.vespa.hosted.controller.deployment;
+
+import com.yahoo.collections.AbstractFilteringList;
+import com.yahoo.component.Version;
+import com.yahoo.vespa.hosted.controller.Instance;
+import com.yahoo.vespa.hosted.controller.application.ApplicationList;
+
+import java.time.Instant;
+import java.util.Collection;
+
+/**
+ * List for filtering deployment status of applications, for inspection and decision making.
+ *
+ * @author jonmv
+ */
+public class DeploymentStatusList extends AbstractFilteringList<DeploymentStatus, DeploymentStatusList> {
+
+ private DeploymentStatusList(Collection<? extends DeploymentStatus> items, boolean negate) {
+ super(items, negate, DeploymentStatusList::new);
+ }
+
+ public static DeploymentStatusList from(Collection<? extends DeploymentStatus> status) {
+ return new DeploymentStatusList(status, false);
+ }
+
+ public ApplicationList asApplicationList() {
+ return ApplicationList.from(mapToList(DeploymentStatus::application));
+ }
+
+ public DeploymentStatusList failing() {
+ return matching(DeploymentStatus::hasFailures);
+ }
+
+ public DeploymentStatusList failingUpgrade() {
+ return matching(status -> status.instanceJobs().values().stream()
+ .anyMatch(jobs -> ! jobs.failing().not().failingApplicationChange().isEmpty()));
+ }
+
+ /** Returns the subset of applications which have been failing an upgrade to the given version since the given instant */
+ public DeploymentStatusList failingUpgradeToVersionSince(Version version, Instant threshold) {
+ return matching(status -> status.instanceJobs().values().stream()
+ .anyMatch(jobs -> failingUpgradeToVersionSince(jobs, version, threshold)));
+ }
+
+ /** Returns the subset of applications which have been failing an application change since the given instant */
+ public DeploymentStatusList failingApplicationChangeSince(Instant threshold) {
+ return matching(status -> status.instanceJobs().values().stream()
+ .anyMatch(jobs -> failingApplicationChangeSince(jobs, threshold)));
+ }
+
+ /** Returns the subset of applications which currently have failing jobs on the given version */
+ public DeploymentStatusList failingOn(Version version) {
+ return matching(status -> status.instanceJobs().values().stream()
+ .anyMatch(jobs -> failingOn(jobs, version)));
+ }
+
+ /** Returns the subset of applications which started failing on the given version */
+ public DeploymentStatusList startedFailingOn(Version version) {
+ return matching(status -> status.instanceJobs().values().stream()
+ .anyMatch(jobs -> ! jobs.firstFailing().on(version).isEmpty()));
+ }
+
+ private static boolean failingOn(JobList jobs, Version version) {
+ return ! jobs.failing()
+ .lastCompleted().on(version)
+ .isEmpty();
+ }
+
+ private static boolean failingUpgradeToVersionSince(JobList jobs, Version version, Instant threshold) {
+ return ! jobs.not().failingApplicationChange()
+ .firstFailing().endedBefore(threshold)
+ .lastCompleted().on(version)
+ .isEmpty();
+ }
+
+ private static boolean failingApplicationChangeSince(JobList jobs, Instant threshold) {
+ return jobs.failingApplicationChange()
+ .firstFailing().endedBefore(threshold)
+ .isEmpty();
+ }
+
+}
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 e7d70793898..90d4b231ec6 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
@@ -478,8 +478,7 @@ public class DeploymentTrigger {
if ( ! application.deploymentSpec().instances().stream()
.allMatch(instance -> instance.canChangeRevisionAt(clock.instant()))) return false;
if (application.change().application().isPresent()) return true; // Replacing a previous application change is ok.
- for (Instance instance : application.instances().values())
- if (instance.deploymentJobs().hasFailures()) return true; // Allow changes to fix upgrade problems.
+ if (jobs.deploymentStatus(application).hasFailures()) return true; // Allow changes to fix upgrade problems.
return application.change().platform().isEmpty();
}
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 e6c59b464a6..84fc7da3fec 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
@@ -20,6 +20,7 @@ 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.ApplicationList;
import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId;
@@ -32,6 +33,7 @@ import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
@@ -298,6 +300,13 @@ public class JobController {
status -> status)));
}
+ /** Adds deployment status to each of the given applications. */
+ public DeploymentStatusList deploymentStatuses(ApplicationList applications) {
+ return DeploymentStatusList.from(applications.asList().stream()
+ .map(this::deploymentStatus)
+ .collect(toUnmodifiableList()));
+ }
+
/** Changes the status of the given step, for the given run, provided it is still active. */
public void update(RunId id, RunStatus status, LockedStep step) {
locked(id, run -> run.with(status, step));
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java
index 56a6bec5777..f771e9314eb 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java
@@ -9,9 +9,11 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
/**
* A list of deployment jobs that can be filtered in various ways.
@@ -41,7 +43,7 @@ public class JobList extends AbstractFilteringList<JobStatus, JobList> {
/** Returns the subset of jobs which are currently failing */
public JobList failing() {
- return matching(job -> ! job.isSuccess());
+ return matching(job -> job.lastCompleted().isPresent() && ! job.isSuccess());
}
public JobList running() {
@@ -105,7 +107,6 @@ public class JobList extends AbstractFilteringList<JobStatus, JobList> {
return new RunFilter(JobStatus::firstFailing);
}
-
/** Allows sub-filters for runs of the given kind */
public class RunFilter {
@@ -120,6 +121,21 @@ public class JobList extends AbstractFilteringList<JobStatus, JobList> {
return matching(run -> true);
}
+ /** Returns the runs of the given kind, mapped by the given function, as a list. */
+ public <OtherType> List<OtherType> mapToList(Function<? super Run, OtherType> mapper) {
+ return present().mapToList(which.andThen(Optional::get).andThen(mapper));
+ }
+
+ /** Returns the subset of jobs where the run of the given type occurred before the given instant */
+ public JobList endedBefore(Instant threshold) {
+ return matching(run -> run.end().orElse(Instant.MAX).isBefore(threshold));
+ }
+
+ /** Returns the subset of jobs where the run of the given type occurred after the given instant */
+ public JobList endedAfter(Instant threshold) {
+ return matching(run -> run.end().orElse(Instant.MIN).isAfter(threshold));
+ }
+
/** Returns the subset of jobs where the run of the given type occurred before the given instant */
public JobList startedBefore(Instant threshold) {
return matching(run -> run.start().isBefore(threshold));
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 568366d7f2a..ccb802d314a 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
@@ -10,8 +10,8 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationV
import com.yahoo.vespa.hosted.controller.application.ApplicationList;
import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics;
-import com.yahoo.vespa.hosted.controller.application.JobList;
-import com.yahoo.vespa.hosted.controller.application.JobStatus;
+import com.yahoo.vespa.hosted.controller.deployment.DeploymentStatusList;
+import com.yahoo.vespa.hosted.controller.deployment.JobList;
import com.yahoo.vespa.hosted.controller.rotation.RotationLock;
import com.yahoo.vespa.hosted.controller.versions.NodeVersions;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
@@ -71,28 +71,25 @@ public class MetricsReporter extends Maintainer {
}
private void reportDeploymentMetrics() {
- 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());
+ ApplicationList applications = ApplicationList.from(controller().applications().asList())
+ .withProductionDeployment();
+ DeploymentStatusList deployments = controller().jobController().deploymentStatuses(applications);
- metric.set(DEPLOYMENT_FAIL_METRIC, deploymentFailRatio(instances) * 100, metric.createContext(Map.of()));
+ metric.set(DEPLOYMENT_FAIL_METRIC, deploymentFailRatio(deployments) * 100, metric.createContext(Map.of()));
- averageDeploymentDurations(instances, clock.instant()).forEach((application, duration) -> {
- metric.set(DEPLOYMENT_AVERAGE_DURATION, duration.getSeconds(), metric.createContext(dimensions(application)));
+ averageDeploymentDurations(deployments, clock.instant()).forEach((instance, duration) -> {
+ metric.set(DEPLOYMENT_AVERAGE_DURATION, duration.getSeconds(), metric.createContext(dimensions(instance)));
});
- deploymentsFailingUpgrade(instances).forEach((application, failingJobs) -> {
- metric.set(DEPLOYMENT_FAILING_UPGRADES, failingJobs, metric.createContext(dimensions(application)));
+ deploymentsFailingUpgrade(deployments).forEach((instance, failingJobs) -> {
+ metric.set(DEPLOYMENT_FAILING_UPGRADES, failingJobs, metric.createContext(dimensions(instance)));
});
- deploymentWarnings(instances).forEach((application, warnings) -> {
+ deploymentWarnings(deployments).forEach((application, warnings) -> {
metric.set(DEPLOYMENT_WARNINGS, warnings, metric.createContext(dimensions(application)));
});
- for (Application application : applications)
+ for (Application application : applications.asList())
application.latestVersion()
.flatMap(ApplicationVersion::buildTime)
.ifPresent(buildTime -> metric.set(DEPLOYMENT_BUILD_AGE_SECONDS,
@@ -142,47 +139,42 @@ public class MetricsReporter extends Maintainer {
return nodesFailingUpgrade;
}
- private static double deploymentFailRatio(List<Instance> instances) {
- return instances.stream()
- .mapToInt(instance -> instance.deploymentJobs().hasFailures() ? 1 : 0)
- .average().orElse(0);
+ private static double deploymentFailRatio(DeploymentStatusList statuses) {
+ return statuses.asList().stream()
+ .mapToInt(status -> status.hasFailures() ? 1 : 0)
+ .average().orElse(0);
}
- private static Map<ApplicationId, Duration> averageDeploymentDurations(List<Instance> instances, Instant now) {
- return instances.stream()
- .collect(Collectors.toMap(Instance::id,
- instance -> averageDeploymentDuration(instance, now)));
+ private static Map<ApplicationId, Duration> averageDeploymentDurations(DeploymentStatusList statuses, Instant now) {
+ return statuses.asList().stream()
+ .flatMap(status -> status.instanceJobs().entrySet().stream())
+ .collect(Collectors.toUnmodifiableMap(entry -> entry.getKey(),
+ entry -> averageDeploymentDuration(entry.getValue(), now)));
}
- private static Map<ApplicationId, Integer> deploymentsFailingUpgrade(List<Instance> instances) {
- return instances.stream()
- .collect(Collectors.toMap(Instance::id, MetricsReporter::deploymentsFailingUpgrade));
+ private static Map<ApplicationId, Integer> deploymentsFailingUpgrade(DeploymentStatusList statuses) {
+ return statuses.asList().stream()
+ .flatMap(status -> status.instanceJobs().entrySet().stream())
+ .collect(Collectors.toUnmodifiableMap(entry -> entry.getKey(),
+ entry -> deploymentsFailingUpgrade(entry.getValue())));
}
- private static int deploymentsFailingUpgrade(Instance instance) {
- return JobList.from(instance).upgrading().failing().size();
+ private static int deploymentsFailingUpgrade(JobList jobs) {
+ return jobs.failing().not().failingApplicationChange().size();
}
- private static Duration averageDeploymentDuration(Instance instance, Instant now) {
- List<Duration> jobDurations = instance.deploymentJobs().jobStatus().values().stream()
- .filter(status -> status.lastTriggered().isPresent())
- .map(status -> {
- Instant triggeredAt = status.lastTriggered().get().at();
- Instant runningUntil = status.lastCompleted()
- .map(JobStatus.JobRun::at)
- .filter(at -> at.isAfter(triggeredAt))
- .orElse(now);
- return Duration.between(triggeredAt, runningUntil);
- })
- .collect(Collectors.toList());
+ private static Duration averageDeploymentDuration(JobList jobs, Instant now) {
+ List<Duration> jobDurations = jobs.lastTriggered()
+ .mapToList(run -> Duration.between(run.start(), run.end().orElse(now)));
return jobDurations.stream()
.reduce(Duration::plus)
.map(totalDuration -> totalDuration.dividedBy(jobDurations.size()))
.orElse(Duration.ZERO);
}
- private static Map<ApplicationId, Integer> deploymentWarnings(List<Instance> instances) {
- return instances.stream()
+ private static Map<ApplicationId, Integer> deploymentWarnings(DeploymentStatusList statuses) {
+ return statuses.asList().stream()
+ .flatMap(status -> status.application().instances().values().stream())
.collect(Collectors.toMap(Instance::id, a -> maxWarningCountOf(a.deployments().values())));
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
index d181ab8d38f..6016eed4704 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
@@ -337,7 +337,7 @@ public class DeploymentContext {
}
/** Simulate convergence time out in given job */
- public void timeOutConvergence(JobType type) {
+ public DeploymentContext timeOutConvergence(JobType type) {
var job = jobId(type);
triggerJobs();
RunId id = currentRun(job).id();
@@ -348,6 +348,7 @@ public class DeploymentContext {
assertTrue(jobs.run(id).get().hasFailed());
assertTrue(jobs.run(id).get().hasEnded());
doTeardown(job);
+ return this;
}
/** Sets a single endpoint in the routing layer for the instance in this */
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java
index 7c87cbf3610..a949625baf4 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java
@@ -86,6 +86,7 @@ public class MetricsReporterTest {
// App spends 3 hours deploying
context.submit(applicationPackage);
+ tester.triggerJobs();
tester.clock().advance(Duration.ofHours(1));
context.runJob(systemTest);
@@ -144,8 +145,7 @@ public class MetricsReporterTest {
Version version = Version.fromString("7.1");
tester.controllerTester().upgradeSystem(version);
tester.upgrader().maintain();
- context.triggerJobs()
- .failDeployment(systemTest)
+ context.failDeployment(systemTest)
.failDeployment(stagingTest);
reporter.maintain();
assertEquals(2, getDeploymentsFailingUpgrade(context.instanceId()));
@@ -153,7 +153,6 @@ public class MetricsReporterTest {
// Test and staging pass and upgrade fails in production
context.runJob(systemTest)
.runJob(stagingTest)
- .triggerJobs()
.failDeployment(productionUsWest1);
reporter.maintain();
assertEquals(1, getDeploymentsFailingUpgrade(context.instanceId()));
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 b5b7c1d0ad0..27305f8956f 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
@@ -305,7 +305,6 @@ public class ApplicationApiTest extends ControllerContainerTest {
.userIdentity(HOSTED_VESPA_OPERATOR),
new File("deploy-result.json"));
- // POST (create) another application
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
.instances("instance1")
.globalServiceId("foo")
@@ -315,6 +314,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
.allow(ValidationId.globalEndpointChange)
.build();
+ // POST (create) another application
tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/default", POST)
.userIdentity(USER_ID)
.oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),