summaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2021-06-07 14:21:38 +0200
committerGitHub <noreply@github.com>2021-06-07 14:21:38 +0200
commitfacc295e58c32bbcc438c7d40349c6cab1b80861 (patch)
treeeab3cb28e571d64a2d74e07c6e6b83a4de27f288 /config-model
parent13275ff0cc24dd1cdaacdf9556448d06b66fdc07 (diff)
parenta34f2f419eaace74ecadb2bc9d573957c6b6d536 (diff)
Merge pull request #18152 from vespa-engine/brattseth/redundancy-increase-validation
Add redundancy increase validation override
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java4
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validator.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/RedundancyIncreaseValidator.java45
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java5
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RedundancyIncreaseValidatorTest.java64
5 files changed, 118 insertions, 2 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java
index 55443d4b260..eccb54780d6 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java
@@ -20,6 +20,7 @@ import com.yahoo.vespa.model.application.validation.change.GlobalDocumentChangeV
import com.yahoo.vespa.model.application.validation.change.IndexedSearchClusterChangeValidator;
import com.yahoo.vespa.model.application.validation.change.IndexingModeChangeValidator;
import com.yahoo.vespa.model.application.validation.change.NodeResourceChangeValidator;
+import com.yahoo.vespa.model.application.validation.change.RedundancyIncreaseValidator;
import com.yahoo.vespa.model.application.validation.change.ResourcesReductionValidator;
import com.yahoo.vespa.model.application.validation.change.StartupCommandChangeValidator;
import com.yahoo.vespa.model.application.validation.change.StreamingSearchClusterChangeValidator;
@@ -105,7 +106,8 @@ public class Validation {
new ClusterSizeReductionValidator(),
new ResourcesReductionValidator(),
new ContainerRestartValidator(),
- new NodeResourceChangeValidator()
+ new NodeResourceChangeValidator(),
+ new RedundancyIncreaseValidator()
};
List<ConfigChangeAction> actions = Arrays.stream(validators)
.flatMap(v -> v.validate(currentModel, nextModel, overrides, now).stream())
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validator.java
index f3bebbe7fb9..fee63828670 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validator.java
@@ -15,7 +15,7 @@ public abstract class Validator {
* Validates the input vespamodel
*
* @param model a VespaModel object
- * @param deployState The {@link DeployState} built from building the model
+ * @param deployState the {@link DeployState} built from building the model
*/
public abstract void validate(VespaModel model, DeployState deployState);
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/RedundancyIncreaseValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/RedundancyIncreaseValidator.java
new file mode 100644
index 00000000000..dcf16222d35
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/RedundancyIncreaseValidator.java
@@ -0,0 +1,45 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.model.application.validation.change;
+
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.application.api.ValidationOverrides;
+import com.yahoo.config.model.api.ConfigChangeAction;
+import com.yahoo.config.provision.Capacity;
+import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.vespa.model.VespaModel;
+import com.yahoo.vespa.model.content.cluster.ContentCluster;
+
+import java.time.Instant;
+import java.util.List;
+
+/**
+ * Checks that redundancy is not increased (without a validation override),
+ * as that may easily cause the cluster to run out of reasources.
+ *
+ * @author bratseth
+ */
+public class RedundancyIncreaseValidator implements ChangeValidator {
+
+ @Override
+ public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides, Instant now) {
+ for (ContentCluster currentCluster : current.getContentClusters().values()) {
+ ContentCluster nextCluster = next.getContentClusters().get(currentCluster.getSubId());
+ if (nextCluster == null) continue;
+ if (redundancyOf(nextCluster) > redundancyOf(currentCluster)) {
+ overrides.invalid(ValidationId.redundancyIncrease,
+ "Increasing redundancy from " + redundancyOf(currentCluster) + " to " +
+ redundancyOf(nextCluster) + " in '" + currentCluster + ". " +
+ "This is a safe operation but verify that you have room for a " +
+ redundancyOf(nextCluster) + "/" + redundancyOf(currentCluster) + "x increase " +
+ "in content size",
+ now);
+ }
+ }
+ return List.of();
+ }
+
+ private int redundancyOf(ContentCluster cluster) {
+ return cluster.redundancy().finalRedundancy();
+ }
+
+}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
index 97093203758..e9264a6d9fc 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
@@ -674,4 +674,9 @@ public class ContentCluster extends AbstractConfigProducer<AbstractConfigProduce
// TODO
}
+ @Override
+ public String toString() {
+ return "content cluster '" + clusterId + "'";
+ }
+
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RedundancyIncreaseValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RedundancyIncreaseValidatorTest.java
new file mode 100644
index 00000000000..ddeada8b33f
--- /dev/null
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RedundancyIncreaseValidatorTest.java
@@ -0,0 +1,64 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.model.application.validation.change;
+
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.application.api.ValidationOverrides;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.vespa.model.VespaModel;
+import com.yahoo.vespa.model.application.validation.ValidationTester;
+import com.yahoo.yolean.Exceptions;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author bratseth
+ */
+public class RedundancyIncreaseValidatorTest {
+
+ private final ValidationTester tester = new ValidationTester(7);
+
+ @Test
+ public void testRedundancyIncreaseValidation() {
+ VespaModel previous = tester.deploy(null, getServices(2), Environment.prod, null).getFirst();
+ try {
+ tester.deploy(previous, getServices(3), Environment.prod, null);
+ fail("Expected exception due to redundancy increase");
+ }
+ catch (IllegalArgumentException expected) {
+ assertEquals("redundancy-increase: " +
+ "Increasing redundancy from 2 to 3 in 'content cluster 'contentClusterId'. " +
+ "This is a safe operation but verify that you have room for a 3/2x increase in content size. " +
+ ValidationOverrides.toAllowMessage(ValidationId.redundancyIncrease),
+ Exceptions.toMessageString(expected));
+ }
+ }
+
+ @Test
+ public void testOverridingContentRemovalValidation() {
+ VespaModel previous = tester.deploy(null, getServices(2), Environment.prod, null).getFirst();
+ tester.deploy(previous, getServices(3), Environment.prod, redundancyIncreaseOverride); // Allowed due to override
+ }
+
+ private static String getServices(int redundancy) {
+ return "<services version='1.0'>" +
+ " <content id='contentClusterId' version='1.0'>" +
+ " <redundancy>" + redundancy + "</redundancy>" +
+ " <engine>" +
+ " <proton/>" +
+ " </engine>" +
+ " <documents>" +
+ " <document type='music' mode='index'/>" +
+ " </documents>" +
+ " <nodes count='3'/>" +
+ " </content>" +
+ "</services>";
+ }
+
+ private static final String redundancyIncreaseOverride =
+ "<validation-overrides>\n" +
+ " <allow until='2000-01-03'>redundancy-increase</allow>\n" +
+ "</validation-overrides>\n";
+
+}