From 55b88522928cc77a341daed62f47e6f4ea56c227 Mon Sep 17 00:00:00 2001 From: Jon Marius Venstad Date: Mon, 21 Dec 2020 16:13:35 +0100 Subject: Find oldest platform from job history when possible --- .../hosted/controller/ApplicationController.java | 51 +++++++++++++++++----- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'controller-server') 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 c6c07bf2feb..fedb51ca5e4 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 @@ -62,7 +62,9 @@ import com.yahoo.vespa.hosted.controller.athenz.impl.AthenzFacade; import com.yahoo.vespa.hosted.controller.certificate.EndpointCertificateManager; import com.yahoo.vespa.hosted.controller.concurrent.Once; import com.yahoo.vespa.hosted.controller.deployment.DeploymentTrigger; +import com.yahoo.vespa.hosted.controller.deployment.JobStatus; import com.yahoo.vespa.hosted.controller.deployment.Run; +import com.yahoo.vespa.hosted.controller.deployment.RunStatus; import com.yahoo.vespa.hosted.controller.deployment.Versions; import com.yahoo.vespa.hosted.controller.persistence.CuratorDb; import com.yahoo.vespa.hosted.controller.security.AccessControl; @@ -75,11 +77,13 @@ import java.security.Principal; import java.time.Clock; 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.EnumSet; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -87,15 +91,20 @@ import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.Logger; import static com.yahoo.vespa.hosted.controller.api.integration.configserver.Node.State.active; import static com.yahoo.vespa.hosted.controller.api.integration.configserver.Node.State.reserved; import static java.util.Comparator.naturalOrder; +import static java.util.function.Function.identity; +import static java.util.function.Predicate.not; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toUnmodifiableMap; /** * A singleton owned by the Controller which contains the methods and state for controlling applications. @@ -256,18 +265,40 @@ public class ApplicationController { return Collections.unmodifiableMap(clusters); } + /** Reads the oldest installed platform for the given application and zone from job history, or a node repo. */ + private Optional oldestInstalledPlatform(JobStatus job) { + Version oldest = null; + for (Run run : job.runs().descendingMap().values()) { + Version version = run.versions().targetPlatform(); + if (oldest == null || version.isBefore(oldest)) + oldest = version; + + if (run.status() == RunStatus.success) + return Optional.of(oldest); + } + // If no successful run was found, ask the node repository in the relevant zone. + return oldestInstalledPlatform(job.id()); + } + + /** Reads the oldest installed platform for the given application and zone from the node repo of that zone. */ + private Optional oldestInstalledPlatform(JobId job) { + return configServer.nodeRepository().list(job.type().zone(controller.system()), + job.application(), + EnumSet.of(active, reserved)) + .stream() + .map(Node::currentVersion) + .filter(version -> ! version.isEmpty()) + .min(naturalOrder()); + } + /** Returns the oldest Vespa version installed on any active or reserved production node for the given application. */ public Version oldestInstalledPlatform(TenantAndApplicationId id) { - return requireApplication(id).instances().values().stream() - .flatMap(instance -> instance.productionDeployments().keySet().stream() - .flatMap(zone -> configServer.nodeRepository().list(zone, - id.instance(instance.name()), - EnumSet.of(active, reserved)) - .stream()) - .map(Node::currentVersion) - .filter(version -> ! version.isEmpty())) - .min(naturalOrder()) - .orElseGet(controller::readSystemVersion); + return controller.jobController().deploymentStatus(requireApplication(id)).jobs() + .production().asList().stream() + .map(this::oldestInstalledPlatform) + .flatMap(Optional::stream) + .min(naturalOrder()) + .orElse(controller.readSystemVersion()); } /** -- cgit v1.2.3