summaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@oath.com>2018-05-02 14:42:32 +0200
committerValerij Fredriksen <valerijf@oath.com>2018-05-04 11:48:49 +0200
commitadfbf772fc345ef7559832f8c07b6323490190d0 (patch)
tree540833253611bc02372dab29e2de64df974988fe /node-repository
parent88fa4649fc79442d3d8e7c3254098f915a2e5889 (diff)
Add REST API to update/view infrastructure versions
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java32
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/UpgradeResponse.java42
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java38
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json3
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json3
6 files changed, 120 insertions, 6 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
index 18af498a38d..7e8cd65d37f 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
@@ -48,10 +48,11 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
private final MetricsReporter metricsReporter;
private final JobControl jobControl;
+ private final InfrastructureVersions infrastructureVersions;
@Inject
public NodeRepositoryMaintenance(NodeRepository nodeRepository, Deployer deployer,
- HostLivenessTracker hostLivenessTracker, ServiceMonitor serviceMonitor,
+ HostLivenessTracker hostLivenessTracker, ServiceMonitor serviceMonitor,
Zone zone, Orchestrator orchestrator, Metric metric,
ConfigserverConfig configserverConfig) {
this(nodeRepository, deployer, hostLivenessTracker, serviceMonitor, zone, Clock.systemUTC(),
@@ -64,6 +65,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
ConfigserverConfig configserverConfig) {
DefaultTimes defaults = new DefaultTimes(zone.environment());
jobControl = new JobControl(nodeRepository.database());
+ infrastructureVersions = new InfrastructureVersions(nodeRepository.database());
nodeFailer = new NodeFailer(deployer, hostLivenessTracker, serviceMonitor, nodeRepository, durationFromEnv("fail_grace").orElse(defaults.failGrace), clock, orchestrator, throttlePolicyFromEnv("throttle_policy").orElse(defaults.throttlePolicy), metric, jobControl, configserverConfig);
periodicApplicationMaintainer = new PeriodicApplicationMaintainer(deployer, nodeRepository, durationFromEnv("periodic_redeploy_interval").orElse(defaults.periodicRedeployInterval), jobControl);
@@ -101,6 +103,10 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
public JobControl jobControl() { return jobControl; }
+ public InfrastructureVersions infrastructureVersions() {
+ return infrastructureVersions;
+ }
+
private static Optional<Duration> durationFromEnv(String envVariable) {
return Optional.ofNullable(System.getenv(envPrefix + envVariable)).map(Long::parseLong).map(Duration::ofSeconds);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java
index 03777078251..54202a15971 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.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.hosted.provision.restapi.v2;
+import com.yahoo.component.Version;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.NodeType;
import com.yahoo.container.jdisc.HttpRequest;
@@ -91,7 +92,7 @@ public class NodesApiHandler extends LoggingRequestHandler {
private HttpResponse handleGET(HttpRequest request) {
String path = request.getUri().getPath();
- if (path.equals( "/nodes/v2/")) return ResourcesResponse.fromStrings(request.getUri(), "state", "node", "command", "maintenance");
+ if (path.equals( "/nodes/v2/")) return ResourcesResponse.fromStrings(request.getUri(), "state", "node", "command", "maintenance", "upgrade");
if (path.equals( "/nodes/v2/node/")) return new NodesResponse(ResponseType.nodeList, request, orchestrator, nodeRepository);
if (path.startsWith("/nodes/v2/node/")) return new NodesResponse(ResponseType.singleNode, request, orchestrator, nodeRepository);
if (path.equals( "/nodes/v2/state/")) return new NodesResponse(ResponseType.stateList, request, orchestrator, nodeRepository);
@@ -99,6 +100,7 @@ public class NodesApiHandler extends LoggingRequestHandler {
if (path.startsWith("/nodes/v2/acl/")) return new NodeAclResponse(request, nodeRepository);
if (path.equals( "/nodes/v2/command/")) return ResourcesResponse.fromStrings(request.getUri(), "restart", "reboot");
if (path.equals( "/nodes/v2/maintenance/")) return new JobsResponse(maintenance.jobControl());
+ if (path.equals( "/nodes/v2/upgrade/")) return new UpgradeResponse(maintenance.infrastructureVersions());
throw new NotFoundException("Nothing at path '" + path + "'");
}
@@ -135,10 +137,16 @@ public class NodesApiHandler extends LoggingRequestHandler {
private HttpResponse handlePATCH(HttpRequest request) {
String path = request.getUri().getPath();
- if ( ! path.startsWith("/nodes/v2/node/")) throw new NotFoundException("Nothing at '" + path + "'");
- Node node = nodeFromRequest(request);
- nodeRepository.write(new NodePatcher(nodeFlavors, request.getData(), node, nodeRepository).apply());
- return new MessageResponse("Updated " + node.hostname());
+ if (path.startsWith("/nodes/v2/node/")) {
+ Node node = nodeFromRequest(request);
+ nodeRepository.write(new NodePatcher(nodeFlavors, request.getData(), node, nodeRepository).apply());
+ return new MessageResponse("Updated " + node.hostname());
+ }
+ else if (path.startsWith("/nodes/v2/upgrade/")) {
+ return setInfrastructureVersion(request);
+ }
+
+ throw new NotFoundException("Nothing at '" + path + "'");
}
private HttpResponse handlePOST(HttpRequest request) {
@@ -276,4 +284,18 @@ public class NodesApiHandler extends LoggingRequestHandler {
return new MessageResponse((active ? "Re-activated" : "Deactivated" ) + " job '" + jobName + "'");
}
+ private MessageResponse setInfrastructureVersion(HttpRequest request) {
+ NodeType nodeType = NodeType.valueOf(lastElement(request.getUri().getPath()).toLowerCase());
+ Inspector inspector = toSlime(request.getData()).get();
+
+ Inspector versionField = inspector.field("version");
+ if (!versionField.valid())
+ throw new IllegalArgumentException("'version' is missing");
+ Version version = Version.fromString(versionField.asString());
+ boolean force = inspector.field("force").asBool();
+
+ maintenance.infrastructureVersions().setTargetVersion(nodeType, version, force);
+
+ return new MessageResponse("Set version for " + nodeType + " to " + version.toFullString());
+ }
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/UpgradeResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/UpgradeResponse.java
new file mode 100644
index 00000000000..12d4e935231
--- /dev/null
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/UpgradeResponse.java
@@ -0,0 +1,42 @@
+// 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.provision.restapi.v2;
+
+import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.JsonFormat;
+import com.yahoo.slime.Slime;
+import com.yahoo.vespa.hosted.provision.maintenance.InfrastructureVersions;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Comparator;
+import java.util.Map;
+
+/** A response containing infrastructure versions */
+public class UpgradeResponse extends HttpResponse {
+
+ private final InfrastructureVersions infrastructureVersions;
+
+ public UpgradeResponse(InfrastructureVersions infrastructureVersions) {
+ super(200);
+ this.infrastructureVersions = infrastructureVersions;
+ }
+
+ @Override
+ public void render(OutputStream stream) throws IOException {
+ Slime slime = new Slime();
+ Cursor root = slime.setObject();
+
+ Cursor versionsObject = root.setObject("versions");
+ infrastructureVersions.getTargetVersions().entrySet().stream()
+ .sorted(Comparator.comparing(Map.Entry::getKey)) // Sort for stable tests
+ .forEach(entry ->
+ versionsObject.setString(entry.getKey().name(), entry.getValue().toFullString()));
+
+ new JsonFormat(true).encode(stream, slime);
+ }
+
+ @Override
+ public String getContentType() { return "application/json"; }
+
+}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
index 2e69867e9b1..5e58d0d89e7 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
@@ -495,6 +495,44 @@ public class RestApiTest {
assertFile(new Request("http://localhost:8080/nodes/v2/node/host6.yahoo.com"), "node6.json");
}
+ @Test
+ public void test_upgrade() throws IOException {
+ // Initially, no versions are set
+ assertResponse(new Request("http://localhost:8080/nodes/v2/upgrade/"), "{\"versions\":{}}");
+
+ // Set version for config and confighost
+ assertResponse(new Request("http://localhost:8080/nodes/v2/upgrade/config",
+ Utf8.toBytes("{\"version\": \"6.123.456\"}"),
+ Request.Method.PATCH),
+ "{\"message\":\"Set version for config to 6.123.456\"}");
+ assertResponse(new Request("http://localhost:8080/nodes/v2/upgrade/confighost",
+ Utf8.toBytes("{\"version\": \"6.123.456\"}"),
+ Request.Method.PATCH),
+ "{\"message\":\"Set version for confighost to 6.123.456\"}");
+
+ // Verify versions are set
+ assertResponse(new Request("http://localhost:8080/nodes/v2/upgrade/"),
+ "{\"versions\":{\"config\":\"6.123.456\",\"confighost\":\"6.123.456\"}}");
+
+ // Downgrade without force fails
+ assertResponse(new Request("http://localhost:8080/nodes/v2/upgrade/confighost",
+ Utf8.toBytes("{\"version\": \"6.123.1\"}"),
+ Request.Method.PATCH),
+ 400,
+ "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Cannot downgrade version without setting 'force'. " +
+ "Current wanted version: 6.123.456, attempted to set wanted version: 6.123.1\"}");
+
+ // Downgrade with force is OK
+ assertResponse(new Request("http://localhost:8080/nodes/v2/upgrade/confighost",
+ Utf8.toBytes("{\"version\": \"6.123.1\",\"force\":true}"),
+ Request.Method.PATCH),
+ "{\"message\":\"Set version for confighost to 6.123.1\"}");
+
+ // Verify version has been updated
+ assertResponse(new Request("http://localhost:8080/nodes/v2/upgrade/"),
+ "{\"versions\":{\"config\":\"6.123.456\",\"confighost\":\"6.123.1\"}}");
+ }
+
/** Tests the rendering of each node separately to make it easier to find errors */
@Test
public void test_single_node_rendering() throws Exception {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json
index 28e28f9678e..99cb9fd91f5 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json
@@ -34,6 +34,9 @@
"name":"MetricsReporter"
},
{
+ "name":"InfrastructureProvisioner"
+ },
+ {
"name":"NodeFailer"
}
],
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json
index 4224718ab06..86becefb146 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json
@@ -11,6 +11,9 @@
},
{
"url": "http://localhost:8080/nodes/v2/maintenance/"
+ },
+ {
+ "url":"http://localhost:8080/nodes/v2/upgrade/"
}
]
} \ No newline at end of file