diff options
Diffstat (limited to 'config-model-api')
6 files changed, 95 insertions, 20 deletions
diff --git a/config-model-api/abi-spec.json b/config-model-api/abi-spec.json index 5561c400745..49290618692 100644 --- a/config-model-api/abi-spec.json +++ b/config-model-api/abi-spec.json @@ -193,9 +193,10 @@ "public" ], "methods": [ - "public void <init>(com.yahoo.config.provision.InstanceName, java.util.List, com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy, java.util.List, java.util.Optional, java.util.Optional, com.yahoo.config.application.api.Notifications, java.util.List)", + "public void <init>(com.yahoo.config.provision.InstanceName, java.util.List, com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy, com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout, java.util.List, java.util.Optional, java.util.Optional, com.yahoo.config.application.api.Notifications, java.util.List)", "public com.yahoo.config.provision.InstanceName name()", "public com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy upgradePolicy()", + "public com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout upgradeRollout()", "public java.util.List changeBlocker()", "public java.util.Optional globalServiceId()", "public boolean canUpgradeAt(java.time.Instant)", @@ -350,6 +351,23 @@ "public static final enum com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy conservative" ] }, + "com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout": { + "superClass": "java.lang.Enum", + "interfaces": [], + "attributes": [ + "public", + "final", + "enum" + ], + "methods": [ + "public static com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout[] values()", + "public static com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout valueOf(java.lang.String)" + ], + "fields": [ + "public static final enum com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout separate", + "public static final enum com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout leading" + ] + }, "com.yahoo.config.application.api.DeploymentSpec": { "superClass": "java.lang.Object", "interfaces": [], diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java index 8813eaf9c8c..cd051ecda7b 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java @@ -27,6 +27,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { private final InstanceName name; private final DeploymentSpec.UpgradePolicy upgradePolicy; + private final DeploymentSpec.UpgradeRollout upgradeRollout; private final List<DeploymentSpec.ChangeBlocker> changeBlockers; private final Optional<String> globalServiceId; private final Optional<AthenzService> athenzService; @@ -36,6 +37,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { public DeploymentInstanceSpec(InstanceName name, List<DeploymentSpec.Step> steps, DeploymentSpec.UpgradePolicy upgradePolicy, + DeploymentSpec.UpgradeRollout upgradeRollout, List<DeploymentSpec.ChangeBlocker> changeBlockers, Optional<String> globalServiceId, Optional<AthenzService> athenzService, @@ -44,6 +46,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { super(steps); this.name = name; this.upgradePolicy = upgradePolicy; + this.upgradeRollout = upgradeRollout; this.changeBlockers = changeBlockers; this.globalServiceId = globalServiceId; this.athenzService = athenzService; @@ -136,6 +139,9 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { /** Returns the upgrade policy of this, which is defaultPolicy if none is specified */ public DeploymentSpec.UpgradePolicy upgradePolicy() { return upgradePolicy; } + /** Returns the upgrade rollout strategy of this, which is separate if none is specified */ + public DeploymentSpec.UpgradeRollout upgradeRollout() { return upgradeRollout; } + /** Returns time windows where upgrades are disallowed for these instances */ public List<DeploymentSpec.ChangeBlocker> changeBlocker() { return changeBlockers; } @@ -181,6 +187,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { DeploymentInstanceSpec other = (DeploymentInstanceSpec) o; return globalServiceId.equals(other.globalServiceId) && upgradePolicy == other.upgradePolicy && + upgradeRollout == other.upgradeRollout && changeBlockers.equals(other.changeBlockers) && steps().equals(other.steps()) && athenzService.equals(other.athenzService) && @@ -190,7 +197,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { @Override public int hashCode() { - return Objects.hash(globalServiceId, upgradePolicy, changeBlockers, steps(), athenzService, notifications, endpoints); + return Objects.hash(globalServiceId, upgradePolicy, upgradeRollout, changeBlockers, steps(), athenzService, notifications, endpoints); } @Override diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java index 24d83e2b7b1..7305f794965 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java @@ -510,6 +510,18 @@ public class DeploymentSpec { conservative } + + /** Determines when application changes deploy, when there is already an ongoing platform upgrade. */ + public enum UpgradeRollout { + /** Separate: Application changes wait for upgrade to complete, unless upgrade fails. */ + separate, + /** Leading: Application changes are allowed to start and catch up to the platform upgrade. */ + leading + // /** Simultaneous: Application changes deploy independently of platform upgrades. */ + // simultaneous + } + + /** A blocking of changes in a given time window */ public static class ChangeBlocker { diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java b/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java index 4bd819b3b6a..88c366e5d96 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java @@ -149,6 +149,7 @@ public class DeploymentSpecXmlReader { // Values where the parent may provide a default DeploymentSpec.UpgradePolicy upgradePolicy = readUpgradePolicy(instanceTag, parentTag); + DeploymentSpec.UpgradeRollout upgradeRollout = readUpgradeRollout(instanceTag, parentTag); List<DeploymentSpec.ChangeBlocker> changeBlockers = readChangeBlockers(instanceTag, parentTag); Optional<AthenzService> athenzService = mostSpecificAttribute(instanceTag, athenzServiceAttribute).map(AthenzService::from); Notifications notifications = readNotifications(instanceTag, parentTag); @@ -165,6 +166,7 @@ public class DeploymentSpecXmlReader { .map(name -> new DeploymentInstanceSpec(InstanceName.from(name), steps, upgradePolicy, + upgradeRollout, changeBlockers, globalServiceId.asOptional(), athenzService, @@ -397,13 +399,13 @@ public class DeploymentSpecXmlReader { } private DeploymentSpec.UpgradePolicy readUpgradePolicy(Element parent, Element fallbackParent) { + String policy; Element upgradeElement = XML.getChild(parent, upgradeTag); if (upgradeElement == null) upgradeElement = XML.getChild(fallbackParent, upgradeTag); - if (upgradeElement == null) + if (upgradeElement == null || (policy = upgradeElement.getAttribute("policy")).isEmpty()) return DeploymentSpec.UpgradePolicy.defaultPolicy; - String policy = upgradeElement.getAttribute("policy"); switch (policy) { case "canary": return DeploymentSpec.UpgradePolicy.canary; case "default": return DeploymentSpec.UpgradePolicy.defaultPolicy; @@ -413,6 +415,23 @@ public class DeploymentSpecXmlReader { } } + private DeploymentSpec.UpgradeRollout readUpgradeRollout(Element parent, Element fallbackParent) { + String rollout; + Element upgradeElement = XML.getChild(parent, upgradeTag); + if (upgradeElement == null) + upgradeElement = XML.getChild(fallbackParent, upgradeTag); + if (upgradeElement == null || (rollout = upgradeElement.getAttribute("rollout")).isEmpty()) + return DeploymentSpec.UpgradeRollout.separate; + + switch (rollout) { + case "separate": return DeploymentSpec.UpgradeRollout.separate; + case "leading": return DeploymentSpec.UpgradeRollout.leading; + // case "simultaneous": return DeploymentSpec.UpgradePolicy.conservative; + default: throw new IllegalArgumentException("Illegal upgrade policy '" + rollout + "': " + + "Must be one of " + Arrays.toString(DeploymentSpec.UpgradePolicy.values())); + } + } + private boolean readActive(Element regionTag) { String activeValue = regionTag.getAttribute("active"); if ("true".equals(activeValue)) return true; diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java index 5561ebdef63..c5f07444ead 100644 --- a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java +++ b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java @@ -118,6 +118,7 @@ public class DeploymentSpecTest { assertFalse(spec.requireInstance("default").globalServiceId().isPresent()); assertEquals(DeploymentSpec.UpgradePolicy.defaultPolicy, spec.requireInstance("default").upgradePolicy()); + assertEquals(DeploymentSpec.UpgradeRollout.separate, spec.requireInstance("default").upgradeRollout()); } @Test @@ -360,33 +361,43 @@ public class DeploymentSpecTest { } @Test + public void productionSpecWithUpgradeRollout() { + StringReader r = new StringReader( + "<deployment>" + + " <instance id='default'>" + + " <upgrade rollout='leading' />" + + " </instance>" + + " <instance id='custom'/>" + + "</deployment>" + ); + DeploymentSpec spec = DeploymentSpec.fromXml(r); + assertEquals("leading", spec.requireInstance("default").upgradeRollout().toString()); + assertEquals("separate", spec.requireInstance("custom").upgradeRollout().toString()); + } + + @Test public void productionSpecWithUpgradePolicy() { StringReader r = new StringReader( "<deployment>" + " <instance id='default'>" + " <upgrade policy='canary'/>" + - " <prod>" + - " <region active='true'>us-west-1</region>" + - " <region active='true'>us-central-1</region>" + - " <region active='true'>us-east-3</region>" + - " </prod>" + " </instance>" + + " <instance id='custom'/>" + "</deployment>" ); - DeploymentSpec spec = DeploymentSpec.fromXml(r); assertEquals("canary", spec.requireInstance("default").upgradePolicy().toString()); + assertEquals("defaultPolicy", spec.requireInstance("custom").upgradePolicy().toString()); } @Test public void upgradePolicyDefault() { StringReader r = new StringReader( "<deployment version='1.0'>" + - " <upgrade policy='canary'/>" + - " <instance id='instance1'>" + - " </instance>" + + " <upgrade policy='canary' rollout='leading'/>" + + " <instance id='instance1'/>" + " <instance id='instance2'>" + - " <upgrade policy='conservative'/>" + + " <upgrade policy='conservative' rollout='separate'/>" + " </instance>" + "</deployment>" ); @@ -394,6 +405,8 @@ public class DeploymentSpecTest { DeploymentSpec spec = DeploymentSpec.fromXml(r); assertEquals("canary", spec.requireInstance("instance1").upgradePolicy().toString()); assertEquals("conservative", spec.requireInstance("instance2").upgradePolicy().toString()); + assertEquals("leading", spec.requireInstance("instance1").upgradeRollout().toString()); + assertEquals("separate", spec.requireInstance("instance2").upgradeRollout().toString()); } @Test diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java index 77ce5c2175d..c71ae92b47a 100644 --- a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java +++ b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java @@ -111,6 +111,7 @@ public class DeploymentSpecWithoutInstanceTest { assertFalse(spec.requireInstance("default").globalServiceId().isPresent()); assertEquals(DeploymentSpec.UpgradePolicy.defaultPolicy, spec.requireInstance("default").upgradePolicy()); + assertEquals(DeploymentSpec.UpgradeRollout.separate, spec.requireInstance("default").upgradeRollout()); } @Test @@ -277,18 +278,23 @@ public class DeploymentSpecWithoutInstanceTest { } @Test + public void productionSpecWithUpgradeRollout() { + StringReader r = new StringReader( + "<deployment>" + + " <upgrade rollout='leading'/>" + + "</deployment>" + ); + DeploymentSpec spec = DeploymentSpec.fromXml(r); + assertEquals("leading", spec.requireInstance("default").upgradeRollout().toString()); + } + + @Test public void productionSpecWithUpgradePolicy() { StringReader r = new StringReader( "<deployment>" + " <upgrade policy='canary'/>" + - " <prod>" + - " <region active='true'>us-west-1</region>" + - " <region active='true'>us-central-1</region>" + - " <region active='true'>us-east-3</region>" + - " </prod>" + "</deployment>" ); - DeploymentSpec spec = DeploymentSpec.fromXml(r); assertEquals("canary", spec.requireInstance("default").upgradePolicy().toString()); } |