aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2017-10-09 12:56:46 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2017-10-09 12:56:46 +0200
commit9585c6091fbdc7cef1a95e3d05b42e155ab1c2c3 (patch)
tree7d9822057eb839d5820c1fda35f05158e22ffd31
parent6cbdad174146cb1c1c847bec218790a8595f1dbf (diff)
block-upgrade -> block-change to support blocking revisions
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java72
-rw-r--r--config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java42
-rw-r--r--config-model/src/main/resources/schema/deployment.rnc9
-rw-r--r--config-model/src/test/schema-test-files/deployment.xml4
4 files changed, 102 insertions, 25 deletions
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 e75ba5871f7..b2a908077e5 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
@@ -48,28 +48,28 @@ public class DeploymentSpec {
private final Optional<String> globalServiceId;
private final UpgradePolicy upgradePolicy;
- private final List<TimeWindow> blockUpgrades;
+ private final List<ChangeBlocker> changeBlockers;
private final List<Step> steps;
private final String xmlForm;
public DeploymentSpec(Optional<String> globalServiceId, UpgradePolicy upgradePolicy,
- List<TimeWindow> blockUpgrades, List<Step> steps) {
- this(globalServiceId, upgradePolicy, blockUpgrades, steps, null);
+ List<ChangeBlocker> changeBlockers, List<Step> steps) {
+ this(globalServiceId, upgradePolicy, changeBlockers, steps, null);
}
private DeploymentSpec(Optional<String> globalServiceId, UpgradePolicy upgradePolicy,
- List<TimeWindow> blockUpgrades, List<Step> steps, String xmlForm) {
+ List<ChangeBlocker> changeBlockers, List<Step> steps, String xmlForm) {
validateTotalDelay(steps);
this.globalServiceId = globalServiceId;
this.upgradePolicy = upgradePolicy;
- this.blockUpgrades = blockUpgrades;
+ this.changeBlockers = changeBlockers;
this.steps = ImmutableList.copyOf(completeSteps(new ArrayList<>(steps)));
this.xmlForm = xmlForm;
validateZones(this.steps);
}
/** Throw an IllegalArgumentException if the total delay exceeds 24 hours */
- private static void validateTotalDelay(List<Step> steps) {
+ private void validateTotalDelay(List<Step> steps) {
long totalDelaySeconds = steps.stream().filter(step -> step instanceof Delay)
.mapToLong(delay -> ((Delay)delay).duration().getSeconds())
.sum();
@@ -123,7 +123,6 @@ public class DeploymentSpec {
/**
* Removes the first occurrence of a deployment step to the given environment and returns it.
*
- * @param environment
* @return the removed step, or null if it is not present
*/
private static DeclaredZone remove(Environment environment, List<Step> steps) {
@@ -144,11 +143,18 @@ public class DeploymentSpec {
/** Returns whether upgrade can occur at the given instant */
public boolean canUpgradeAt(Instant instant) {
- return blockUpgrades.stream().noneMatch(timeWindow -> timeWindow.includes(instant));
+ return changeBlockers.stream().filter(block -> block.blocksVersions())
+ .noneMatch(block -> block.window().includes(instant));
}
- /** Returns time windows where upgrade is disallowed */
- public List<TimeWindow> blockUpgrades() { return blockUpgrades; }
+ /** Returns whether an application revision change can occur at the given instant */
+ public boolean canChangeRevisionAt(Instant instant) {
+ return changeBlockers.stream().filter(block -> block.blocksRevisions())
+ .noneMatch(block -> block.window().includes(instant));
+ }
+
+ /** Returns time windows where upgrades are disallowed */
+ public List<ChangeBlocker> changeBlocker() { return changeBlockers; }
/** Returns the deployment steps of this in the order they will be performed */
public List<Step> steps() { return steps; }
@@ -223,8 +229,7 @@ public class DeploymentSpec {
else if (readGlobalServiceId(environmentTag).isPresent())
throw new IllegalArgumentException("Attribute 'global-service-id' is only valid on 'prod' tag.");
}
- return new DeploymentSpec(globalServiceId, readUpgradePolicy(root), readBlockUpgradeWindows(root), steps,
- xmlForm);
+ return new DeploymentSpec(globalServiceId, readUpgradePolicy(root), readChangeBlockers(root), steps, xmlForm);
}
/** Returns the given attribute as an integer, or 0 if it is not present */
@@ -259,21 +264,31 @@ public class DeploymentSpec {
}
}
- private static List<TimeWindow> readBlockUpgradeWindows(Element root) {
- List<TimeWindow> timeWindows = new ArrayList<>();
+ private static List<ChangeBlocker> readChangeBlockers(Element root) {
+ List<ChangeBlocker> changeBlockers = new ArrayList<>();
for (Element tag : XML.getChildren(root)) {
- if (!"block-upgrade".equals(tag.getTagName())) {
- continue;
- }
+ // TODO: Remove block-upgrade on Vespa 7
+ if ( ! "block-change".equals(tag.getTagName()) && !"block-upgrade".equals(tag.getTagName())) continue;
+
+ boolean blockVersions = trueOrMissing(tag.getAttribute("versions"));
+ boolean blockRevisions = trueOrMissing(tag.getAttribute("revisions"))
+ && !tag.getTagName().equals("block-upgrade"); // TODO: Remove condition on Vespa 7
+
String daySpec = tag.getAttribute("days");
String hourSpec = tag.getAttribute("hours");
String zoneSpec = tag.getAttribute("time-zone");
if (zoneSpec.isEmpty()) { // Default to UTC time zone
zoneSpec = "UTC";
}
- timeWindows.add(TimeWindow.from(daySpec, hourSpec, zoneSpec));
+ changeBlockers.add(new ChangeBlocker(blockRevisions, blockVersions,
+ TimeWindow.from(daySpec, hourSpec, zoneSpec)));
}
- return Collections.unmodifiableList(timeWindows);
+ return Collections.unmodifiableList(changeBlockers);
+ }
+
+ /** Returns true if the given value is "true", or if it is missing */
+ private static boolean trueOrMissing(String value) {
+ return value == null || value.isEmpty() || value.equals("true");
}
private static UpgradePolicy readUpgradePolicy(Element root) {
@@ -474,4 +489,23 @@ public class DeploymentSpec {
conservative
}
+ /** A blocking of changes in a given time window */
+ public static class ChangeBlocker {
+
+ private final boolean revision;
+ private final boolean version;
+ private final TimeWindow window;
+
+ private ChangeBlocker(boolean revision, boolean version, TimeWindow window) {
+ this.revision = revision;
+ this.version = version;
+ this.window = window;
+ }
+
+ public boolean blocksRevisions() { return revision; }
+ public boolean blocksVersions() { return version; }
+ public TimeWindow window() { return window; }
+
+ }
+
}
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 3540a5d785f..c2b68b54655 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
@@ -290,9 +290,45 @@ public class DeploymentSpecTest {
"</deployment>"
);
DeploymentSpec spec = DeploymentSpec.fromXml(r);
- assertEquals(2, spec.blockUpgrades().size());
- assertEquals(ZoneId.of("UTC"), spec.blockUpgrades().get(0).zone());
- assertEquals(ZoneId.of("CET"), spec.blockUpgrades().get(1).zone());
+ assertEquals(2, spec.changeBlocker().size());
+ assertTrue(spec.changeBlocker().get(0).blocksVersions());
+ assertFalse(spec.changeBlocker().get(0).blocksRevisions());
+ assertEquals(ZoneId.of("UTC"), spec.changeBlocker().get(0).window().zone());
+
+ assertTrue(spec.changeBlocker().get(1).blocksVersions());
+ assertFalse(spec.changeBlocker().get(1).blocksRevisions());
+ assertEquals(ZoneId.of("CET"), spec.changeBlocker().get(1).window().zone());
+
+ assertTrue(spec.canUpgradeAt(Instant.parse("2017-09-18T14:15:30.00Z")));
+ assertFalse(spec.canUpgradeAt(Instant.parse("2017-09-18T15:15:30.00Z")));
+ assertFalse(spec.canUpgradeAt(Instant.parse("2017-09-18T16:15:30.00Z")));
+ assertTrue(spec.canUpgradeAt(Instant.parse("2017-09-18T17:15:30.00Z")));
+
+ assertTrue(spec.canUpgradeAt(Instant.parse("2017-09-23T09:15:30.00Z")));
+ assertFalse(spec.canUpgradeAt(Instant.parse("2017-09-23T08:15:30.00Z"))); // 10 in CET
+ assertTrue(spec.canUpgradeAt(Instant.parse("2017-09-23T10:15:30.00Z")));
+ }
+
+ @Test
+ public void deploymentSpecWithChangeBlocker() {
+ StringReader r = new StringReader(
+ "<deployment>\n" +
+ " <block-change revisions='false' days='mon,tue' hours='15-16'/>\n" +
+ " <block-change days='sat' hours='10' time-zone='CET'/>\n" +
+ " <prod>\n" +
+ " <region active='true'>us-west-1</region>\n" +
+ " </prod>\n" +
+ "</deployment>"
+ );
+ DeploymentSpec spec = DeploymentSpec.fromXml(r);
+ assertEquals(2, spec.changeBlocker().size());
+ assertTrue(spec.changeBlocker().get(0).blocksVersions());
+ assertFalse(spec.changeBlocker().get(0).blocksRevisions());
+ assertEquals(ZoneId.of("UTC"), spec.changeBlocker().get(0).window().zone());
+
+ assertTrue(spec.changeBlocker().get(1).blocksVersions());
+ assertTrue(spec.changeBlocker().get(1).blocksRevisions());
+ assertEquals(ZoneId.of("CET"), spec.changeBlocker().get(1).window().zone());
assertTrue(spec.canUpgradeAt(Instant.parse("2017-09-18T14:15:30.00Z")));
assertFalse(spec.canUpgradeAt(Instant.parse("2017-09-18T15:15:30.00Z")));
diff --git a/config-model/src/main/resources/schema/deployment.rnc b/config-model/src/main/resources/schema/deployment.rnc
index 31212b7f69d..16cc3acfafa 100644
--- a/config-model/src/main/resources/schema/deployment.rnc
+++ b/config-model/src/main/resources/schema/deployment.rnc
@@ -5,6 +5,7 @@
start = element deployment {
attribute version { "1.0" } &
Upgrade? &
+ BlockChange* &
BlockUpgrade* &
Test? &
Staging? &
@@ -15,12 +16,18 @@ Upgrade = element upgrade {
attribute policy { xsd:string }
}
-BlockUpgrade = element block-upgrade {
+BlockChange = element block-change {
+ attribute revisions { xsd:boolean }? &
+ attribute versions { xsd:boolean }? &
attribute days { xsd:string } &
attribute hours { xsd:string } &
attribute time-zone { xsd:string }?
}
+BlockUpgrade = element block-upgrade { # Legacy name - remove on Vespa 7
+ BlockChange
+}
+
Test = element test {
text
}
diff --git a/config-model/src/test/schema-test-files/deployment.xml b/config-model/src/test/schema-test-files/deployment.xml
index 6f16817e627..2fd6d7c3ec8 100644
--- a/config-model/src/test/schema-test-files/deployment.xml
+++ b/config-model/src/test/schema-test-files/deployment.xml
@@ -1,8 +1,8 @@
<!-- Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<deployment version='1.0'>
<upgrade policy='canary'/>
- <block-upgrade days="mon,tue" hours="14,15"/>
- <block-upgrade days="mon,tue" hours="14,15" time-zone="CET"/>
+ <block-change revisions='true' versions='false' days="mon,tue" hours="14,15"/>
+ <block-change days="mon,tue" hours="14,15" time-zone="CET"/>
<test/>
<staging/>
<prod global-service-id='qrs'>