aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2022-01-10 14:02:40 +0100
committerMartin Polden <mpolden@mpolden.no>2022-01-10 14:02:40 +0100
commit82a734fc6bea66959852bcf3471f228a60a68607 (patch)
tree22c0720af5cfa045dcba050303e2c51b9e74eba6 /controller-server
parentc0c25b25dc02315e3d5bc09a720db8f02e42e2b2 (diff)
Track latest OS release in CD system
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java31
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ArtifactRepositoryMock.java20
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java69
3 files changed, 69 insertions, 51 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java
index b2d3e1b780f..aa087f58059 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java
@@ -6,7 +6,7 @@ import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ArtifactRepository;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.StableOsVersion;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.OsRelease;
import com.yahoo.vespa.hosted.controller.versions.OsVersionTarget;
import java.time.Duration;
@@ -67,10 +67,10 @@ public class OsUpgradeScheduler extends ControllerMaintainer {
}
private Release releaseIn(CloudName cloud) {
- boolean useStableRelease = controller().zoneRegistry().zones().reprovisionToUpgradeOs().ofCloud(cloud)
+ boolean useTaggedRelease = controller().zoneRegistry().zones().reprovisionToUpgradeOs().ofCloud(cloud)
.zones().isEmpty();
- if (useStableRelease) {
- return new StableRelease(controller().system(), controller().serviceRegistry().artifactRepository());
+ if (useTaggedRelease) {
+ return new TaggedRelease(controller().system(), controller().serviceRegistry().artifactRepository());
}
return new CalendarVersionedRelease(controller().system());
}
@@ -85,32 +85,37 @@ public class OsUpgradeScheduler extends ControllerMaintainer {
}
- /** OS release based on a stable tag */
- private static class StableRelease implements Release {
+ /** OS release based on a tag */
+ private static class TaggedRelease implements Release {
private final SystemName system;
private final ArtifactRepository artifactRepository;
- private StableRelease(SystemName system, ArtifactRepository artifactRepository) {
+ private TaggedRelease(SystemName system, ArtifactRepository artifactRepository) {
this.system = Objects.requireNonNull(system);
this.artifactRepository = Objects.requireNonNull(artifactRepository);
}
@Override
public Version version(OsVersionTarget currentTarget, Instant now) {
- StableOsVersion stableVersion = artifactRepository.stableOsVersion(currentTarget.osVersion().version().getMajor());
- boolean cooldownPassed = stableVersion.promotedAt().isBefore(now.minus(cooldown()));
- return cooldownPassed ? stableVersion.version() : currentTarget.osVersion().version();
+ OsRelease release = artifactRepository.osRelease(currentTarget.osVersion().version().getMajor(), tag());
+ boolean cooldownPassed = !release.taggedAt().plus(cooldown()).isAfter(now);
+ return cooldownPassed ? release.version() : currentTarget.osVersion().version();
}
@Override
public Duration upgradeBudget() {
- return Duration.ZERO; // Stable releases happen in-place so no budget is required
+ return Duration.ZERO; // Upgrades to tagged releases happen in-place so no budget is required
}
- /** The cool-down period that must pass before a stable version can be used */
+ /** Returns the release tag tracked by this system */
+ private OsRelease.Tag tag() {
+ return system.isCd() ? OsRelease.Tag.latest : OsRelease.Tag.stable;
+ }
+
+ /** The cool-down period that must pass before a release can be used */
private Duration cooldown() {
- return system.isCd() ? Duration.ZERO : Duration.ofDays(7);
+ return system.isCd() ? Duration.ofDays(1) : Duration.ZERO;
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ArtifactRepositoryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ArtifactRepositoryMock.java
index aa4cabb4fe8..dc7010312a2 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ArtifactRepositoryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ArtifactRepositoryMock.java
@@ -6,7 +6,7 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ArtifactRepository;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.StableOsVersion;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.OsRelease;
import java.util.HashMap;
import java.util.Map;
@@ -16,7 +16,7 @@ import java.util.Map;
*/
public class ArtifactRepositoryMock extends AbstractComponent implements ArtifactRepository {
- private final Map<Integer, StableOsVersion> stableOsVersions = new HashMap<>();
+ private final Map<String, OsRelease> releases = new HashMap<>();
@Override
public byte[] getSystemApplicationPackage(ApplicationId application, ZoneId zone, Version version) {
@@ -24,14 +24,18 @@ public class ArtifactRepositoryMock extends AbstractComponent implements Artifac
}
@Override
- public StableOsVersion stableOsVersion(int major) {
- StableOsVersion version = stableOsVersions.get(major);
- if (version == null) throw new IllegalArgumentException("No version set for major " + major);
- return version;
+ public OsRelease osRelease(int major, OsRelease.Tag tag) {
+ OsRelease release = releases.get(key(major, tag));
+ if (release == null) throw new IllegalArgumentException("No version set for major " + major + " with tag " + tag);
+ return release;
}
- public void promoteOsVersion(StableOsVersion stableOsVersion) {
- stableOsVersions.put(stableOsVersion.version().getMajor(), stableOsVersion);
+ public void addRelease(OsRelease osRelease) {
+ releases.put(key(osRelease.version().getMajor(), osRelease.tag()), osRelease);
+ }
+
+ private static String key(int major, OsRelease.Tag tag) {
+ return major + "@" + tag.name();
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java
index 51bda73025d..300aa86b5ea 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeSchedulerTest.java
@@ -3,9 +3,10 @@ package com.yahoo.vespa.hosted.controller.maintenance;
import com.yahoo.component.Version;
import com.yahoo.config.provision.CloudName;
+import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.vespa.hosted.controller.ControllerTester;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.StableOsVersion;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.OsRelease;
import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock;
import com.yahoo.vespa.hosted.controller.versions.OsVersionTarget;
import org.junit.Test;
@@ -68,7 +69,6 @@ public class OsUpgradeSchedulerTest {
@Test
public void schedule_stable_release() {
ControllerTester tester = new ControllerTester();
- OsUpgradeScheduler scheduler = new OsUpgradeScheduler(tester.controller(), Duration.ofDays(1));
Instant t0 = Instant.parse("2021-06-21T07:00:00.00Z"); // Inside trigger period
tester.clock().setInstant(t0);
@@ -77,40 +77,49 @@ public class OsUpgradeSchedulerTest {
Version version0 = Version.fromString("8.0");
tester.controller().upgradeOsIn(cloud, version0, Duration.ZERO, false);
- // New version is promoted to stable
+ // Stable release is scheduled immediately
Version version1 = Version.fromString("8.1");
- tester.serviceRegistry().artifactRepository().promoteOsVersion(new StableOsVersion(version1, tester.clock().instant()));
- scheduler.maintain();
- assertEquals("Target is unchanged as not enough time has passed", version0,
- tester.controller().osVersionTarget(cloud).get().osVersion().version());
-
- // Enough time passes since promotion of stable release
- tester.clock().advance(Duration.ofDays(7).plus(Duration.ofSeconds(1)));
- scheduler.maintain();
- OsVersionTarget target0 = tester.controller().osVersionTarget(cloud).get();
- assertEquals(version1, target0.osVersion().version());
- assertEquals("No budget when upgrading to stable release",
- Duration.ZERO, target0.upgradeBudget());
-
- // Another version is promoted, but target remains unchanged as the release hasn't aged enough
- tester.clock().advance(Duration.ofDays(1));
- Version version2 = Version.fromString("8.2");
- tester.serviceRegistry().artifactRepository().promoteOsVersion(new StableOsVersion(version2, tester.clock().instant()));
- scheduler.maintain();
- OsVersionTarget target1 = tester.controller().osVersionTarget(cloud).get();
- assertEquals("Target is unchanged as not enough time has passed", version1,
- target1.osVersion().version());
- assertEquals("Target is not re-scheduled", target0.scheduledAt(), target1.scheduledAt());
+ tester.serviceRegistry().artifactRepository().addRelease(new OsRelease(version1, OsRelease.Tag.stable,
+ tester.clock().instant()));
+ scheduleUpgradeAfter(Duration.ZERO, version1, tester);
// A newer version is triggered manually
Version version3 = Version.fromString("8.3");
tester.controller().upgradeOsIn(cloud, version3, Duration.ZERO, false);
- // Enough time passes for stable version to be promoted. Nothing happens as stable is now before the manually
- // triggered version
- tester.clock().advance(Duration.ofDays(7).plus(Duration.ofSeconds(1)));
- scheduler.maintain();
- assertEquals(version3, tester.controller().osVersionTarget(cloud).get().osVersion().version());
+ // Nothing happens in next iteration as tagged release is older than manually triggered version
+ scheduleUpgradeAfter(Duration.ofDays(7), version3, tester);
+ }
+
+ @Test
+ public void schedule_latest_release_in_cd() {
+ ControllerTester tester = new ControllerTester(SystemName.cd);
+ Instant t0 = Instant.parse("2021-06-21T07:00:00.00Z"); // Inside trigger period
+ tester.clock().setInstant(t0);
+
+ // Set initial target
+ CloudName cloud = tester.controller().clouds().iterator().next();
+ Version version0 = Version.fromString("8.0");
+ tester.controller().upgradeOsIn(cloud, version0, Duration.ZERO, false);
+
+ // Latest release is not scheduled immediately
+ Version version1 = Version.fromString("8.1");
+ tester.serviceRegistry().artifactRepository().addRelease(new OsRelease(version1, OsRelease.Tag.latest,
+ tester.clock().instant()));
+ scheduleUpgradeAfter(Duration.ZERO, version0, tester);
+
+ // Cooldown period passes and latest release is scheduled
+ scheduleUpgradeAfter(Duration.ofDays(1), version1, tester);
+ }
+
+ private void scheduleUpgradeAfter(Duration duration, Version version, ControllerTester tester) {
+ tester.clock().advance(duration);
+ new OsUpgradeScheduler(tester.controller(), Duration.ofDays(1)).maintain();
+ CloudName cloud = tester.controller().clouds().iterator().next();
+ OsVersionTarget target = tester.controller().osVersionTarget(cloud).get();
+ assertEquals(version, target.osVersion().version());
+ assertEquals("No budget when scheduling a tagged release",
+ Duration.ZERO, target.upgradeBudget());
}
private static ZoneApi zone(String id, CloudName cloud) {