summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java10
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/ValidationOverrideTest.java13
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java10
-rw-r--r--configserver/src/test/apps/validationOverride/validation-overrides.xml2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java50
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java82
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java31
-rw-r--r--testutil/src/main/java/com/yahoo/test/ManualClock.java11
8 files changed, 124 insertions, 85 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java
index 0dccc2c9750..b3bcab01ed8 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java
@@ -30,6 +30,7 @@ import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.Reader;
+import java.time.Clock;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
@@ -44,6 +45,7 @@ public class VespaModelFactory implements ModelFactory {
private static final Logger log = Logger.getLogger(VespaModelFactory.class.getName());
private final ConfigModelRegistry configModelRegistry;
private final Zone zone;
+ private final Clock clock;
@Inject
public VespaModelFactory(ComponentRegistry<ConfigModelPlugin> pluginRegistry, Zone zone) {
@@ -55,9 +57,13 @@ public class VespaModelFactory implements ModelFactory {
}
this.configModelRegistry = new MapConfigModelRegistry(modelBuilders);
this.zone = zone;
+ this.clock = Clock.systemUTC();
}
public VespaModelFactory(ConfigModelRegistry configModelRegistry) {
+ this(configModelRegistry, Clock.systemUTC());
+ }
+ public VespaModelFactory(ConfigModelRegistry configModelRegistry, Clock clock) {
if (configModelRegistry == null) {
this.configModelRegistry = new NullConfigModelRegistry();
log.info("Will not load config models from plugins, as no registry is available");
@@ -65,6 +71,7 @@ public class VespaModelFactory implements ModelFactory {
this.configModelRegistry = configModelRegistry;
}
this.zone = Zone.defaultZone();
+ this.clock = clock;
}
@Override
@@ -95,7 +102,8 @@ public class VespaModelFactory implements ModelFactory {
.properties(createDeployProperties(modelContext.properties()))
.modelHostProvisioner(createHostProvisioner(modelContext))
.rotations(modelContext.properties().rotations())
- .zone(zone);
+ .zone(zone)
+ .now(clock.instant());
modelContext.previousModel().ifPresent(builder::previousModel);
return builder.build();
}
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
index 3354e9320fc..57e3cfa9dfa 100644
--- 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
@@ -1,6 +1,7 @@
// Copyright 2016 Yahoo Inc. 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;
@@ -32,7 +33,7 @@ public class ValidationOverrideTest {
{
ValidationOverrides overrides = new ValidationOverridesXMLReader().read(Optional.of(new StringReader(validationOverrides)),
- at("2000-01-01T23:59:00"));
+ ManualClock.at("2000-01-01T23:59:00"));
assertOverridden("indexing-change", overrides);
assertOverridden("indexing-mode-change", overrides);
assertNotOverridden("field-type-change", overrides);
@@ -40,7 +41,7 @@ public class ValidationOverrideTest {
{
ValidationOverrides overrides = new ValidationOverridesXMLReader().read(Optional.of(new StringReader(validationOverrides)),
- at("2000-01-02T00:00:00"));
+ ManualClock.at("2000-01-02T00:00:00"));
assertNotOverridden("indexing-change", overrides);
assertOverridden("indexing-mode-change", overrides);
assertNotOverridden("field-type-change", overrides);
@@ -48,7 +49,7 @@ public class ValidationOverrideTest {
{
ValidationOverrides overrides = new ValidationOverridesXMLReader().read(Optional.of(new StringReader(validationOverrides)),
- at("2000-01-04T00:00:00"));
+ ManualClock.at("2000-01-04T00:00:00"));
assertNotOverridden("indexing-change", overrides);
assertNotOverridden("indexing-mode-change", overrides);
assertNotOverridden("field-type-change", overrides);
@@ -65,7 +66,7 @@ public class ValidationOverrideTest {
try {
new ValidationOverridesXMLReader().read(Optional.of(new StringReader(validationOverrides)),
- at("2000-01-01T23:59:00"));
+ ManualClock.at("2000-01-01T23:59:00"));
fail("Expected validation interval override validation validation failure");
}
catch (IllegalArgumentException e) {
@@ -75,10 +76,6 @@ public class ValidationOverrideTest {
}
}
- private Instant at(String utcIsoTime) {
- return LocalDateTime.parse(utcIsoTime, DateTimeFormatter.ISO_DATE_TIME).atZone(ZoneOffset.UTC).toInstant();
- }
-
private void assertOverridden(String validationId, ValidationOverrides overrides) {
overrides.invalid(ValidationId.from(validationId).get(), "message"); // should not throw exception
}
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 925b442ea3a..3956e5d9a8f 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
@@ -173,12 +173,13 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
private void checkIfActiveHasChanged(LocalSession session, LocalSession currentActiveSession, boolean ignoreStaleSessionFailure) {
long activeSessionAtCreate = session.getActiveSessionAtCreate();
- log.log(LogLevel.DEBUG, currentActiveSession.logPre()+"active session id at create time=" + activeSessionAtCreate);
+ log.log(LogLevel.DEBUG, currentActiveSession.logPre() + "active session id at create time=" + activeSessionAtCreate);
if (activeSessionAtCreate == 0) return; // No active session at create
long sessionId = session.getSessionId();
long currentActiveSessionSessionId = currentActiveSession.getSessionId();
- log.log(LogLevel.DEBUG, currentActiveSession.logPre()+"sessionId=" + sessionId + ", current active session=" + currentActiveSessionSessionId);
+ log.log(LogLevel.DEBUG, currentActiveSession.logPre() + "sessionId=" + sessionId +
+ ", current active session=" + currentActiveSessionSessionId);
if (currentActiveSession.isNewerThan(activeSessionAtCreate) &&
currentActiveSessionSessionId != sessionId) {
String errMsg = currentActiveSession.logPre()+"Cannot activate session " +
@@ -186,7 +187,7 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
currentActiveSessionSessionId + ") has changed since session " + sessionId +
" was created (was " + activeSessionAtCreate + " at creation time)";
if (ignoreStaleSessionFailure) {
- log.warning(errMsg+ " (Continuing because of force.)");
+ log.warning(errMsg + " (Continuing because of force.)");
} else {
throw new IllegalStateException(errMsg);
}
@@ -198,7 +199,8 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
private void checkIfActiveIsNewerThanSessionToBeActivated(long sessionId, long currentActiveSessionId) {
if (sessionId < currentActiveSessionId) {
throw new IllegalArgumentException("It is not possible to activate session " + sessionId +
- ", because it is older than current active session (" + currentActiveSessionId + ")");
+ ", because it is older than current active session (" +
+ currentActiveSessionId + ")");
}
}
}
diff --git a/configserver/src/test/apps/validationOverride/validation-overrides.xml b/configserver/src/test/apps/validationOverride/validation-overrides.xml
index 28e25cd793d..1f209d21c94 100644
--- a/configserver/src/test/apps/validationOverride/validation-overrides.xml
+++ b/configserver/src/test/apps/validationOverride/validation-overrides.xml
@@ -1,3 +1,3 @@
<validation-overrides>
- <allow until="2016-09-01">skip-old-config-models</allow>
+ <allow until="2016-10-10">skip-old-config-models</allow>
</validation-overrides> \ No newline at end of file
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 21196a1f57b..be31b5c1fc9 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
@@ -1,10 +1,16 @@
package com.yahoo.vespa.config.server.deploy;
import com.yahoo.cloud.config.ConfigserverConfig;
+import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.model.NullConfigModelRegistry;
import com.yahoo.config.model.api.HostProvisioner;
+import com.yahoo.config.model.api.Model;
+import com.yahoo.config.model.api.ModelContext;
+import com.yahoo.config.model.api.ModelCreateResult;
import com.yahoo.config.model.api.ModelFactory;
+import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.provision.InMemoryProvisioner;
+import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
@@ -14,6 +20,7 @@ import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.ProvisionLogger;
import com.yahoo.config.provision.Provisioner;
+import com.yahoo.config.provision.Version;
import com.yahoo.path.Path;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.config.server.ApplicationRepository;
@@ -30,6 +37,7 @@ import com.yahoo.vespa.config.server.tenant.Tenants;
import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
+import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.VespaModelFactory;
import org.apache.curator.framework.CuratorFramework;
import org.junit.Before;
@@ -38,6 +46,10 @@ import java.io.File;
import java.io.IOException;
import java.time.Clock;
import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -56,7 +68,7 @@ public class DeployTester {
private ApplicationId id;
public DeployTester(String appPath) {
- this(appPath, Collections.singletonList(createDefaultModelFactory()));
+ this(appPath, Collections.singletonList(createDefaultModelFactory(Clock.systemUTC())));
}
public DeployTester(String appPath, List<ModelFactory> modelFactories) {
@@ -73,7 +85,11 @@ public class DeployTester {
public Tenant tenant() { return tenants.defaultTenant(); }
- public static ModelFactory createDefaultModelFactory() { return new VespaModelFactory(new NullConfigModelRegistry()); }
+ /** Create the model factory which will be used in production */
+ public static ModelFactory createDefaultModelFactory(Clock clock) { return new VespaModelFactory(new NullConfigModelRegistry(), clock); }
+
+ /** Create a model factory which always fails validation */
+ public static ModelFactory createFailingModelFactory(Version version) { return new FailingModelFactory(version); }
/**
* Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet.
@@ -136,4 +152,34 @@ public class DeployTester {
}
+ private static class FailingModelFactory implements ModelFactory {
+
+ private final Version version;
+
+ public FailingModelFactory(Version version) {
+ this.version = version;
+ }
+
+ @Override
+ public Version getVersion() { return version; }
+
+ @Override
+ public Model createModel(ModelContext modelContext) {
+ try {
+ Instant now = LocalDate.parse("2000-01-01", DateTimeFormatter.ISO_DATE).atStartOfDay().atZone(ZoneOffset.UTC).toInstant();
+ ApplicationPackage application = new MockApplicationPackage.Builder().withEmptyHosts().withEmptyServices().build();
+ DeployState deployState = new DeployState.Builder().applicationPackage(application).now(now).build();
+ return new VespaModel(deployState);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public ModelCreateResult createAndValidateModel(ModelContext modelContext, boolean ignoreValidationErrors) {
+ throw new IllegalArgumentException("Validation fails");
+ }
+
+ }
+
}
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 585b988bffc..4f7febd54cc 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
@@ -1,48 +1,19 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.deploy;
-import com.yahoo.cloud.config.ConfigserverConfig;
-import com.yahoo.config.model.NullConfigModelRegistry;
-import com.yahoo.config.model.api.HostProvisioner;
-import com.yahoo.config.model.provision.InMemoryProvisioner;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ApplicationName;
-import com.yahoo.config.provision.Capacity;
-import com.yahoo.config.provision.ClusterSpec;
-import com.yahoo.config.provision.HostFilter;
-import com.yahoo.config.provision.HostSpec;
-import com.yahoo.config.provision.InstanceName;
-import com.yahoo.config.provision.ProvisionLogger;
-import com.yahoo.config.provision.Provisioner;
-import com.yahoo.path.Path;
-import com.yahoo.transaction.NestedTransaction;
-import com.yahoo.vespa.config.server.ApplicationRepository;
-import com.yahoo.vespa.config.server.TestComponentRegistry;
-import com.yahoo.vespa.config.server.TestWithCurator;
-import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
-import com.yahoo.vespa.config.server.monitoring.Metrics;
-import com.yahoo.vespa.config.server.tenant.Tenant;
-import com.yahoo.vespa.config.server.tenant.Tenants;
-import com.yahoo.vespa.config.server.tenant.TestWithTenant;
-import com.yahoo.vespa.config.server.TimeoutBudget;
-import com.yahoo.vespa.config.server.provision.HostProvisionerProvider;
-import com.yahoo.vespa.config.server.session.LocalSession;
-import com.yahoo.vespa.config.server.session.PrepareParams;
-import com.yahoo.vespa.config.server.session.SilentDeployLogger;
-import com.yahoo.vespa.model.VespaModelFactory;
-import org.junit.Before;
+import com.yahoo.config.model.api.ModelFactory;
+import com.yahoo.config.provision.Version;
+import com.yahoo.test.ManualClock;
import org.junit.Test;
-import java.io.File;
import java.io.IOException;
-import java.time.Clock;
import java.time.Duration;
-import java.util.Collection;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* @author bratseth
@@ -53,8 +24,8 @@ public class HostedDeployTest {
public void testRedeploy() throws InterruptedException, IOException {
DeployTester tester = new DeployTester("src/test/apps/hosted/");
tester.deployApp("myApp");
- Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
-
+
+ Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
assertTrue(deployment.isPresent());
deployment.get().prepare();
deployment.get().activate();
@@ -62,13 +33,42 @@ public class HostedDeployTest {
@Test
public void testRedeployAfterExpiredValidationOverride() throws InterruptedException, IOException {
- DeployTester tester = new DeployTester("src/test/apps/validationOverride/");
+ // Old version of model fails, but application disables loading old models until 2016-10-10, so deployment works
+ ManualClock clock = new ManualClock("2016-10-09T00:00:00");
+ List<ModelFactory> modelFactories = new ArrayList<>();
+ 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);
tester.deployApp("myApp");
- Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
- assertTrue(deployment.isPresent());
- deployment.get().prepare();
- deployment.get().activate();
+ // Redeployment from local active works
+ {
+ Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
+ assertTrue(deployment.isPresent());
+ deployment.get().prepare();
+ deployment.get().activate();
+ }
+
+ clock.advance(Duration.ofDays(2)); // validation override expires
+
+ // Redeployment from local active also works after the validation override expires
+ {
+ Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
+ assertTrue(deployment.isPresent());
+ deployment.get().prepare();
+ deployment.get().activate();
+ }
+
+ // However, redeployment from the outside fails after this date
+ {
+ try {
+ tester.deployApp("myApp");
+ fail("Expected redeployment to fail");
+ }
+ catch (IllegalArgumentException expected) {
+ // success
+ }
+ }
}
}
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 5a2f13c34ee..ebfcca5c6a7 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
@@ -16,6 +16,7 @@ import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Version;
import com.yahoo.path.Path;
+import com.yahoo.test.ManualClock;
import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.TestWithCurator;
@@ -78,8 +79,8 @@ public class RedeployTest {
@Test
public void testNoRedeploy() {
List<ModelFactory> modelFactories = new ArrayList<>();
- modelFactories.add(DeployTester.createDefaultModelFactory());
- modelFactories.add(new OldNonWorkingModelFactory());
+ modelFactories.add(DeployTester.createDefaultModelFactory(Clock.systemUTC()));
+ modelFactories.add(DeployTester.createFailingModelFactory(Version.fromIntValues(1, 0, 0)));
DeployTester tester = new DeployTester("ignored/app/path", modelFactories);
ApplicationId id = ApplicationId.from(TenantName.from("default"),
ApplicationName.from("default"),
@@ -87,30 +88,4 @@ public class RedeployTest {
assertFalse(tester.redeployFromLocalActive(id).isPresent());
}
- private static class OldNonWorkingModelFactory implements ModelFactory {
-
- @Override
- public Version getVersion() {
- return Version.fromIntValues(1, 0, 0);
- }
-
- @Override
- public Model createModel(ModelContext modelContext) {
- try {
- Instant now = LocalDate.parse("2000-01-01", DateTimeFormatter.ISO_DATE).atStartOfDay().atZone(ZoneOffset.UTC).toInstant();
- ApplicationPackage application = new MockApplicationPackage.Builder().withEmptyHosts().withEmptyServices().build();
- DeployState deployState = new DeployState.Builder().applicationPackage(application).now(now).build();
- return new VespaModel(deployState);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public ModelCreateResult createAndValidateModel(ModelContext modelContext, boolean ignoreValidationErrors) {
- throw new IllegalArgumentException("Validation fails");
- }
-
- }
-
}
diff --git a/testutil/src/main/java/com/yahoo/test/ManualClock.java b/testutil/src/main/java/com/yahoo/test/ManualClock.java
index b8325b3e3fc..1ffc7aa77da 100644
--- a/testutil/src/main/java/com/yahoo/test/ManualClock.java
+++ b/testutil/src/main/java/com/yahoo/test/ManualClock.java
@@ -3,7 +3,10 @@ package com.yahoo.test;
import java.time.Clock;
import java.time.Instant;
+import java.time.LocalDateTime;
import java.time.ZoneId;
+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 */
@@ -13,6 +16,10 @@ public class ManualClock extends Clock {
public ManualClock() {}
+ public ManualClock(String utcIsoTime) {
+ this(at(utcIsoTime));
+ }
+
public ManualClock(Instant currentTime) {
this.currentTime = currentTime;
}
@@ -33,4 +40,8 @@ public class ManualClock extends Clock {
@Override
public long millis() { return currentTime.toEpochMilli(); }
+ public static Instant at(String utcIsoTime) {
+ return LocalDateTime.parse(utcIsoTime, DateTimeFormatter.ISO_DATE_TIME).atZone(ZoneOffset.UTC).toInstant();
+ }
+
}