summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <jonbratseth@yahoo.com>2017-06-16 11:14:13 +0200
committerGitHub <noreply@github.com>2017-06-16 11:14:13 +0200
commitfa64d4836b8df9bfa0ed57daee66a6fc84c4b6bf (patch)
treecd5832f9fee4cc17dac334d6dc93c94b8c2a02a2
parentd91ef9c2ea42ca7c5d8925c4ff21664adb43892b (diff)
parent95eef9b4bc9e4607ab63f8a5e9bec6bcaaebbc2e (diff)
Merge pull request #2794 from yahoo/bratseth/move-validation-overrides
Bratseth/move validation overrides
-rw-r--r--config-model-api/pom.xml6
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java2
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/ValidationId.java (renamed from config-model/src/main/java/com/yahoo/vespa/model/application/validation/ValidationId.java)2
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/ValidationOverrides.java162
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/model/api/Model.java16
-rw-r--r--config-model-api/src/test/java/com/yahoo/config/application/api/ValidationOverrideTest.java96
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java12
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java15
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java9
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/ValidationOverrides.java104
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ChangeValidator.java6
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ClusterSizeReductionValidator.java18
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java7
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java6
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java10
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java22
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java21
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java7
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java17
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java15
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java23
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java13
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/xml/ValidationOverridesXMLReader.java57
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/ValidationOverrideTest.java92
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java14
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidatorTest.java5
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidatorTest.java5
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java14
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java9
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java13
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java49
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java10
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java13
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationSet.java9
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java8
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java29
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java5
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java8
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java12
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java9
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java10
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java16
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java9
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationMapperTest.java15
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationSetTest.java11
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java9
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java11
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java65
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java29
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java5
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java27
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java17
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java7
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java19
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java62
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java27
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java27
-rw-r--r--pom.xml2
-rwxr-xr-xsearchlib/src/vespa/searchlib/features/create-class-cpp.sh2
-rw-r--r--testutil/src/main/java/com/yahoo/test/ManualClock.java6
67 files changed, 748 insertions, 605 deletions
diff --git a/config-model-api/pom.xml b/config-model-api/pom.xml
index fd62a5c4c2f..6618612df31 100644
--- a/config-model-api/pom.xml
+++ b/config-model-api/pom.xml
@@ -63,6 +63,12 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>testutil</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<version>17.0</version>
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 6c996961e59..2842ac5bd30 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
@@ -128,7 +128,7 @@ public class DeploymentSpec {
.collect(Collectors.toList());
}
- /** Returns the XML form of this spec, or null if it was not created by fromXml or is the empty spec */
+ /** Returns the XML form of this spec, or null if it was not created by fromXml, nor is empty */
public String xmlForm() { return xmlForm; }
/** Returns whether this deployment spec specifies the given zone, either implicitly or explicitly */
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ValidationId.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationId.java
index 8f9b0081db1..37cb6e40f3d 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ValidationId.java
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationId.java
@@ -1,5 +1,5 @@
// Copyright 2017 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;
+package com.yahoo.config.application.api;
import java.util.Optional;
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationOverrides.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationOverrides.java
new file mode 100644
index 00000000000..11f9add6b25
--- /dev/null
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ValidationOverrides.java
@@ -0,0 +1,162 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.application.api;
+
+import com.google.common.collect.ImmutableList;
+import com.yahoo.io.IOUtils;
+import com.yahoo.text.XML;
+import org.w3c.dom.Element;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * A set of allows which suppresses specific validations in limited time periods.
+ * This is useful to be able to complete a deployment in cases where the application
+ * owner believes that the changes to be deployed have acceptable consequences.
+ * Immutable.
+ *
+ * @author bratseth
+ */
+public class ValidationOverrides {
+
+ public static final ValidationOverrides empty = new ValidationOverrides(ImmutableList.of(), "<deployment version='1.0'/>");
+
+ private final List<Allow> overrides;
+
+ private final String xmlForm;
+
+ /** Creates a validation overrides which does not have an xml form */
+ public ValidationOverrides(List<Allow> overrides) {
+ this(overrides, null);
+ }
+
+ private ValidationOverrides(List<Allow> overrides, String xmlForm) {
+ this.overrides = ImmutableList.copyOf(overrides);
+ this.xmlForm = xmlForm;
+ }
+
+ /** Throws a ValidationException unless this validation is overridden at this time */
+ public void invalid(ValidationId validationId, String message, Instant now) {
+ if ( ! allows(validationId, now))
+ throw new ValidationException(validationId, message);
+ }
+
+ public boolean allows(String validationIdString, Instant now) {
+ Optional<ValidationId> validationId = ValidationId.from(validationIdString);
+ if ( ! validationId.isPresent()) return false; // unknown id -> not allowed
+ return allows(validationId.get(), now);
+ }
+
+ /** Returns whether the given (assumed invalid) change is allowed by this at the moment */
+ public boolean allows(ValidationId validationId, Instant now) {
+ for (Allow override : overrides) {
+ if (now.plus(Duration.ofDays(30)).isBefore(override.until))
+ throw new IllegalArgumentException(override + " is too far in the future: Max 30 days is allowed");
+ if (override.allows(validationId, now))
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns the XML form of this, or null if it was not created by fromXml, nor is empty */
+ public String xmlForm() { return xmlForm; }
+
+ /**
+ * Returns a ValidationOverrides instance with the content of the given Reader.
+ *
+ * @param reader the reader containing a validation-overrides XML structure
+ * @return a ValidationOverrides from the argument
+ * @throws IllegalArgumentException if the validation-allows.xml file exists but is invalid
+ */
+ public static ValidationOverrides fromXml(Reader reader) {
+ try {
+ return fromXml(IOUtils.readAll(reader));
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Could not read deployment spec", e);
+ }
+ }
+
+ /**
+ * Returns a ValidationOverrides instance with the content of the given XML string.
+ * An empty ValidationOverrides is returned if the argument is empty.
+ *
+ * @param xmlForm the string which optionally contains a validation-overrides XML structure
+ * @return a ValidationOverrides from the argument
+ * @throws IllegalArgumentException if the validation-allows.xml file exists but is invalid
+ */
+ public static ValidationOverrides fromXml(String xmlForm) {
+ if ( xmlForm.isEmpty()) return ValidationOverrides.empty;
+
+ try {
+ // Assume valid structure is ensured by schema validation
+ Element root = XML.getDocument(xmlForm).getDocumentElement();
+ List<ValidationOverrides.Allow> overrides = new ArrayList<>();
+ for (Element allow : XML.getChildren(root, "allow")) {
+ Instant until = LocalDate.parse(allow.getAttribute("until"), DateTimeFormatter.ISO_DATE)
+ .atStartOfDay().atZone(ZoneOffset.UTC).toInstant()
+ .plus(Duration.ofDays(1)); // Make the override valid *on* the "until" date
+ Optional<ValidationId> validationId = ValidationId.from(XML.getValue(allow));
+ if (validationId.isPresent()) // skip unknown ids as they may be valid for other model versions
+ overrides.add(new ValidationOverrides.Allow(validationId.get(), until));
+ }
+ return new ValidationOverrides(overrides, xmlForm);
+ }
+ catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("validation-overrides is invalid", e);
+ }
+ }
+
+ /** A validation override which allows a particular change. Immutable. */
+ public static class Allow {
+
+ private final ValidationId validationId;
+ private final Instant until;
+
+ public Allow(ValidationId validationId, Instant until) {
+ this.validationId = validationId;
+ this.until = until;
+ }
+
+ public boolean allows(ValidationId validationId, Instant now) {
+ return this.validationId.equals(validationId) && now.isBefore(until);
+ }
+
+ @Override
+ public String toString() { return "allow '" + validationId + "' until " + until; }
+
+ }
+
+ /**
+ * A deployment validation exception.
+ * Deployment validations can be {@link ValidationOverrides overridden} based on their id.
+ * The purpose of this exception is to model that id as a separate field.
+ */
+ public static class ValidationException extends IllegalArgumentException {
+
+ static final long serialVersionUID = 789984668;
+
+ private final ValidationId validationId;
+
+ private ValidationException(ValidationId validationId, String message) {
+ super(message);
+ this.validationId = validationId;
+ }
+
+ /** Returns the unique id of this validation, which can be used to {@link ValidationOverrides override} it */
+ public ValidationId validationId() { return validationId; }
+
+ /** Returns "validationId: message" */
+ @Override
+ public String getMessage() { return validationId + ": " + super.getMessage(); }
+
+ }
+
+}
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java b/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java
index c86859d2357..0c038077fe4 100644
--- a/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java
+++ b/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java
@@ -6,6 +6,8 @@ import com.yahoo.vespa.config.ConfigKey;
import com.yahoo.vespa.config.ConfigPayload;
import com.yahoo.vespa.config.buildergen.ConfigDefinition;
+import java.time.Clock;
+import java.time.Instant;
import java.util.Optional;
import java.util.Set;
import java.util.Collection;
@@ -67,7 +69,12 @@ public interface Model {
* This is a validation override which is useful when we skip loading old config models
* due to some problem, or when we need to try a newer version of the platform on some node.
*/
- default boolean allowModelVersionMismatch() { return false; }
+ default boolean allowModelVersionMismatch(Instant now) { return false; }
+
+ /** @deprecated pass now. */
+ // TODO: Remove this when no version older than 6.115 is deployed anywhere
+ @Deprecated
+ default boolean allowModelVersionMismatch() { return allowModelVersionMismatch(Clock.systemUTC().instant()); }
/**
* Returns whether old config models should be loaded (default) or not.
@@ -79,6 +86,11 @@ public interface Model {
* If a model returns true to this it should also return true to {@link #allowModelVersionMismatch}
* or clients requesting config for those old models will not get config at all.
*/
- default boolean skipOldConfigModels() { return false; }
+ default boolean skipOldConfigModels(Instant now) { return false; }
+
+ /** @deprecated pass now. */
+ // TODO: Remove this when no version older than 6.115 is deployed anywhere
+ @Deprecated
+ default boolean skipOldConfigModels() { return skipOldConfigModels(Clock.systemUTC().instant()); }
}
diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/ValidationOverrideTest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/ValidationOverrideTest.java
new file mode 100644
index 00000000000..c17b9a6f220
--- /dev/null
+++ b/config-model-api/src/test/java/com/yahoo/config/application/api/ValidationOverrideTest.java
@@ -0,0 +1,96 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.application.api;
+
+import com.yahoo.test.ManualClock;
+import org.junit.Assert;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.time.Instant;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author bratseth
+ */
+public class ValidationOverrideTest {
+
+ @Test
+ public void testValidationOverridesInIsolation() throws IOException, SAXException {
+ String validationOverrides =
+ "<validation-overrides>" +
+ " <allow until='2000-01-01'>indexing-change</allow>" +
+ " <allow until='2000-01-03' comment='any text'>indexing-mode-change</allow>" +
+ "</validation-overrides>";
+ {
+
+ ValidationOverrides overrides = ValidationOverrides.fromXml(new StringReader(validationOverrides));
+ Instant now = ManualClock.at("2000-01-01T23:59:00");
+ assertOverridden("indexing-change", overrides, now);
+ assertOverridden("indexing-mode-change", overrides, now);
+ assertNotOverridden("field-type-change", overrides, now);
+
+ assertEquals(validationOverrides, overrides.xmlForm());
+ }
+
+ {
+ ValidationOverrides overrides = ValidationOverrides.fromXml(new StringReader(validationOverrides));
+ Instant now = ManualClock.at("2000-01-02T00:00:00");
+ assertNotOverridden("indexing-change", overrides, now);
+ assertOverridden("indexing-mode-change", overrides, now);
+ assertNotOverridden("field-type-change", overrides, now);
+ }
+
+ {
+ ValidationOverrides overrides = ValidationOverrides.fromXml(new StringReader(validationOverrides));
+ Instant now = ManualClock.at("2000-01-04T00:00:00");
+ assertNotOverridden("indexing-change", overrides, now);
+ assertNotOverridden("indexing-mode-change", overrides, now);
+ assertNotOverridden("field-type-change", overrides, now);
+ }
+
+ }
+
+ @Test
+ public void testInvalidOverridePeriod() throws IOException, SAXException {
+ String validationOverrides =
+ "<validation-overrides>" +
+ " <allow until='2000-02-02'>indexing-change</allow>" +
+ "</validation-overrides>";
+
+ try {
+ ValidationOverrides overrides = ValidationOverrides.fromXml(new StringReader(validationOverrides));
+ Instant now = ManualClock.at("2000-01-01T23:59:00");
+ overrides.allows("indexing-change", now);
+ Assert.fail("Expected validation interval override validation validation failure");
+ }
+ catch (IllegalArgumentException e) {
+ Assert.assertEquals("allow 'indexing-change' until 2000-02-03T00:00:00Z is too far in the future: Max 30 days is allowed",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testEmpty() {
+ ValidationOverrides empty = ValidationOverrides.empty;
+ ValidationOverrides emptyReserialized = ValidationOverrides.fromXml(empty.xmlForm());
+ assertEquals(empty.xmlForm(), emptyReserialized.xmlForm());
+ }
+
+ private void assertOverridden(String validationId, ValidationOverrides overrides, Instant now) {
+ overrides.invalid(ValidationId.from(validationId).get(), "message", now); // should not throw exception
+ }
+
+ private void assertNotOverridden(String validationId, ValidationOverrides overrides, Instant now) {
+ try {
+ overrides.invalid(ValidationId.from(validationId).get(), "message", now);
+ Assert.fail("Expected '" + validationId + "' to not be overridden");
+ }
+ catch (ValidationOverrides.ValidationException expected) {
+ }
+ }
+
+}
diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java
index 2499f2f625d..25d45dee234 100644
--- a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java
+++ b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java
@@ -7,7 +7,6 @@ import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.application.api.FileRegistry;
import com.yahoo.config.application.api.UnparsedConfigDefinition;
-import com.yahoo.config.codegen.CNode;
import com.yahoo.config.model.api.ConfigDefinitionRepo;
import com.yahoo.config.model.api.HostProvisioner;
import com.yahoo.config.model.api.Model;
@@ -19,7 +18,6 @@ import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.config.provision.Rotation;
import com.yahoo.config.provision.Zone;
import com.yahoo.io.reader.NamedReader;
-import com.yahoo.log.LogLevel;
import com.yahoo.searchdefinition.RankProfileRegistry;
import com.yahoo.searchdefinition.SearchBuilder;
import com.yahoo.searchdefinition.parser.ParseException;
@@ -27,8 +25,7 @@ import com.yahoo.vespa.config.ConfigDefinition;
import com.yahoo.vespa.config.ConfigDefinitionBuilder;
import com.yahoo.vespa.config.ConfigDefinitionKey;
import com.yahoo.vespa.documentmodel.DocumentModel;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
-import com.yahoo.vespa.model.application.validation.xml.ValidationOverridesXMLReader;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.container.search.QueryProfiles;
import com.yahoo.vespa.model.container.search.QueryProfilesBuilder;
import com.yahoo.vespa.model.container.search.SemanticRuleBuilder;
@@ -46,7 +43,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.logging.Logger;
/**
* Contains various state during deploy that should be available in all builders of a {@link com.yahoo.config.model.ConfigModel}
@@ -71,6 +67,7 @@ public class DeployState implements ConfigDefinitionStore {
private final SemanticRules semanticRules;
private final ValidationOverrides validationOverrides;
private final Version wantedNodeVespaVersion;
+ private final Instant now;
private final HostProvisioner provisioner;
@@ -102,8 +99,9 @@ public class DeployState implements ConfigDefinitionStore {
this.zone = zone;
this.queryProfiles = queryProfiles; // TODO: Remove this by seeing how pagetemplates are propagated
this.semanticRules = semanticRules; // TODO: Remove this by seeing how pagetemplates are propagated
- this.validationOverrides = new ValidationOverridesXMLReader().read(applicationPackage.getValidationOverrides(), now);
+ this.validationOverrides = applicationPackage.getValidationOverrides().map(ValidationOverrides::fromXml).orElse(ValidationOverrides.empty);
this.wantedNodeVespaVersion = wantedNodeVespaVersion;
+ this.now = now;
}
public static HostProvisioner getDefaultModelHostProvisioner(ApplicationPackage applicationPackage) {
@@ -213,6 +211,8 @@ public class DeployState implements ConfigDefinitionStore {
public SemanticRules getSemanticRules() { return semanticRules; }
public Version getWantedNodeVespaVersion() { return wantedNodeVespaVersion; }
+
+ public Instant now() { return now; }
public static class Builder {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
index 1be22be1947..c61435ca831 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
@@ -29,8 +29,8 @@ import com.yahoo.vespa.config.ConfigPayloadBuilder;
import com.yahoo.vespa.config.GenericConfig;
import com.yahoo.vespa.config.buildergen.ConfigDefinition;
import com.yahoo.vespa.model.admin.Admin;
-import com.yahoo.vespa.model.application.validation.ValidationId;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.builder.VespaModelBuilder;
import com.yahoo.vespa.model.builder.xml.dom.VespaDomBuilder;
import com.yahoo.vespa.model.clients.Clients;
@@ -51,6 +51,7 @@ import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
@@ -212,14 +213,14 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
public ApplicationConfigProducerRoot getVespa() { return root; }
@Override
- public boolean allowModelVersionMismatch() {
- return validationOverrides.allows(ValidationId.configModelVersionMismatch) ||
- validationOverrides.allows(ValidationId.skipOldConfigModels); // implies this
+ public boolean allowModelVersionMismatch(Instant now) {
+ return validationOverrides.allows(ValidationId.configModelVersionMismatch, now) ||
+ validationOverrides.allows(ValidationId.skipOldConfigModels, now); // implies this
}
@Override
- public boolean skipOldConfigModels() {
- return validationOverrides.allows(ValidationId.skipOldConfigModels);
+ public boolean skipOldConfigModels(Instant now) {
+ return validationOverrides.allows(ValidationId.skipOldConfigModels, now);
}
/**
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 d1b8ae63641..490627e7b45 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
@@ -2,6 +2,7 @@
package com.yahoo.vespa.model.application.validation;
import com.yahoo.config.application.api.DeployLogger;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.config.model.api.Model;
import com.yahoo.config.model.deploy.DeployState;
@@ -15,6 +16,7 @@ import com.yahoo.vespa.model.application.validation.change.IndexedSearchClusterC
import com.yahoo.vespa.model.application.validation.change.IndexingModeChangeValidator;
import com.yahoo.vespa.model.application.validation.change.StartupCommandChangeValidator;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -56,13 +58,14 @@ public class Validation {
Optional<Model> currentActiveModel = deployState.getPreviousModel();
if (currentActiveModel.isPresent() && (currentActiveModel.get() instanceof VespaModel))
return validateChanges((VespaModel)currentActiveModel.get(), model,
- deployState.validationOverrides(), deployState.getDeployLogger());
+ deployState.validationOverrides(), deployState.getDeployLogger(), deployState.now());
else
return new ArrayList<>();
}
private static List<ConfigChangeAction> validateChanges(VespaModel currentModel, VespaModel nextModel,
- ValidationOverrides overrides, DeployLogger logger) {
+ ValidationOverrides overrides, DeployLogger logger,
+ Instant now) {
ChangeValidator[] validators = new ChangeValidator[] {
new IndexingModeChangeValidator(),
new IndexedSearchClusterChangeValidator(),
@@ -73,7 +76,7 @@ public class Validation {
new ContainerRestartValidator(),
};
return Arrays.stream(validators)
- .flatMap(v -> v.validate(currentModel, nextModel, overrides).stream())
+ .flatMap(v -> v.validate(currentModel, nextModel, overrides, now).stream())
.collect(toList());
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ValidationOverrides.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ValidationOverrides.java
deleted file mode 100644
index 25464ce40ba..00000000000
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ValidationOverrides.java
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2017 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;
-
-import com.google.common.collect.ImmutableList;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * A set of allows which suppresses specific validations in limited time periods.
- * This is useful to be able to complete a deployment in cases where the application
- * owner believes that the changes to be deployed have acceptable consequences.
- * Immutable.
- *
- * @author bratseth
- */
-public class ValidationOverrides {
-
- private final List<Allow> overrides;
-
- /** Instant to use as "now". This is a field to allow unit testing. */
- private final Instant now;
-
- /** Creates validation overrides for the current instant */
- public ValidationOverrides(List<Allow> overrides) {
- this(overrides, Instant.now());
- }
-
- public ValidationOverrides(List<Allow> overrides, Instant now) {
- this.overrides = ImmutableList.copyOf(overrides);
- this.now = now;
- for (Allow override : overrides)
- if (now.plus(Duration.ofDays(30)).isBefore(override.until))
- throw new IllegalArgumentException(override + " is too far in the future: Max 30 days is allowed");
- }
-
- /** Throws a ValidationException unless this validation is overridden at this time */
- public void invalid(ValidationId validationId, String message) {
- if ( ! allows(validationId))
- throw new ValidationException(validationId, message);
- }
-
- public boolean allows(String validationIdString) {
- Optional<ValidationId> validationId = ValidationId.from(validationIdString);
- if ( ! validationId.isPresent()) return false; // unknown id -> not allowed
- return allows(validationId.get());
- }
-
- /** Returns whether the given (assumed invalid) change is allowed by this at the moment */
- public boolean allows(ValidationId validationId) {
- for (Allow override : overrides)
- if (override.allows(validationId, now))
- return true;
- return false;
- }
-
- public static ValidationOverrides empty() { return new ValidationOverrides(ImmutableList.of()); }
-
- /** A validation override which allows a particular change. Immutable. */
- public static class Allow {
-
- private final ValidationId validationId;
- private final Instant until;
-
- public Allow(ValidationId validationId, Instant until) {
- this.validationId = validationId;
- this.until = until;
- }
-
- public boolean allows(ValidationId validationId, Instant now) {
- return this.validationId.equals(validationId) && now.isBefore(until);
- }
-
- @Override
- public String toString() { return "allow '" + validationId + "' until " + until; }
-
- }
-
- /**
- * A deployment validation exception.
- * Deployment validations can be {@link ValidationOverrides overridden} based on their id.
- * The purpose of this exception is to model that id as a separate field.
- */
- public static class ValidationException extends IllegalArgumentException {
-
- private final ValidationId validationId;
-
- private ValidationException(ValidationId validationId, String message) {
- super(message);
- this.validationId = validationId;
- }
-
- /** Returns the unique id of this validation, which can be used to {@link ValidationOverrides override} it */
- public ValidationId validationId() { return validationId; }
-
- /** Returns "validationId: message" */
- @Override
- public String getMessage() { return validationId + ": " + super.getMessage(); }
-
- }
-
-}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ChangeValidator.java
index 72eda0ae3ec..bec7fd1518f 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ChangeValidator.java
@@ -3,8 +3,9 @@ package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
+import java.time.Instant;
import java.util.List;
/**
@@ -22,9 +23,10 @@ public interface ChangeValidator {
* @param current the current active model
* @param next the next model we would like to activate
* @param overrides validation overrides
+ * @param now the instant to use as now
* @return a list of actions specifying what needs to be done in order to activate the new model.
* Return an empty list if nothing needs to be done
*/
- List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides);
+ List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides, Instant now);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ClusterSizeReductionValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ClusterSizeReductionValidator.java
index 056b1a80d23..d14fe91a53b 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ClusterSizeReductionValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ClusterSizeReductionValidator.java
@@ -3,11 +3,12 @@ package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationId;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.container.ContainerCluster;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
+import java.time.Instant;
import java.util.Collections;
import java.util.List;
@@ -19,14 +20,15 @@ import java.util.List;
public class ClusterSizeReductionValidator implements ChangeValidator {
@Override
- public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides) {
+ public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides, Instant now) {
for (ContainerCluster currentCluster : current.getContainerClusters().values()) {
ContainerCluster nextCluster = next.getContainerClusters().get(currentCluster.getName());
if (nextCluster == null) continue;
validate(currentCluster.getContainers().size(),
nextCluster.getContainers().size(),
currentCluster.getName(),
- overrides);
+ overrides,
+ now);
}
for (ContentCluster currentCluster : current.getContentClusters().values()) {
@@ -35,18 +37,20 @@ public class ClusterSizeReductionValidator implements ChangeValidator {
validate(currentCluster.getSearch().getSearchNodes().size(),
nextCluster.getSearch().getSearchNodes().size(),
currentCluster.getName(),
- overrides);
+ overrides,
+ now);
}
return Collections.emptyList();
}
- private void validate(int currentSize, int nextSize, String clusterName, ValidationOverrides overrides) {
+ private void validate(int currentSize, int nextSize, String clusterName, ValidationOverrides overrides, Instant now) {
// don't allow more than 50% reduction, but always allow to reduce size with 1
if ( nextSize < ((double)currentSize) * 0.5 && nextSize != currentSize - 1)
overrides.invalid(ValidationId.clusterSizeReduction,
"Size reduction in '" + clusterName + "' is too large. Current size: " + currentSize +
- ", new size: " + nextSize + ". New size must be at least 50% of the current size");
+ ", new size: " + nextSize + ". New size must be at least 50% of the current size",
+ now);
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java
index d1d5a1cbfcb..3a97bf4b876 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java
@@ -9,12 +9,11 @@ import com.yahoo.config.model.producer.AbstractConfigProducerRoot;
import com.yahoo.vespa.model.Service;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.application.validation.RestartConfigs;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
-import com.yahoo.vespa.model.application.validation.change.ChangeValidator;
-import com.yahoo.vespa.model.application.validation.change.VespaRestartAction;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.utils.internal.ReflectionUtil;
import org.apache.commons.lang3.ClassUtils;
+import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@@ -42,7 +41,7 @@ public class ConfigValueChangeValidator implements ChangeValidator {
/** Inspects the configuration in the new and old Vespa model to determine which services that require restart */
@Override
public List<ConfigChangeAction> validate(VespaModel currentModel, VespaModel nextModel,
- ValidationOverrides overrides) {
+ ValidationOverrides overrides, Instant now) {
return findConfigChangesFromModels(currentModel, nextModel).collect(Collectors.toList());
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java
index c2286264771..c27600578b5 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java
@@ -4,9 +4,10 @@ package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.container.QrConfig;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.container.Container;
+import java.time.Instant;
import java.util.List;
import static java.util.stream.Collectors.toList;
@@ -19,7 +20,8 @@ import static java.util.stream.Collectors.toList;
public class ContainerRestartValidator implements ChangeValidator {
@Override
- public List<ConfigChangeAction> validate(VespaModel currentModel, VespaModel nextModel, ValidationOverrides ignored) {
+ public List<ConfigChangeAction> validate(VespaModel currentModel, VespaModel nextModel, ValidationOverrides ignored,
+ Instant now) {
return nextModel.getContainerClusters().values().stream()
.flatMap(cluster -> cluster.getContainers().stream())
.filter(container -> isExistingContainer(container, currentModel))
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java
index 5441592b391..52253411419 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java
@@ -3,10 +3,11 @@ package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationId;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
+import java.time.Instant;
import java.util.Collections;
import java.util.List;
@@ -19,13 +20,14 @@ import java.util.List;
public class ContentClusterRemovalValidator implements ChangeValidator {
@Override
- public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides) {
+ public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides, Instant now) {
for (String currentClusterId : current.getContentClusters().keySet()) {
ContentCluster nextCluster = next.getContentClusters().get(currentClusterId);
if (nextCluster == null)
overrides.invalid(ValidationId.contentClusterRemoval,
"Content cluster '" + currentClusterId + "' is removed. " +
- "This will cause loss of all data in this cluster");
+ "This will cause loss of all data in this cluster",
+ now);
}
return Collections.emptyList();
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java
index ca8bc7a3eeb..4ed28331467 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java
@@ -5,13 +5,14 @@ import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.config.model.api.ServiceInfo;
import com.yahoo.documentmodel.NewDocumentType;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.search.DocumentDatabaseChangeValidator;
import com.yahoo.vespa.model.content.ContentSearchCluster;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
import com.yahoo.vespa.model.search.DocumentDatabase;
import com.yahoo.vespa.model.search.IndexedSearchCluster;
+import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@@ -24,12 +25,12 @@ import java.util.stream.Collectors;
public class IndexedSearchClusterChangeValidator implements ChangeValidator {
@Override
- public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides) {
+ public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides, Instant now) {
List<ConfigChangeAction> result = new ArrayList<>();
for (Map.Entry<String, ContentCluster> currentEntry : current.getContentClusters().entrySet()) {
ContentCluster nextCluster = next.getContentClusters().get(currentEntry.getKey());
if (nextCluster != null && nextCluster.getSearch().hasIndexedCluster()) {
- result.addAll(validateContentCluster(currentEntry.getValue(), nextCluster, overrides));
+ result.addAll(validateContentCluster(currentEntry.getValue(), nextCluster, overrides, now));
}
}
return result;
@@ -37,15 +38,17 @@ public class IndexedSearchClusterChangeValidator implements ChangeValidator {
private static List<ConfigChangeAction> validateContentCluster(ContentCluster currentCluster,
ContentCluster nextCluster,
- ValidationOverrides overrides) {
+ ValidationOverrides overrides,
+ Instant now) {
List<ConfigChangeAction> result = new ArrayList<>();
- result.addAll(validateDocumentDatabases(currentCluster, nextCluster, overrides));
+ result.addAll(validateDocumentDatabases(currentCluster, nextCluster, overrides, now));
return result;
}
private static List<ConfigChangeAction> validateDocumentDatabases(ContentCluster currentCluster,
ContentCluster nextCluster,
- ValidationOverrides overrides) {
+ ValidationOverrides overrides,
+ Instant now) {
List<ConfigChangeAction> result = new ArrayList<>();
for (DocumentDatabase currentDb : getDocumentDbs(currentCluster.getSearch())) {
String docTypeName = currentDb.getName();
@@ -53,7 +56,7 @@ public class IndexedSearchClusterChangeValidator implements ChangeValidator {
filter(db -> db.getName().equals(docTypeName)).findFirst();
if (nextDb.isPresent()) {
result.addAll(validateDocumentDatabase(currentCluster, nextCluster, docTypeName,
- currentDb, nextDb.get(), overrides));
+ currentDb, nextDb.get(), overrides, now));
}
}
return result;
@@ -64,11 +67,12 @@ public class IndexedSearchClusterChangeValidator implements ChangeValidator {
String docTypeName,
DocumentDatabase currentDb,
DocumentDatabase nextDb,
- ValidationOverrides overrides) {
+ ValidationOverrides overrides,
+ Instant now) {
NewDocumentType currentDocType = currentCluster.getDocumentDefinitions().get(docTypeName);
NewDocumentType nextDocType = nextCluster.getDocumentDefinitions().get(docTypeName);
List<VespaConfigChangeAction> result =
- new DocumentDatabaseChangeValidator(currentDb, currentDocType, nextDb, nextDocType).validate(overrides);
+ new DocumentDatabaseChangeValidator(currentDb, currentDocType, nextDb, nextDocType).validate(overrides, now);
return modifyActions(result, getSearchNodeServices(nextCluster.getSearch().getIndexed()), docTypeName);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java
index e876630a401..908809b4b44 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java
@@ -3,12 +3,11 @@ package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationId;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
-import com.yahoo.vespa.model.application.validation.change.ChangeValidator;
-import com.yahoo.vespa.model.application.validation.change.VespaRefeedAction;
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -22,13 +21,14 @@ import java.util.Optional;
public class IndexingModeChangeValidator implements ChangeValidator {
@Override
- public List<ConfigChangeAction> validate(VespaModel currentModel, VespaModel nextModel, ValidationOverrides overrides) {
+ public List<ConfigChangeAction> validate(VespaModel currentModel, VespaModel nextModel,
+ ValidationOverrides overrides, Instant now) {
List<ConfigChangeAction> actions = new ArrayList<>();
for (Map.Entry<String, ContentCluster> currentEntry : currentModel.getContentClusters().entrySet()) {
ContentCluster nextCluster = nextModel.getContentClusters().get(currentEntry.getKey());
if (nextCluster == null) continue;
- Optional<ConfigChangeAction> change = validateContentCluster(currentEntry.getValue(), nextCluster, overrides);
+ Optional<ConfigChangeAction> change = validateContentCluster(currentEntry.getValue(), nextCluster, overrides, now);
if (change.isPresent())
actions.add(change.get());
}
@@ -36,16 +36,17 @@ public class IndexingModeChangeValidator implements ChangeValidator {
}
private Optional<ConfigChangeAction> validateContentCluster(ContentCluster currentCluster, ContentCluster nextCluster,
- ValidationOverrides overrides) {
- final boolean currentClusterIsIndexed = currentCluster.getSearch().hasIndexedCluster();
- final boolean nextClusterIsIndexed = nextCluster.getSearch().hasIndexedCluster();
+ ValidationOverrides overrides, Instant now) {
+ boolean currentClusterIsIndexed = currentCluster.getSearch().hasIndexedCluster();
+ boolean nextClusterIsIndexed = nextCluster.getSearch().hasIndexedCluster();
if (currentClusterIsIndexed == nextClusterIsIndexed) return Optional.empty();
return Optional.of(VespaRefeedAction.of(ValidationId.indexModeChange.value(),
overrides,
"Cluster '" + currentCluster.getName() + "' changed indexing mode from '" +
- indexingMode(currentClusterIsIndexed) + "' to '" + indexingMode(nextClusterIsIndexed) + "'"));
+ indexingMode(currentClusterIsIndexed) + "' to '" + indexingMode(nextClusterIsIndexed) + "'",
+ now));
}
private String indexingMode(boolean isIndexed) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java
index 7ead547e042..840ab69ba08 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java
@@ -5,10 +5,9 @@ import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.config.model.producer.AbstractConfigProducerRoot;
import com.yahoo.vespa.model.Service;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
-import com.yahoo.vespa.model.application.validation.change.ChangeValidator;
-import com.yahoo.vespa.model.application.validation.change.VespaRestartAction;
+import com.yahoo.config.application.api.ValidationOverrides;
+import java.time.Instant;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -25,7 +24,7 @@ public class StartupCommandChangeValidator implements ChangeValidator {
@Override
public List<ConfigChangeAction> validate(VespaModel currentModel, VespaModel nextModel,
- ValidationOverrides overrides) {
+ ValidationOverrides overrides, Instant now) {
return findServicesWithChangedStartupCommmand(currentModel, nextModel).collect(Collectors.toList());
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java
index 502b1b42aba..0fd38e5dbdd 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java
@@ -3,8 +3,9 @@ package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeRefeedAction;
import com.yahoo.config.model.api.ServiceInfo;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
+import java.time.Instant;
import java.util.Collections;
import java.util.List;
@@ -26,29 +27,31 @@ public class VespaRefeedAction extends VespaConfigChangeAction implements Config
private final String documentType;
private final boolean allowed;
+ private final Instant now;
- private VespaRefeedAction(String name, String message, List<ServiceInfo> services, String documentType, boolean allowed) {
+ private VespaRefeedAction(String name, String message, List<ServiceInfo> services, String documentType, boolean allowed, Instant now) {
super(message, services);
this.name = name;
this.documentType = documentType;
this.allowed = allowed;
+ this.now = now;
}
/** Creates a refeed action with some missing information */
// TODO: We should require document type or model its absence properly
- public static VespaRefeedAction of(String name, ValidationOverrides overrides, String message) {
- return new VespaRefeedAction(name, message, Collections.emptyList(), "", overrides.allows(name));
+ public static VespaRefeedAction of(String name, ValidationOverrides overrides, String message, Instant now) {
+ return new VespaRefeedAction(name, message, Collections.emptyList(), "", overrides.allows(name, now), now);
}
/** Creates a refeed action */
public static VespaRefeedAction of(String name, ValidationOverrides overrides, String message,
- List<ServiceInfo> services, String documentType) {
- return new VespaRefeedAction(name, message, services, documentType, overrides.allows(name));
+ List<ServiceInfo> services, String documentType, Instant now) {
+ return new VespaRefeedAction(name, message, services, documentType, overrides.allows(name, now), now);
}
@Override
public VespaConfigChangeAction modifyAction(String newMessage, List<ServiceInfo> newServices, String documentType) {
- return new VespaRefeedAction(name, newMessage, newServices, documentType, allowed);
+ return new VespaRefeedAction(name, newMessage, newServices, documentType, allowed, now);
}
@Override
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java
index e534bdfc225..95ae03d4e5f 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java
@@ -5,11 +5,12 @@ import com.yahoo.documentmodel.NewDocumentType;
import com.yahoo.searchdefinition.derived.AttributeFields;
import com.yahoo.searchdefinition.derived.IndexSchema;
import com.yahoo.searchdefinition.document.Attribute;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import com.yahoo.vespa.model.application.validation.change.VespaRefeedAction;
import com.yahoo.vespa.model.application.validation.change.VespaRestartAction;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -46,12 +47,12 @@ public class AttributeChangeValidator {
this.nextDocType = nextDocType;
}
- public List<VespaConfigChangeAction> validate(final ValidationOverrides overrides) {
+ public List<VespaConfigChangeAction> validate(ValidationOverrides overrides, Instant now) {
List<VespaConfigChangeAction> result = new ArrayList<>();
result.addAll(validateAddAttributeAspect());
result.addAll(validateRemoveAttributeAspect());
result.addAll(validateAttributeSettings());
- result.addAll(validateTensorTypes(overrides));
+ result.addAll(validateTensorTypes(overrides, now));
return result;
}
@@ -94,7 +95,7 @@ public class AttributeChangeValidator {
return result;
}
- private List<VespaConfigChangeAction> validateTensorTypes(final ValidationOverrides overrides) {
+ private List<VespaConfigChangeAction> validateTensorTypes(final ValidationOverrides overrides, Instant now) {
final List<VespaConfigChangeAction> result = new ArrayList<>();
for (final Attribute nextAttr : nextFields.attributes()) {
@@ -109,7 +110,7 @@ public class AttributeChangeValidator {
// Tensor attribute has changed type
if (!nextAttr.tensorType().get().equals(currentAttr.tensorType().get())) {
- result.add(createTensorTypeChangedRefeedAction(currentAttr, nextAttr, overrides));
+ result.add(createTensorTypeChangedRefeedAction(currentAttr, nextAttr, overrides, now));
}
}
}
@@ -117,7 +118,7 @@ public class AttributeChangeValidator {
return result;
}
- private static VespaRefeedAction createTensorTypeChangedRefeedAction(Attribute currentAttr, Attribute nextAttr, ValidationOverrides overrides) {
+ private static VespaRefeedAction createTensorTypeChangedRefeedAction(Attribute currentAttr, Attribute nextAttr, ValidationOverrides overrides, Instant now) {
return VespaRefeedAction.of(
"tensor-type-change",
overrides,
@@ -125,7 +126,7 @@ public class AttributeChangeValidator {
.addChange(
"tensor type",
currentAttr.tensorType().get().toString(),
- nextAttr.tensorType().get().toString()).build());
+ nextAttr.tensorType().get().toString()).build(), now);
}
private static void validateAttributeSetting(Attribute currentAttr, Attribute nextAttr,
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java
index dd5aa6cf363..bd287f83a1a 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java
@@ -2,10 +2,11 @@
package com.yahoo.vespa.model.application.validation.change.search;
import com.yahoo.documentmodel.NewDocumentType;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import com.yahoo.vespa.model.search.DocumentDatabase;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@@ -32,29 +33,29 @@ public class DocumentDatabaseChangeValidator {
this.nextDocType = nextDocType;
}
- public List<VespaConfigChangeAction> validate(final ValidationOverrides overrides) {
+ public List<VespaConfigChangeAction> validate(ValidationOverrides overrides, Instant now) {
List<VespaConfigChangeAction> result = new ArrayList<>();
- result.addAll(validateAttributeChanges(overrides));
- result.addAll(validateIndexingScriptChanges(overrides));
- result.addAll(validateDocumentTypeChanges(overrides));
+ result.addAll(validateAttributeChanges(overrides, now));
+ result.addAll(validateIndexingScriptChanges(overrides, now));
+ result.addAll(validateDocumentTypeChanges(overrides, now));
return result;
}
- private List<VespaConfigChangeAction> validateAttributeChanges(final ValidationOverrides overrides) {
+ private List<VespaConfigChangeAction> validateAttributeChanges(ValidationOverrides overrides, Instant now) {
return new AttributeChangeValidator(
currentDatabase.getDerivedConfiguration().getAttributeFields(),
currentDatabase.getDerivedConfiguration().getIndexSchema(), currentDocType,
nextDatabase.getDerivedConfiguration().getAttributeFields(),
- nextDatabase.getDerivedConfiguration().getIndexSchema(), nextDocType).validate(overrides);
+ nextDatabase.getDerivedConfiguration().getIndexSchema(), nextDocType).validate(overrides, now);
}
- private List<VespaConfigChangeAction> validateIndexingScriptChanges(ValidationOverrides overrides) {
+ private List<VespaConfigChangeAction> validateIndexingScriptChanges(ValidationOverrides overrides, Instant now) {
return new IndexingScriptChangeValidator(currentDatabase.getDerivedConfiguration().getSearch(),
- nextDatabase.getDerivedConfiguration().getSearch()).validate(overrides);
+ nextDatabase.getDerivedConfiguration().getSearch()).validate(overrides, now);
}
- private List<VespaConfigChangeAction> validateDocumentTypeChanges(ValidationOverrides overrides) {
- return new DocumentTypeChangeValidator(currentDocType, nextDocType).validate(overrides);
+ private List<VespaConfigChangeAction> validateDocumentTypeChanges(ValidationOverrides overrides, Instant now) {
+ return new DocumentTypeChangeValidator(currentDocType, nextDocType).validate(overrides, now);
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java
index 745ecd58d34..4fd5e82e93f 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java
@@ -4,10 +4,11 @@ package com.yahoo.vespa.model.application.validation.change.search;
import com.yahoo.document.StructDataType;
import com.yahoo.documentmodel.NewDocumentType;
import com.yahoo.document.Field;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import com.yahoo.vespa.model.application.validation.change.VespaRefeedAction;
+import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;
@@ -132,7 +133,7 @@ public class DocumentTypeChangeValidator {
this.nextDocType = nextDocType;
}
- public List<VespaConfigChangeAction> validate(ValidationOverrides overrides) {
+ public List<VespaConfigChangeAction> validate(ValidationOverrides overrides, Instant now) {
return currentDocType.getAllFields().stream().
map(field -> createFieldChange(field, nextDocType)).
filter(fieldChange -> fieldChange.valid() && fieldChange.changedType()).
@@ -140,7 +141,8 @@ public class DocumentTypeChangeValidator {
overrides,
new ChangeMessageBuilder(fieldChange.fieldName()).
addChange("data type", fieldChange.currentTypeName(),
- fieldChange.nextTypeName()).build())).
+ fieldChange.nextTypeName()).build(),
+ now)).
collect(Collectors.toList());
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java
index cb3f0d40742..ff9230b34f3 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java
@@ -7,11 +7,12 @@ import com.yahoo.vespa.indexinglanguage.ExpressionConverter;
import com.yahoo.vespa.indexinglanguage.expressions.Expression;
import com.yahoo.vespa.indexinglanguage.expressions.OutputExpression;
import com.yahoo.vespa.indexinglanguage.expressions.ScriptExpression;
-import com.yahoo.vespa.model.application.validation.ValidationId;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import com.yahoo.vespa.model.application.validation.change.VespaRefeedAction;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -32,27 +33,27 @@ public class IndexingScriptChangeValidator {
this.nextSearch = nextSearch;
}
- public List<VespaConfigChangeAction> validate(ValidationOverrides overrides) {
+ public List<VespaConfigChangeAction> validate(ValidationOverrides overrides, Instant now) {
List<VespaConfigChangeAction> result = new ArrayList<>();
for (SDField nextField : nextSearch.allConcreteFields()) {
String fieldName = nextField.getName();
SDField currentField = currentSearch.getConcreteField(fieldName);
if (currentField != null) {
- validateScripts(currentField, nextField, overrides).ifPresent(r -> result.add(r));
+ validateScripts(currentField, nextField, overrides, now).ifPresent(r -> result.add(r));
}
}
return result;
}
private Optional<VespaConfigChangeAction> validateScripts(SDField currentField, SDField nextField,
- ValidationOverrides overrides) {
+ ValidationOverrides overrides, Instant now) {
ScriptExpression currentScript = currentField.getIndexingScript();
ScriptExpression nextScript = nextField.getIndexingScript();
if ( ! equalScripts(currentScript, nextScript)) {
ChangeMessageBuilder messageBuilder = new ChangeMessageBuilder(nextField.getName());
new IndexingScriptChangeMessageBuilder(currentSearch, currentField, nextSearch, nextField).populate(messageBuilder);
messageBuilder.addChange("indexing script", currentScript.toString(), nextScript.toString());
- return Optional.of(VespaRefeedAction.of(ValidationId.indexingChange.value(), overrides, messageBuilder.build()));
+ return Optional.of(VespaRefeedAction.of(ValidationId.indexingChange.value(), overrides, messageBuilder.build(), now));
}
return Optional.empty();
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/xml/ValidationOverridesXMLReader.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/xml/ValidationOverridesXMLReader.java
deleted file mode 100644
index 75a7dc84eaa..00000000000
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/xml/ValidationOverridesXMLReader.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2017 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.xml;
-
-import com.yahoo.text.XML;
-import com.yahoo.vespa.model.application.validation.ValidationId;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
-import org.w3c.dom.Element;
-
-import java.io.Reader;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.ZoneOffset;
-import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Reader of the validation-allows.xml file in application packages.
- *
- * @author bratseth
- */
-public class ValidationOverridesXMLReader {
-
- /**
- * Returns a ValidationOverrides instance with the content of the given Reader.
- * An empty ValidationOverrides is returned if the argument is empty.
- *
- * @param reader the reader which optionally contains a validation-overrides XML structure
- * @param now the instant to use as "now", settable for unit testing
- * @return a ValidationOverrides from the argument
- * @throws IllegalArgumentException if the validation-allows.xml file exists but is invalid
- */
- public ValidationOverrides read(Optional<Reader> reader, Instant now) {
- if ( ! reader.isPresent()) return ValidationOverrides.empty();
-
- try {
- // Assume valid structure is ensured by schema validation
- Element root = XML.getDocument(reader.get()).getDocumentElement();
- List<ValidationOverrides.Allow> overrides = new ArrayList<>();
- for (Element allow : XML.getChildren(root, "allow")) {
- Instant until = LocalDate.parse(allow.getAttribute("until"), DateTimeFormatter.ISO_DATE)
- .atStartOfDay().atZone(ZoneOffset.UTC).toInstant()
- .plus(Duration.ofDays(1)); // Make the override valid *on* the "until" date
- Optional<ValidationId> validationId = ValidationId.from(XML.getValue(allow));
- if (validationId.isPresent()) // skip unknonw ids as they may be valid for other model versions
- overrides.add(new ValidationOverrides.Allow(validationId.get(), until));
- }
- return new ValidationOverrides(overrides, now);
- }
- catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("validation-overrides is invalid", e);
- }
- }
-
-}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ValidationOverrideTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ValidationOverrideTest.java
deleted file mode 100644
index 61aa847edeb..00000000000
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ValidationOverrideTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2017 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;
-
-import com.yahoo.test.ManualClock;
-import com.yahoo.vespa.model.application.validation.xml.ValidationOverridesXMLReader;
-import org.junit.Test;
-import org.xml.sax.SAXException;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneOffset;
-import java.time.format.DateTimeFormatter;
-import java.util.Optional;
-
-import static org.junit.Assert.fail;
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author bratseth
- */
-public class ValidationOverrideTest {
-
- @Test
- public void testValidationOverridesInIsolation() throws IOException, SAXException {
- String validationOverrides =
- "<validation-overrides>" +
- " <allow until='2000-01-01'>indexing-change</allow>" +
- " <allow until='2000-01-03' comment='any text'>indexing-mode-change</allow>" +
- "</validation-overrides>";
-
- {
-
- ValidationOverrides overrides = new ValidationOverridesXMLReader().read(Optional.of(new StringReader(validationOverrides)),
- ManualClock.at("2000-01-01T23:59:00"));
- assertOverridden("indexing-change", overrides);
- assertOverridden("indexing-mode-change", overrides);
- assertNotOverridden("field-type-change", overrides);
- }
-
- {
- ValidationOverrides overrides = new ValidationOverridesXMLReader().read(Optional.of(new StringReader(validationOverrides)),
- ManualClock.at("2000-01-02T00:00:00"));
- assertNotOverridden("indexing-change", overrides);
- assertOverridden("indexing-mode-change", overrides);
- assertNotOverridden("field-type-change", overrides);
- }
-
- {
- ValidationOverrides overrides = new ValidationOverridesXMLReader().read(Optional.of(new StringReader(validationOverrides)),
- ManualClock.at("2000-01-04T00:00:00"));
- assertNotOverridden("indexing-change", overrides);
- assertNotOverridden("indexing-mode-change", overrides);
- assertNotOverridden("field-type-change", overrides);
- }
-
- }
-
- @Test
- public void testInvalidOverridePeriod() throws IOException, SAXException {
- String validationOverrides =
- "<validation-overrides>" +
- " <allow until='2000-02-02'>indexing-change</allow>" +
- "</validation-overrides>";
-
- try {
- new ValidationOverridesXMLReader().read(Optional.of(new StringReader(validationOverrides)),
- ManualClock.at("2000-01-01T23:59:00"));
- fail("Expected validation interval override validation validation failure");
- }
- catch (IllegalArgumentException e) {
- assertEquals("validation-overrides is invalid", e.getMessage());
- assertEquals("allow 'indexing-change' until 2000-02-03T00:00:00Z is too far in the future: Max 30 days is allowed",
- e.getCause().getMessage());
- }
- }
-
- private void assertOverridden(String validationId, ValidationOverrides overrides) {
- overrides.invalid(ValidationId.from(validationId).get(), "message"); // should not throw exception
- }
-
- private void assertNotOverridden(String validationId, ValidationOverrides overrides) {
- try {
- overrides.invalid(ValidationId.from(validationId).get(), "message");
- fail("Expected '" + validationId + "' to not be overridden");
- }
- catch (ValidationOverrides.ValidationException expected) {
- }
- }
-
-}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java
index 8a9d1e9963b..3738add1a6d 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java
@@ -2,11 +2,9 @@
package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ServiceInfo;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
-import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
-import com.yahoo.vespa.model.application.validation.change.VespaRefeedAction;
-import com.yahoo.vespa.model.application.validation.change.VespaRestartAction;
+import com.yahoo.config.application.api.ValidationOverrides;
+import java.time.Instant;
import java.util.List;
public class ConfigChangeTestUtils {
@@ -19,12 +17,12 @@ public class ConfigChangeTestUtils {
return new VespaRestartAction(message, services);
}
- public static VespaConfigChangeAction newRefeedAction(String name, ValidationOverrides overrides, String message) {
- return VespaRefeedAction.of(name, overrides, message);
+ public static VespaConfigChangeAction newRefeedAction(String name, ValidationOverrides overrides, String message, Instant now) {
+ return VespaRefeedAction.of(name, overrides, message, now);
}
public static VespaConfigChangeAction newRefeedAction(String name, ValidationOverrides overrides, String message,
- List<ServiceInfo> services, String documentType) {
- return VespaRefeedAction.of(name, overrides, message, services, documentType);
+ List<ServiceInfo> services, String documentType, Instant now) {
+ return VespaRefeedAction.of(name, overrides, message, services, documentType, now);
}
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidatorTest.java
index 0b7ef914abb..cbb725987eb 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidatorTest.java
@@ -14,12 +14,13 @@ import com.yahoo.vespa.model.Host;
import com.yahoo.vespa.model.HostResource;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.application.validation.RestartConfigs;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.test.utils.DeployLoggerStub;
import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg;
import org.junit.Before;
import org.junit.Test;
+import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -143,7 +144,7 @@ public class ConfigValueChangeValidatorTest {
private List<ConfigChangeAction> getConfigChanges(VespaModel currentModel, VespaModel nextModel) {
ConfigValueChangeValidator validator = new ConfigValueChangeValidator(logger);
- return validator.validate(currentModel, nextModel, ValidationOverrides.empty());
+ return validator.validate(currentModel, nextModel, ValidationOverrides.empty, Instant.now());
}
private List<ConfigChangeAction> getConfigChanges(AbstractConfigProducerRoot currentModel,
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidatorTest.java
index 952377dcb4c..1a6bd89bb3f 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidatorTest.java
@@ -4,10 +4,11 @@ package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.vespa.defaults.Defaults;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg;
import org.junit.Test;
+import java.time.Instant;
import java.util.Collections;
import java.util.List;
@@ -45,7 +46,7 @@ public class ContainerRestartValidatorTest {
private static List<ConfigChangeAction> validateModel(VespaModel current, VespaModel next) {
return new ContainerRestartValidator()
- .validate(current, next, new ValidationOverrides(Collections.emptyList()));
+ .validate(current, next, new ValidationOverrides(Collections.emptyList()), Instant.now());
}
private static VespaModel createModel(boolean restartOnDeploy) {
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java
index 164b5a79e11..387b8912018 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java
@@ -4,15 +4,13 @@ package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.config.model.api.ServiceInfo;
import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
-import com.yahoo.vespa.model.application.validation.change.IndexedSearchClusterChangeValidator;
-import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
-import com.yahoo.vespa.model.application.validation.change.VespaRefeedAction;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.content.utils.ApplicationPackageBuilder;
import com.yahoo.vespa.model.content.utils.ContentClusterBuilder;
import com.yahoo.vespa.model.content.utils.SearchDefinitionBuilder;
import org.junit.Test;
+import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -78,7 +76,7 @@ public class IndexedSearchClusterChangeValidatorTest {
public void assertValidation() {
List<ConfigChangeAction> act = normalizeServicesInActions(validator.validate(currentModel, nextModel,
- ValidationOverrides.empty()));
+ ValidationOverrides.empty, Instant.now()));
assertThat(act.size(), is(0));
}
@@ -105,7 +103,7 @@ public class IndexedSearchClusterChangeValidatorTest {
public void assertValidation(List<ConfigChangeAction> exp) {
List<ConfigChangeAction> act = normalizeServicesInActions(validator.validate(currentModel, nextModel,
- ValidationOverrides.empty()));
+ ValidationOverrides.empty, Instant.now()));
exp.sort((lhs, rhs) -> lhs.getMessage().compareTo(rhs.getMessage()));
act.sort((lhs, rhs) -> lhs.getMessage().compareTo(rhs.getMessage()));
assertThat(act, equalTo(exp));
@@ -168,8 +166,8 @@ public class IndexedSearchClusterChangeValidatorTest {
public void requireThatChangingFieldTypeIsDiscovered() {
Fixture f = Fixture.newOneDocFixture(STRING_FIELD, INT_FIELD);
f.assertValidation(Arrays.asList(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Document type 'd1': " + FIELD_TYPE_CHANGE_MSG, FOO_SERVICE, "d1")));
+ ValidationOverrides.empty,
+ "Document type 'd1': " + FIELD_TYPE_CHANGE_MSG, FOO_SERVICE, "d1", Instant.now())));
}
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java
index a7cce283354..eab12db20ef 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java
@@ -1,10 +1,11 @@
// Copyright 2017 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.search;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import org.junit.Test;
+import java.time.Instant;
import java.util.List;
import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newRefeedAction;
@@ -28,7 +29,7 @@ public class AttributeChangeValidatorTest {
@Override
public List<VespaConfigChangeAction> validate() {
- return validator.validate(ValidationOverrides.empty());
+ return validator.validate(ValidationOverrides.empty, Instant.now());
}
}
@@ -115,8 +116,8 @@ public class AttributeChangeValidatorTest {
"field f1 type tensor(y[]) { indexing: attribute \n attribute: tensor(y[]) }")
.assertValidation(newRefeedAction(
"tensor-type-change",
- ValidationOverrides.empty(),
- "Field 'f1' changed: tensor type: 'tensor(x[100])' -> 'tensor(y[])'"));
+ ValidationOverrides.empty,
+ "Field 'f1' changed: tensor type: 'tensor(x[100])' -> 'tensor(y[])'", Instant.now()));
}
@Test
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java
index 1a82fed42b7..ba736af2159 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java
@@ -1,10 +1,11 @@
// Copyright 2017 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.search;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import org.junit.Test;
+import java.time.Instant;
import java.util.Arrays;
import java.util.List;
@@ -23,7 +24,7 @@ public class DocumentDatabaseChangeValidatorTest {
@Override
public List<VespaConfigChangeAction> validate() {
- return validator.validate(ValidationOverrides.empty());
+ return validator.validate(ValidationOverrides.empty, Instant.now());
}
}
@@ -39,12 +40,12 @@ public class DocumentDatabaseChangeValidatorTest {
f.assertValidation(Arrays.asList(
newRestartAction("Field 'f1' changed: add attribute aspect"),
newRefeedAction("indexing-change",
- ValidationOverrides.empty(),
+ ValidationOverrides.empty,
"Field 'f2' changed: add index aspect, indexing script: '{ input f2 | summary f2; }' -> " +
- "'{ input f2 | tokenize normalize stem:\"SHORTEST\" | index f2 | summary f2; }'"),
+ "'{ input f2 | tokenize normalize stem:\"SHORTEST\" | index f2 | summary f2; }'", Instant.now()),
newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f3' changed: data type: 'int' -> 'string'")));
+ ValidationOverrides.empty,
+ "Field 'f3' changed: data type: 'int' -> 'string'", Instant.now())));
}
@Test
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java
index 4bf7be82318..a4ab5ebdb5e 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java
@@ -7,11 +7,12 @@ import com.yahoo.document.ReferenceDataType;
import com.yahoo.document.StructDataType;
import com.yahoo.documentmodel.NewDocumentType;
import com.yahoo.searchdefinition.FieldSets;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import com.yahoo.vespa.model.application.validation.change.VespaRefeedAction;
import org.junit.Test;
+import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -29,6 +30,7 @@ import static org.junit.Assert.assertTrue;
public class DocumentTypeChangeValidatorTest {
private static class Fixture extends ContentClusterFixture {
+
DocumentTypeChangeValidator validator;
public Fixture(String currentSd, String nextSd) throws Exception {
@@ -38,7 +40,7 @@ public class DocumentTypeChangeValidatorTest {
@Override
public List<VespaConfigChangeAction> validate() {
- return validator.validate(ValidationOverrides.empty());
+ return validator.validate(ValidationOverrides.empty, Instant.now());
}
}
@@ -62,8 +64,9 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("field f1 type string { indexing: summary }",
"field f1 type int { indexing: summary }");
f.assertValidation(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f1' changed: data type: 'string' -> 'int'"));
+ ValidationOverrides.empty,
+ "Field 'f1' changed: data type: 'string' -> 'int'",
+ Instant.now()));
}
@Test
@@ -71,8 +74,8 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("field f1 type string { indexing: summary }",
"field f1 type array<string> { indexing: summary }");
f.assertValidation(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f1' changed: data type: 'string' -> 'Array<string>'"));
+ ValidationOverrides.empty,
+ "Field 'f1' changed: data type: 'string' -> 'Array<string>'", Instant.now()));
}
@@ -88,8 +91,8 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("field f1 type array<string> { indexing: summary }",
"field f1 type array<int> { indexing: summary }");
f.assertValidation(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f1' changed: data type: 'Array<string>' -> 'Array<int>'"));
+ ValidationOverrides.empty,
+ "Field 'f1' changed: data type: 'Array<string>' -> 'Array<int>'", Instant.now()));
}
@Test
@@ -97,8 +100,8 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("field f1 type array<string> { indexing: summary }",
"field f1 type weightedset<string> { indexing: summary }");
f.assertValidation(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f1' changed: data type: 'Array<string>' -> 'WeightedSet<string>'"));
+ ValidationOverrides.empty,
+ "Field 'f1' changed: data type: 'Array<string>' -> 'WeightedSet<string>'", Instant.now()));
}
@Test
@@ -106,11 +109,11 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("field f1 type string { indexing: summary } field f2 type int { indexing: summary }" ,
"field f2 type string { indexing: summary } field f1 type int { indexing: summary }");
f.assertValidation(Arrays.asList(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f1' changed: data type: 'string' -> 'int'"),
+ ValidationOverrides.empty,
+ "Field 'f1' changed: data type: 'string' -> 'int'", Instant.now()),
newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f2' changed: data type: 'int' -> 'string'")));
+ ValidationOverrides.empty,
+ "Field 'f2' changed: data type: 'int' -> 'string'", Instant.now())));
}
@Test
@@ -146,8 +149,8 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("struct s1 { field f1 type string {} } field f2 type s1 { indexing: summary }",
"struct s1 { field f1 type int {} } field f2 type s1 { indexing: summary }");
f.assertValidation(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f2' changed: data type: 's1:{f1:string}' -> 's1:{f1:int}'"));
+ ValidationOverrides.empty,
+ "Field 'f2' changed: data type: 's1:{f1:string}' -> 's1:{f1:int}'", Instant.now()));
}
@Test
@@ -155,8 +158,8 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("struct s1 { field f1 type array<string> {} } field f2 type s1 { indexing: summary }",
"struct s1 { field f1 type array<int> {} } field f2 type s1 { indexing: summary }");
f.assertValidation(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f2' changed: data type: 's1:{f1:Array<string>}' -> 's1:{f1:Array<int>}'"));
+ ValidationOverrides.empty,
+ "Field 'f2' changed: data type: 's1:{f1:Array<string>}' -> 's1:{f1:Array<int>}'", Instant.now()));
}
@Test
@@ -164,8 +167,8 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("struct s1 { field f1 type string {} } struct s2 { field f2 type s1 {} } field f3 type s2 { indexing: summary }",
"struct s1 { field f1 type int {} } struct s2 { field f2 type s1 {} } field f3 type s2 { indexing: summary }");
f.assertValidation(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f3' changed: data type: 's2:{s1:{f1:string}}' -> 's2:{s1:{f1:int}}'"));
+ ValidationOverrides.empty,
+ "Field 'f3' changed: data type: 's2:{s1:{f1:string}}' -> 's2:{s1:{f1:int}}'", Instant.now()));
}
@Test
@@ -173,8 +176,8 @@ public class DocumentTypeChangeValidatorTest {
Fixture f = new Fixture("struct s1 { field f1 type string {} field f2 type int {} } field f3 type s1 { indexing: summary }",
"struct s1 { field f1 type int {} field f2 type string {} } field f3 type s1 { indexing: summary }");
f.assertValidation(newRefeedAction("field-type-change",
- ValidationOverrides.empty(),
- "Field 'f3' changed: data type: 's1:{f1:string,f2:int}' -> 's1:{f1:int,f2:string}'"));
+ ValidationOverrides.empty,
+ "Field 'f3' changed: data type: 's1:{f1:string,f2:int}' -> 's1:{f1:int,f2:string}'", Instant.now()));
}
@Test
@@ -182,7 +185,7 @@ public class DocumentTypeChangeValidatorTest {
DocumentTypeChangeValidator validator = new DocumentTypeChangeValidator(
createDocumentTypeWithReferenceField("oldDoc"),
createDocumentTypeWithReferenceField("newDoc"));
- List<VespaConfigChangeAction> result = validator.validate(ValidationOverrides.empty());
+ List<VespaConfigChangeAction> result = validator.validate(ValidationOverrides.empty, Instant.now());
assertEquals(1, result.size());
VespaConfigChangeAction action = result.get(0);
assertTrue(action instanceof VespaRefeedAction);
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java
index dde8479ad19..3fe3c27a648 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java
@@ -2,11 +2,12 @@
package com.yahoo.vespa.model.application.validation.change.search;
import com.yahoo.vespa.indexinglanguage.expressions.ScriptExpression;
-import com.yahoo.vespa.model.application.validation.ValidationOverrides;
+import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import com.yahoo.vespa.model.application.validation.change.VespaRefeedAction;
import org.junit.Test;
+import java.time.Instant;
import java.util.Arrays;
import java.util.List;
@@ -25,7 +26,7 @@ public class IndexingScriptChangeValidatorTest {
@Override
public List<VespaConfigChangeAction> validate() {
- return validator.validate(ValidationOverrides.empty());
+ return validator.validate(ValidationOverrides.empty, Instant.now());
}
}
@@ -52,10 +53,11 @@ public class IndexingScriptChangeValidatorTest {
private static VespaConfigChangeAction expectedAction(String field, String changedMsg, String fromScript, String toScript) {
return VespaRefeedAction.of("indexing-change",
- ValidationOverrides.empty(),
+ ValidationOverrides.empty,
"Field '" + field + "' changed: " +
(changedMsg.isEmpty() ? "" : changedMsg + ", ") +
- "indexing script: '" + fromScript + "' -> '" + toScript + "'");
+ "indexing script: '" + fromScript + "' -> '" + toScript + "'",
+ Instant.now());
}
@Test
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index 5d74760ca9a..61458d871ac 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -207,7 +207,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
private Application getApplication(Tenant tenant, ApplicationId applicationId) {
long sessionId = getSessionIdForApplication(tenant, applicationId);
RemoteSession session = tenant.getRemoteSessionRepo().getSession(sessionId, 0);
- return session.ensureApplicationLoaded().getForVersionOrLatest(Optional.empty());
+ return session.ensureApplicationLoaded().getForVersionOrLatest(Optional.empty(), clock.instant());
}
public long getSessionIdForApplication(Tenant tenant, ApplicationId applicationId) {
@@ -307,7 +307,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
LocalSession session = getLocalSession(tenant, sessionId);
ApplicationId appId = params.getApplicationId();
Optional<ApplicationSet> currentActiveApplicationSet = getCurrentActiveApplicationSet(tenant, appId);
- return session.prepare(logger, params, currentActiveApplicationSet, tenant.getPath());
+ return session.prepare(logger, params, currentActiveApplicationSet, tenant.getPath(), clock.instant());
}
private List<ApplicationId> listApplicationIds(Tenant tenant) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java
index 6b9c82a04ee..105bd9a5b2a 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java
@@ -22,6 +22,7 @@ import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory;
import com.yahoo.vespa.config.server.rpc.ConfigResponseFactoryFactory;
import java.io.IOException;
+import java.time.Instant;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -74,7 +75,7 @@ public class SuperModelRequestHandler implements RequestHandler {
newModels.put(tenant, new LinkedHashMap<>());
}
// TODO: Should supermodel care about multiple versions?
- newModels.get(tenant).put(applicationSet.getId(), applicationSet.getForVersionOrLatest(Optional.empty()));
+ newModels.get(tenant).put(applicationSet.getId(), applicationSet.getForVersionOrLatest(Optional.empty(), Instant.now()));
handler = createNewHandler(newModels);
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java
index 019a8123648..459bee99d75 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.config.server.application;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Version;
+import java.time.Instant;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
@@ -48,19 +49,19 @@ public final class ApplicationMapper {
*
* @return the matching application, or null if none matches
*/
- public Application getForVersion(ApplicationId applicationId, Optional<Version> vespaVersion) throws VersionDoesNotExistException {
- return getApplicationSet(applicationId).getForVersionOrLatest(vespaVersion);
+ public Application getForVersion(ApplicationId applicationId, Optional<Version> vespaVersion, Instant now) throws VersionDoesNotExistException {
+ return getApplicationSet(applicationId).getForVersionOrLatest(vespaVersion, now);
}
/** Returns whether this registry has an application for the given application id */
- public boolean hasApplication(ApplicationId applicationId) {
- return hasApplicationForVersion(applicationId, Optional.<Version>empty());
+ public boolean hasApplication(ApplicationId applicationId, Instant now) {
+ return hasApplicationForVersion(applicationId, Optional.<Version>empty(), now);
}
/** Returns whether this registry has an application for the given application id and vespa version */
- public boolean hasApplicationForVersion(ApplicationId applicationId, Optional<Version> vespaVersion) {
+ public boolean hasApplicationForVersion(ApplicationId applicationId, Optional<Version> vespaVersion, Instant now) {
try {
- return getForVersion(applicationId, vespaVersion) != null;
+ return getForVersion(applicationId, vespaVersion, now) != null;
}
catch (VersionDoesNotExistException | NotFoundException ex) {
return false;
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationSet.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationSet.java
index 6d6ed925ebd..7d46152dd4d 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationSet.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationSet.java
@@ -4,6 +4,7 @@ import com.yahoo.config.model.api.HostInfo;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Version;
+import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@@ -32,18 +33,18 @@ public final class ApplicationSet {
latestVersion = applications.keySet().stream().max((a, b) -> a.compareTo(b)).get();
}
- public Application getForVersionOrLatest(Optional<Version> optionalVersion) {
- return resolveForVersion(optionalVersion.orElse(latestVersion));
+ public Application getForVersionOrLatest(Optional<Version> optionalVersion, Instant now) {
+ return resolveForVersion(optionalVersion.orElse(latestVersion), now);
}
- private Application resolveForVersion(Version vespaVersion) {
+ private Application resolveForVersion(Version vespaVersion, Instant now) {
Application application = applications.get(vespaVersion);
if (application != null)
return application;
// Does the latest version specify we can use it regardless?
Application latest = applications.get(latestVersion);
- if (latest.getModel().allowModelVersionMismatch())
+ if (latest.getModel().allowModelVersionMismatch(now))
return latest;
throw new VersionDoesNotExistException(String.format("No application with vespa version %s exists", vespaVersion.toString()));
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
index b04b00b8223..61382af6a30 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
@@ -110,7 +110,8 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
.vespaVersion(version.toString())
.build(),
Optional.empty(),
- tenantPath);
+ tenantPath,
+ clock.instant());
this.prepared = true;
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
index a4a98dd3431..a805d335c2e 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
@@ -30,6 +30,7 @@ import com.yahoo.vespa.config.server.session.SessionZooKeeperClient;
import com.yahoo.vespa.config.server.session.SilentDeployLogger;
import com.yahoo.vespa.curator.Curator;
+import java.time.Instant;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Logger;
@@ -71,8 +72,11 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
}
@Override
- protected Application buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage,
- ApplicationId applicationId, com.yahoo.component.Version wantedNodeVespaVersion) {
+ protected Application buildModelVersion(ModelFactory modelFactory,
+ ApplicationPackage applicationPackage,
+ ApplicationId applicationId,
+ com.yahoo.component.Version wantedNodeVespaVersion,
+ Instant now) {
log.log(LogLevel.DEBUG, String.format("Loading model version %s for session %s application %s",
modelFactory.getVersion(), appGeneration, applicationId));
ServerCache cache = zkClient.loadServerCache();
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
index 0faee6a4eb7..509a26370ff 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
@@ -14,6 +14,7 @@ import com.yahoo.vespa.config.server.ConfigServerSpec;
import com.yahoo.vespa.config.server.deploy.ModelContextImpl;
import com.yahoo.vespa.config.server.http.UnknownVespaVersionException;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -42,7 +43,9 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
}
public List<MODELRESULT> buildModels(ApplicationId applicationId,
- com.yahoo.component.Version wantedNodeVespaVersion, ApplicationPackage applicationPackage) {
+ com.yahoo.component.Version wantedNodeVespaVersion,
+ ApplicationPackage applicationPackage,
+ Instant now) {
Set<Version> versions = modelFactoryRegistry.allVersions();
// If the application specifies a major, load models only for that
@@ -63,10 +66,10 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
for (int i = 0; i < majorVersions.size(); i++) {
try {
allApplicationModels.addAll(buildModelVersion(filterByMajorVersion(majorVersions.get(i), versions),
- applicationId, wantedNodeVespaVersion, applicationPackage));
+ applicationId, wantedNodeVespaVersion, applicationPackage, now));
// skip old config models if requested after we have found a major version which works
- if (allApplicationModels.size() > 0 && allApplicationModels.get(0).getModel().skipOldConfigModels())
+ if (allApplicationModels.size() > 0 && allApplicationModels.get(0).getModel().skipOldConfigModels(now))
break;
}
catch (OutOfCapacityException e) {
@@ -88,11 +91,16 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
private List<MODELRESULT> buildModelVersion(Set<Version> versions, ApplicationId applicationId,
com.yahoo.component.Version wantedNodeVespaVersion,
- ApplicationPackage applicationPackage) {
+ ApplicationPackage applicationPackage,
+ Instant now) {
Version latest = findLatest(versions);
// load latest application version
- MODELRESULT latestApplicationVersion = buildModelVersion(modelFactoryRegistry.getFactory(latest), applicationPackage, applicationId, wantedNodeVespaVersion);
- if (latestApplicationVersion.getModel().skipOldConfigModels()) {
+ MODELRESULT latestApplicationVersion = buildModelVersion(modelFactoryRegistry.getFactory(latest),
+ applicationPackage,
+ applicationId,
+ wantedNodeVespaVersion,
+ now);
+ if (latestApplicationVersion.getModel().skipOldConfigModels(now)) {
return Collections.singletonList(latestApplicationVersion);
}
else { // load old model versions
@@ -100,7 +108,11 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
allApplicationVersions.add(latestApplicationVersion);
for (Version version : versions) {
if (version.equals(latest)) continue; // already loaded
- allApplicationVersions.add(buildModelVersion(modelFactoryRegistry.getFactory(version), applicationPackage, applicationId, wantedNodeVespaVersion));
+ allApplicationVersions.add(buildModelVersion(modelFactoryRegistry.getFactory(version),
+ applicationPackage,
+ applicationId,
+ wantedNodeVespaVersion,
+ now));
}
return allApplicationVersions;
}
@@ -121,7 +133,8 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
protected abstract MODELRESULT buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage,
ApplicationId applicationId,
- com.yahoo.component.Version wantedNodeVespaVersion);
+ com.yahoo.component.Version wantedNodeVespaVersion,
+ Instant now);
protected ModelContext.Properties createModelContextProperties(ApplicationId applicationId,
ConfigserverConfig configserverConfig,
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
index 4e87de70759..98741c631b1 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
@@ -28,6 +28,7 @@ import com.yahoo.vespa.config.server.session.SessionContext;
import java.io.File;
import java.io.IOException;
+import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;
@@ -79,7 +80,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
protected PreparedModelResult buildModelVersion(ModelFactory modelFactory,
ApplicationPackage applicationPackage,
ApplicationId applicationId,
- com.yahoo.component.Version wantedNodeVespaVersion) {
+ com.yahoo.component.Version wantedNodeVespaVersion, Instant now) {
Version modelVersion = modelFactory.getVersion();
log.log(LogLevel.DEBUG, "Start building model for Vespa version " + modelVersion);
FileDistributionProvider fileDistributionProvider = fileDistributionFactory.createProvider(
@@ -88,7 +89,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
Optional<HostProvisioner> hostProvisioner = createHostProvisionerAdapter(properties);
Optional<Model> previousModel = currentActiveApplicationSet
- .map(set -> set.getForVersionOrLatest(Optional.of(modelVersion)).getModel());
+ .map(set -> set.getForVersionOrLatest(Optional.of(modelVersion), now).getModel());
ModelContext modelContext = new ModelContextImpl(
applicationPackage,
previousModel,
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
index baa4dc2ca79..a222182f87a 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
@@ -22,6 +22,7 @@ import com.yahoo.vespa.config.server.tenant.Tenants;
import com.yahoo.vespa.curator.Curator;
import java.io.File;
+import java.time.Instant;
import java.util.Optional;
/**
@@ -62,10 +63,11 @@ public class LocalSession extends Session implements Comparable<LocalSession> {
public ConfigChangeActions prepare(DeployLogger logger,
PrepareParams params,
Optional<ApplicationSet> currentActiveApplicationSet,
- Path tenantPath) {
+ Path tenantPath,
+ Instant now) {
Curator.CompletionWaiter waiter = zooKeeperClient.createPrepareWaiter();
- ConfigChangeActions actions = sessionPreparer.prepare(sessionContext, logger, params,
- currentActiveApplicationSet, tenantPath);
+ ConfigChangeActions actions = sessionPreparer.prepare(sessionContext, logger, params,
+ currentActiveApplicationSet, tenantPath, now);
setPrepared();
waiter.awaitCompletion(params.getTimeoutBudget().timeLeft());
return actions;
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
index df0a407c408..c20f6e0b853 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
@@ -10,6 +10,8 @@ import com.yahoo.vespa.config.server.tenant.Tenants;
import com.yahoo.vespa.curator.Curator;
import org.apache.zookeeper.KeeperException;
+import java.time.Clock;
+import java.time.Instant;
import java.util.*;
import java.util.logging.Logger;
@@ -25,6 +27,7 @@ public class RemoteSession extends Session {
private static final Logger log = Logger.getLogger(RemoteSession.class.getName());
private volatile ApplicationSet applicationSet = null;
private final ActivatedModelsBuilder applicationLoader;
+ private final Clock clock;
/**
* Creates a session. This involves loading the application, validating it and distributing it.
@@ -37,9 +40,11 @@ public class RemoteSession extends Session {
public RemoteSession(TenantName tenant,
long sessionId,
GlobalComponentRegistry globalComponentRegistry,
- SessionZooKeeperClient zooKeeperClient) {
+ SessionZooKeeperClient zooKeeperClient,
+ Clock clock) {
super(tenant, sessionId, zooKeeperClient);
this.applicationLoader = new ActivatedModelsBuilder(tenant, sessionId, zooKeeperClient, globalComponentRegistry);
+ this.clock = clock;
}
public void loadPrepared() {
@@ -51,7 +56,8 @@ public class RemoteSession extends Session {
private ApplicationSet loadApplication() {
return ApplicationSet.fromList(applicationLoader.buildModels(zooKeeperClient.readApplicationId(),
zooKeeperClient.readVespaVersion(),
- zooKeeperClient.loadApplicationPackage()));
+ zooKeeperClient.loadApplicationPackage(),
+ clock.instant()));
}
public ApplicationSet ensureApplicationLoaded() {
@@ -83,7 +89,7 @@ public class RemoteSession extends Session {
@Override
public String logPre() {
if (applicationSet != null) {
- return Tenants.logPre(applicationSet.getForVersionOrLatest(Optional.empty()).getId());
+ return Tenants.logPre(applicationSet.getForVersionOrLatest(Optional.empty(), Instant.now()).getId());
}
return Tenants.logPre(getTenant());
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java
index e4e368716ee..0f1e65aaf2b 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionFactory.java
@@ -9,6 +9,8 @@ import com.yahoo.vespa.config.server.GlobalComponentRegistry;
import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
import com.yahoo.vespa.curator.Curator;
+import java.time.Clock;
+
/**
* @author lulf
* @since 5.1.24
@@ -22,10 +24,12 @@ public class RemoteSessionFactory {
private final ConfigDefinitionRepo defRepo;
private final TenantName tenant;
private final ConfigserverConfig configserverConfig;
+ private final Clock clock;
public RemoteSessionFactory(GlobalComponentRegistry componentRegistry,
Path sessionsPath,
- TenantName tenant) {
+ TenantName tenant,
+ Clock clock) {
this.componentRegistry = componentRegistry;
this.curator = componentRegistry.getCurator();
this.configCurator = componentRegistry.getConfigCurator();
@@ -33,6 +37,7 @@ public class RemoteSessionFactory {
this.tenant = tenant;
this.defRepo = componentRegistry.getConfigDefinitionRepo();
this.configserverConfig = componentRegistry.getConfigserverConfig();
+ this.clock = clock;
}
public RemoteSession createSession(long sessionId) {
@@ -43,7 +48,7 @@ public class RemoteSessionFactory {
defRepo,
configserverConfig.serverId(),
componentRegistry.getZone().nodeFlavors());
- return new RemoteSession(tenant, sessionId, componentRegistry, sessionZKClient);
+ return new RemoteSession(tenant, sessionId, componentRegistry, sessionZKClient, clock);
}
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
index 23c3b4bf8c4..0b76c57e142 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
@@ -28,6 +28,7 @@ import com.yahoo.vespa.curator.Curator;
import org.xml.sax.SAXException;
import java.io.IOException;
+import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -86,11 +87,12 @@ public class SessionPreparer {
* @return the config change actions that must be done to handle the activation of the models prepared.
*/
public ConfigChangeActions prepare(SessionContext context, DeployLogger logger, PrepareParams params,
- Optional<ApplicationSet> currentActiveApplicationSet, Path tenantPath) {
+ Optional<ApplicationSet> currentActiveApplicationSet, Path tenantPath,
+ Instant now) {
Preparation preparation = new Preparation(context, logger, params, currentActiveApplicationSet, tenantPath);
preparation.preprocess();
try {
- preparation.buildModels();
+ preparation.buildModels(now);
preparation.makeResult();
if ( ! params.isDryRun()) {
preparation.writeStateZK();
@@ -175,8 +177,8 @@ public class SessionPreparer {
checkTimeout("preprocess");
}
- void buildModels() {
- this.modelResultList = preparedModelsBuilder.buildModels(applicationId, vespaVersion, applicationPackage);
+ void buildModels(Instant now) {
+ this.modelResultList = preparedModelsBuilder.buildModels(applicationId, vespaVersion, applicationPackage, now);
checkTimeout("build models");
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java
index 075888168e2..144bbf10dc6 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java
@@ -31,6 +31,7 @@ import java.util.concurrent.Executors;
* @since 5.1
*/
public class TenantBuilder {
+
private final Path tenantPath;
private final GlobalComponentRegistry componentRegistry;
private final TenantName tenant;
@@ -46,6 +47,7 @@ public class TenantBuilder {
private RemoteSessionFactory remoteSessionFactory;
private TenantFileSystemDirs tenantFileSystemDirs;
private HostValidator<ApplicationId> hostValidator;
+ private Clock clock = Clock.systemUTC();
private TenantBuilder(GlobalComponentRegistry componentRegistry, TenantName tenant, Path zkPath) {
this.componentRegistry = componentRegistry;
@@ -88,6 +90,11 @@ public class TenantBuilder {
return this;
}
+ public TenantBuilder withClock(Clock clock) {
+ this.clock = clock;
+ return this;
+ }
+
/**
* Create a real tenant from the properties given by this builder.
*
@@ -97,7 +104,7 @@ public class TenantBuilder {
public Tenant build() throws Exception {
createTenantRequestHandler();
createApplicationRepo();
- createRemoteSessionFactory();
+ createRemoteSessionFactory(clock);
createRemoteSessionRepo();
createSessionCounter();
createServerDbDirs();
@@ -164,12 +171,9 @@ public class TenantBuilder {
}
}
- private void createRemoteSessionFactory() {
+ private void createRemoteSessionFactory(Clock clock) {
if (remoteSessionFactory == null) {
- remoteSessionFactory = new RemoteSessionFactory(
- componentRegistry,
- sessionsPath,
- tenant);
+ remoteSessionFactory = new RemoteSessionFactory(componentRegistry, sessionsPath, tenant, clock);
}
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java
index bc9ff9b79be..20d1e88440f 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java
@@ -1,6 +1,8 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.tenant;
+import java.time.Clock;
+import java.time.Instant;
import java.util.*;
import com.yahoo.config.provision.Version;
@@ -43,6 +45,7 @@ public class TenantRequestHandler implements RequestHandler, ReloadHandler, Host
private final HostRegistry<ApplicationId> hostRegistry;
private final ApplicationMapper applicationMapper = new ApplicationMapper();
private final MetricUpdater tenantMetricUpdater;
+ private final Clock clock = Clock.systemUTC();
public TenantRequestHandler(Metrics metrics,
TenantName tenant,
@@ -93,7 +96,7 @@ public class TenantRequestHandler implements RequestHandler, ReloadHandler, Host
@Override
public void removeApplication(ApplicationId applicationId) {
- if (applicationMapper.hasApplication(applicationId)) {
+ if (applicationMapper.hasApplication(applicationId, clock.instant())) {
applicationMapper.remove(applicationId);
hostRegistry.removeHostsForKey(applicationId);
reloadListenersOnRemove(applicationId);
@@ -182,7 +185,7 @@ public class TenantRequestHandler implements RequestHandler, ReloadHandler, Host
private Application getApplication(ApplicationId appId, Optional<Version> vespaVersion) {
try {
- return applicationMapper.getForVersion(appId, vespaVersion);
+ return applicationMapper.getForVersion(appId, vespaVersion, clock.instant());
} catch (VersionDoesNotExistException ex) {
throw new NotFoundException(String.format("%sNo such application (id %s): %s", Tenants.logPre(tenant), appId, ex.getMessage()));
}
@@ -200,7 +203,7 @@ public class TenantRequestHandler implements RequestHandler, ReloadHandler, Host
}
private boolean hasHandler(ApplicationId appId, Optional<Version> vespaVersion) {
- return applicationMapper.hasApplicationForVersion(appId, vespaVersion);
+ return applicationMapper.hasApplicationForVersion(appId, vespaVersion, clock.instant());
}
@Override
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationMapperTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationMapperTest.java
index 8748db808b3..a83f2676a4d 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationMapperTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationMapperTest.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.application;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;
@@ -16,6 +17,7 @@ import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ApplicationMapperTest {
+
ApplicationId appId;
ApplicationMapper applicationMapper;
ArrayList<Version> vespaVersions = new ArrayList<>();
@@ -37,22 +39,22 @@ public class ApplicationMapperTest {
@Test
public void testGetForVersionReturnsCorrectVersion() {
applicationMapper.register(appId, ApplicationSet.fromList(applications));
- assertEquals(applicationMapper.getForVersion(appId, Optional.of(vespaVersions.get(0))), applications.get(0));
- assertEquals(applicationMapper.getForVersion(appId, Optional.of(vespaVersions.get(1))), applications.get(1));
- assertEquals(applicationMapper.getForVersion(appId, Optional.of(vespaVersions.get(2))), applications.get(2));
+ assertEquals(applicationMapper.getForVersion(appId, Optional.of(vespaVersions.get(0)), Instant.now()), applications.get(0));
+ assertEquals(applicationMapper.getForVersion(appId, Optional.of(vespaVersions.get(1)), Instant.now()), applications.get(1));
+ assertEquals(applicationMapper.getForVersion(appId, Optional.of(vespaVersions.get(2)), Instant.now()), applications.get(2));
}
@Test
public void testGetForVersionReturnsLatestVersion() {
applicationMapper.register(appId, ApplicationSet.fromList(applications));
- assertEquals(applicationMapper.getForVersion(appId, Optional.empty()), applications.get(2));
+ assertEquals(applicationMapper.getForVersion(appId, Optional.empty(), Instant.now()), applications.get(2));
}
@Test (expected = VersionDoesNotExistException.class)
public void testGetForVersionThrows() {
applicationMapper.register(appId, ApplicationSet.fromList(Arrays.asList(applications.get(0), applications.get(2))));
- applicationMapper.getForVersion(appId, Optional.of(vespaVersions.get(1)));
+ applicationMapper.getForVersion(appId, Optional.of(vespaVersions.get(1)), Instant.now());
}
@Test (expected = NotFoundException.class)
@@ -61,6 +63,7 @@ public class ApplicationMapperTest {
applicationMapper.getForVersion(new ApplicationId.Builder()
.tenant("different").applicationName("different").instanceName("different").build(),
- Optional.of(vespaVersions.get(1)));
+ Optional.of(vespaVersions.get(1)),
+ Instant.now());
}
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationSetTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationSetTest.java
index 8d54ee6b530..98bedb76599 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationSetTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationSetTest.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.application;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -36,21 +37,21 @@ public class ApplicationSetTest {
@Test
public void testGetForVersionOrLatestReturnsCorrectVersion() {
applicationSet = ApplicationSet.fromList(applications);
- assertEquals(applicationSet.getForVersionOrLatest(Optional.of(vespaVersions.get(0))), applications.get(0));
- assertEquals(applicationSet.getForVersionOrLatest(Optional.of(vespaVersions.get(1))), applications.get(1));
- assertEquals(applicationSet.getForVersionOrLatest(Optional.of(vespaVersions.get(2))), applications.get(2));
+ assertEquals(applicationSet.getForVersionOrLatest(Optional.of(vespaVersions.get(0)), Instant.now()), applications.get(0));
+ assertEquals(applicationSet.getForVersionOrLatest(Optional.of(vespaVersions.get(1)), Instant.now()), applications.get(1));
+ assertEquals(applicationSet.getForVersionOrLatest(Optional.of(vespaVersions.get(2)), Instant.now()), applications.get(2));
}
@Test
public void testGetForVersionOrLatestReturnsLatestVersion() {
applicationSet = ApplicationSet.fromList(applications);
- assertEquals(applicationSet.getForVersionOrLatest(Optional.empty()), applications.get(2));
+ assertEquals(applicationSet.getForVersionOrLatest(Optional.empty(), Instant.now()), applications.get(2));
}
@Test (expected = VersionDoesNotExistException.class)
public void testGetForVersionOrLatestThrows() {
applicationSet = ApplicationSet.fromList(Arrays.asList(applications.get(0), applications.get(2)));
- applicationSet.getForVersionOrLatest(Optional.of(vespaVersions.get(1)));
+ applicationSet.getForVersionOrLatest(Optional.of(vespaVersions.get(1)), Instant.now());
}
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
index 861cbe467ae..c9556425dda 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
@@ -108,14 +108,14 @@ public class DeployTester {
/**
* Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet.
*/
- public ApplicationId deployApp(String appName) {
- return deployApp(appName, Optional.empty());
+ public ApplicationId deployApp(String appName, Instant now) {
+ return deployApp(appName, Optional.empty(), now);
}
/**
* Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet.
*/
- public ApplicationId deployApp(String appName, Optional<String> vespaVersion) {
+ public ApplicationId deployApp(String appName, Optional<String> vespaVersion, Instant now) {
Tenant tenant = tenant();
LocalSession session = tenant.getSessionFactory().createSession(testApp, appName, new TimeoutBudget(Clock.systemUTC(), Duration.ofSeconds(60)));
ApplicationId id = ApplicationId.from(tenant.getName(), ApplicationName.from(appName), InstanceName.defaultName());
@@ -126,7 +126,8 @@ public class DeployTester {
session.prepare(new SilentDeployLogger(),
paramsBuilder.build(),
Optional.empty(),
- tenant.getPath());
+ tenant.getPath(),
+ now);
session.createActivateTransaction().commit();
tenant.getLocalSessionRepo().addSession(session);
this.id = id;
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
index e5d8d1b7b94..31e92cc9f93 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
@@ -12,6 +12,7 @@ import org.junit.Test;
import java.io.IOException;
import java.time.Duration;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -31,7 +32,7 @@ public class HostedDeployTest {
@Test
public void testRedeployWithVersion() throws InterruptedException, IOException {
DeployTester tester = new DeployTester("src/test/apps/hosted/", createConfigserverConfig());
- tester.deployApp("myApp", Optional.of("4.5.6"));
+ tester.deployApp("myApp", Optional.of("4.5.6"), Instant.now());
Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
assertTrue(deployment.isPresent());
@@ -43,7 +44,7 @@ public class HostedDeployTest {
@Test
public void testRedeploy() throws InterruptedException, IOException {
DeployTester tester = new DeployTester("src/test/apps/hosted/", createConfigserverConfig());
- tester.deployApp("myApp");
+ tester.deployApp("myApp", Instant.now());
Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
assertTrue(deployment.isPresent());
@@ -59,7 +60,7 @@ public class HostedDeployTest {
modelFactories.add(DeployTester.createDefaultModelFactory(clock));
modelFactories.add(DeployTester.createFailingModelFactory(Version.fromIntValues(1, 0, 0))); // older than default
DeployTester tester = new DeployTester("src/test/apps/validationOverride/", modelFactories, createConfigserverConfig());
- tester.deployApp("myApp");
+ tester.deployApp("myApp", clock.instant());
// Redeployment from local active works
{
@@ -82,7 +83,7 @@ public class HostedDeployTest {
// However, redeployment from the outside fails after this date
{
try {
- tester.deployApp("myApp");
+ tester.deployApp("myApp", Instant.now());
fail("Expected redeployment to fail");
}
catch (Exception expected) {
@@ -96,7 +97,7 @@ public class HostedDeployTest {
public void testDeployWithDockerImage() throws InterruptedException, IOException {
final String vespaVersion = "6.51.1";
DeployTester tester = new DeployTester("src/test/apps/hosted/", createConfigserverConfig());
- ApplicationId applicationId = tester.deployApp("myApp", Optional.of(vespaVersion));
+ ApplicationId applicationId = tester.deployApp("myApp", Optional.of(vespaVersion), Instant.now());
assertProvisionInfo(vespaVersion, tester, applicationId);
System.out.println("Redeploy");
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java
index b3dc14a1178..5658e0fb2aa 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java
@@ -11,6 +11,7 @@ import org.junit.Test;
import java.io.IOException;
import java.time.Clock;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -29,7 +30,7 @@ public class RedeployTest {
@Test
public void testRedeploy() throws InterruptedException, IOException {
DeployTester tester = new DeployTester("src/test/apps/app");
- tester.deployApp("myapp");
+ tester.deployApp("myapp", Instant.now());
Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
assertTrue(deployment.isPresent());
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java
index 1f181e74b73..eef0058e13e 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java
@@ -10,6 +10,7 @@ import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.IOException;
+import java.time.Clock;
import java.util.Collections;
import java.util.Optional;
@@ -17,6 +18,7 @@ import com.yahoo.config.application.api.ApplicationMetaData;
import com.yahoo.config.model.application.provider.FilesApplicationPackage;
import com.yahoo.config.model.application.provider.MockFileRegistry;
import com.yahoo.config.provision.*;
+import com.yahoo.test.ManualClock;
import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
import com.yahoo.vespa.config.server.SuperModelGenerationCounter;
import com.yahoo.vespa.config.server.TestComponentRegistry;
@@ -56,15 +58,17 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
@Test
public void testThatPreviousSessionIsDeactivated() throws Exception {
- RemoteSession firstSession = activateAndAssertOK(90l, 0l);
- activateAndAssertOK(91l, 90l);
+ Clock clock = Clock.systemUTC();
+ RemoteSession firstSession = activateAndAssertOK(90l, 0l, clock);
+ activateAndAssertOK(91l, 90l, clock);
assertThat(firstSession.getStatus(), is(Session.Status.DEACTIVATE));
}
@Test
public void testForceActivationWithActivationInBetween() throws Exception {
- activateAndAssertOK(90l, 0l);
- activateAndAssertOK(92l, 89l, "?force=true");
+ Clock clock = Clock.systemUTC();
+ activateAndAssertOK(90l, 0l, clock);
+ activateAndAssertOK(92l, 89l, "?force=true", clock);
}
@Test
@@ -75,8 +79,9 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
@Test
public void testActivationWithActivationInBetween() throws Exception {
- activateAndAssertOK(90l, 0l);
- activateAndAssertError(92l, 89l,
+ Clock clock = Clock.systemUTC();
+ activateAndAssertOK(90l, 0l, clock);
+ activateAndAssertError(92l, 89l, clock,
HttpErrorResponse.errorCodes.BAD_REQUEST,
getActivateLogPre() +
"Cannot activate session 92 because the currently active session (90) has changed since session 92 was created (was 89 at creation time)");
@@ -87,9 +92,9 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
@Test
public void testActivationOfUnpreparedSession() throws Exception {
// Needed so we can test that previous active session is still active after a failed activation
- RemoteSession firstSession = activateAndAssertOK(90l, 0l);
+ RemoteSession firstSession = activateAndAssertOK(90l, 0l, Clock.systemUTC());
long sessionId = 91l;
- ActivateRequest activateRequest = new ActivateRequest(sessionId, 0l, Session.Status.NEW, "").invoke();
+ ActivateRequest activateRequest = new ActivateRequest(sessionId, 0l, Session.Status.NEW, "", Clock.systemUTC()).invoke();
HttpResponse actResponse = activateRequest.getActResponse();
RemoteSession session = activateRequest.getSession();
assertThat(actResponse.getStatus(), is(BAD_REQUEST));
@@ -101,16 +106,16 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
@Test
public void testActivationWithBarrierTimeout() throws Exception {
// Needed so we can test that previous active session is still active after a failed activation
- activateAndAssertOK(90l, 0l);
+ activateAndAssertOK(90l, 0l, Clock.systemUTC());
((MockCurator) curator).timeoutBarrierOnEnter(true);
- ActivateRequest activateRequest = new ActivateRequest(91l, 90l, "").invoke();
+ ActivateRequest activateRequest = new ActivateRequest(91l, 90l, "", Clock.systemUTC()).invoke();
HttpResponse actResponse = activateRequest.getActResponse();
assertThat(actResponse.getStatus(), is(INTERNAL_SERVER_ERROR));
}
@Test
public void testActivationOfSessionThatDoesNotExistAsLocalSession() throws Exception {
- ActivateRequest activateRequest = new ActivateRequest(90l, 0l, "").invoke(false);
+ ActivateRequest activateRequest = new ActivateRequest(90l, 0l, "", Clock.systemUTC()).invoke(false);
HttpResponse actResponse = activateRequest.getActResponse();
assertThat(actResponse.getStatus(), is(NOT_FOUND));
String message = getRenderedString(actResponse);
@@ -119,13 +124,15 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
@Test
public void require_that_session_created_from_active_that_is_no_longer_active_cannot_be_activated() throws Exception {
+ Clock clock = Clock.systemUTC();
+
long sessionId = 1;
- activateAndAssertOK(1, 0);
+ activateAndAssertOK(1, 0, clock);
sessionId++;
- activateAndAssertOK(sessionId, 1);
+ activateAndAssertOK(sessionId, 1, clock);
sessionId++;
- ActivateRequest activateRequest = new ActivateRequest(sessionId, 1, "").invoke();
+ ActivateRequest activateRequest = new ActivateRequest(sessionId, 1, "", Clock.systemUTC()).invoke();
HttpResponse actResponse = activateRequest.getActResponse();
String message = getRenderedString(actResponse);
assertThat(message, actResponse.getStatus(), Is.is(BAD_REQUEST));
@@ -135,7 +142,7 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
@Test
public void testAlreadyActivatedSession() throws Exception {
- activateAndAssertOK(1, 0);
+ activateAndAssertOK(1, 0, Clock.systemUTC());
HttpResponse response = createHandler().handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.ACTIVE, 1l));
String message = getRenderedString(response);
assertThat(message, response.getStatus(), Is.is(BAD_REQUEST));
@@ -144,7 +151,7 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
protected abstract SessionHandler createHandler() throws Exception;
- private RemoteSession createRemoteSession(long sessionId, Session.Status status, SessionZooKeeperClient zkClient) throws IOException {
+ private RemoteSession createRemoteSession(long sessionId, Session.Status status, SessionZooKeeperClient zkClient, Clock clock) throws IOException {
zkClient.writeStatus(status);
ZooKeeperClient zkC = new ZooKeeperClient(configCurator, new BaseDeployLogger(), false, pathProvider.getSessionDirs().append(String.valueOf(sessionId)));
VespaModelFactory modelFactory = new VespaModelFactory(new NullConfigModelRegistry());
@@ -155,7 +162,7 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
.configCurator(configCurator)
.modelFactoryRegistry(new ModelFactoryRegistry(Collections.singletonList(modelFactory)))
.build();
- RemoteSession session = new RemoteSession(TenantName.from("default"), sessionId, componentRegistry, zkClient);
+ RemoteSession session = new RemoteSession(TenantName.from("default"), sessionId, componentRegistry, zkClient, clock);
remoteSessionRepo.addSession(session);
return session;
}
@@ -170,12 +177,12 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
protected abstract void writeApplicationId(SessionZooKeeperClient zkc, String applicationName);
- protected abstract Session activateAndAssertOK(long sessionId, long previousSessionId, String subPath) throws Exception;
+ protected abstract Session activateAndAssertOK(long sessionId, long previousSessionId, String subPath, Clock clock) throws Exception;
- protected abstract RemoteSession activateAndAssertOK(long sessionId, long previousSessionId) throws Exception;
+ protected abstract RemoteSession activateAndAssertOK(long sessionId, long previousSessionId, Clock clock) throws Exception;
- protected ActivateRequest activateAndAssertOKPut(long sessionId, long previousSessionId, String subPath) throws Exception {
- ActivateRequest activateRequest = new ActivateRequest(sessionId, previousSessionId, subPath);
+ protected ActivateRequest activateAndAssertOKPut(long sessionId, long previousSessionId, String subPath, Clock clock) throws Exception {
+ ActivateRequest activateRequest = new ActivateRequest(sessionId, previousSessionId, subPath, clock);
activateRequest.invoke();
HttpResponse actResponse = activateRequest.getActResponse();
String message = getRenderedString(actResponse);
@@ -188,10 +195,10 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
protected abstract void assertActivationMessageOK(ActivateRequest activateRequest, String message) throws IOException;
- protected abstract void activateAndAssertError(long sessionId, long previousSessionId, HttpErrorResponse.errorCodes errorCode, String expectedError) throws Exception;
+ protected abstract void activateAndAssertError(long sessionId, long previousSessionId, Clock clock, HttpErrorResponse.errorCodes errorCode, String expectedError) throws Exception;
- protected ActivateRequest activateAndAssertErrorPut(long sessionId, long previousSessionId, HttpErrorResponse.errorCodes errorCode, String expectedError) throws Exception {
- ActivateRequest activateRequest = new ActivateRequest(sessionId, previousSessionId, "");
+ protected ActivateRequest activateAndAssertErrorPut(long sessionId, long previousSessionId, Clock clock, HttpErrorResponse.errorCodes errorCode, String expectedError) throws Exception {
+ ActivateRequest activateRequest = new ActivateRequest(sessionId, previousSessionId, "", clock);
activateRequest.invoke();
HttpResponse actResponse = activateRequest.getActResponse();
RemoteSession session = activateRequest.getSession();
@@ -219,16 +226,18 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
private DeployData deployData;
private ApplicationMetaData metaData;
private String subPath;
+ private Clock clock;
- public ActivateRequest(long sessionId, long previousSessionId, String subPath) {
- this(sessionId, previousSessionId, Session.Status.PREPARE, subPath);
+ public ActivateRequest(long sessionId, long previousSessionId, String subPath, Clock clock) {
+ this(sessionId, previousSessionId, Session.Status.PREPARE, subPath, clock);
}
- public ActivateRequest(long sessionId, long previousSessionId, Session.Status initialStatus, String subPath) {
+ public ActivateRequest(long sessionId, long previousSessionId, Session.Status initialStatus, String subPath, Clock clock) {
this.sessionId = sessionId;
this.initialStatus = initialStatus;
this.deployData = new DeployData("foo", "bar", appName, 0l, sessionId, previousSessionId);
this.subPath = subPath;
+ this.clock = clock;
}
public RemoteSession getSession() {
@@ -258,7 +267,7 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest {
public ActivateRequest invoke(boolean createLocalSession) throws Exception {
SessionZooKeeperClient zkClient = new MockSessionZKClient(curator, pathProvider.getSessionDirs().append(String.valueOf(sessionId)),
Optional.of(ProvisionInfo.withHosts(Collections.singleton(new HostSpec("bar", Collections.emptyList())))));
- session = createRemoteSession(sessionId, initialStatus, zkClient);
+ session = createRemoteSession(sessionId, initialStatus, zkClient, clock);
if (createLocalSession) {
LocalSessionRepo repo = addLocalSession(sessionId, deployData, zkClient);
metaData = repo.getSession(sessionId).getMetaData();
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java
index 7379e4a2fab..448b2db2b71 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java
@@ -23,6 +23,7 @@ import com.yahoo.vespa.config.server.configchange.ConfigChangeActions;
import com.yahoo.vespa.config.server.session.*;
import java.io.*;
+import java.time.Instant;
import java.util.Optional;
/**
@@ -95,7 +96,7 @@ public class SessionHandlerTest {
}
@Override
- public ConfigChangeActions prepare(DeployLogger logger, PrepareParams params, Optional<ApplicationSet> application, Path tenantPath) {
+ public ConfigChangeActions prepare(DeployLogger logger, PrepareParams params, Optional<ApplicationSet> application, Path tenantPath, Instant now) {
status = Session.Status.PREPARE;
if (doVerboseLogging) {
logger.log(LogLevel.DEBUG, "debuglog");
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
index 3fd338fbfde..8c4fa1ffc6c 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
@@ -53,6 +53,7 @@ import javax.ws.rs.client.Client;
import java.io.File;
import java.io.IOException;
import java.net.URI;
+import java.time.Clock;
import java.util.Collections;
import static org.hamcrest.CoreMatchers.is;
@@ -135,6 +136,7 @@ public class ApplicationHandlerTest {
@Test
public void testDelete() throws Exception {
+ Clock clock = Clock.systemUTC();
ApplicationId defaultId = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build();
assertApplicationExists(mytenantName, null, Zone.defaultZone());
@@ -162,7 +164,7 @@ public class ApplicationHandlerTest {
sessionId++;
{
- addMockApplication(tenants.getTenant(mytenantName), defaultId, sessionId);
+ addMockApplication(tenants.getTenant(mytenantName), defaultId, sessionId, clock);
deleteAndAssertOKResponseMocked(defaultId, true);
ApplicationId fooId = new ApplicationId.Builder()
@@ -171,8 +173,8 @@ public class ApplicationHandlerTest {
sessionId++;
- addMockApplication(tenants.getTenant(mytenantName), fooId, sessionId);
- addMockApplication(tenants.getTenant(foobar), fooId, sessionId);
+ addMockApplication(tenants.getTenant(mytenantName), fooId, sessionId, clock);
+ addMockApplication(tenants.getTenant(foobar), fooId, sessionId, clock);
assertApplicationExists(mytenantName, fooId, Zone.defaultZone());
assertApplicationExists(foobar, fooId, Zone.defaultZone());
deleteAndAssertOKResponseMocked(fooId, true);
@@ -187,7 +189,7 @@ public class ApplicationHandlerTest {
ApplicationId baliId = new ApplicationId.Builder()
.tenant(mytenantName)
.applicationName("bali").instanceName("quux").build();
- addMockApplication(tenants.getTenant(mytenantName), baliId, sessionId);
+ addMockApplication(tenants.getTenant(mytenantName), baliId, sessionId, clock);
deleteAndAssertOKResponseMocked(baliId, true);
assertApplicationExists(mytenantName, null, Zone.defaultZone());
}
@@ -197,7 +199,7 @@ public class ApplicationHandlerTest {
public void testGet() throws Exception {
long sessionId = 1;
ApplicationId defaultId = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build();
- addMockApplication(tenants.getTenant(mytenantName), defaultId, sessionId);
+ addMockApplication(tenants.getTenant(mytenantName), defaultId, sessionId, Clock.systemUTC());
assertApplicationGeneration(defaultId, Zone.defaultZone(), 1, true);
assertApplicationGeneration(defaultId, Zone.defaultZone(), 1, false);
}
@@ -206,7 +208,7 @@ public class ApplicationHandlerTest {
public void testRestart() throws Exception {
long sessionId = 1;
ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build();
- addMockApplication(tenants.getTenant(mytenantName), application, sessionId);
+ addMockApplication(tenants.getTenant(mytenantName), application, sessionId, Clock.systemUTC());
assertFalse(provisioner.restarted);
restart(application, Zone.defaultZone());
assertTrue(provisioner.restarted);
@@ -217,7 +219,7 @@ public class ApplicationHandlerTest {
public void testConverge() throws Exception {
long sessionId = 1;
ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build();
- addMockApplication(tenants.getTenant(mytenantName), application, sessionId);
+ addMockApplication(tenants.getTenant(mytenantName), application, sessionId, Clock.systemUTC());
converge(application, Zone.defaultZone());
}
@@ -225,7 +227,7 @@ public class ApplicationHandlerTest {
public void testGrabLog() throws Exception {
long sessionId = 1;
ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build();
- addMockApplication(tenants.getTenant(mytenantName), application, sessionId);
+ addMockApplication(tenants.getTenant(mytenantName), application, sessionId, Clock.systemUTC());
assertEquals("log line", grabLog(application, Zone.defaultZone()));
}
@@ -233,7 +235,7 @@ public class ApplicationHandlerTest {
public void testClusterControllerStatus() throws Exception {
long sessionId = 1;
ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build();
- addMockApplication(tenants.getTenant(mytenantName), application, sessionId);
+ addMockApplication(tenants.getTenant(mytenantName), application, sessionId, Clock.systemUTC());
String host = "foo.yahoo.com";
String url = toUrlPath(application, Zone.defaultZone(), true) + "/clustercontroller/" + host + "/status/v1/clusterName1";
@@ -259,7 +261,7 @@ public class ApplicationHandlerTest {
new HttpProxy(new SimpleHttpFetcher()),
new LogServerLogGrabber());
final ApplicationId applicationId = ApplicationId.defaultId();
- addMockApplication(tenants.getTenant(mytenantName), applicationId, 1);
+ addMockApplication(tenants.getTenant(mytenantName), applicationId, 1, Clock.systemUTC());
assertApplicationExists(mytenantName, applicationId, Zone.defaultZone());
provisioner.activated = true;
@@ -269,14 +271,14 @@ public class ApplicationHandlerTest {
Assert.assertTrue(provisioner.activated);
}
- static void addMockApplication(Tenant tenant, ApplicationId applicationId, long sessionId) {
+ static void addMockApplication(Tenant tenant, ApplicationId applicationId, long sessionId, Clock clock) {
tenant.getApplicationRepo().createPutApplicationTransaction(applicationId, sessionId).commit();
ApplicationPackage app = FilesApplicationPackage.fromFile(testApp);
tenant.getLocalSessionRepo().addSession(new SessionHandlerTest.MockSession(sessionId, app, applicationId));
TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder()
.modelFactoryRegistry(new ModelFactoryRegistry(Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry()))))
.build();
- tenant.getRemoteSessionRepo().addSession(new RemoteSession(tenant.getName(), sessionId, componentRegistry, new MockSessionZKClient(app)));
+ tenant.getRemoteSessionRepo().addSession(new RemoteSession(tenant.getName(), sessionId, componentRegistry, new MockSessionZKClient(app), clock));
}
static Tenants addApplication(ApplicationId applicationId, long sessionId) throws Exception {
@@ -322,7 +324,8 @@ public class ApplicationHandlerTest {
.modelFactoryRegistry(new ModelFactoryRegistry(
Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry()))))
.build(),
- sessionClient));
+ sessionClient,
+ Clock.systemUTC()));
return tenants;
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java
index 288c05e7a6f..e439f424c45 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java
@@ -16,6 +16,7 @@ import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
+import java.time.Clock;
import java.util.Collections;
import static org.hamcrest.CoreMatchers.is;
@@ -62,14 +63,14 @@ public class HostHandlerTest {
assertThat(hostRegistries, is(hostHandler.hostRegistries));
long sessionId = 1;
ApplicationId id = ApplicationId.from(mytenant, ApplicationName.defaultName(), InstanceName.defaultName());
- ApplicationHandlerTest.addMockApplication(tenants.getTenant(mytenant), id, sessionId);
+ ApplicationHandlerTest.addMockApplication(tenants.getTenant(mytenant), id, sessionId, Clock.systemUTC());
assertApplicationForHost(hostname, mytenant, id, Zone.defaultZone());
}
@Test
public void require_that_handler_gives_error_for_unknown_hostname() throws Exception {
long sessionId = 1;
- ApplicationHandlerTest.addMockApplication(tenants.getTenant(mytenant), ApplicationId.defaultId(), sessionId);
+ ApplicationHandlerTest.addMockApplication(tenants.getTenant(mytenant), ApplicationId.defaultId(), sessionId, Clock.systemUTC());
final String hostname = "unknown";
assertErrorForHost(hostname,
Response.Status.NOT_FOUND,
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
index 5adc3a108f7..01855637005 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
@@ -46,6 +46,7 @@ import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.time.Clock;
import java.util.Collection;
import java.util.List;
@@ -76,13 +77,14 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase {
@Test
public void testActivation() throws Exception {
- activateAndAssertOK(1, 0);
+ activateAndAssertOK(1, 0, Clock.systemUTC());
}
@Test
public void testActivationWithActivationInBetween() throws Exception {
- activateAndAssertOK(90l, 0l);
- activateAndAssertError(92l, 89l,
+ Clock clock = Clock.systemUTC();
+ activateAndAssertOK(90l, 0l, clock);
+ activateAndAssertError(92l, 89l, clock,
HttpErrorResponse.errorCodes.BAD_REQUEST,
"tenant:"+tenant+" app:default:default Cannot activate session 92 because the currently active session (90) has changed since session 92 was created (was 89 at creation time)");
}
@@ -90,10 +92,11 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase {
@Test
public void testActivationOfUnpreparedSession() throws Exception {
+ Clock clock = Clock.systemUTC();
// Needed so we can test that previous active session is still active after a failed activation
- RemoteSession firstSession = activateAndAssertOK(90l, 0l);
+ RemoteSession firstSession = activateAndAssertOK(90l, 0l, clock);
long sessionId = 91L;
- ActivateRequest activateRequest = new ActivateRequest(sessionId, 0l, Session.Status.NEW, "").invoke();
+ ActivateRequest activateRequest = new ActivateRequest(sessionId, 0l, Session.Status.NEW, "", clock).invoke();
HttpResponse actResponse = activateRequest.getActResponse();
RemoteSession session = activateRequest.getSession();
assertThat(actResponse.getStatus(), is(Response.Status.BAD_REQUEST));
@@ -115,19 +118,19 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase {
public void require_that_handler_gives_error_when_provisioner_activated_fails() throws Exception {
hostProvisioner = new FailingMockProvisioner();
hostProvisioner.activated = false;
- activateAndAssertError(1, 0, HttpErrorResponse.errorCodes.BAD_REQUEST, "Cannot activate application");
+ activateAndAssertError(1, 0, Clock.systemUTC(), HttpErrorResponse.errorCodes.BAD_REQUEST, "Cannot activate application");
assertFalse(hostProvisioner.activated);
}
@Override
- protected RemoteSession activateAndAssertOK(long sessionId, long previousSessionId) throws Exception {
- ActivateRequest activateRequest = activateAndAssertOKPut(sessionId, previousSessionId, "");
+ protected RemoteSession activateAndAssertOK(long sessionId, long previousSessionId, Clock clock) throws Exception {
+ ActivateRequest activateRequest = activateAndAssertOKPut(sessionId, previousSessionId, "", clock);
return activateRequest.getSession();
}
@Override
- protected Session activateAndAssertOK(long sessionId, long previousSessionId, String subPath) throws Exception {
- ActivateRequest activateRequest = activateAndAssertOKPut(sessionId, previousSessionId, subPath);
+ protected Session activateAndAssertOK(long sessionId, long previousSessionId, String subPath, Clock clock) throws Exception {
+ ActivateRequest activateRequest = activateAndAssertOKPut(sessionId, previousSessionId, subPath, clock);
return activateRequest.getSession();
}
@@ -146,9 +149,9 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase {
}
@Override
- protected void activateAndAssertError(long sessionId, long previousSessionId, HttpErrorResponse.errorCodes errorCode, String expectedError) throws Exception {
+ protected void activateAndAssertError(long sessionId, long previousSessionId, Clock clock, HttpErrorResponse.errorCodes errorCode, String expectedError) throws Exception {
hostProvisioner.activated = false;
- activateAndAssertErrorPut(sessionId, previousSessionId, errorCode, expectedError);
+ activateAndAssertErrorPut(sessionId, previousSessionId, clock, errorCode, expectedError);
assertFalse(hostProvisioner.activated);
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
index f321f6f67ef..2d63dcf9b0b 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
@@ -42,6 +42,8 @@ import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.time.Clock;
+import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -146,7 +148,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
/**
* A mock remote session repo based on contents of local repo
*/
- private RemoteSessionRepo fromLocalSessionRepo(LocalSessionRepo localRepo) {
+ private RemoteSessionRepo fromLocalSessionRepo(LocalSessionRepo localRepo, Clock clock) {
RemoteSessionRepo remoteRepo = new RemoteSessionRepo();
PathProvider pathProvider = new PathProvider(Path.createRoot());
for (LocalSession ls : localRepo.listSessions()) {
@@ -155,7 +157,8 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
if (ls.getStatus()!=null) zooKeeperClient.writeStatus(ls.getStatus());
RemoteSession remSess = new RemoteSession(TenantName.from("default"), ls.getSessionId(),
new TestComponentRegistry.Builder().curator(curator).build(),
- zooKeeperClient);
+ zooKeeperClient,
+ clock);
remoteRepo.addSession(remSess);
}
return remoteRepo;
@@ -165,7 +168,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_get_response_activate_url_on_ok() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- SessionHandler sessHandler = createHandler(fromLocalSessionRepo(localRepo));
+ SessionHandler sessHandler = createHandler(fromLocalSessionRepo(localRepo, Clock.systemUTC()));
sessHandler.handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
session.setStatus(Session.Status.PREPARE);
zooKeeperClient.writeStatus(Session.Status.PREPARE);
@@ -177,7 +180,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_get_response_error_on_not_prepared() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- SessionHandler sessHandler = createHandler(fromLocalSessionRepo(localRepo));
+ SessionHandler sessHandler = createHandler(fromLocalSessionRepo(localRepo, Clock.systemUTC()));
session.setStatus(Session.Status.NEW);
zooKeeperClient.writeStatus(Session.Status.NEW);
HttpResponse getResponse = sessHandler.handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.GET, Cmd.PREPARED, 1L));
@@ -197,7 +200,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
session.setStatus(Session.Status.ACTIVATE);
- SessionHandler sessionHandler = createHandler(fromLocalSessionRepo(localRepo));
+ SessionHandler sessionHandler = createHandler(fromLocalSessionRepo(localRepo, Clock.systemUTC()));
HttpResponse putResponse = sessionHandler.handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(putResponse, BAD_REQUEST,
HttpErrorResponse.errorCodes.BAD_REQUEST,
@@ -208,7 +211,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_get_response_error_when_session_id_does_not_exist() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- SessionHandler sessHandler = createHandler(fromLocalSessionRepo(localRepo));
+ SessionHandler sessHandler = createHandler(fromLocalSessionRepo(localRepo, Clock.systemUTC()));
HttpResponse getResponse = sessHandler.handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.GET, Cmd.PREPARED, 9999L));
HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(getResponse, NOT_FOUND,
HttpErrorResponse.errorCodes.NOT_FOUND,
@@ -397,7 +400,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
}
@Override
- public ConfigChangeActions prepare(DeployLogger logger, PrepareParams params, Optional<ApplicationSet> application, Path tenantPath) {
+ public ConfigChangeActions prepare(DeployLogger logger, PrepareParams params, Optional<ApplicationSet> application, Path tenantPath, Instant now) {
throw exception;
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java
index eb51627bb95..d5f4dd573c6 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java
@@ -5,6 +5,7 @@ import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
import java.io.IOException;
+import java.time.Clock;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
@@ -84,13 +85,13 @@ public class TenantHandlerTest extends TenantTest {
@Test
public void testDeleteTenantWithActiveApplications() throws Exception {
putSync(HttpRequest.createTestRequest("http://deploy.example.yahoo.com:80/application/v2/tenant/" + a, Method.PUT));
- final Tenant tenant = tenants.getTenant(a);
+ Tenant tenant = tenants.getTenant(a);
assertEquals(a, tenant.getName());
- final int sessionId = 1;
+ int sessionId = 1;
ApplicationId app = ApplicationId.from(a,
ApplicationName.from("foo"), InstanceName.defaultName());
- ApplicationHandlerTest.addMockApplication(tenant, app, sessionId);
+ ApplicationHandlerTest.addMockApplication(tenant, app, sessionId, Clock.systemUTC());
try {
handler.handleDELETE(HttpRequest.createTestRequest("http://deploy.example.yahoo.com:80/application/v2/tenant/" + a, Method.DELETE));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
index cf9c046dada..f0086eabd26 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
@@ -21,6 +21,7 @@ import org.junit.Before;
import org.junit.Test;
import java.io.File;
+import java.time.Instant;
import java.util.*;
import static org.hamcrest.core.Is.is;
@@ -59,7 +60,7 @@ public class LocalSessionTest {
public void require_that_session_status_is_updated() throws Exception {
LocalSession session = createSession(TenantName.defaultName(), 3);
assertThat(session.getStatus(), is(Session.Status.NEW));
- doPrepare(session);
+ doPrepare(session, Instant.now());
assertThat(session.getStatus(), is(Session.Status.PREPARE));
session.createActivateTransaction().commit();
assertThat(session.getStatus(), is(Session.Status.ACTIVATE));
@@ -68,7 +69,7 @@ public class LocalSessionTest {
@Test
public void require_that_marking_session_modified_changes_status_to_new() throws Exception {
LocalSession session = createSession(TenantName.defaultName(), 3);
- doPrepare(session);
+ doPrepare(session, Instant.now());
assertThat(session.getStatus(), is(Session.Status.PREPARE));
session.getApplicationFile(Path.createRoot(), LocalSession.Mode.READ);
assertThat(session.getStatus(), is(Session.Status.PREPARE));
@@ -81,7 +82,7 @@ public class LocalSessionTest {
SessionTest.MockSessionPreparer preparer = new SessionTest.MockSessionPreparer();
LocalSession session = createSession(TenantName.defaultName(), 3, preparer);
assertFalse(preparer.isPrepared);
- doPrepare(session);
+ doPrepare(session, Instant.now());
assertTrue(preparer.isPrepared);
assertThat(session.getStatus(), is(Session.Status.PREPARE));
}
@@ -130,7 +131,7 @@ public class LocalSessionTest {
ApplicationId origId = new ApplicationId.Builder()
.tenant("tenant")
.applicationName("foo").instanceName("quux").build();
- doPrepare(session, new PrepareParams.Builder().applicationId(origId).build());
+ doPrepare(session, new PrepareParams.Builder().applicationId(origId).build(), Instant.now());
ProvisionInfo info = session.getProvisionInfo();
assertNotNull(info);
assertThat(info.getHosts().size(), is(1));
@@ -140,7 +141,7 @@ public class LocalSessionTest {
@Test
public void require_that_application_metadata_is_correct() throws Exception {
LocalSession session = createSession(TenantName.defaultName(), 3);
- doPrepare(session, new PrepareParams.Builder().build());
+ doPrepare(session, new PrepareParams.Builder().build(), Instant.now());
assertThat(session.getMetaData().toString(), is("n/a, n/a, 0, 0, , 0"));
}
@@ -167,12 +168,12 @@ public class LocalSessionTest {
return new LocalSession(tenant, sessionId, preparer, new SessionContext(FilesApplicationPackage.fromFile(testApp), zkc, sessionDir, new MemoryTenantApplications(), new HostRegistry<>(), superModelGenerationCounter));
}
- private void doPrepare(LocalSession session) {
- doPrepare(session, new PrepareParams.Builder().build());
+ private void doPrepare(LocalSession session, Instant now) {
+ doPrepare(session, new PrepareParams.Builder().build(), now);
}
- private void doPrepare(LocalSession session, PrepareParams params) {
- session.prepare(getLogger(false), params, Optional.empty(), tenantPath);
+ private void doPrepare(LocalSession session, PrepareParams params, Instant now) {
+ session.prepare(getLogger(false), params, Optional.empty(), tenantPath, now);
}
DeployHandlerLogger getLogger(boolean verbose) {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java
index d6b7a38345e..44f304847ba 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java
@@ -27,6 +27,7 @@ import org.junit.Test;
import org.xml.sax.SAXException;
import java.io.IOException;
+import java.time.Clock;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
@@ -59,28 +60,29 @@ public class RemoteSessionTest {
@Test
public void require_that_session_is_initialized() {
- Session session = createSession(2);
+ Clock clock = Clock.systemUTC();
+ Session session = createSession(2, clock);
assertThat(session.getSessionId(), is(2l));
- session = createSession(Long.MAX_VALUE);
+ session = createSession(Long.MAX_VALUE, clock);
assertThat(session.getSessionId(), is(Long.MAX_VALUE));
}
@Test
public void require_that_applications_are_loaded() throws IOException, SAXException {
- RemoteSession session = createSession(3, Arrays.asList(new MockModelFactory(), new VespaModelFactory(new NullConfigModelRegistry())));
+ RemoteSession session = createSession(3, Arrays.asList(new MockModelFactory(), new VespaModelFactory(new NullConfigModelRegistry())), Clock.systemUTC());
session.loadPrepared();
ApplicationSet applicationSet = session.ensureApplicationLoaded();
assertNotNull(applicationSet);
assertThat(applicationSet.getApplicationGeneration(), is(3l));
- assertThat(applicationSet.getForVersionOrLatest(Optional.empty()).getId().application().value(), is("foo"));
- assertNotNull(applicationSet.getForVersionOrLatest(Optional.empty()).getModel());
+ assertThat(applicationSet.getForVersionOrLatest(Optional.empty(), Instant.now()).getId().application().value(), is("foo"));
+ assertNotNull(applicationSet.getForVersionOrLatest(Optional.empty(), Instant.now()).getModel());
session.deactivate();
applicationSet = session.ensureApplicationLoaded();
assertNotNull(applicationSet);
assertThat(applicationSet.getApplicationGeneration(), is(3l));
- assertThat(applicationSet.getForVersionOrLatest(Optional.empty()).getId().application().value(), is("foo"));
- assertNotNull(applicationSet.getForVersionOrLatest(Optional.empty()).getModel());
+ assertThat(applicationSet.getForVersionOrLatest(Optional.empty(), Instant.now()).getId().application().value(), is("foo"));
+ assertNotNull(applicationSet.getForVersionOrLatest(Optional.empty(), Instant.now()).getModel());
}
@Test(expected = IllegalArgumentException.class)
@@ -93,7 +95,7 @@ public class RemoteSessionTest {
okFactory.vespaVersion = Version.fromIntValues(1, 1, 0);
okFactory.throwOnLoad = false;
- RemoteSession session = createSession(3, Arrays.asList(okFactory, failingFactory));
+ RemoteSession session = createSession(3, Arrays.asList(okFactory, failingFactory), failingFactory.clock());
session.loadPrepared();
}
@@ -111,7 +113,7 @@ public class RemoteSessionTest {
failingFactory.vespaVersion = Version.fromIntValues(2, 0, 0);
failingFactory.throwOnLoad = true;
- RemoteSession session = createSession(3, Arrays.asList(okFactory1, failingFactory, okFactory2));
+ RemoteSession session = createSession(3, Arrays.asList(okFactory1, failingFactory, okFactory2), failingFactory.clock());
session.loadPrepared();
}
@@ -126,7 +128,7 @@ public class RemoteSessionTest {
okFactory.vespaVersion = Version.fromIntValues(1, 2, 0);
okFactory.throwOnLoad = false;
- RemoteSession session = createSession(3, Arrays.asList(okFactory, failingFactory));
+ RemoteSession session = createSession(3, Arrays.asList(okFactory, failingFactory), failingFactory.clock());
session.loadPrepared();
}
@@ -141,7 +143,7 @@ public class RemoteSessionTest {
okFactory.vespaVersion = Version.fromIntValues(2, 0, 0);
okFactory.throwOnLoad = false;
- RemoteSession session = createSession(3, Arrays.asList(okFactory, failingFactory));
+ RemoteSession session = createSession(3, Arrays.asList(okFactory, failingFactory), failingFactory.clock());
session.loadPrepared();
}
@@ -161,7 +163,7 @@ public class RemoteSessionTest {
tooNewFactory.vespaVersion = Version.fromIntValues(2, 0, 0);
tooNewFactory.throwOnLoad = true;
- RemoteSession session = createSession(3, Arrays.asList(tooNewFactory, okFactory, failingFactory));
+ RemoteSession session = createSession(3, Arrays.asList(tooNewFactory, okFactory, failingFactory), failingFactory.clock());
session.loadPrepared();
}
@@ -179,7 +181,7 @@ public class RemoteSessionTest {
okFactory.throwOnLoad = false;
SessionZooKeeperClient zkc = new MockSessionZKClient(curator, pathProvider.getSessionDir(3), application);
- RemoteSession session = createSession(3, zkc, Arrays.asList(okFactory, failingFactory));
+ RemoteSession session = createSession(3, zkc, Arrays.asList(okFactory, failingFactory), failingFactory.clock());
session.loadPrepared();
// Does not cause an exception because model version 3 is skipped
@@ -188,7 +190,7 @@ public class RemoteSessionTest {
@Test
public void require_that_session_status_is_updated() throws IOException, SAXException {
SessionZooKeeperClient zkc = new MockSessionZKClient(curator, pathProvider.getSessionDir(3));
- RemoteSession session = createSession(3, zkc);
+ RemoteSession session = createSession(3, zkc, Clock.systemUTC());
assertThat(session.getStatus(), is(Session.Status.NEW));
zkc.writeStatus(Session.Status.PREPARE);
assertThat(session.getStatus(), is(Session.Status.PREPARE));
@@ -202,7 +204,7 @@ public class RemoteSessionTest {
try {
int sessionId = 3;
SessionZooKeeperClient zkc = new MockSessionZKClient(curator, pathProvider.getSessionDir(sessionId));
- createSession(sessionId, zkc, Collections.singletonList(mockModelFactory), permanentApp).ensureApplicationLoaded();
+ createSession(sessionId, zkc, Collections.singletonList(mockModelFactory), permanentApp, mockModelFactory.clock()).ensureApplicationLoaded();
} catch (Exception e) {
e.printStackTrace();
// ignore, we're not interested in deploy errors as long as the below state is OK.
@@ -211,22 +213,23 @@ public class RemoteSessionTest {
assertTrue(mockModelFactory.modelContext.permanentApplicationPackage().isPresent());
}
- private RemoteSession createSession(long sessionId) {
- return createSession(sessionId, Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry())));
+ private RemoteSession createSession(long sessionId, Clock clock) {
+ return createSession(sessionId, Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry())), clock);
}
- private RemoteSession createSession(long sessionId, SessionZooKeeperClient zkc) {
- return createSession(sessionId, zkc, Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry())));
+ private RemoteSession createSession(long sessionId, SessionZooKeeperClient zkc, Clock clock) {
+ return createSession(sessionId, zkc, Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry())), clock);
}
- private RemoteSession createSession(long sessionId, List<ModelFactory> modelFactories) {
+ private RemoteSession createSession(long sessionId, List<ModelFactory> modelFactories, Clock clock) {
SessionZooKeeperClient zkc = new MockSessionZKClient(curator, pathProvider.getSessionDir(sessionId));
- return createSession(sessionId, zkc, modelFactories);
+ return createSession(sessionId, zkc, modelFactories, clock);
}
- private RemoteSession createSession(long sessionId, SessionZooKeeperClient zkc, List<ModelFactory> modelFactories) {
- return createSession(sessionId, zkc, modelFactories, Optional.empty());
+ private RemoteSession createSession(long sessionId, SessionZooKeeperClient zkc, List<ModelFactory> modelFactories, Clock clock) {
+ return createSession(sessionId, zkc, modelFactories, Optional.empty(), clock);
}
- private RemoteSession createSession(long sessionId, SessionZooKeeperClient zkc, List<ModelFactory> modelFactories, Optional<PermanentApplicationPackage> permanentApplicationPackage) {
+ private RemoteSession createSession(long sessionId, SessionZooKeeperClient zkc, List<ModelFactory> modelFactories,
+ Optional<PermanentApplicationPackage> permanentApplicationPackage, Clock clock) {
zkc.writeStatus(Session.Status.NEW);
zkc.writeApplicationId(new ApplicationId.Builder().applicationName("foo").instanceName("bim").build());
TestComponentRegistry.Builder registryBuilder = new TestComponentRegistry.Builder()
@@ -237,7 +240,8 @@ public class RemoteSessionTest {
return new RemoteSession(TenantName.from("default"), sessionId,
registryBuilder.build(),
- zkc);
+ zkc,
+ clock);
}
private class MockModelFactory implements ModelFactory {
@@ -248,6 +252,8 @@ public class RemoteSessionTest {
/** The validation overrides of this, or null if none */
private final String validationOverrides;
+
+ private Clock clock = Clock.fixed(LocalDate.parse("2000-01-01", DateTimeFormatter.ISO_DATE).atStartOfDay().atZone(ZoneOffset.UTC).toInstant(), ZoneOffset.UTC);
public MockModelFactory() { this(null); }
@@ -259,6 +265,9 @@ public class RemoteSessionTest {
public Version getVersion() {
return vespaVersion;
}
+
+ /** Returns the clock used by this, which is fixed at the instant 2000-01-01T00:00:00 */
+ public Clock clock() { return clock; }
@Override
public Model createModel(ModelContext modelContext) {
@@ -271,9 +280,8 @@ public class RemoteSessionTest {
public Model loadModel() {
try {
- Instant now = LocalDate.parse("2000-01-01", DateTimeFormatter.ISO_DATE).atStartOfDay().atZone(ZoneOffset.UTC).toInstant();
ApplicationPackage application = new MockApplicationPackage.Builder().withEmptyHosts().withEmptyServices().withValidationOverrides(validationOverrides).build();
- DeployState deployState = new DeployState.Builder().applicationPackage(application).now(now).build();
+ DeployState deployState = new DeployState.Builder().applicationPackage(application).now(clock.instant()).build();
return new VespaModel(deployState);
} catch (Exception e) {
throw new RuntimeException(e);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
index 1ef350461ab..13815e30bbd 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
@@ -40,6 +40,7 @@ import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
+import java.time.Instant;
import java.util.*;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -99,7 +100,7 @@ public class SessionPreparerTest extends TestWithCurator {
@Test(expected = InvalidApplicationException.class)
public void require_that_application_validation_exception_is_not_caught() throws IOException, SAXException {
FilesApplicationPackage app = getApplicationPackage(invalidTestApp);
- preparer.prepare(getContext(app), getLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath);
+ preparer.prepare(getContext(app), getLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath, Instant.now());
}
@Test
@@ -107,14 +108,14 @@ public class SessionPreparerTest extends TestWithCurator {
FilesApplicationPackage app = getApplicationPackage(invalidTestApp);
preparer.prepare(getContext(app), getLogger(),
new PrepareParams.Builder().ignoreValidationErrors(true).timeoutBudget(TimeoutBudgetTest.day()).build(),
- Optional.empty(), tenantPath);
+ Optional.empty(), tenantPath, Instant.now());
}
@Test
public void require_that_zookeeper_is_not_written_to_if_dryrun() throws IOException {
preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(),
new PrepareParams.Builder().dryRun(true).timeoutBudget(TimeoutBudgetTest.day()).build(),
- Optional.empty(), tenantPath);
+ Optional.empty(), tenantPath, Instant.now());
assertFalse(configCurator.exists(appPath.append(ConfigCurator.USERAPP_ZK_SUBPATH).append("services.xml").getAbsolute()));
}
@@ -122,7 +123,7 @@ public class SessionPreparerTest extends TestWithCurator {
public void require_that_filedistribution_is_ignored_on_dryrun() throws IOException {
preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(),
new PrepareParams.Builder().dryRun(true).timeoutBudget(TimeoutBudgetTest.day()).build(),
- Optional.empty(), tenantPath);
+ Optional.empty(), tenantPath, Instant.now());
assertThat(fileDistributionFactory.mockFileDistributionProvider.getMockFileDBHandler().sendDeployedFilesCalled, is(0));
assertThat(fileDistributionFactory.mockFileDistributionProvider.getMockFileDBHandler().limitSendingOfDeployedFilesToCalled, is(0));
assertThat(fileDistributionFactory.mockFileDistributionProvider.getMockFileDBHandler().reloadDeployFileDistributorCalled, is(0));
@@ -130,7 +131,7 @@ public class SessionPreparerTest extends TestWithCurator {
@Test
public void require_that_application_is_prepared() throws Exception {
- preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath);
+ preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath, Instant.now());
assertThat(fileDistributionFactory.mockFileDistributionProvider.getMockFileDBHandler().sendDeployedFilesCalled, is(2));
assertThat(fileDistributionFactory.mockFileDistributionProvider.getMockFileDBHandler().limitSendingOfDeployedFilesToCalled, is(2));
// Should be called only once no matter how many model versions are built
@@ -144,7 +145,7 @@ public class SessionPreparerTest extends TestWithCurator {
new TestModelFactory(Version.fromIntValues(1, 2, 3)),
new FailingModelFactory(Version.fromIntValues(3, 2, 1), new IllegalArgumentException("BOOHOO"))));
preparer = createPreparer(modelFactoryRegistry, HostProvisionerProvider.empty());
- preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath);
+ preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath, Instant.now());
}
@Test(expected = InvalidApplicationException.class)
@@ -153,14 +154,14 @@ public class SessionPreparerTest extends TestWithCurator {
new TestModelFactory(Version.fromIntValues(3, 2, 3)),
new FailingModelFactory(Version.fromIntValues(1, 2, 1), new IllegalArgumentException("BOOHOO"))));
preparer = createPreparer(modelFactoryRegistry, HostProvisionerProvider.empty());
- preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath);
+ preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath, Instant.now());
}
@Test(expected = InvalidApplicationException.class)
public void require_exception_for_overlapping_host() throws IOException {
SessionContext ctx = getContext(getApplicationPackage(testApp));
((HostRegistry<ApplicationId>)ctx.getHostValidator()).update(applicationId("foo"), Collections.singletonList("mytesthost"));
- preparer.prepare(ctx, new BaseDeployLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath);
+ preparer.prepare(ctx, new BaseDeployLogger(), new PrepareParams.Builder().build(), Optional.empty(), tenantPath, Instant.now());
}
@Test
@@ -172,7 +173,7 @@ public class SessionPreparerTest extends TestWithCurator {
System.out.println(level + ": "+message);
if (level.equals(LogLevel.WARNING) && message.contains("The host mytesthost is already in use")) logged.append("ok");
};
- preparer.prepare(ctx, logger, new PrepareParams.Builder().build(), Optional.empty(), tenantPath);
+ preparer.prepare(ctx, logger, new PrepareParams.Builder().build(), Optional.empty(), tenantPath, Instant.now());
assertEquals(logged.toString(), "");
}
@@ -183,7 +184,7 @@ public class SessionPreparerTest extends TestWithCurator {
.tenant(tenant)
.applicationName("foo").instanceName("quux").build();
PrepareParams params = new PrepareParams.Builder().applicationId(origId).build();
- preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), params, Optional.empty(), tenantPath);
+ preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), params, Optional.empty(), tenantPath, Instant.now());
SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, appPath);
assertTrue(configCurator.exists(appPath.append(SessionZooKeeperClient.APPLICATION_ID_PATH).getAbsolute()));
assertThat(zkc.readApplicationId(), is(origId));
@@ -200,7 +201,7 @@ public class SessionPreparerTest extends TestWithCurator {
preparer = createPreparer(modelFactoryRegistry, HostProvisionerProvider.empty());
List<RestartActions.Entry> actions =
preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(),
- new PrepareParams.Builder().build(), Optional.empty(), tenantPath)
+ new PrepareParams.Builder().build(), Optional.empty(), tenantPath, Instant.now())
.getRestartActions().getEntries();
assertThat(actions.size(), is(1));
assertThat(actions.get(0).getMessages(), equalTo(ImmutableSet.of("change", "other change")));
@@ -216,7 +217,7 @@ public class SessionPreparerTest extends TestWithCurator {
final ApplicationId applicationId = applicationId("test");
PrepareParams params = new PrepareParams.Builder().applicationId(applicationId).rotations(rotations).build();
File app = new File("src/test/resources/deploy/app");
- preparer.prepare(getContext(getApplicationPackage(app)), getLogger(), params, Optional.empty(), tenantPath);
+ preparer.prepare(getContext(getApplicationPackage(app)), getLogger(), params, Optional.empty(), tenantPath, Instant.now());
assertThat(readRotationsFromZK(applicationId), contains(new Rotation(rotations)));
}
@@ -232,7 +233,7 @@ public class SessionPreparerTest extends TestWithCurator {
new Rotations(curator, tenantPath).writeRotationsToZooKeeper(applicationId, Collections.singleton(new Rotation(rotations)));
final PrepareParams params = new PrepareParams.Builder().applicationId(applicationId).build();
final File app = new File("src/test/resources/deploy/app");
- preparer.prepare(getContext(getApplicationPackage(app)), getLogger(), params, Optional.empty(), tenantPath);
+ preparer.prepare(getContext(getApplicationPackage(app)), getLogger(), params, Optional.empty(), tenantPath, Instant.now());
// check that the rotation from zookeeper were used
final ModelContext modelContext = modelFactory.getModelContext();
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java
index 9d5890377c5..71b31754c5d 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java
@@ -7,6 +7,7 @@ import com.yahoo.vespa.config.server.application.ApplicationSet;
import com.yahoo.vespa.config.server.configchange.ConfigChangeActions;
import com.yahoo.vespa.curator.mock.MockCurator;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Optional;
@@ -24,7 +25,7 @@ public class SessionTest {
}
@Override
- public ConfigChangeActions prepare(SessionContext context, DeployLogger logger, PrepareParams params, Optional<ApplicationSet> currentActiveApplicationSet, Path tenantPath) {
+ public ConfigChangeActions prepare(SessionContext context, DeployLogger logger, PrepareParams params, Optional<ApplicationSet> currentActiveApplicationSet, Path tenantPath, Instant now) {
isPrepared = true;
return new ConfigChangeActions(new ArrayList<>());
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
index a5b4739091b..65f546e149a 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
@@ -47,6 +47,7 @@ import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
+import java.time.Clock;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
@@ -96,17 +97,17 @@ public class TenantRequestHandlerTest extends TestWithCurator {
deployer.deploy(FilesApplicationPackage.fromFile(appDir), Collections.singletonMap(vespaVersion, new MockFileRegistry()), Collections.emptyMap());
}
- private ApplicationSet reloadConfig(long id) {
- return reloadConfig(id, "default");
+ private ApplicationSet reloadConfig(long id, Clock clock) {
+ return reloadConfig(id, "default", clock);
}
- private ApplicationSet reloadConfig(long id, String application) {
+ private ApplicationSet reloadConfig(long id, String application, Clock clock) {
SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, configCurator,
new PathProvider(Path.createRoot()).getSessionDir(id),
new TestConfigDefinitionRepo(),
"", Optional.empty());
zkc.writeApplicationId(new ApplicationId.Builder().tenant(tenant).applicationName(application).build());
- RemoteSession session = new RemoteSession(tenant, id, componentRegistry, zkc);
+ RemoteSession session = new RemoteSession(tenant, id, componentRegistry, zkc, clock);
return session.ensureApplicationLoaded();
}
@@ -146,15 +147,17 @@ public class TenantRequestHandlerTest extends TestWithCurator {
@Test
public void testReloadConfig() throws IOException, SAXException {
+ Clock clock = Clock.systemUTC();
ApplicationId applicationId = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(tenant).build();
- server.reloadConfig(reloadConfig(1));
+
+ server.reloadConfig(reloadConfig(1, clock));
assertThat(listener.reloaded.get(), is(1));
// Using only payload list for this simple test
SimpletypesConfig config = resolve(SimpletypesConfig.class, server, "");
assertThat(config.intval(), is(1337));
assertThat(server.getApplicationGeneration(applicationId, Optional.of(vespaVersion)), is(1l));
- server.reloadConfig(reloadConfig(1l));
+ server.reloadConfig(reloadConfig(1l, clock));
config = resolve(SimpletypesConfig.class, server, "");
assertThat(config.intval(), is(1337));
assertThat(listener.reloaded.get(), is(2));
@@ -164,7 +167,7 @@ public class TenantRequestHandlerTest extends TestWithCurator {
listener.reloaded.set(0);
feedApp(app2, 2);
- server.reloadConfig(reloadConfig(2l));
+ server.reloadConfig(reloadConfig(2l, clock));
config = resolve(SimpletypesConfig.class, server, "");
assertThat(config.intval(), is(1330));
assertThat(listener.reloaded.get(), is(1));
@@ -173,7 +176,7 @@ public class TenantRequestHandlerTest extends TestWithCurator {
@Test
public void testRemoveApplication() {
- server.reloadConfig(reloadConfig(1));
+ server.reloadConfig(reloadConfig(1, Clock.systemUTC()));
assertThat(listener.removed.get(), is(0));
server.removeApplication(new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(tenant).build());
assertThat(listener.removed.get(), is(1));
@@ -190,7 +193,7 @@ public class TenantRequestHandlerTest extends TestWithCurator {
.tenant(tenant)
.applicationName("myapp").instanceName("myinst").build();
zkc.writeApplicationId(appId);
- RemoteSession session = new RemoteSession(appId.tenant(), id, componentRegistry, zkc);
+ RemoteSession session = new RemoteSession(appId.tenant(), id, componentRegistry, zkc, Clock.systemUTC());
server.reloadConfig(session.ensureApplicationLoaded());
SimpletypesConfig config = resolve(SimpletypesConfig.class, server, appId, vespaVersion, "");
assertThat(config.intval(), is(1337));
@@ -229,7 +232,7 @@ public class TenantRequestHandlerTest extends TestWithCurator {
feedApp(appDir, sessionId, appId);
SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, new PathProvider(Path.createRoot()).getSessionDir(sessionId));
zkc.writeApplicationId(appId);
- RemoteSession session = new RemoteSession(tenant, sessionId, componentRegistry, zkc);
+ RemoteSession session = new RemoteSession(tenant, sessionId, componentRegistry, zkc, Clock.systemUTC());
server.reloadConfig(session.ensureApplicationLoaded());
}
@@ -260,7 +263,7 @@ public class TenantRequestHandlerTest extends TestWithCurator {
@Test
public void testHasApplication() throws IOException, SAXException {
assertdefaultAppNotFound();
- server.reloadConfig(reloadConfig(1l));
+ server.reloadConfig(reloadConfig(1l, Clock.systemUTC()));
assertTrue(server.hasApplication(new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(tenant).build(), Optional.of(vespaVersion)));
}
@@ -271,7 +274,7 @@ public class TenantRequestHandlerTest extends TestWithCurator {
@Test
public void testMultipleApplicationsReload() {
assertdefaultAppNotFound();
- server.reloadConfig(reloadConfig(1l, "foo"));
+ server.reloadConfig(reloadConfig(1l, "foo", Clock.systemUTC()));
assertdefaultAppNotFound();
assertTrue(server.hasApplication(new ApplicationId.Builder().tenant(tenant).applicationName("foo").build(),
Optional.of(vespaVersion)));
diff --git a/pom.xml b/pom.xml
index a9d5915a909..bd3af56f862 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
<developers>
<developer>
- <name>Yahoo Inc.</name>
+ <name>Vespa</name>
<url>https://github.com/yahoo</url>
</developer>
</developers>
diff --git a/searchlib/src/vespa/searchlib/features/create-class-cpp.sh b/searchlib/src/vespa/searchlib/features/create-class-cpp.sh
index 188143f02ee..1e38a837609 100755
--- a/searchlib/src/vespa/searchlib/features/create-class-cpp.sh
+++ b/searchlib/src/vespa/searchlib/features/create-class-cpp.sh
@@ -6,7 +6,7 @@ guard=`echo $class | tr 'a-z' 'A-Z'`
name=`echo $class | tr 'A-Z' 'a-z'`
cat <<EOF
-// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "$name.h"
diff --git a/testutil/src/main/java/com/yahoo/test/ManualClock.java b/testutil/src/main/java/com/yahoo/test/ManualClock.java
index 785e69e4bfd..28ccdc8d27e 100644
--- a/testutil/src/main/java/com/yahoo/test/ManualClock.java
+++ b/testutil/src/main/java/com/yahoo/test/ManualClock.java
@@ -10,7 +10,11 @@ import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAmount;
-/** A clock which initially has the time of its creation but can only be advanced by calling advance */
+/**
+ * A clock which initially has the time of its creation but can only be advanced by calling advance
+ *
+ * @author bratseth
+ */
public class ManualClock extends Clock {
private Instant currentTime = Instant.now();