diff options
author | Jon Marius Venstad <venstad@gmail.com> | 2021-02-18 13:04:16 +0100 |
---|---|---|
committer | Jon Marius Venstad <venstad@gmail.com> | 2021-02-19 17:40:10 +0100 |
commit | 3fea94f5bfcbbfd90520770fda44a7cbfbd936cc (patch) | |
tree | f3c3ce2c46b477d3f0c24fbf35909c7d8ae2a111 | |
parent | 844b11c9fafcfd31f8e259126979c1d483d7e611 (diff) |
Test DedicatedClusterControllerClusterMigrator
-rw-r--r-- | node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DedicatedClusterControllerClusterMigratorTest.java | 133 |
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); + } + + } + +} |