aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Marius Venstad <jonmv@users.noreply.github.com>2019-04-11 09:41:00 +0200
committerGitHub <noreply@github.com>2019-04-11 09:41:00 +0200
commitaccba940ad0884d4f52880f75a7509f60908ab84 (patch)
tree89715986fa90b69d014911fc8128107f34dfa1b5
parent9f9476e91cc7c92424cdb6f92eb6743f36413fa4 (diff)
parent5769a20f4b4c98bfab9ba8e5caaddd1fd41f37d1 (diff)
Merge pull request #9081 from vespa-engine/jvenstad/nodes-in-application-v4
Jvenstad/nodes in application v4
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Node.java31
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java1
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java54
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java25
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgraderTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-nodes.json13
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java2
9 files changed, 126 insertions, 10 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Node.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Node.java
index d166bb0d3fb..d618464fc2a 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Node.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/Node.java
@@ -31,10 +31,14 @@ public class Node {
private final long wantedRestartGeneration;
private final long rebootGeneration;
private final long wantedRebootGeneration;
+ private final String canonicalFlavor;
+ private final String clusterId;
+ private final ClusterType clusterType;
public Node(HostName hostname, State state, NodeType type, Optional<ApplicationId> owner,
Version currentVersion, Version wantedVersion, Version currentOsVersion, Version wantedOsVersion, ServiceState serviceState,
- long restartGeneration, long wantedRestartGeneration, long rebootGeneration, long wantedRebootGeneration) {
+ long restartGeneration, long wantedRestartGeneration, long rebootGeneration, long wantedRebootGeneration,
+ String canonicalFlavor, String clusterId, ClusterType clusterType) {
this.hostname = hostname;
this.state = state;
this.type = type;
@@ -48,13 +52,17 @@ public class Node {
this.wantedRestartGeneration = wantedRestartGeneration;
this.rebootGeneration = rebootGeneration;
this.wantedRebootGeneration = wantedRebootGeneration;
+ this.canonicalFlavor = canonicalFlavor;
+ this.clusterId = clusterId;
+ this.clusterType = clusterType;
}
@TestOnly
public Node(HostName hostname, State state, NodeType type, Optional<ApplicationId> owner,
Version currentVersion, Version wantedVersion) {
this(hostname, state, type, owner, currentVersion, wantedVersion,
- Version.emptyVersion, Version.emptyVersion, ServiceState.unorchestrated, 0, 0, 0, 0);
+ Version.emptyVersion, Version.emptyVersion, ServiceState.unorchestrated, 0, 0, 0, 0,
+ "d-2-8-50", "cluster", ClusterType.container);
}
public HostName hostname() {
@@ -107,6 +115,18 @@ public class Node {
return wantedRebootGeneration;
}
+ public String canonicalFlavor() {
+ return canonicalFlavor;
+ }
+
+ public String clusterId() {
+ return clusterId;
+ }
+
+ public ClusterType clusterType() {
+ return clusterType;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -139,4 +159,11 @@ public class Node {
unorchestrated
}
+ /** Known cluster types. */
+ public enum ClusterType {
+ admin,
+ container,
+ content
+ }
+
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
index ba6f19c19ba..23bf8514b9c 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
@@ -64,6 +64,7 @@ public enum PathGroup {
Optional.of("/api"),
"/application/v4/tenant/{tenant}/application/{application}/deploying/{*}",
"/application/v4/tenant/{tenant}/application/{application}/instance/{*}",
+ "/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/nodes",
"/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/logs",
"/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/suspended",
"/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/service/{*}",
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index 547e53acb77..b48c8723d44 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -44,6 +44,7 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.TenantId;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServerException;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.Log;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.Logs;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
@@ -173,6 +174,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
if (path.matches("/application/v4/tenant/{tenant}/application/{application}")) return application(path.get("tenant"), path.get("application"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying")) return deploying(path.get("tenant"), path.get("application"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying/pin")) return deploying(path.get("tenant"), path.get("application"), request);
+ if (path.matches("/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/nodes")) return nodes(path.get("tenant"), path.get("application"), path.get("instance"), path.get("environment"), path.get("region"));
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/environment/{environment}/region/{region}/instance/{instance}/logs")) return logs(path.get("tenant"), path.get("application"), path.get("instance"), path.get("environment"), path.get("region"), request.propertyMap());
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job")) return JobControllerApiHandlerHelper.jobTypeResponse(controller, appIdFromPath(path), request.getUri());
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/job/{jobtype}")) return JobControllerApiHandlerHelper.runResponse(controller.jobController().runs(appIdFromPath(path), jobTypeFromPath(path)), request.getUri());
@@ -324,6 +326,58 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
.orElseThrow(() -> new NotExistsException(applicationId + " not found"));
}
+ private HttpResponse nodes(String tenantName, String applicationName, String instanceName, String environment, String region) {
+ ApplicationId id = ApplicationId.from(tenantName, applicationName, instanceName);
+ ZoneId zone = ZoneId.from(environment, region);
+ List<Node> nodes = controller.configServer().nodeRepository().list(zone, id);
+
+ Slime slime = new Slime();
+ Cursor nodesArray = slime.setObject().setArray("nodes");
+ for (Node node : nodes) {
+ Cursor nodeObject = nodesArray.addObject();
+ nodeObject.setString("hostname", node.hostname().value());
+ nodeObject.setString("state", valueOf(node.state()));
+ nodeObject.setString("orchestration", valueOf(node.serviceState()));
+ nodeObject.setString("version", node.currentVersion().toString());
+ nodeObject.setString("flavor", node.canonicalFlavor());
+ nodeObject.setString("clusterId", node.clusterId());
+ nodeObject.setString("clusterType", valueOf(node.clusterType()));
+ }
+ return new SlimeJsonResponse(slime);
+ }
+
+ private static String valueOf(Node.State state) {
+ switch (state) {
+ case failed: return "failed";
+ case parked: return "parked";
+ case dirty: return "dirty";
+ case ready: return "ready";
+ case active: return "active";
+ case inactive: return "inactive";
+ case reserved: return "reserved";
+ case provisioned: return "provisioned";
+ default: throw new IllegalArgumentException("Unexpected node state '" + state + "'.");
+ }
+ }
+
+ private static String valueOf(Node.ServiceState state) {
+ switch (state) {
+ case expectedUp: return "expectedUp";
+ case allowedDown: return "allowedDown";
+ case unorchestrated: return "unorchestrated";
+ default: throw new IllegalArgumentException("Unexpected node state '" + state + "'.");
+ }
+ }
+
+ private static String valueOf(Node.ClusterType type) {
+ switch (type) {
+ case admin: return "admin";
+ case content: return "content";
+ case container: return "container";
+ default: throw new IllegalArgumentException("Unexpected node cluster type '" + type + "'.");
+ }
+ }
+
private HttpResponse logs(String tenantName, String applicationName, String instanceName, String environment, String region, Map<String, String> queryParameters) {
ApplicationId application = ApplicationId.from(tenantName, applicationName, instanceName);
ZoneId zone = ZoneId.from(environment, region);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java
index 61c397d893a..927596ca9ab 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java
@@ -248,7 +248,8 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer
List<Node> nodes = nodeRepository.list(deployment.zoneId(), deployment.applicationId());
for (Node node : nodes) {
nodeRepository.putByHostname(deployment.zoneId(), new Node(node.hostname(),
- node.state(), node.type(),
+ Node.State.active,
+ node.type(),
node.owner(),
node.currentVersion(),
application.version().get()));
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java
index ac15ab046c3..49bc910ac33 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java
@@ -89,7 +89,10 @@ public class NodeRepositoryMock implements NodeRepository {
node.restartGeneration(),
node.wantedRestartGeneration(),
node.rebootGeneration(),
- node.wantedRebootGeneration()))
+ node.wantedRebootGeneration(),
+ node.canonicalFlavor(),
+ node.clusterId(),
+ node.clusterType()))
.forEach(node -> putByHostname(zone, node));
}
@@ -131,7 +134,10 @@ public class NodeRepositoryMock implements NodeRepository {
node.restartGeneration(),
node.wantedRestartGeneration() + 1,
node.rebootGeneration(),
- node.wantedRebootGeneration()));
+ node.wantedRebootGeneration(),
+ node.canonicalFlavor(),
+ node.clusterId(),
+ node.clusterType()));
}
public void doRestart(DeploymentId deployment, Optional<HostName> hostname) {
@@ -147,7 +153,10 @@ public class NodeRepositoryMock implements NodeRepository {
node.restartGeneration() + 1,
node.wantedRestartGeneration(),
node.rebootGeneration(),
- node.wantedRebootGeneration()));
+ node.wantedRebootGeneration(),
+ node.canonicalFlavor(),
+ node.clusterId(),
+ node.clusterType()));
}
public void requestReboot(DeploymentId deployment, Optional<HostName> hostname) {
@@ -163,7 +172,10 @@ public class NodeRepositoryMock implements NodeRepository {
node.restartGeneration(),
node.wantedRestartGeneration(),
node.rebootGeneration(),
- node.wantedRebootGeneration() + 1));
+ node.wantedRebootGeneration() + 1,
+ node.canonicalFlavor(),
+ node.clusterId(),
+ node.clusterType()));
}
public void doReboot(DeploymentId deployment, Optional<HostName> hostname) {
@@ -179,7 +191,10 @@ public class NodeRepositoryMock implements NodeRepository {
node.restartGeneration(),
node.wantedRestartGeneration(),
node.rebootGeneration() + 1,
- node.wantedRebootGeneration()));
+ node.wantedRebootGeneration(),
+ node.canonicalFlavor(),
+ node.clusterId(),
+ node.clusterType()));
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgraderTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgraderTest.java
index b053bfa1bfe..7a008d1f478 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgraderTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgraderTest.java
@@ -168,7 +168,7 @@ public class OsUpgraderTest {
node.hostname(), node.state(), node.type(), node.owner(), node.currentVersion(),
node.wantedVersion(), node.wantedOsVersion(), node.wantedOsVersion(), node.serviceState(),
node.restartGeneration(), node.wantedRestartGeneration(), node.rebootGeneration(),
- node.wantedRebootGeneration()));
+ node.wantedRebootGeneration(), node.canonicalFlavor(), node.clusterId(), node.clusterType()));
}
assertCurrent(version, application, zone);
}
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 ec17e26d867..e60bbdc4d84 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
@@ -380,6 +380,11 @@ public class ApplicationApiTest extends ControllerContainerTest {
.recursive("true"),
new File("application1-recursive.json"));
+ // GET nodes
+ tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/default/nodes", GET)
+ .userIdentity(USER_ID),
+ new File("application-nodes.json"));
+
// GET logs
tester.assertResponse(request("/application/v4/tenant/tenant2/application/application1/environment/prod/region/us-central-1/instance/default/logs?from=1233&to=3214", GET)
.userIdentity(USER_ID),
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-nodes.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-nodes.json
new file mode 100644
index 00000000000..eb53ff7161e
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-nodes.json
@@ -0,0 +1,13 @@
+{
+ "nodes": [
+ {
+ "hostname": "host-tenant1:application1:default-prod.us-central-1",
+ "state": "active",
+ "orchestration": "unorchestrated",
+ "version": "6.1",
+ "flavor": "d-2-8-50",
+ "clusterId": "cluster",
+ "clusterType": "container"
+ }
+ ]
+}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java
index 1eb3316a33e..bc8dd8d4479 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java
@@ -149,7 +149,7 @@ public class OsApiTest extends ControllerContainerTest {
node.hostname(), node.state(), node.type(), node.owner(), node.currentVersion(),
node.wantedVersion(), node.wantedOsVersion(), node.wantedOsVersion(), node.serviceState(),
node.restartGeneration(), node.wantedRestartGeneration(), node.rebootGeneration(),
- node.wantedRebootGeneration()));
+ node.wantedRebootGeneration(), node.canonicalFlavor(), node.clusterId(), node.clusterType()));
}
}
}