aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2018-04-19 10:47:52 +0200
committerMartin Polden <mpolden@mpolden.no>2018-04-19 15:05:00 +0200
commit5dc7c835d796f32bb2c9e0079693dd5da833635f (patch)
tree07161759a2973c43641500b2e38c8879dfcef126
parent3991eda2b969053748350b3a745b31d391f6917b (diff)
Decide controller version across all controllers
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServerClient.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java19
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java30
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/MockCuratorDb.java13
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionSerializer.java30
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializer.java22
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java11
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.java49
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java32
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerClientMock.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java15
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java11
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java11
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdaterTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializerTest.java19
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java15
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java16
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java19
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java38
22 files changed, 272 insertions, 109 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServerClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServerClient.java
index da3e32df5c9..77203f445d2 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServerClient.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServerClient.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration.configserver;
import com.fasterxml.jackson.databind.JsonNode;
@@ -47,7 +47,7 @@ public interface ConfigServerClient {
Map<?,?> getServiceApiResponse(String tenantName, String applicationName, String instanceName, String environment, String region, String serviceName, String restPath);
/** Returns the version this particular config server is running */
- Version version(URI configserverUri);
+ Version version(URI configServerUri);
/**
* Set new status on en endpoint in one zone.
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
index 7b9f27d8a96..f7757d2a335 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller;
import com.fasterxml.jackson.databind.JsonNode;
@@ -6,6 +6,7 @@ import com.google.inject.Inject;
import com.yahoo.component.AbstractComponent;
import com.yahoo.component.Version;
import com.yahoo.component.Vtag;
+import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
@@ -40,6 +41,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
+import java.util.function.Supplier;
import java.util.logging.Logger;
/**
@@ -57,6 +59,7 @@ public class Controller extends AbstractComponent {
private static final Logger log = Logger.getLogger(Controller.class.getName());
+ private final Supplier<String> hostnameSupplier;
private final CuratorDb curator;
private final ApplicationController applicationController;
private final TenantController tenantController;
@@ -88,7 +91,8 @@ public class Controller extends AbstractComponent {
this(curator, rotationsConfig,
gitHub, entityService, organization, globalRoutingService, zoneRegistry,
configServer, nodeRepository, metricsService, nameService, routingGenerator, chef,
- Clock.systemUTC(), athenzClientFactory, artifactRepository, buildService);
+ Clock.systemUTC(), athenzClientFactory, artifactRepository, buildService,
+ com.yahoo.net.HostName::getLocalhost);
}
public Controller(CuratorDb curator, RotationsConfig rotationsConfig,
@@ -98,8 +102,9 @@ public class Controller extends AbstractComponent {
MetricsService metricsService, NameService nameService,
RoutingGenerator routingGenerator, Chef chef, Clock clock,
AthenzClientFactory athenzClientFactory, ArtifactRepository artifactRepository,
- BuildService buildService) {
+ BuildService buildService, Supplier<String> hostnameSupplier) {
+ this.hostnameSupplier = Objects.requireNonNull(hostnameSupplier, "HostnameSupplier cannot be null");
this.curator = Objects.requireNonNull(curator, "Curator cannot be null");
this.gitHub = Objects.requireNonNull(gitHub, "GitHub cannot be null");
this.entityService = Objects.requireNonNull(entityService, "EntityService cannot be null");;
@@ -122,6 +127,9 @@ public class Controller extends AbstractComponent {
Objects.requireNonNull(buildService, "BuildService cannot be null"),
clock);
tenantController = new TenantController(this, curator, athenzClientFactory);
+
+ // Record the version of this controller
+ curator().writeControllerVersion(this.hostname(), Vtag.currentVersion);
}
/** Returns the instance controlling tenants */
@@ -204,6 +212,11 @@ public class Controller extends AbstractComponent {
.orElse(Vtag.currentVersion);
}
+ /** Returns the hostname of this controller */
+ public HostName hostname() {
+ return HostName.from(hostnameSupplier.get());
+ }
+
public MetricsService metricsService() {
return metricsService;
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
index 535e5a71fb6..843a3e8d97a 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.maintenance;
import com.yahoo.component.Version;
@@ -72,6 +72,8 @@ public class Upgrader extends Maintainer {
private Optional<Version> newestVersionWithConfidence(Confidence confidence) {
return reversed(controller().versionStatus().versions()).stream()
+ // Ensure we never pick a version newer than the system
+ .filter(v -> !v.versionNumber().isAfter(controller().systemVersion()))
.filter(v -> v.confidence().equalOrHigherThan(confidence))
.findFirst()
.map(VespaVersion::versionNumber);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
index 5a5a8263b3f..4224609f1e2 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
@@ -1,9 +1,11 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.persistence;
import com.google.inject.Inject;
import com.yahoo.component.Version;
+import com.yahoo.component.Vtag;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.path.Path;
import com.yahoo.slime.Slime;
@@ -21,6 +23,7 @@ import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.time.Duration;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -50,9 +53,11 @@ public class CuratorDb {
private static final Path lockRoot = root.append("locks");
private static final Path tenantRoot = root.append("tenants");
private static final Path applicationRoot = root.append("applications");
+ private static final Path controllerRoot = root.append("controllers");
private final StringSetSerializer stringSetSerializer = new StringSetSerializer();
private final VersionStatusSerializer versionStatusSerializer = new VersionStatusSerializer();
+ private final VersionSerializer versionSerializer = new VersionSerializer();
private final ConfidenceOverrideSerializer confidenceOverrideSerializer = new ConfidenceOverrideSerializer();
private final TenantSerializer tenantSerializer = new TenantSerializer();
private final ApplicationSerializer applicationSerializer = new ApplicationSerializer();
@@ -70,6 +75,15 @@ public class CuratorDb {
this.curator = curator;
}
+ /** Returns all hosts configured to be part of this ZooKeeper cluster */
+ public List<HostName> cluster() {
+ return Arrays.stream(curator.zooKeeperEnsembleConnectionSpec().split(","))
+ .filter(hostAndPort -> !hostAndPort.isEmpty())
+ .map(hostAndPort -> hostAndPort.split(":")[0])
+ .map(HostName::from)
+ .collect(Collectors.toList());
+ }
+
// -------------- Locks ---------------------------------------------------
public Lock lock(TenantName name, Duration timeout) {
@@ -180,6 +194,16 @@ public class CuratorDb {
.orElseGet(Collections::emptyMap);
}
+ public void writeControllerVersion(HostName hostname, Version version) {
+ curator.set(controllerPath(hostname.value()), asJson(versionSerializer.toSlime(version)));
+ }
+
+ public Version readControllerVersion(HostName hostname) {
+ return readSlime(controllerPath(hostname.value()))
+ .map(versionSerializer::fromSlime)
+ .orElse(Vtag.currentVersion);
+ }
+
// -------------- Tenant --------------------------------------------------
public void writeTenant(UserTenant tenant) {
@@ -353,4 +377,8 @@ public class CuratorDb {
return applicationRoot.append(application.serializedForm());
}
+ private static Path controllerPath(String hostname) {
+ return controllerRoot.append(hostname);
+ }
+
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/MockCuratorDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/MockCuratorDb.java
index 5dc8ca0e545..57364cee049 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/MockCuratorDb.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/MockCuratorDb.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.persistence;
import com.yahoo.vespa.curator.mock.MockCurator;
@@ -12,7 +12,16 @@ import com.yahoo.vespa.curator.mock.MockCurator;
public class MockCuratorDb extends CuratorDb {
public MockCuratorDb() {
- super(new MockCurator());
+ this("test-controller:2222");
+ }
+
+ public MockCuratorDb(String zooKeeperEnsembleConnectionSpec) {
+ super(new MockCurator() {
+ @Override
+ public String zooKeeperEnsembleConnectionSpec() {
+ return zooKeeperEnsembleConnectionSpec;
+ }
+ });
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionSerializer.java
new file mode 100644
index 00000000000..78045a15e9c
--- /dev/null
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionSerializer.java
@@ -0,0 +1,30 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.persistence;
+
+import com.yahoo.component.Version;
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.Inspector;
+import com.yahoo.slime.Slime;
+
+/**
+ * Serializer for version numbers.
+ *
+ * @author mpolden
+ */
+public class VersionSerializer {
+
+ private static final String versionField = "version";
+
+ public Slime toSlime(Version version) {
+ Slime slime = new Slime();
+ Cursor root = slime.setObject();
+ root.setString(versionField, version.toFullString());
+ return slime;
+ }
+
+ public Version fromSlime(Slime slime) {
+ Inspector root = slime.get();
+ return Version.fromString(root.field(versionField).asString());
+ }
+
+}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializer.java
index 18648d4a488..e0c443f2110 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializer.java
@@ -1,8 +1,9 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.persistence;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.HostName;
import com.yahoo.slime.ArrayTraverser;
import com.yahoo.slime.Cursor;
import com.yahoo.slime.Inspector;
@@ -32,7 +33,8 @@ public class VersionStatusSerializer {
// VespaVersion fields
private static final String releaseCommitField = "releaseCommit";
private static final String committedAtField = "releasedAt";
- private static final String isCurrentSystemVersionField = "isCurrentSystemVersion";
+ private static final String isControllerVersionField = "isCurrentControllerVersion";
+ private static final String isSystemVersionField = "isCurrentSystemVersion";
private static final String deploymentStatisticsField = "deploymentStatistics";
private static final String confidenceField = "confidence";
private static final String configServersField = "configServerHostnames";
@@ -62,14 +64,15 @@ public class VersionStatusSerializer {
private void vespaVersionToSlime(VespaVersion version, Cursor object) {
object.setString(releaseCommitField, version.releaseCommit());
object.setLong(committedAtField, version.committedAt().toEpochMilli());
- object.setBool(isCurrentSystemVersionField, version.isCurrentSystemVersion());
+ object.setBool(isControllerVersionField, version.isControllerVersion());
+ object.setBool(isSystemVersionField, version.isSystemVersion());
deploymentStatisticsToSlime(version.statistics(), object.setObject(deploymentStatisticsField));
object.setString(confidenceField, version.confidence().name());
configServersToSlime(version.configServerHostnames(), object.setArray(configServersField));
}
- private void configServersToSlime(Set<String> configServerHostnames, Cursor array) {
- configServerHostnames.forEach(array::addString);
+ private void configServersToSlime(Set<HostName> configServerHostnames, Cursor array) {
+ configServerHostnames.stream().map(HostName::value).forEach(array::addString);
}
private void deploymentStatisticsToSlime(DeploymentStatistics statistics, Cursor object) {
@@ -93,15 +96,16 @@ public class VersionStatusSerializer {
return new VespaVersion(deploymentStatisticsFromSlime(object.field(deploymentStatisticsField)),
object.field(releaseCommitField).asString(),
Instant.ofEpochMilli(object.field(committedAtField).asLong()),
- object.field(isCurrentSystemVersionField).asBool(),
+ object.field(isControllerVersionField).asBool(),
+ object.field(isSystemVersionField).asBool(),
configServersFromSlime(object.field(configServersField)),
VespaVersion.Confidence.valueOf(object.field(confidenceField).asString())
);
}
- private Set<String> configServersFromSlime(Inspector array) {
- Set<String> configServerHostnames = new LinkedHashSet<>();
- array.traverse((ArrayTraverser) (i, entry) -> configServerHostnames.add(entry.asString()));
+ private Set<HostName> configServersFromSlime(Inspector array) {
+ Set<HostName> configServerHostnames = new LinkedHashSet<>();
+ array.traverse((ArrayTraverser) (i, entry) -> configServerHostnames.add(HostName.from(entry.asString())));
return Collections.unmodifiableSet(configServerHostnames);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java
index f9d3901765f..8e981884f47 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java
@@ -1,9 +1,10 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.restapi.deployment;
import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.HostName;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.container.jdisc.LoggingRequestHandler;
@@ -85,13 +86,13 @@ public class DeploymentApiHandler extends LoggingRequestHandler {
versionObject.setString("confidence", version.confidence().name());
versionObject.setString("commit", version.releaseCommit());
versionObject.setLong("date", version.committedAt().toEpochMilli());
- versionObject.setBool("controllerVersion", version.isSelfVersion());
- versionObject.setBool("systemVersion", version.isCurrentSystemVersion());
+ versionObject.setBool("controllerVersion", version.isControllerVersion());
+ versionObject.setBool("systemVersion", version.isSystemVersion());
Cursor configServerArray = versionObject.setArray("configServers");
- for (String configServerHostnames : version.configServerHostnames()) {
+ for (HostName hostname : version.configServerHostnames()) {
Cursor configServerObject = configServerArray.addObject();
- configServerObject.setString("hostname", configServerHostnames);
+ configServerObject.setString("hostname", hostname.value());
}
Cursor failingArray = versionObject.setArray("failingApplications");
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.java
index 0d9bd25257f..1f72edf9538 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.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.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.versions;
import com.google.common.collect.ImmutableList;
import com.yahoo.collections.ListMap;
import com.yahoo.component.Version;
import com.yahoo.component.Vtag;
+import com.yahoo.config.provision.HostName;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.api.integration.github.GitSha;
@@ -52,13 +53,18 @@ public class VersionStatus {
public VersionStatus(List<VespaVersion> versions) {
this.versions = ImmutableList.copyOf(versions);
}
+
+ /** Returns the current version of controllers in this system */
+ public Optional<VespaVersion> controllerVersion() {
+ return versions().stream().filter(VespaVersion::isControllerVersion).findFirst();
+ }
/**
* Returns the current Vespa version of the system controlled by this,
* or empty if we have not currently determined what the system version is in this status.
*/
public Optional<VespaVersion> systemVersion() {
- return versions().stream().filter(VespaVersion::isCurrentSystemVersion).findAny();
+ return versions().stream().filter(VespaVersion::isSystemVersion).findFirst();
}
/**
@@ -79,17 +85,16 @@ public class VersionStatus {
/** Create a full, updated version status. This is expensive and should be done infrequently */
public static VersionStatus compute(Controller controller) {
- return compute(controller, Vtag.currentVersion);
- }
-
- /** Compute version status using the given current version. This is useful for testing. */
- public static VersionStatus compute(Controller controller, Version currentVersion) {
- ListMap<Version, String> configServerVersions = findConfigServerVersions(controller);
+ ListMap<Version, HostName> configServerVersions = findConfigServerVersions(controller);
+ ListMap<Version, HostName> controllerVersions = findControllerVersions(controller);
Set<Version> infrastructureVersions = new HashSet<>();
- infrastructureVersions.add(currentVersion);
+ infrastructureVersions.addAll(controllerVersions.keySet());
infrastructureVersions.addAll(configServerVersions.keySet());
+ // The controller version is the lowest controller version of all controllers
+ Version controllerVersion = controllerVersions.keySet().stream().sorted().findFirst().get();
+
// The system version is the oldest infrastructure version
Version systemVersion = infrastructureVersions.stream().sorted().findFirst().get();
@@ -102,6 +107,7 @@ public class VersionStatus {
try {
VespaVersion vespaVersion = createVersion(statistics,
+ statistics.version().equals(controllerVersion),
statistics.version().equals(systemVersion),
configServerVersions.getList(statistics.version()),
controller);
@@ -116,7 +122,7 @@ public class VersionStatus {
return new VersionStatus(versions);
}
- private static ListMap<Version, String> findConfigServerVersions(Controller controller) {
+ private static ListMap<Version, HostName> findConfigServerVersions(Controller controller) {
List<URI> configServers = controller.zoneRegistry().zones()
.controllerManaged()
// TODO jvenstad: Remove this when AWS is automatically upgraded.
@@ -125,9 +131,22 @@ public class VersionStatus {
.flatMap(zoneId -> controller.zoneRegistry().getConfigServerUris(zoneId).stream())
.collect(Collectors.toList());
- ListMap<Version, String> versions = new ListMap<>();
+ ListMap<Version, HostName> versions = new ListMap<>();
for (URI configServer : configServers)
- versions.put(controller.applications().configServer().version(configServer), configServer.getHost());
+ versions.put(controller.applications().configServer().version(configServer),
+ HostName.from(configServer.getHost()));
+ return versions;
+ }
+
+ private static ListMap<Version, HostName> findControllerVersions(Controller controller) {
+ ListMap<Version, HostName> versions = new ListMap<>();
+ if (controller.curator().cluster().isEmpty()) { // Use vtag if we do not have cluster
+ versions.put(Vtag.currentVersion, controller.hostname());
+ } else {
+ for (HostName hostname : controller.curator().cluster()) {
+ versions.put(controller.curator().readControllerVersion(hostname), hostname);
+ }
+ }
return versions;
}
@@ -176,15 +195,16 @@ public class VersionStatus {
}
private static VespaVersion createVersion(DeploymentStatistics statistics,
+ boolean isControllerVersion,
boolean isSystemVersion,
- Collection<String> configServerHostnames,
+ Collection<HostName> configServerHostnames,
Controller controller) {
GitSha gitSha = controller.gitHub().getCommit(VESPA_REPO_OWNER, VESPA_REPO, statistics.version().toFullString());
Instant committedAt = Instant.ofEpochMilli(gitSha.commit.author.date.getTime());
VespaVersion.Confidence confidence = controller.curator().readConfidenceOverrides().get(statistics.version());
// Compute confidence if there's no override
if (confidence == null) {
- if (isSystemVersion) { // Always compute confidence for system version
+ if (isSystemVersion || isControllerVersion) { // Always compute confidence for system and controller
confidence = VespaVersion.confidenceFrom(statistics, controller);
} else { // Keep existing confidence for non-system versions if already computed
confidence = confidenceFor(statistics.version(), controller)
@@ -193,6 +213,7 @@ public class VersionStatus {
}
return new VespaVersion(statistics,
gitSha.sha, committedAt,
+ isControllerVersion,
isSystemVersion,
configServerHostnames,
confidence
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
index 1aa94507b61..5fecb5de79f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
@@ -1,9 +1,9 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.versions;
import com.google.common.collect.ImmutableSet;
import com.yahoo.component.Version;
-import com.yahoo.component.Vtag;
+import com.yahoo.config.provision.HostName;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.application.ApplicationList;
@@ -25,18 +25,21 @@ public class VespaVersion implements Comparable<VespaVersion> {
private final String releaseCommit;
private final Instant committedAt;
- private final boolean isCurrentSystemVersion;
+ private final boolean isControllerVersion;
+ private final boolean isSystemVersion;
private final DeploymentStatistics statistics;
- private final ImmutableSet<String> configServerHostnames;
+ private final ImmutableSet<HostName> configServerHostnames;
private final Confidence confidence;
public VespaVersion(DeploymentStatistics statistics, String releaseCommit, Instant committedAt,
- boolean isCurrentSystemVersion, Collection<String> configServerHostnames,
+ boolean isControllerVersion, boolean isSystemVersion,
+ Collection<HostName> configServerHostnames,
Confidence confidence) {
this.statistics = statistics;
this.releaseCommit = releaseCommit;
this.committedAt = committedAt;
- this.isCurrentSystemVersion = isCurrentSystemVersion;
+ this.isControllerVersion = isControllerVersion;
+ this.isSystemVersion = isSystemVersion;
this.configServerHostnames = ImmutableSet.copyOf(configServerHostnames);
this.confidence = confidence;
}
@@ -83,22 +86,25 @@ public class VespaVersion implements Comparable<VespaVersion> {
/** Statistics about deployment of this version */
public DeploymentStatistics statistics() { return statistics; }
- /** Returns whether this is the version currently running on this controller */
- public boolean isSelfVersion() { return versionNumber().equals(Vtag.currentVersion); }
+ /** Returns whether this is the current version of controllers in this system (the lowest version across all
+ * controllers) */
+ public boolean isControllerVersion() {
+ return isControllerVersion;
+ }
/**
* Returns whether this is the current version of the infrastructure of the system
- * (i.e the lowest version across this controller and all config servers in all zones).
- * A goal of the controller is to eventually (limited by safety and upgrade capacity) drive
+ * (i.e the lowest version across all controllers and all config servers in all zones).
+ * A goal of the controllers is to eventually (limited by safety and upgrade capacity) drive
* all applications to this version.
*
* Note that the self version may be higher than the current system version if
- * all config servers are not yet upgraded to the version of this controller.
+ * all config servers are not yet upgraded to the version of the controllers.
*/
- public boolean isCurrentSystemVersion() { return isCurrentSystemVersion; }
+ public boolean isSystemVersion() { return isSystemVersion; }
/** Returns the host names of the config servers (across all zones) which are currently of this version */
- public Set<String> configServerHostnames() { return configServerHostnames; }
+ public Set<HostName> configServerHostnames() { return configServerHostnames; }
/** Returns the confidence we have in this versions suitability for production */
public Confidence confidence() { return confidence; }
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerClientMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerClientMock.java
index 068f7b21933..4e3783b6569 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerClientMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerClientMock.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller;
import com.fasterxml.jackson.databind.JsonNode;
@@ -183,8 +183,8 @@ public class ConfigServerClientMock extends AbstractComponent implements ConfigS
}
@Override
- public Version version(URI configServerURI) {
- return versions.getOrDefault(configServerURI, defaultVersion);
+ public Version version(URI configServerUri) {
+ return versions.getOrDefault(configServerUri, defaultVersion);
}
@Override
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
index 8e5f09346b1..ee426557596 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller;
import com.yahoo.component.Version;
@@ -77,12 +77,6 @@ public class ControllerTest {
.region("corp-us-east-1")
.build();
- private static final ApplicationPackage applicationPackage2 = new ApplicationPackageBuilder()
- .environment(Environment.prod)
- .region("corp-us-east-1")
- .region("us-west-1")
- .build();
-
@Test
public void testDeployment() {
// Setup system
@@ -296,15 +290,18 @@ public class ControllerTest {
"commit1",
Instant.now(),
true,
+ true,
Collections.emptyList(),
VespaVersion.Confidence.low
);
List<VespaVersion> versions = new ArrayList<>(controller.versionStatus().versions());
for (int i = 0; i < versions.size(); i++) {
VespaVersion c = versions.get(i);
- if (c.isCurrentSystemVersion())
+ if (c.isSystemVersion())
versions.set(i, new VespaVersion(c.statistics(), c.releaseCommit(), c.committedAt(),
- false, c.configServerHostnames(),
+ false,
+ false,
+ c.configServerHostnames(),
c.confidence()));
}
versions.add(newSystemVespaVersion);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
index 110455dac35..c098e49dbcb 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller;
import com.yahoo.config.provision.ApplicationId;
@@ -89,6 +89,12 @@ public final class ControllerTester {
new ArtifactRepositoryMock(), new MemoryEntityService(), new MockBuildService());
}
+ public ControllerTester(MockCuratorDb curatorDb) {
+ this(new AthenzDbMock(), new ManualClock(), new ConfigServerClientMock(),
+ new ZoneRegistryMock(), new GitHubMock(), curatorDb, defaultRotationsConfig(),
+ new MemoryNameService(), new ArtifactRepositoryMock(), new MemoryEntityService(), new MockBuildService());
+ }
+
private ControllerTester(AthenzDbMock athenzDb, ManualClock clock,
ConfigServerClientMock configServer, ZoneRegistryMock zoneRegistry,
GitHubMock gitHub, CuratorDb curator, RotationsConfig rotationsConfig,
@@ -270,7 +276,8 @@ public final class ControllerTester {
clock,
new AthenzClientFactoryMock(athensDb),
artifactRepository,
- buildService);
+ buildService,
+ () -> "test-controller");
controller.updateVersionStatus(VersionStatus.compute(controller));
return controller;
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
index f752cfd4f7a..ac1e5e7c677 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.deployment;
import com.yahoo.component.Version;
@@ -90,12 +90,13 @@ public class DeploymentTester {
}
public void updateVersionStatus() {
- controller().updateVersionStatus(VersionStatus.compute(controller(), tester.controller().systemVersion()));
+ updateVersionStatus(tester.controller().systemVersion());
}
- public void updateVersionStatus(Version currentVersion) {
- configServer().setDefaultVersion(currentVersion);
- controller().updateVersionStatus(VersionStatus.compute(controller(), currentVersion));
+ public void updateVersionStatus(Version newVersion) {
+ controller().curator().writeControllerVersion(controller().hostname(), newVersion);
+ configServer().setDefaultVersion(newVersion);
+ controller().updateVersionStatus(VersionStatus.compute(controller()));
}
public void upgradeSystem(Version version) {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdaterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdaterTest.java
index a7cecda3695..33284457e78 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdaterTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdaterTest.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.maintenance;
import com.yahoo.vespa.hosted.controller.ControllerTester;
@@ -17,7 +17,8 @@ import static org.junit.Assert.assertTrue;
*/
public class VersionStatusUpdaterTest {
- /** Test that this job updates the status. Test of the content of the update is in VersionStatusTest */
+ /** Test that this job updates the status. Test of the content of the update is in
+ * {@link com.yahoo.vespa.hosted.controller.versions.VersionStatusTest} */
@Test
public void testVersionUpdating() {
ControllerTester tester = new ControllerTester();
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializerTest.java
index 05b671baea0..b0306178ae3 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/VersionStatusSerializerTest.java
@@ -1,8 +1,9 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.persistence;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.HostName;
import com.yahoo.vespa.hosted.controller.versions.DeploymentStatistics;
import com.yahoo.vespa.hosted.controller.versions.VersionStatus;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
@@ -12,6 +13,7 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
@@ -31,10 +33,10 @@ public class VersionStatusSerializerTest {
Arrays.asList(ApplicationId.from("tenant1", "failing1", "default"),
ApplicationId.from("tenant2", "success2", "default"))
);
- vespaVersions.add(new VespaVersion(statistics, "dead", Instant.now(), false,
- Arrays.asList("cfg1", "cfg2", "cfg3"), VespaVersion.Confidence.normal));
- vespaVersions.add(new VespaVersion(statistics, "cafe", Instant.now(), true,
- Arrays.asList("cfg1", "cfg2", "cfg3"), VespaVersion.Confidence.normal));
+ vespaVersions.add(new VespaVersion(statistics, "dead", Instant.now(), false, false,
+ asHostnames("cfg1", "cfg2", "cfg3"), VespaVersion.Confidence.normal));
+ vespaVersions.add(new VespaVersion(statistics, "cafe", Instant.now(), true, true,
+ asHostnames("cfg1", "cfg2", "cfg3"), VespaVersion.Confidence.normal));
VersionStatus status = new VersionStatus(vespaVersions);
VersionStatusSerializer serializer = new VersionStatusSerializer();
VersionStatus deserialized = serializer.fromSlime(serializer.toSlime(status));
@@ -45,7 +47,8 @@ public class VersionStatusSerializerTest {
VespaVersion b = deserialized.versions().get(i);
assertEquals(a.releaseCommit(), b.releaseCommit());
assertEquals(a.committedAt(), b.committedAt());
- assertEquals(a.isCurrentSystemVersion(), b.isCurrentSystemVersion());
+ assertEquals(a.isControllerVersion(), b.isControllerVersion());
+ assertEquals(a.isSystemVersion(), b.isSystemVersion());
assertEquals(a.statistics(), b.statistics());
assertEquals(a.configServerHostnames(), b.configServerHostnames());
assertEquals(a.confidence(), b.confidence());
@@ -53,4 +56,8 @@ public class VersionStatusSerializerTest {
}
+ private static List<HostName> asHostnames(String... hostname) {
+ return Arrays.stream(hostname).map(HostName::from).collect(Collectors.toList());
+ }
+
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
index 1a876e6b246..243cf7276bd 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.restapi;
import com.yahoo.application.container.JDisc;
@@ -10,6 +10,7 @@ import com.yahoo.container.http.filter.FilterChainRepository;
import com.yahoo.io.IOUtils;
import com.yahoo.jdisc.http.filter.SecurityRequestFilter;
import com.yahoo.jdisc.http.filter.SecurityRequestFilterChain;
+import com.yahoo.vespa.hosted.controller.ConfigServerClientMock;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.versions.VersionStatus;
import org.junit.ComparisonFailure;
@@ -43,12 +44,18 @@ public class ContainerTester {
return (Controller) container.components().getComponent(Controller.class.getName());
}
- public void updateSystemVersion() {
+ public ConfigServerClientMock configServer() {
+ return (ConfigServerClientMock) container.components().getComponent(ConfigServerClientMock.class.getName());
+ }
+
+ public void updateVersionStatus() {
controller().updateVersionStatus(VersionStatus.compute(controller()));
}
- public void updateSystemVersion(Version version) {
- controller().updateVersionStatus(VersionStatus.compute(controller(), version));
+ public void updateVersionStatus(Version version) {
+ controller().curator().writeControllerVersion(controller().hostname(), version);
+ configServer().setDefaultVersion(version);
+ controller().updateVersionStatus(VersionStatus.compute(controller()));
}
public void assertResponse(Supplier<Request> request, File responseFile) throws IOException {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
index e4c4df279b8..704e9fa1a07 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.restapi.application;
import com.yahoo.application.container.handler.Request;
@@ -106,7 +106,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
public void testApplicationApi() throws Exception {
ContainerControllerTester controllerTester = new ContainerControllerTester(container, responseFiles);
ContainerTester tester = controllerTester.containerTester();
- tester.updateSystemVersion();
+ tester.updateVersionStatus();
createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // (Necessary but not provided in this API)
@@ -397,7 +397,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// Setup
ContainerControllerTester controllerTester = new ContainerControllerTester(container, responseFiles);
ContainerTester tester = controllerTester.containerTester();
- tester.updateSystemVersion();
+ tester.updateVersionStatus();
createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID);
// Create tenant
@@ -433,7 +433,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// Setup
ContainerControllerTester controllerTester = new ContainerControllerTester(container, responseFiles);
ContainerTester tester = controllerTester.containerTester();
- tester.updateSystemVersion();
+ tester.updateVersionStatus();
UserId userId = new UserId("new_user");
createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, userId);
@@ -458,7 +458,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// Setup
ContainerControllerTester controllerTester = new ContainerControllerTester(container, responseFiles);
ContainerTester tester = controllerTester.containerTester();
- tester.updateSystemVersion();
+ tester.updateVersionStatus();
createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID);
// Create tenant
@@ -533,7 +533,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
@Test
public void testErrorResponses() throws Exception {
ContainerTester tester = new ContainerTester(container, responseFiles);
- tester.updateSystemVersion();
+ tester.updateVersionStatus();
createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID);
// PUT (update) non-existing tenant
@@ -844,7 +844,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
public void testJobStatusReporting() throws Exception {
ContainerControllerTester tester = new ContainerControllerTester(container, responseFiles);
addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR));
- tester.containerTester().updateSystemVersion();
+ tester.containerTester().updateVersionStatus();
long projectId = 1;
Application app = tester.createApplication();
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
@@ -892,7 +892,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
@Test
public void testJobStatusReportingOutOfCapacity() {
ContainerControllerTester tester = new ContainerControllerTester(container, responseFiles);
- tester.containerTester().updateSystemVersion();
+ tester.containerTester().updateVersionStatus();
long projectId = 1;
Application app = tester.createApplication();
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java
index f52cc9e9e11..fef6fd209e8 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java
@@ -1,9 +1,10 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.restapi.deployment;
import com.google.common.collect.ImmutableSet;
import com.yahoo.component.Version;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.RegionName;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
@@ -22,6 +23,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* @author bratseth
@@ -41,7 +43,7 @@ public class DeploymentApiTest extends ControllerContainerTest {
public void testDeploymentApi() throws IOException {
ContainerControllerTester tester = new ContainerControllerTester(container, responseFiles);
Version version = Version.fromString("5.0");
- tester.containerTester().updateSystemVersion(version);
+ tester.containerTester().updateVersionStatus(version);
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
.environment(Environment.prod)
.region("corp-us-east-1")
@@ -64,7 +66,7 @@ public class DeploymentApiTest extends ControllerContainerTest {
// New version released
version = Version.fromString("5.1");
- tester.containerTester().updateSystemVersion(version);
+ tester.containerTester().updateVersionStatus(version);
// Applications upgrade, 1/2 succeed
tester.upgrader().maintain();
@@ -82,11 +84,14 @@ public class DeploymentApiTest extends ControllerContainerTest {
List<VespaVersion> censored = new ArrayList<>();
for (VespaVersion version : versionStatus.versions()) {
if ( ! version.configServerHostnames().isEmpty())
- version = new VespaVersion(version.statistics(),
- version.releaseCommit(),
+ version = new VespaVersion(version.statistics(),
+ version.releaseCommit(),
version.committedAt(),
- version.isCurrentSystemVersion(),
- ImmutableSet.of("config1.test", "config2.test"),
+ version.isControllerVersion(),
+ version.isSystemVersion(),
+ ImmutableSet.of("config1.test", "config2.test").stream()
+ .map(HostName::from)
+ .collect(Collectors.toSet()),
VespaVersion.confidenceFrom(version.statistics(), controller)
);
censored.add(version);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json
index 5f7fedfd75f..772e41dda42 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json
@@ -1,7 +1,7 @@
{
"versions":[
{
- "version": "(ignore)",
+ "version": "5",
"confidence": "high",
"commit": "(ignore)",
"date": 0,
@@ -23,7 +23,7 @@
"deployingApplications": [ ]
},
{
- "version":"(ignore)",
+ "version":"5.1",
"confidence":"normal",
"commit":"(ignore)",
"date":0,
@@ -82,4 +82,4 @@
"deployingApplications": [ ]
}
]
-} \ No newline at end of file
+}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java
index a8e4c970cf7..6e79f53cae6 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java
@@ -1,9 +1,8 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.restapi.screwdriver;
import com.yahoo.application.container.handler.Request;
import com.yahoo.vespa.hosted.controller.Application;
-import com.yahoo.vespa.hosted.controller.application.DeploymentJobs;
import com.yahoo.vespa.hosted.controller.restapi.ContainerControllerTester;
import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest;
import com.yahoo.vespa.hosted.controller.versions.VersionStatus;
@@ -11,7 +10,6 @@ import org.junit.Test;
import java.io.File;
import java.nio.charset.StandardCharsets;
-import java.util.Optional;
import java.util.OptionalLong;
/**
@@ -37,7 +35,7 @@ public class ScrewdriverApiTest extends ControllerContainerTest {
@Test
public void testTriggerJobForApplication() {
ContainerControllerTester tester = new ContainerControllerTester(container, responseFiles);
- tester.containerTester().updateSystemVersion();
+ tester.containerTester().updateVersionStatus();
Application app = tester.createApplication();
tester.controller().applications().lockOrThrow(app.id(), application ->
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java
index 7f3cfe665cc..b11c826d645 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.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.
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.versions;
import com.google.common.collect.ImmutableSet;
import com.yahoo.component.Version;
import com.yahoo.component.Vtag;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
@@ -12,13 +13,14 @@ import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester;
+import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion.Confidence;
import org.junit.Test;
import java.net.URI;
-import java.net.URISyntaxException;
-import java.time.Duration;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobType.productionUsEast3;
import static com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobType.productionUsWest1;
@@ -43,7 +45,7 @@ public class VersionStatusTest {
}
@Test
- public void testSystemVersionIsControllerVersionIfConfigserversAreNewer() {
+ public void testSystemVersionIsControllerVersionIfConfigServersAreNewer() {
ControllerTester tester = new ControllerTester();
Version largerThanCurrent = new Version(Vtag.currentVersion.getMajor() + 1);
tester.configServer().setDefaultVersion(largerThanCurrent);
@@ -52,15 +54,39 @@ public class VersionStatusTest {
}
@Test
- public void testSystemVersionIsVersionOfOldestConfigServer() throws URISyntaxException {
+ public void testSystemVersionIsVersionOfOldestConfigServer() {
ControllerTester tester = new ControllerTester();
Version oldest = new Version(5);
- tester.configServer().versions().put(new URI("https://cfg.prod.corp-us-east-1.test:4443"), oldest);
+ tester.configServer().versions().put(URI.create("https://cfg.prod.corp-us-east-1.test:4443"), oldest);
VersionStatus versionStatus = VersionStatus.compute(tester.controller());
assertEquals(oldest, versionStatus.systemVersion().get().versionNumber());
}
@Test
+ public void testControllerVersionIsVersionOfOldestController() {
+ HostName controller1 = HostName.from("controller-1");
+ HostName controller2 = HostName.from("controller-2");
+ HostName controller3 = HostName.from("controller-3");
+ MockCuratorDb db = new MockCuratorDb(Stream.of(controller1, controller2, controller3)
+ .map(hostName -> hostName.value() + ":2222")
+ .collect(Collectors.joining(",")));
+ ControllerTester tester = new ControllerTester(db);
+
+ db.writeControllerVersion(controller1, Version.fromString("6.2"));
+ db.writeControllerVersion(controller2, Version.fromString("6.1"));
+ db.writeControllerVersion(controller3, Version.fromString("6.2"));
+
+ VersionStatus versionStatus = VersionStatus.compute(tester.controller());
+ assertEquals("Controller version is oldest version", Version.fromString("6.1"),
+ versionStatus.controllerVersion().get().versionNumber());
+
+ // Last controller upgrades
+ db.writeControllerVersion(controller2, Version.fromString("6.2"));
+ versionStatus = VersionStatus.compute(tester.controller());
+ assertEquals(Version.fromString("6.2"), versionStatus.controllerVersion().get().versionNumber());
+ }
+
+ @Test
public void testVersionStatusAfterApplicationUpdates() {
DeploymentTester tester = new DeploymentTester();
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()