summaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2021-06-07 14:59:57 +0200
committerJon Bratseth <bratseth@gmail.com>2021-06-07 14:59:57 +0200
commitbcdd3565654fb7fe7bdcd17f6a5a5904088c8e82 (patch)
tree2c63af6f88a48c7086dcfcbaa3be0837a3609b4d /config-model
parentfacc295e58c32bbcc438c7d40349c6cab1b80861 (diff)
Validate redundancy=1 on first deployment
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java7
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/first/RedundancyOnFirstDeploymentValidator.java42
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/first/RedundancyOnFirstDeploymentValidatorTest.java64
4 files changed, 114 insertions, 1 deletions
diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
index 2927df57bc1..e08c57a6fb4 100644
--- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
+++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
@@ -42,6 +42,7 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
private double defaultTermwiseLimit = 1.0;
private String jvmGCOptions = null;
private String sequencerType = "LATENCY";
+ private boolean firstTimeDeployment = false;
private String responseSequencerType = "ADAPTIVE";
private int responseNumThreads = 2;
private Optional<EndpointCertificateSecrets> endpointCertificateSecrets = Optional.empty();
@@ -77,7 +78,7 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
@Override public String jvmGCOptions(Optional<ClusterSpec.Type> clusterType) { return jvmGCOptions; }
@Override public String feedSequencerType() { return sequencerType; }
@Override public boolean isBootstrap() { return false; }
- @Override public boolean isFirstTimeDeployment() { return false; }
+ @Override public boolean isFirstTimeDeployment() { return firstTimeDeployment; }
@Override public boolean useDedicatedNodeForLogserver() { return useDedicatedNodeForLogserver; }
@Override public Optional<EndpointCertificateSecrets> endpointCertificateSecrets() { return endpointCertificateSecrets; }
@Override public double defaultTermwiseLimit() { return defaultTermwiseLimit; }
@@ -133,6 +134,10 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
responseSequencerType = type;
return this;
}
+ public TestProperties setFirstTimeDeployment(boolean firstTimeDeployment) {
+ this.firstTimeDeployment = firstTimeDeployment;
+ return this;
+ }
public TestProperties setResponseNumThreads(int numThreads) {
responseNumThreads = numThreads;
return this;
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 eccb54780d6..66f497f5040 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
@@ -25,6 +25,7 @@ import com.yahoo.vespa.model.application.validation.change.ResourcesReductionVal
import com.yahoo.vespa.model.application.validation.change.StartupCommandChangeValidator;
import com.yahoo.vespa.model.application.validation.change.StreamingSearchClusterChangeValidator;
import com.yahoo.vespa.model.application.validation.first.AccessControlOnFirstDeploymentValidator;
+import com.yahoo.vespa.model.application.validation.first.RedundancyOnFirstDeploymentValidator;
import java.time.Instant;
import java.util.Arrays;
@@ -124,6 +125,7 @@ public class Validation {
private static void validateFirstTimeDeployment(VespaModel model, DeployState deployState) {
new AccessControlOnFirstDeploymentValidator().validate(model, deployState);
+ new RedundancyOnFirstDeploymentValidator().validate(model, deployState);
}
private static void deferConfigChangesForClustersToBeRestarted(List<ConfigChangeAction> actions, VespaModel model) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/first/RedundancyOnFirstDeploymentValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/first/RedundancyOnFirstDeploymentValidator.java
new file mode 100644
index 00000000000..acffb0cf292
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/first/RedundancyOnFirstDeploymentValidator.java
@@ -0,0 +1,42 @@
+// 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.first;
+
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.model.ConfigModelContext.ApplicationType;
+import com.yahoo.config.model.deploy.DeployState;
+import com.yahoo.vespa.model.VespaModel;
+import com.yahoo.vespa.model.application.validation.Validator;
+import com.yahoo.vespa.model.container.ApplicationContainerCluster;
+import com.yahoo.vespa.model.container.Container;
+import com.yahoo.vespa.model.container.ContainerCluster;
+import com.yahoo.vespa.model.content.cluster.ContentCluster;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.yahoo.collections.CollectionUtil.mkString;
+import static com.yahoo.config.provision.InstanceName.defaultName;
+import static com.yahoo.vespa.model.container.http.AccessControl.hasHandlerThatNeedsProtection;
+
+/**
+ * Validates that applications in prod zones do not have redundancy 1 (without a validation override).
+ *
+ * @author bratseth
+ */
+public class RedundancyOnFirstDeploymentValidator extends Validator {
+
+ @Override
+ public void validate(VespaModel model, DeployState deployState) {
+ if ( ! deployState.zone().environment().isProduction()) return;
+
+ for (ContentCluster cluster : model.getContentClusters().values()) {
+ if (cluster.redundancy().finalRedundancy() == 1)
+ deployState.validationOverrides().invalid(ValidationId.redundancyOne,
+ cluster + " has redundancy 1, which will cause it to lose data " +
+ "if a node fails. This requires an override on first deployment " +
+ "in a production zone",
+ deployState.now());
+ }
+ }
+
+}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/first/RedundancyOnFirstDeploymentValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/first/RedundancyOnFirstDeploymentValidatorTest.java
new file mode 100644
index 00000000000..d59b2f7227c
--- /dev/null
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/first/RedundancyOnFirstDeploymentValidatorTest.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.first;
+
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.application.api.ValidationOverrides;
+import com.yahoo.config.model.deploy.TestProperties;
+import com.yahoo.config.provision.Environment;
+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 RedundancyOnFirstDeploymentValidatorTest {
+
+ private final ValidationTester tester = new ValidationTester(7, false,
+ new TestProperties().setFirstTimeDeployment(true)
+ .setHostedVespa(true));
+
+ @Test
+ public void testRedundancyOnFirstDeploymentValidation() {
+ try {
+ tester.deploy(null, getServices(1), Environment.prod, null);
+ fail("Expected exception due to redundancy 1");
+ }
+ catch (IllegalArgumentException expected) {
+ assertEquals("redundancy-one: " +
+ "content cluster 'contentClusterId' has redundancy 1, which will cause it to lose data if a node fails. " +
+ "This requires an override on first deployment in a production zone. " +
+ ValidationOverrides.toAllowMessage(ValidationId.redundancyOne),
+ Exceptions.toMessageString(expected));
+ }
+ }
+
+ @Test
+ public void testOverridingRedundancyOnFirstDeploymentValidation() {
+ tester.deploy(null, getServices(1), Environment.prod, redundancyOneOverride); // 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 redundancyOneOverride =
+ "<validation-overrides>\n" +
+ " <allow until='2000-01-03'>redundancy-one</allow>\n" +
+ "</validation-overrides>\n";
+
+}