diff options
author | Tor Brede Vekterli <vekterli@oath.com> | 2018-05-08 16:00:28 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-08 16:00:28 +0200 |
commit | 9282c9bacd7b2d09e55552d44f1ec9d8ebceb610 (patch) | |
tree | a3b5a36dcc07dc871c8b43c6bea6adc2239ecd1c | |
parent | 3004035566035bac14d2bd30284342623ce49a15 (diff) | |
parent | 3c5db05f6c70558fad4bc3b63be23fc5aef0da06 (diff) |
Merge pull request #5816 from vespa-engine/toregge/add-global-document-change-validator
Validate that global attribute on document types in a content cluster are unchanged
4 files changed, 118 insertions, 0 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationId.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationId.java index 1ce9ac2275f..6d8fd553502 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationId.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationId.java @@ -18,6 +18,7 @@ public enum ValidationId { contentClusterRemoval("content-cluster-removal"), // Removal (or id change) of content clusters deploymentRemoval("deployment-removal"), // Removal of production zones from deployment.xml skipAutomaticTenantUpgradeTests("skip-automatic-tenant-upgrade-test"), // Skip platform supplied staging tests + globalDocumentChange("global-document-change"), // Changing global attribute for document types in content clusters configModelVersionMismatch("config-model-version-mismatch"), // Internal use skipOldConfigModels("skip-old-config-models"), // Internal use forceAutomaticTenantUpgradeTests("force-automatic-tenant-upgrade-test"); // Internal use 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 50e93789159..523ced52306 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 @@ -13,6 +13,7 @@ import com.yahoo.vespa.model.application.validation.change.ConfigValueChangeVali import com.yahoo.vespa.model.application.validation.change.ContainerRestartValidator; import com.yahoo.vespa.model.application.validation.change.ContentClusterRemovalValidator; import com.yahoo.vespa.model.application.validation.change.ContentTypeRemovalValidator; +import com.yahoo.vespa.model.application.validation.change.GlobalDocumentChangeValidator; 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.StartupCommandChangeValidator; @@ -72,6 +73,7 @@ public class Validation { Instant now) { ChangeValidator[] validators = new ChangeValidator[] { new IndexingModeChangeValidator(), + new GlobalDocumentChangeValidator(), new IndexedSearchClusterChangeValidator(), new StreamingSearchClusterChangeValidator(), new ConfigValueChangeValidator(logger), diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/GlobalDocumentChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/GlobalDocumentChangeValidator.java new file mode 100644 index 00000000000..73bf3a4fe3e --- /dev/null +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/GlobalDocumentChangeValidator.java @@ -0,0 +1,51 @@ +// Copyright 2018 Yahoo Holdings. 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.documentmodel.NewDocumentType; +import com.yahoo.vespa.model.VespaModel; +import com.yahoo.vespa.model.content.cluster.ContentCluster; + +import java.util.Collections; +import java.time.Instant; +import java.util.List; +import java.util.Map; + +/** + * Class that fails via exception if global attribute changes for a document + * type in a content cluster unless corresponding override is present. + */ +public class GlobalDocumentChangeValidator implements ChangeValidator { + + @Override + public List<ConfigChangeAction> validate(VespaModel currentModel, VespaModel nextModel, + ValidationOverrides overrides, Instant now) { + if (!overrides.allows(ValidationId.globalDocumentChange.value(), now)) { + for (Map.Entry<String, ContentCluster> currentEntry : currentModel.getContentClusters().entrySet()) { + ContentCluster nextCluster = nextModel.getContentClusters().get(currentEntry.getKey()); + if (nextCluster == null) continue; + + validateContentCluster(currentEntry.getValue(), nextCluster); + } + } + return Collections.emptyList(); + } + + private void validateContentCluster(ContentCluster currentCluster, ContentCluster nextCluster) { + String clusterName = currentCluster.getName(); + currentCluster.getDocumentDefinitions().forEach((documentTypeName, currentDocumentType) -> { + NewDocumentType nextDocumentType = nextCluster.getDocumentDefinitions().get(documentTypeName); + if (nextDocumentType != null) { + boolean currentIsGlobal = currentCluster.isGloballyDistributed(currentDocumentType); + boolean nextIsGlobal = nextCluster.isGloballyDistributed(nextDocumentType); + if (currentIsGlobal != nextIsGlobal) { + throw new IllegalStateException(String.format("Document type %s in cluster %s changed global from %s to %s", + documentTypeName, clusterName, currentIsGlobal, nextIsGlobal)); + } + } + }); + } +} + diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/GlobalDocumentChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/GlobalDocumentChangeValidatorTest.java new file mode 100644 index 00000000000..65423ad1333 --- /dev/null +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/GlobalDocumentChangeValidatorTest.java @@ -0,0 +1,64 @@ +// Copyright 2018 Yahoo Holdings. 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.model.api.ConfigChangeAction; +import com.yahoo.config.model.api.ConfigChangeRefeedAction; +import com.yahoo.vespa.model.VespaModel; +import com.yahoo.vespa.model.application.validation.ValidationTester; +import org.junit.Test; +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +/** + * Test that global attribute changes are detected by change validator. + */ +public class GlobalDocumentChangeValidatorTest { + + @Test + public void testChangGlobalAttribute() throws IOException, SAXException { + testChangeGlobalAttribute(true, false, false, null); + testChangeGlobalAttribute(true, true, true, null); + testChangeGlobalAttribute(false, false, true, null); + testChangeGlobalAttribute(false, true, false, null); + testChangeGlobalAttribute(true, false, true, globalDocumentValidationOverrides); + testChangeGlobalAttribute(true, true, false, globalDocumentValidationOverrides); + } + + private void testChangeGlobalAttribute(boolean allowed, boolean oldGlobal, boolean newGlobal, String validationOverrides) { + ValidationTester tester = new ValidationTester(); + VespaModel oldModel = tester.deploy(null, getServices(oldGlobal), validationOverrides).getFirst(); + try { + tester.deploy(oldModel, getServices(newGlobal), validationOverrides).getSecond(); + assertTrue(allowed); + } catch (IllegalStateException e) { + assertFalse(allowed); + assertEquals("Document type music in cluster default changed global from " + oldGlobal + " to " + newGlobal, + e.getMessage()); + } + } + private static final String getServices(boolean isGlobal) { + return "<services version='1.0'>" + + " <content id='default' version='1.0'>" + + " <redundancy>1</redundancy>" + + " <documents>" + + " <document type='music' mode='index' global='" + + isGlobal + "'/>" + + " </documents>" + + " <nodes count='1'/>" + + " </content>" + + "</services>"; + } + + private static final String globalDocumentValidationOverrides = + "<validation-overrides>\n" + + " <allow until='2000-01-14' comment='test override'>global-document-change</allow>\n" + + "</validation-overrides>\n"; + +} |