diff options
author | Martin Polden <mpolden@mpolden.no> | 2022-01-10 14:02:40 +0100 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2022-01-10 14:02:40 +0100 |
commit | 82a734fc6bea66959852bcf3471f228a60a68607 (patch) | |
tree | 22c0720af5cfa045dcba050303e2c51b9e74eba6 /controller-server | |
parent | c0c25b25dc02315e3d5bc09a720db8f02e42e2b2 (diff) |
Track latest OS release in CD system
Diffstat (limited to 'controller-server')
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) { |