aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Marius Venstad <venstad@gmail.com>2021-02-18 13:04:16 +0100
committerJon Marius Venstad <venstad@gmail.com>2021-02-19 17:40:10 +0100
commit3fea94f5bfcbbfd90520770fda44a7cbfbd936cc (patch)
treef3c3ce2c46b477d3f0c24fbf35909c7d8ae2a111
parent844b11c9fafcfd31f8e259126979c1d483d7e611 (diff)
Test DedicatedClusterControllerClusterMigrator
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DedicatedClusterControllerClusterMigratorTest.java133
1 files changed, 133 insertions, 0 deletions
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DedicatedClusterControllerClusterMigratorTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DedicatedClusterControllerClusterMigratorTest.java
new file mode 100644
index 00000000000..52f90163c60
--- /dev/null
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DedicatedClusterControllerClusterMigratorTest.java
@@ -0,0 +1,133 @@
+// Copyright Verizon Media. 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.config.provision.ApplicationId;
+import com.yahoo.config.provision.Capacity;
+import com.yahoo.config.provision.ClusterResources;
+import com.yahoo.config.provision.Deployer;
+import com.yahoo.config.provision.Deployment;
+import com.yahoo.config.provision.HostFilter;
+import com.yahoo.config.provision.NodeResources;
+import com.yahoo.jdisc.test.MockMetric;
+import com.yahoo.vespa.flags.Flags;
+import com.yahoo.vespa.flags.InMemoryFlagSource;
+import com.yahoo.vespa.hosted.provision.applications.Application;
+import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester;
+import com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock;
+import org.junit.Test;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author jonmv
+ */
+public class DedicatedClusterControllerClusterMigratorTest {
+
+ @Test
+ public void testMigration() throws InterruptedException, TimeoutException {
+ ApplicationId id1 = ApplicationId.from("t", "a", "i1"), id2 = ApplicationId.from("t", "a", "i2");
+ ProvisioningTester tester = new ProvisioningTester.Builder().build();
+ tester.makeReadyNodes(4, new NodeResources(1.5, 8, 50, 0.3));
+ tester.makeReadyHosts(1, NodeResources.unspecified());
+ tester.deploy(id1, Capacity.from(new ClusterResources(2, 1, NodeResources.unspecified())));
+ tester.deploy(id2, Capacity.from(new ClusterResources(2, 1, NodeResources.unspecified())));
+ tester.clock().setInstant(Instant.EPOCH); // EPOCH was a week-day.
+ MockDeployer deployer = new MockDeployer();
+ InMemoryFlagSource flags = new InMemoryFlagSource();
+ AtomicBoolean isQuiescent = new AtomicBoolean();
+ OrchestratorMock orchestrator = new OrchestratorMock() {
+ @Override public boolean isQuiescent(ApplicationId id) { return isQuiescent.get(); }
+ };
+
+ DedicatedClusterControllerClusterMigrator migrator = new DedicatedClusterControllerClusterMigrator(deployer,
+ new MockMetric(),
+ tester.nodeRepository(),
+ Duration.ofDays(365),
+ flags,
+ orchestrator);
+ assertFalse(deployer.getDedicatedClusterControllerCluster(id1));
+
+ // Set all conditions true except time window.
+ flags.withBooleanFlag(Flags.DEDICATED_CLUSTER_CONTROLLER_CLUSTER.id(), true);
+ isQuiescent.set(true);
+ migrator.maintain();
+ assertFalse(deployer.getDedicatedClusterControllerCluster(id1));
+
+ // Enter time window, but no longer quiescent.
+ tester.clock().advance(Duration.ofHours(9));
+ isQuiescent.set(false);
+ migrator.maintain();
+ assertFalse(deployer.getDedicatedClusterControllerCluster(id1));
+
+ // Quiescent, but no longer flagged.
+ isQuiescent.set(true);
+ flags.withBooleanFlag(Flags.DEDICATED_CLUSTER_CONTROLLER_CLUSTER.id(), false);
+ migrator.maintain();
+ assertFalse(deployer.getDedicatedClusterControllerCluster(id1));
+
+ // Finally, all stars align.
+ flags.withBooleanFlag(Flags.DEDICATED_CLUSTER_CONTROLLER_CLUSTER.id(), true);
+ migrator.maintain();
+ assertTrue(deployer.getDedicatedClusterControllerCluster(id1)); // Lex sorting, t.a.i1 before t.a.i2.
+ assertFalse(deployer.getDedicatedClusterControllerCluster(id2));
+ assertEquals(1, deployer.phaser.awaitAdvanceInterruptibly(deployer.phaser.arrive(), 10, TimeUnit.SECONDS));
+
+ migrator.maintain();
+ assertTrue(deployer.getDedicatedClusterControllerCluster(id2));
+ assertEquals(2, deployer.phaser.awaitAdvanceInterruptibly(deployer.phaser.arrive(), 10, TimeUnit.SECONDS));
+
+ assertEquals(Set.of(), migrator.applicationsNeedingMaintenance());
+ }
+
+
+ private static class MockDeployer implements Deployer {
+
+ final Phaser phaser = new Phaser(2); // Test thread and deployer.
+ final Set<ApplicationId> dedicatedCCC = new ConcurrentSkipListSet<>();
+
+ @Override
+ public Optional<Deployment> deployFromLocalActive(ApplicationId application, boolean bootstrap) {
+ return Optional.of(new Deployment() {
+ @Override public void prepare() { fail("Shouldn't run"); }
+ @Override public long activate() { return phaser.arriveAndAwaitAdvance(); }
+ @Override public void restart(HostFilter filter) { fail("Shouldn't run"); }
+ });
+ }
+
+ @Override
+ public Optional<Deployment> deployFromLocalActive(ApplicationId application, Duration timeout, boolean bootstrap) {
+ return deployFromLocalActive(application, bootstrap);
+ }
+
+ @Override
+ public Optional<Instant> lastDeployTime(ApplicationId application) {
+ return Optional.empty();
+ }
+
+ @Override
+ public void setDedicatedClusterControllerCluster(ApplicationId id) {
+ dedicatedCCC.add(id);
+ }
+
+ @Override
+ public boolean getDedicatedClusterControllerCluster(ApplicationId id) {
+ return dedicatedCCC.contains(id);
+ }
+
+ }
+
+}