diff options
7 files changed, 289 insertions, 107 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessment.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessor.java index e44dc58c028..61d003c4aa0 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessment.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessor.java @@ -1,36 +1,34 @@ package com.yahoo.vespa.hosted.controller.maintenance; - import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository; import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode; import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState; -import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -public class ChangeManagementAssessment { +public class ChangeManagementAssessor { private final NodeRepository nodeRepository; public static class Assessment { - String app; - String zone; - String cluster; - long clusterImpact; - long clusterTotal; - long groupsImpact; - long groupsTotal; - String upgradePolicy; - String suggestedAction; - String impact; + public String app; + public String zone; + public String cluster; + public long clusterImpact; + public long clusterSize; + public long groupsImpact; + public long groupsTotal; + public String upgradePolicy; + public String suggestedAction; + public String impact; } - public ChangeManagementAssessment(Controller controller) { + public ChangeManagementAssessor(Controller controller) { this.nodeRepository = controller.serviceRegistry().configServer().nodeRepository(); } @@ -44,7 +42,7 @@ public class ChangeManagementAssessment { .filter(node -> impactedHostnames.contains(node.getParentHostname() == null ? "" : node.getParentHostname())).collect(Collectors.toList()); // Group nodes pr cluster - Map<String, List<NodeRepositoryNode>> prCluster = containerNodes.stream().collect(Collectors.groupingBy(ChangeManagementAssessment::clusterKey)); + Map<String, List<NodeRepositoryNode>> prCluster = containerNodes.stream().collect(Collectors.groupingBy(ChangeManagementAssessor::clusterKey)); // Report assessment pr cluster return prCluster.entrySet().stream().map((entry) -> { @@ -53,20 +51,24 @@ public class ChangeManagementAssessment { String app = Arrays.stream(key.split(":")).limit(3).collect(Collectors.joining(":")); String cluster = Arrays.stream(key.split(":")).skip(3).collect(Collectors.joining(":")); - long[] totalStats = clusterStats(key, containerNodes); + long[] totalStats = clusterStats(key, allNodes); long[] impactedStats = clusterStats(key, nodes); Assessment assessment = new Assessment(); assessment.app = app; assessment.zone = zone.value(); assessment.cluster = cluster; - assessment.clusterTotal = totalStats[0]; + assessment.clusterSize = totalStats[0]; assessment.clusterImpact = impactedStats[0]; assessment.groupsTotal = totalStats[1]; assessment.groupsImpact = impactedStats[1]; - assessment.upgradePolicy = "na"; //TODO - assessment.suggestedAction = "nothing"; //TODO - assessment.impact = "high"; //TODO + + // TODO check upgrade policy + assessment.upgradePolicy = "na"; + // TODO do some heuristic on suggestion action + assessment.suggestedAction = "nothing"; + // TODO do some heuristic on impact + assessment.impact = "na"; return assessment; }).collect(Collectors.toList()); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandler.java index 1dbeaf7c235..ff45955ee76 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandler.java @@ -1,26 +1,35 @@ package com.yahoo.vespa.hosted.controller.restapi.changemanagement; +import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.jdisc.LoggingRequestHandler; import com.yahoo.restapi.ErrorResponse; import com.yahoo.restapi.Path; import com.yahoo.restapi.SlimeJsonResponse; +import com.yahoo.slime.ArrayTraverser; import com.yahoo.slime.Cursor; +import com.yahoo.slime.Inspector; import com.yahoo.slime.Slime; +import com.yahoo.slime.SlimeUtils; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.auditlog.AuditLoggingRequestHandler; +import com.yahoo.vespa.hosted.controller.maintenance.ChangeManagementAssessor; import com.yahoo.yolean.Exceptions; +import javax.ws.rs.BadRequestException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; public class ChangeManagementApiHandler extends AuditLoggingRequestHandler { - private final Controller controller; + private final ChangeManagementAssessor assessor; public ChangeManagementApiHandler(LoggingRequestHandler.Context ctx, Controller controller) { super(ctx, controller.auditLogger()); - this.controller = controller; + assessor = new ChangeManagementAssessor(controller); } @Override @@ -42,48 +51,78 @@ public class ChangeManagementApiHandler extends AuditLoggingRequestHandler { private HttpResponse post(HttpRequest request) { Path path = new Path(request.getUri()); - if (path.matches("/changemanagement/v1/assessment")) return new SlimeJsonResponse(assessment()); + if (path.matches("/changemanagement/v1/assessment")) return new SlimeJsonResponse(doAssessment(request)); return ErrorResponse.notFoundError("Nothing at " + path); } - private Slime assessment() { + private Inspector inspectorOrThrow(HttpRequest request) { + try { + return SlimeUtils.jsonToSlime(request.getData().readAllBytes()).get(); + } catch (IOException e) { + throw new BadRequestException("Failed to parse request body"); + } + } + + private static Inspector getInspectorFieldOrThrow(Inspector inspector, String field) { + if (!inspector.field(field).valid()) + throw new BadRequestException("Field " + field + " cannot be null"); + return inspector.field(field); + } + + // The structure here should be + // + // { + // zone: string + // hosts: string[] + // switches: string[] + // switchInSequence: boolean + // } + // + // Only zone and host are supported right now + private Slime doAssessment(HttpRequest request) { + + Inspector inspector = inspectorOrThrow(request); + + // For now; mandatory fields + String zoneStr = getInspectorFieldOrThrow(inspector, "zone").asString(); + Inspector hostArray = getInspectorFieldOrThrow(inspector, "hosts"); + + // The impacted hostnames + List<String> hostNames = new ArrayList<>(); + if (hostArray.valid()) { + hostArray.traverse((ArrayTraverser) (i, host) -> hostNames.add(host.asString())); + } + + List<ChangeManagementAssessor.Assessment> assessments = assessor.assessment(hostNames, ZoneId.from(zoneStr)); + Slime slime = new Slime(); Cursor root = slime.setObject(); // This is the main structure that might be part of something bigger later - Cursor assessment = root.setObject("assessment"); + Cursor assessmentCursor = root.setObject("assessment"); - // Updated gives clue to if the assessement is old - assessment.setString("updated", "2021-03-12:12:12:12Z"); + // Updated gives clue to if the assessment is old + assessmentCursor.setString("updated", "2021-03-12:12:12:12Z"); // Assessment on the cluster level - Cursor apps = assessment.setArray("clusters"); - Cursor oneCluster = apps.addObject(); - oneCluster.setString("app", "mytenant:myapp:myinstance"); - oneCluster.setString("zone", "prod.us-east-3"); - oneCluster.setString("cluster", "mycontent"); - oneCluster.setLong("clusterSize", 19); - oneCluster.setLong("clusterImpact", 3); - oneCluster.setString("upgradePolicy","10%"); - oneCluster.setDouble("utilizationInWindow", 0.5); - oneCluster.setString("suggestedAction", "nothing|bcp"); - oneCluster.setString("impact", "low|degraded|outage"); - - Cursor groups = oneCluster.setArray("groups"); - Cursor oneGroup = groups.addObject(); - oneGroup.setString("groupId", "23"); - oneGroup.setLong("groupSize", 4); - oneGroup.setLong("groupImpact", 2); - - // Assessment on the host level - Cursor hosts = assessment.setArray("hosts"); - Cursor oneHost = hosts.addObject(); - oneHost.setString("hostname", "myhostname"); - oneHost.setString("resources", "vcpu:memory:disk"); - oneHost.setString("state", "active"); - oneHost.setLong("containers", 10); - oneHost.setString("suggestedAction", "nothing|retire"); - oneHost.setString("impact", "low|degraded|outage"); //For hosts this is mostly decided by request + Cursor clustersCursor = assessmentCursor.setArray("clusters"); + + assessments.forEach(assessment -> { + Cursor oneCluster = clustersCursor.addObject(); + oneCluster.setString("app", assessment.app); + oneCluster.setString("zone", assessment.zone); + oneCluster.setString("cluster", assessment.cluster); + oneCluster.setLong("clusterSize", assessment.clusterSize); + oneCluster.setLong("clusterImpact", assessment.clusterImpact); + oneCluster.setLong("groupsTotal", assessment.groupsTotal); + oneCluster.setLong("groupsImpact", assessment.groupsImpact); + oneCluster.setString("upgradePolicy", assessment.upgradePolicy); + oneCluster.setString("suggestedAction", assessment.suggestedAction); + oneCluster.setString("impact", assessment.impact); + }); + + // Assessment on the host level - TODO + assessmentCursor.setArray("hosts"); return slime; } 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 0c558ef3ea8..e2b1e90555d 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 @@ -1,6 +1,7 @@ // 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.integration; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import com.yahoo.collections.Pair; import com.yahoo.component.Version; @@ -15,12 +16,17 @@ import com.yahoo.vespa.hosted.controller.api.integration.configserver.Applicatio import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node; import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository; import com.yahoo.vespa.hosted.controller.api.integration.configserver.TargetVersions; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeEnvironment; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeHistory; import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeList; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeMembership; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeOwner; import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode; import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState; import java.net.URI; import java.time.Duration; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -29,6 +35,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.function.UnaryOperator; import java.util.stream.Collectors; @@ -46,6 +53,10 @@ public class NodeRepositoryMock implements NodeRepository { private final Map<DeploymentId, Pair<Double, Double>> trafficFractions = new HashMap<>(); private final Map<ZoneId, Map<TenantName, URI>> archiveUris = new HashMap<>(); + // A separate/alternative list of NodeRepositoryNode nodes. + // Methods operating with Node and NodeRepositoryNode lives separate lives. + private final Map<ZoneId, List<NodeRepositoryNode>> nodeRepoNodes = new HashMap<>(); + private boolean allowPatching = false; /** Add or update given nodes in zone */ @@ -77,6 +88,7 @@ public class NodeRepositoryMock implements NodeRepository { /** Remove all nodes in all zones */ public void clear() { nodeRepository.clear(); + nodeRepoNodes.clear(); } /** Replace nodes in zone with given nodes */ @@ -131,7 +143,7 @@ public class NodeRepositoryMock implements NodeRepository { @Override public void addNodes(ZoneId zone, Collection<NodeRepositoryNode> nodes) { - throw new UnsupportedOperationException(); + nodeRepoNodes.put(zone, new ArrayList<>(nodes)); } @Override @@ -151,7 +163,7 @@ public class NodeRepositoryMock implements NodeRepository { @Override public NodeList listNodes(ZoneId zone) { - throw new UnsupportedOperationException(); + return new NodeList(nodeRepoNodes.get(zone)); } @Override diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessmentTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessmentTest.java deleted file mode 100644 index 966ba956991..00000000000 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessmentTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.yahoo.vespa.hosted.controller.maintenance; - - -import com.yahoo.config.provision.zone.ZoneId; -import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode; -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ChangeManagementAssessmentTest{ - - @Test - public void empty_input_variations() { - ZoneId zone = ZoneId.from("prod", "eu-trd"); - List<String> hostNames = new ArrayList<>(); - List<NodeRepositoryNode> allNodesInZone = new ArrayList<>(); - - // Both zone and hostnames are empty - List<ChangeManagementAssessment.Assessment> assessments - = ChangeManagementAssessment.assessmentInner(hostNames, allNodesInZone, zone); - Assert.assertEquals(0, assessments.size()); - } -}
\ No newline at end of file diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessorTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessorTest.java new file mode 100644 index 00000000000..f3cb996c048 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ChangeManagementAssessorTest.java @@ -0,0 +1,124 @@ +package com.yahoo.vespa.hosted.controller.maintenance; + + +import com.yahoo.config.provision.zone.ZoneId; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeMembership; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeOwner; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class ChangeManagementAssessorTest { + + @Test + public void empty_input_variations() { + ZoneId zone = ZoneId.from("prod", "eu-trd"); + List<String> hostNames = new ArrayList<>(); + List<NodeRepositoryNode> allNodesInZone = new ArrayList<>(); + + // Both zone and hostnames are empty + List<ChangeManagementAssessor.Assessment> assessments + = ChangeManagementAssessor.assessmentInner(hostNames, allNodesInZone, zone); + Assert.assertEquals(0, assessments.size()); + } + + @Test + public void one_host_one_cluster_no_groups() { + ZoneId zone = ZoneId.from("prod", "eu-trd"); + List<String> hostNames = Collections.singletonList("host1"); + List<NodeRepositoryNode> allNodesInZone = new ArrayList<>(); + allNodesInZone.add(createNode("node1", "host1", "myapp", "default", 0 )); + allNodesInZone.add(createNode("node2", "host1", "myapp", "default", 0 )); + allNodesInZone.add(createNode("node3", "host1", "myapp", "default", 0 )); + + // Add an not impacted hosts + allNodesInZone.add(createNode("node4", "host2", "myapp", "default", 0 )); + + // Make Assessment + List<ChangeManagementAssessor.Assessment> assessments + = ChangeManagementAssessor.assessmentInner(hostNames, allNodesInZone, zone); + + // Assess the assessment :-o + Assert.assertEquals(1, assessments.size()); + Assert.assertEquals(3, assessments.get(0).clusterImpact); + Assert.assertEquals(4, assessments.get(0).clusterSize); + Assert.assertEquals(1, assessments.get(0).groupsImpact); + Assert.assertEquals(1, assessments.get(0).groupsTotal); + Assert.assertEquals("content:default", assessments.get(0).cluster); + Assert.assertEquals("mytenant:myapp:default", assessments.get(0).app); + Assert.assertEquals("prod.eu-trd", assessments.get(0).zone); + } + + @Test + public void one_of_two_groups_in_one_of_two_clusters() { + ZoneId zone = ZoneId.from("prod", "eu-trd"); + List<String> hostNames = Arrays.asList("host1", "host2"); + List<NodeRepositoryNode> allNodesInZone = new ArrayList<>(); + + // Two impacted nodes on host1 + allNodesInZone.add(createNode("node1", "host1", "myapp", "default", 0 )); + allNodesInZone.add(createNode("node2", "host1", "myapp", "default", 0 )); + + // One impacted nodes on host2 + allNodesInZone.add(createNode("node3", "host2", "myapp", "default", 0 )); + + // Another group on hosts not impacted + allNodesInZone.add(createNode("node4", "host3", "myapp", "default", 1 )); + allNodesInZone.add(createNode("node5", "host3", "myapp", "default", 1 )); + allNodesInZone.add(createNode("node6", "host3", "myapp", "default", 1 )); + + // Another cluster on hosts not impacted - this one also with three different groups (should all be ignored here) + allNodesInZone.add(createNode("node4", "host4", "myapp", "myman", 4 )); + allNodesInZone.add(createNode("node5", "host4", "myapp", "myman", 5 )); + allNodesInZone.add(createNode("node6", "host4", "myapp", "myman", 6 )); + + // Make Assessment + List<ChangeManagementAssessor.Assessment> assessments + = ChangeManagementAssessor.assessmentInner(hostNames, allNodesInZone, zone); + + // Assess the assessment :-o + Assert.assertEquals(1, assessments.size()); //One cluster is impacted + Assert.assertEquals(3, assessments.get(0).clusterImpact); + Assert.assertEquals(6, assessments.get(0).clusterSize); + Assert.assertEquals(1, assessments.get(0).groupsImpact); + Assert.assertEquals(2, assessments.get(0).groupsTotal); + Assert.assertEquals("content:default", assessments.get(0).cluster); + Assert.assertEquals("mytenant:myapp:default", assessments.get(0).app); + Assert.assertEquals("prod.eu-trd", assessments.get(0).zone); + } + + private NodeOwner createOwner(String tenant, String application, String instance) { + NodeOwner owner = new NodeOwner(); + owner.tenant = tenant; + owner.application = application; + owner.instance = instance; + return owner; + } + + private NodeMembership createMembership(String clusterId, int group) { + NodeMembership membership = new NodeMembership(); + membership.group = "" + group; + membership.clusterid = clusterId; + membership.clustertype = "content"; + membership.index = 2; + membership.retired = false; + return membership; + } + + private NodeRepositoryNode createNode(String nodename, String hostname, String appName, String clusterId, int group) { + NodeRepositoryNode node = new NodeRepositoryNode(); + node.setHostname(nodename); + node.setParentHostname(hostname); + node.setState(NodeState.active); + node.setOwner(createOwner("mytenant", appName, "default")); + node.setMembership(createMembership(clusterId, group)); + + return node; + } +}
\ No newline at end of file diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandlerTest.java index ff0b3b83383..28f2b836365 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandlerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandlerTest.java @@ -2,8 +2,13 @@ package com.yahoo.vespa.hosted.controller.restapi.changemanagement; import com.yahoo.application.container.handler.Request; +import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.vespa.athenz.api.AthenzIdentity; import com.yahoo.vespa.athenz.api.AthenzUser; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeMembership; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeOwner; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeRepositoryNode; +import com.yahoo.vespa.hosted.controller.api.integration.noderepository.NodeState; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest; import org.intellij.lang.annotations.Language; @@ -11,6 +16,8 @@ import org.junit.Before; import org.junit.Test; import java.io.File; +import java.util.ArrayList; +import java.util.List; public class ChangeManagementApiHandlerTest extends ControllerContainerTest { @@ -23,11 +30,12 @@ public class ChangeManagementApiHandlerTest extends ControllerContainerTest { public void before() { tester = new ContainerTester(container, responses); addUserToHostedOperatorRole(operator); + tester.serviceRegistry().configServer().nodeRepository().addNodes(ZoneId.from("prod.us-east-3"), createNodes()); } @Test public void test_api() { - assertFile(new Request("http://localhost:8080/changemanagement/v1/assessment", "{}", Request.Method.POST), "initial.json"); + assertFile(new Request("http://localhost:8080/changemanagement/v1/assessment", "{\"zone\":\"prod.us-east-3\", \"hosts\": [\"host1\"]}", Request.Method.POST), "initial.json"); } private void assertResponse(Request request, @Language("JSON") String body, int statusCode) { @@ -39,4 +47,42 @@ public class ChangeManagementApiHandlerTest extends ControllerContainerTest { addIdentityToRequest(request, operator); tester.assertResponse(request, new File(filename)); } + + private List<NodeRepositoryNode> createNodes() { + List<NodeRepositoryNode> nodes = new ArrayList<>(); + nodes.add(createNode("node1", "host1", "myapp", "default", 0 )); + nodes.add(createNode("node2", "host1", "myapp", "default", 0 )); + nodes.add(createNode("node3", "host1", "myapp", "default", 0 )); + nodes.add(createNode("node4", "host2", "myapp", "default", 0 )); + return nodes; + } + + private NodeOwner createOwner(String tenant, String application, String instance) { + NodeOwner owner = new NodeOwner(); + owner.tenant = tenant; + owner.application = application; + owner.instance = instance; + return owner; + } + + private NodeMembership createMembership(String clusterId, int group) { + NodeMembership membership = new NodeMembership(); + membership.group = "" + group; + membership.clusterid = clusterId; + membership.clustertype = "content"; + membership.index = 2; + membership.retired = false; + return membership; + } + + private NodeRepositoryNode createNode(String nodename, String hostname, String appName, String clusterId, int group) { + NodeRepositoryNode node = new NodeRepositoryNode(); + node.setHostname(nodename); + node.setParentHostname(hostname); + node.setState(NodeState.active); + node.setOwner(createOwner("mytenant", appName, "default")); + node.setMembership(createMembership(clusterId, group)); + + return node; + } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/responses/initial.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/responses/initial.json index b402ff313dc..a9b0dacb968 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/responses/initial.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/responses/initial.json @@ -3,33 +3,18 @@ "updated": "2021-03-12:12:12:12Z", "clusters": [ { - "app": "mytenant:myapp:myinstance", + "app": "mytenant:myapp:default", "zone": "prod.us-east-3", - "cluster": "mycontent", - "clusterSize": 19, + "cluster": "content:default", + "clusterSize": 4, "clusterImpact": 3, - "upgradePolicy": "10%", - "utilizationInWindow": 0.5, - "suggestedAction": "nothing|bcp", - "impact": "low|degraded|outage", - "groups": [ - { - "groupId": "23", - "groupSize": 4, - "groupImpact": 2 - } - ] + "groupsTotal": 1, + "groupsImpact": 1, + "upgradePolicy": "na", + "suggestedAction": "nothing", + "impact": "na" } ], - "hosts": [ - { - "hostname": "myhostname", - "resources": "vcpu:memory:disk", - "state": "active", - "containers": 10, - "suggestedAction": "nothing|retire", - "impact": "low|degraded|outage" - } - ] + "hosts": [] } }
\ No newline at end of file |