summaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authorvalerijf <valerijf@yahoo-inc.com>2017-04-27 13:01:13 +0200
committervalerijf <valerijf@yahoo-inc.com>2017-04-27 13:03:26 +0200
commitcca34767a2462f73f36ab9abbb36dd0ba6b304c3 (patch)
tree595b490777d1231dd0551b5727b51e2757f015f8 /node-repository
parent3b111667ee4ed3389bbe5bd9a2d3af19175e6a06 (diff)
Rewritten NodeRetirer test to work on non-mocked node-repository
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java15
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java279
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java125
3 files changed, 255 insertions, 164 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java
index 4c0c670a2ff..18be5f7661e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java
@@ -21,10 +21,12 @@ import java.util.stream.Collectors;
public class NodeRetirer extends Maintainer {
private final RetirementPolicy retirementPolicy;
- public NodeRetirer(NodeRepository nodeRepository, Zone zone, Duration interval, RetirementPolicy retirementPolicy, Zone... applies) {
- super(nodeRepository, interval);
- this.retirementPolicy = retirementPolicy;
+ public NodeRetirer(NodeRepository nodeRepository, Zone zone, Duration interval, JobControl jobControl,
+ RetirementPolicy retirementPolicy, Zone... applies) {
+ super(nodeRepository, interval, jobControl);
if (! Arrays.asList(applies).contains(zone)) deconstruct();
+
+ this.retirementPolicy = retirementPolicy;
}
@Override
@@ -62,7 +64,7 @@ public class NodeRetirer extends Maintainer {
boolean limitedPark(Set<Node> nodesToPark, long limit) {
nodesToPark.stream()
.limit(limit)
- .forEach(node -> nodeRepository().park(node.hostname(), Agent.NodeRetirer, "Parked by NodeRetirer, Policy: " + retirementPolicy.getClass().getName()));
+ .forEach(node -> nodeRepository().park(node.hostname(), Agent.NodeRetirer, "Parked by NodeRetirer, Policy: " + retirementPolicy.getClass().getSimpleName()));
return limit >= nodesToPark.size();
}
@@ -92,9 +94,4 @@ public class NodeRetirer extends Maintainer {
long numNodesToSpare = (long) Math.ceil(0.1 * numActiveNodes);
return Math.max(0L, numReadyNodes - numNodesToSpare);
}
-
- @Override
- public String toString() {
- return "Node retirer";
- }
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java
index 929b3d8da1f..628d334c2c0 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java
@@ -1,25 +1,16 @@
package com.yahoo.vespa.hosted.provision.maintenance;
-import com.yahoo.component.Version;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ClusterMembership;
-import com.yahoo.config.provision.ClusterSpec;
-import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.RegionName;
-import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.hosted.provision.Node;
-import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.maintenance.retire.RetirementPolicy;
-import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.node.Allocation;
-import com.yahoo.vespa.hosted.provision.node.Generation;
import com.yahoo.vespa.hosted.provision.node.History;
import com.yahoo.vespa.hosted.provision.node.Status;
-import com.yahoo.vespa.hosted.provision.testutils.FlavorConfigBuilder;
import org.junit.Before;
import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
import java.time.Duration;
import java.util.ArrayList;
@@ -36,173 +27,151 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* @author freva
*/
+@RunWith(Enclosed.class)
public class NodeRetirerTest {
- private final List<Flavor> flavors = makeFlavors(5);
- private final Map<String, Node> nodesByHostname = new HashMap<>();
- private final NodeRepository nodeRepository = mock(NodeRepository.class);
- private final Zone zone = new Zone(Environment.prod, RegionName.from("us-north-3"));
-
- @Test
- public void testRetireUnallocatedNodes() {
- addNodesByFlavor(Node.State.ready, 5, 3, 77, 47);
- deployApp("vespa", "calendar", 0, 3);
- deployApp("vespa", "notes", 2, 12);
- deployApp("sports", "results", 2, 7);
- deployApp("search", "images", 3, 6);
-
- RetirementPolicy policy = node -> node.ipAddresses().equals(Collections.singleton("::1"));
- NodeRetirer retirer = new NodeRetirer(nodeRepository, zone, Duration.ofDays(1), policy);
- Map<Flavor, Long> expected = expectedCountsByFlavor(1, 3, 56, 40);
- Map<Flavor, Long> actual = retirer.getNumberSpareReadyNodesByFlavor(nodeRepository.getNodes());
- assertEquals(expected, actual);
-
- // Not all nodes that we wanted to retire could be retired now (Not enough spare nodes)
- assertFalse(retirer.retireUnallocated());
- Map<Flavor, Long> parkedCountsByFlavor = nodesByHostname.values().stream()
- .filter(node -> node.state() == Node.State.parked)
- .collect(Collectors.groupingBy(Node::flavor, Collectors.counting()));
- assertEquals(expected, parkedCountsByFlavor);
-
- expected = expectedCountsByFlavor(0, 0, 0, 0);
- expected.remove(flavors.get(1)); // Flavor-1 has 0 ready nodes, so just remove it to easily compare maps
- actual = retirer.getNumberSpareReadyNodesByFlavor(nodeRepository.getNodes());
- assertEquals(expected, actual);
-
- // Lets remove all the currently parked nodes and reprovision them different IP address
- nodesByHostname.entrySet().stream().filter(entry -> entry.getValue().state() == Node.State.parked).forEach(entry ->
- updateNode(entry.getKey(), entry.getValue().flavor(), Node.State.ready, Optional.empty(), Collections.singleton("::2")));
-
- expected = expectedCountsByFlavor(1, 3, 56, 40);
- actual = retirer.getNumberSpareReadyNodesByFlavor(nodeRepository.getNodes());
- assertEquals(expected, actual);
-
- // The remaining nodes we wanted to retire has been retired
- assertTrue(retirer.retireUnallocated());
- parkedCountsByFlavor = nodesByHostname.values().stream()
- .filter(node -> node.state() == Node.State.parked)
- .collect(Collectors.groupingBy(Node::flavor, Collectors.counting()));
- expected = expectedCountsByFlavor(1, 0, 2, 1);
- expected.remove(flavors.get(1)); // Flavor-1 already had all its nodes retired & reprovisioned, so just remove it to easily compare maps
- assertEquals(expected, parkedCountsByFlavor);
- }
-
- @Test
- public void testGetNumberSpareNodesWithNoActiveNodes() {
- addNodesByFlavor(Node.State.ready, 5, 3, 77);
- NodeRetirer retirer = new NodeRetirer(nodeRepository, zone, Duration.ofDays(1), node -> false);
- Map<Flavor, Long> expected = expectedCountsByFlavor(5, 3, 77);
- Map<Flavor, Long> actual = retirer.getNumberSpareReadyNodesByFlavor(nodeRepository.getNodes());
- assertEquals(expected, actual);
+ public static class FullNodeRepositoryTester {
+
+ @Test
+ public void testRetireUnallocatedNodes() {
+ NodeRetirerTester tester = new NodeRetirerTester(NodeRetirerTester.makeFlavors(5));
+ RetirementPolicy policy = node -> node.ipAddresses().equals(Collections.singleton("::1"));
+ NodeRetirer retirer = new NodeRetirer(tester.nodeRepository, NodeRetirerTester.zone, Duration.ofDays(1), new JobControl(tester.nodeRepository.database()), policy);
+
+ tester.createReadyNodesByFlavor(5, 3, 77, 47);
+ tester.deployApp("vespa", "calendar", 0, 3);
+ tester.deployApp("vespa", "notes", 2, 12);
+ tester.deployApp("sports", "results", 2, 7);
+ tester.deployApp("search", "images", 3, 6);
+
+ Map<Flavor, Long> expected = tester.expectedCountsByFlavor(1, 3, 56, 40);
+ Map<Flavor, Long> actual = retirer.getNumberSpareReadyNodesByFlavor(tester.nodeRepository.getNodes());
+ assertEquals(expected, actual);
+
+ // Not all nodes that we wanted to retire could be retired now (Not enough spare nodes)
+ assertFalse(retirer.retireUnallocated());
+ Map<Flavor, Long> parkedCountsByFlavor = tester.nodeRepository.getNodes(Node.State.parked).stream()
+ .collect(Collectors.groupingBy(Node::flavor, Collectors.counting()));
+ assertEquals(expected, parkedCountsByFlavor);
+
+ expected = tester.expectedCountsByFlavor(0, -1, 0, 0);
+ actual = retirer.getNumberSpareReadyNodesByFlavor(tester.nodeRepository.getNodes());
+ assertEquals(expected, actual);
+
+ // Lets change parked nodes IP address and set it back to ready
+ tester.nodeRepository.getNodes(Node.State.parked)
+ .forEach(node -> {
+ tester.nodeRepository.write(node.withIpAddresses(Collections.singleton("::2")));
+ tester.nodeRepository.setDirty(node.hostname());
+ tester.nodeRepository.setReady(node.hostname());
+ });
+
+ expected = tester.expectedCountsByFlavor(1, 3, 56, 40);
+ actual = retirer.getNumberSpareReadyNodesByFlavor(tester.nodeRepository.getNodes());
+ assertEquals(expected, actual);
+
+ // The remaining nodes we wanted to retire has been retired
+ assertTrue(retirer.retireUnallocated());
+ parkedCountsByFlavor = tester.nodeRepository.getNodes(Node.State.parked).stream()
+ .collect(Collectors.groupingBy(Node::flavor, Collectors.counting()));
+ expected = tester.expectedCountsByFlavor(1, -1, 2, 1);
+ assertEquals(expected, parkedCountsByFlavor);
+ }
}
- @Test
- public void testGetNumberSpareNodesWithActiveNodes() {
- addNodesByFlavor(Node.State.ready, 5, 3, 77, 47);
- addNodesByFlavor(Node.State.active, 0, 10, 2, 230, 137);
- NodeRetirer retirer = new NodeRetirer(nodeRepository, zone, Duration.ofDays(1), node -> false);
- Map<Flavor, Long> expected = expectedCountsByFlavor(5, 2, 76, 24);
- Map<Flavor, Long> actual = retirer.getNumberSpareReadyNodesByFlavor(nodeRepository.getNodes());
- assertEquals(expected, actual);
- }
+ /**
+ * For testing methods that require minimal node repository and flavor setup
+ */
+ public static class HelperMethodsTester {
+ private final List<Flavor> flavors = NodeRetirerTester.makeFlavors(5).getFlavors();
+ private final List<Node> nodes = new ArrayList<>();
+ private final NodeRetirer retirer = mock(NodeRetirer.class);
- @Test
- public void testGetNumSpareNodes() {
- NodeRetirer retirer = new NodeRetirer(nodeRepository, zone, Duration.ofDays(1), node -> false);
- assertEquals(retirer.getNumSpareNodes(0, 0), 0L);
- assertEquals(retirer.getNumSpareNodes(0, 1), 1L);
- assertEquals(retirer.getNumSpareNodes(0, 100), 100L);
-
- assertEquals(retirer.getNumSpareNodes(1, 0), 0L);
- assertEquals(retirer.getNumSpareNodes(1, 1), 0L);
- assertEquals(retirer.getNumSpareNodes(1, 2), 1L);
- assertEquals(retirer.getNumSpareNodes(43, 23), 18L);
- }
+ @Test
+ public void testGetNumberSpareNodesWithNoActiveNodes() {
+ addNodesByFlavor(Node.State.ready, 5, 3, 77);
+ Map<Flavor, Long> expected = expectedCountsByFlavor(5, 3, 77);
+ Map<Flavor, Long> actual = retirer.getNumberSpareReadyNodesByFlavor(nodes);
+ assertEquals(expected, actual);
+ }
- @Before
- public void setup() {
- when(nodeRepository.getNodes()).thenAnswer(invoc -> new ArrayList<>(nodesByHostname.values()));
- when(nodeRepository.lockUnallocated()).thenReturn(null);
- when(nodeRepository.park(anyString(), eq(Agent.NodeRetirer), any())).then(invocation -> {
- Object[] args = invocation.getArguments();
- String hostname = (String) args[0];
- Node nodeToPark = Optional.ofNullable(nodesByHostname.get(hostname))
- .orElseThrow(() -> new RuntimeException("Could not find node with hostname " + hostname));
- if (nodeToPark.state() == Node.State.parked) throw new RuntimeException("Node already parked!");
-
- updateNode(nodeToPark.hostname(), nodeToPark.flavor(), Node.State.parked, nodeToPark.allocation(), nodeToPark.ipAddresses());
- return null;
- });
- }
+ @Test
+ public void testGetNumberSpareNodesWithActiveNodes() {
+ addNodesByFlavor(Node.State.ready, 5, 3, 77, 47);
+ addNodesByFlavor(Node.State.active, 0, 10, 2, 230, 137);
- private Map<Flavor, Long> expectedCountsByFlavor(int... nums) {
- Map<Flavor, Long> countsByFlavor = new HashMap<>();
- for (int i = 0; i < nums.length; i++) {
- Flavor flavor = flavors.get(i);
- countsByFlavor.put(flavor, (long) nums[i]);
+ Map<Flavor, Long> expected = expectedCountsByFlavor(5, 2, 76, 24);
+ Map<Flavor, Long> actual = retirer.getNumberSpareReadyNodesByFlavor(nodes);
+ assertEquals(expected, actual);
+ }
+
+ @Before
+ public void setup() {
+ when(retirer.getNumSpareNodes(any(Long.class), any(Long.class))).thenCallRealMethod();
+ when(retirer.getNumberSpareReadyNodesByFlavor(any())).thenCallRealMethod();
}
- return countsByFlavor;
- }
- private void addNodesByFlavor(Node.State state, int... nums) {
- for (int i = 0; i < nums.length; i++) {
- Flavor flavor = flavors.get(i);
- for (int j = 0; j < nums[i]; j++) {
- int id = nodesByHostname.size();
- updateNode("host-" + id + ".yahoo.com", flavor, state, Optional.empty(), Collections.singleton("::1"));
+ private Map<Flavor, Long> expectedCountsByFlavor(int... nums) {
+ Map<Flavor, Long> countsByFlavor = new HashMap<>();
+ for (int i = 0; i < nums.length; i++) {
+ Flavor flavor = flavors.get(i);
+ countsByFlavor.put(flavor, (long) nums[i]);
}
+ return countsByFlavor;
}
- }
- private void deployApp(String tenantName, String applicationName, int flavorId, int numNodes) {
- Flavor flavor = flavors.get(flavorId);
- List<Node> freeNodes = nodeRepository.getNodes().stream()
- .filter(node -> node.state() == Node.State.ready)
- .filter(node -> node.flavor() == flavor)
- .collect(Collectors.toList());
-
- if (freeNodes.size() < numNodes) throw new IllegalArgumentException(
- "Not enough nodes to deploy " + applicationName + " on " + flavor + " needed " + numNodes + " but has " + freeNodes.size());
-
- ApplicationId applicationId = ApplicationId.from(tenantName, applicationName, "default");
- ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Version.fromString("6.99"));
- Allocation allocation = new Allocation(applicationId, ClusterMembership.from(cluster, 0), new Generation(0, 0), false);
- freeNodes.stream().limit(numNodes).forEach(node -> {
- updateNode(node.hostname(), node.flavor(), Node.State.active, Optional.of(allocation), node.ipAddresses());
- });
- }
+ private void addNodesByFlavor(Node.State state, int... nums) {
+ for (int i = 0; i < nums.length; i++) {
+ Flavor flavor = flavors.get(i);
+ for (int j = 0; j < nums[i]; j++) {
+ int id = nodes.size();
+ Node node = createNode("host-" + id + ".yahoo.com", flavor, state, Optional.empty(), Collections.singleton("::1"));
+ nodes.add(node);
+ }
+ }
+ }
- private List<Flavor> makeFlavors(int numFlavors) {
- FlavorConfigBuilder flavorConfigBuilder = new FlavorConfigBuilder();
- for (int i = 0; i < numFlavors; i++) {
- flavorConfigBuilder.addFlavor("flavor-" + i, 1. /* cpu*/, 3. /* mem GB*/, 2. /*disk GB*/, Flavor.Type.BARE_METAL);
+ private Node createNode(String hostname, Flavor flavor, Node.State state, Optional<Allocation> allocation, Set<String> ipAddresses) {
+ return new Node(
+ UUID.randomUUID().toString(),
+ ipAddresses,
+ hostname,
+ Optional.empty(),
+ flavor,
+ Status.initial(),
+ state,
+ allocation,
+ History.empty(),
+ NodeType.tenant);
}
- return flavorConfigBuilder.build().flavor().stream().map(Flavor::new).collect(Collectors.toList());
}
- private void updateNode(String hostname, Flavor flavor, Node.State state, Optional<Allocation> allocation, Set<String> ipAddresses) {
- Node node = new Node(
- UUID.randomUUID().toString(),
- ipAddresses,
- hostname,
- Optional.empty(),
- flavor,
- Status.initial(),
- state,
- allocation,
- History.empty(),
- NodeType.tenant);
-
- nodesByHostname.put(hostname, node);
+ /**
+ * For testing methods that require no internal state and independent of other methods
+ */
+ public static class IndependentMethodTester {
+ private final NodeRetirer retirer = mock(NodeRetirer.class);
+
+ @Test
+ public void testGetNumSpareNodes() {
+ when(retirer.getNumSpareNodes(any(Long.class), any(Long.class))).thenCallRealMethod();
+
+ assertEquals(retirer.getNumSpareNodes(0, 0), 0L);
+ assertEquals(retirer.getNumSpareNodes(0, 1), 1L);
+ assertEquals(retirer.getNumSpareNodes(0, 100), 100L);
+
+ assertEquals(retirer.getNumSpareNodes(1, 0), 0L);
+ assertEquals(retirer.getNumSpareNodes(1, 1), 0L);
+ assertEquals(retirer.getNumSpareNodes(1, 2), 1L);
+ assertEquals(retirer.getNumSpareNodes(43, 23), 18L);
+ }
}
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java
new file mode 100644
index 00000000000..635e7ac7d10
--- /dev/null
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java
@@ -0,0 +1,125 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.provision.maintenance;
+
+import com.yahoo.component.Version;
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.Capacity;
+import com.yahoo.config.provision.ClusterMembership;
+import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.HostSpec;
+import com.yahoo.config.provision.NodeFlavors;
+import com.yahoo.config.provision.NodeType;
+import com.yahoo.config.provision.RegionName;
+import com.yahoo.config.provision.Zone;
+import com.yahoo.test.ManualClock;
+import com.yahoo.transaction.NestedTransaction;
+import com.yahoo.vespa.curator.Curator;
+import com.yahoo.vespa.curator.mock.MockCurator;
+import com.yahoo.vespa.curator.transaction.CuratorTransaction;
+import com.yahoo.vespa.hosted.provision.Node;
+import com.yahoo.vespa.hosted.provision.NodeRepository;
+import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
+import com.yahoo.vespa.hosted.provision.testutils.FlavorConfigBuilder;
+import com.yahoo.vespa.hosted.provision.testutils.MockDeployer;
+import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
+import com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock;
+import com.yahoo.vespa.hosted.provision.testutils.ServiceMonitorStub;
+import com.yahoo.vespa.orchestrator.Orchestrator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+
+/**
+ * @author freva
+ */
+public class NodeRetirerTester {
+ public static final Zone zone = new Zone(Environment.prod, RegionName.from("us-east"));
+
+ // Components with state
+ public final ManualClock clock;
+ public final NodeRepository nodeRepository;
+ public ServiceMonitorStub serviceMonitor;
+ public MockDeployer deployer;
+ private final Orchestrator orchestrator;
+ private final NodeRepositoryProvisioner provisioner;
+ private final Curator curator;
+ private final List<Flavor> flavors;
+ private int nextNodeId = 0;
+
+ public NodeRetirerTester(NodeFlavors nodeFlavors) {
+ clock = new ManualClock();
+ curator = new MockCurator();
+ nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, new MockNameResolver().mockAnyLookup());
+ provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, zone);
+ orchestrator = new OrchestratorMock();
+ deployer = new MockDeployer(provisioner, Collections.emptyMap());
+ serviceMonitor = new ServiceMonitorStub(Collections.emptyMap(), nodeRepository);
+ flavors = nodeFlavors.getFlavors();
+ }
+
+ public void suspend(ApplicationId app) {
+ try {
+ orchestrator.suspend(app);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void createReadyNodesByFlavor(int... nums) {
+ List<Node> nodes = new ArrayList<>();
+ for (int i = 0; i < nums.length; i++) {
+ Flavor flavor = flavors.get(i);
+ for (int j = 0; j < nums[i]; j++) {
+ int id = nextNodeId++;
+ nodes.add(nodeRepository.createNode("node" + id, "host" + id + ".test.yahoo.com",
+ Collections.singleton("::1"), Optional.empty(), flavor, NodeType.tenant));
+ }
+ }
+
+ nodes = nodeRepository.addNodes(nodes);
+ nodes = nodeRepository.setDirty(nodes);
+ nodeRepository.setReady(nodes);
+ }
+
+ public void deployApp(String tenantName, String applicationName, int flavorId, int numNodes) {
+ Flavor flavor = flavors.get(flavorId);
+
+ ApplicationId applicationId = ApplicationId.from(tenantName, applicationName, "default");
+ ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Version.fromString("6.99"));
+ Capacity capacity = Capacity.fromNodeCount(numNodes, flavor.name());
+
+ activate(applicationId, cluster, capacity);
+ }
+
+ private void activate(ApplicationId applicationId, ClusterSpec cluster, Capacity capacity) {
+ List<HostSpec> hosts = provisioner.prepare(applicationId, cluster, capacity, 1, null);
+ NestedTransaction transaction = new NestedTransaction().add(new CuratorTransaction(curator));
+ provisioner.activate(transaction, applicationId, hosts);
+ transaction.commit();
+ }
+
+ public Map<Flavor, Long> expectedCountsByFlavor(long... nums) {
+ Map<Flavor, Long> countsByFlavor = new HashMap<>();
+ for (int i = 0; i < nums.length; i++) {
+ if (nums[i] < 0) continue;
+ Flavor flavor = flavors.get(i);
+ countsByFlavor.put(flavor, nums[i]);
+ }
+ return countsByFlavor;
+ }
+
+ public static NodeFlavors makeFlavors(int numFlavors) {
+ FlavorConfigBuilder flavorConfigBuilder = new FlavorConfigBuilder();
+ for (int i = 0; i < numFlavors; i++) {
+ flavorConfigBuilder.addFlavor("flavor-" + i, 1. /* cpu*/, 3. /* mem GB*/, 2. /*disk GB*/, Flavor.Type.BARE_METAL);
+ }
+ return new NodeFlavors(flavorConfigBuilder.build());
+ }
+}