diff options
author | Martin Polden <mpolden@mpolden.no> | 2021-03-01 18:38:36 +0100 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2021-03-02 20:12:27 +0100 |
commit | e49336237655b4adb7e4da5f29d6267a6d660ed2 (patch) | |
tree | 5ce52b4434cfd0b6ff8135da8d02eda37c235db4 | |
parent | df5d09f858e23d80ab24bfbd76ae532be9a2f0f8 (diff) |
Consolidate HostProvisioner mocks
4 files changed, 202 insertions, 226 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java new file mode 100644 index 00000000000..4c9323ca68e --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java @@ -0,0 +1,173 @@ +// 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.testutils; + +import com.yahoo.component.Version; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.Flavor; +import com.yahoo.config.provision.NodeResources; +import com.yahoo.config.provision.OutOfCapacityException; +import com.yahoo.vespa.hosted.provision.Node; +import com.yahoo.vespa.hosted.provision.node.Address; +import com.yahoo.vespa.hosted.provision.node.IP; +import com.yahoo.vespa.hosted.provision.provisioning.FatalProvisioningException; +import com.yahoo.vespa.hosted.provision.provisioning.HostProvisioner; +import com.yahoo.vespa.hosted.provision.provisioning.ProvisionedHost; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * @author mpolden + */ +public class MockHostProvisioner implements HostProvisioner { + + private final List<ProvisionedHost> provisionedHosts = new ArrayList<>(); + private final List<Flavor> flavors; + private final MockNameResolver nameResolver; + private final int memoryTaxGb; + + private int deprovisionedHosts = 0; + private EnumSet<Behaviour> behaviours = EnumSet.noneOf(Behaviour.class); + private Optional<Flavor> hostFlavor = Optional.empty(); + + public MockHostProvisioner(List<Flavor> flavors, MockNameResolver nameResolver, int memoryTaxGb) { + this.flavors = List.copyOf(flavors); + this.nameResolver = nameResolver; + this.memoryTaxGb = memoryTaxGb; + } + + public MockHostProvisioner(List<Flavor> flavors) { + this(flavors, 0); + } + + public MockHostProvisioner(List<Flavor> flavors, int memoryTaxGb) { + this(flavors, new MockNameResolver().mockAnyLookup(), memoryTaxGb); + } + + @Override + public List<ProvisionedHost> provisionHosts(List<Integer> provisionIndexes, NodeResources resources, + ApplicationId applicationId, Version osVersion, HostSharing sharing) { + Flavor hostFlavor = this.hostFlavor.orElseGet(() -> flavors.stream().filter(f -> compatible(f, resources)) + .findFirst() + .orElseThrow(() -> new OutOfCapacityException("No host flavor matches " + resources))); + List<ProvisionedHost> hosts = new ArrayList<>(); + for (int index : provisionIndexes) { + hosts.add(new ProvisionedHost("host" + index, + "hostname" + index, + hostFlavor, + Optional.empty(), + createAddressesForHost(hostFlavor, index), + resources, + osVersion)); + } + provisionedHosts.addAll(hosts); + return hosts; + } + + @Override + public List<Node> provision(Node host, Set<Node> children) throws FatalProvisioningException { + if (behaviours.contains(Behaviour.failProvisioning)) throw new FatalProvisioningException("Failed to provision node(s)"); + if (host.state() != Node.State.provisioned) throw new IllegalStateException("Host to provision must be in " + Node.State.provisioned); + List<Node> result = new ArrayList<>(); + result.add(withIpAssigned(host)); + for (var child : children) { + if (child.state() != Node.State.reserved) throw new IllegalStateException("Child to provisioned must be in " + Node.State.reserved); + result.add(withIpAssigned(child)); + } + return result; + } + + @Override + public void deprovision(Node host) { + if (behaviours.contains(Behaviour.failDeprovisioning)) throw new FatalProvisioningException("Failed to deprovision node"); + provisionedHosts.removeIf(provisionedHost -> provisionedHost.hostHostname().equals(host.hostname())); + deprovisionedHosts++; + } + + /** Returns the hosts that have been provisioned by this */ + public List<ProvisionedHost> provisionedHosts() { + return Collections.unmodifiableList(provisionedHosts); + } + + /** Returns the number of hosts deprovisioned by this */ + public int deprovisionedHosts() { + return deprovisionedHosts; + } + + public MockHostProvisioner with(Behaviour first, Behaviour... rest) { + this.behaviours = EnumSet.of(first, rest); + return this; + } + + public MockHostProvisioner without(Behaviour first, Behaviour... rest) { + Set<Behaviour> behaviours = new HashSet<>(this.behaviours); + behaviours.removeAll(EnumSet.of(first, rest)); + this.behaviours = behaviours.isEmpty() ? EnumSet.noneOf(Behaviour.class) : EnumSet.copyOf(behaviours); + return this; + } + + public MockHostProvisioner overrideHostFlavor(String flavorName) { + Flavor flavor = flavors.stream().filter(f -> f.name().equals(flavorName)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("No such flavor '" + flavorName + "'")); + hostFlavor = Optional.of(flavor); + return this; + } + + public boolean compatible(Flavor flavor, NodeResources resources) { + NodeResources resourcesToVerify = resources.withMemoryGb(resources.memoryGb() - memoryTaxGb); + + if (flavor.resources().storageType() == NodeResources.StorageType.remote + && flavor.resources().diskGb() >= resources.diskGb()) + resourcesToVerify = resourcesToVerify.withDiskGb(flavor.resources().diskGb()); + if (flavor.resources().bandwidthGbps() >= resources.bandwidthGbps()) + resourcesToVerify = resourcesToVerify.withBandwidthGbps(flavor.resources().bandwidthGbps()); + return flavor.resources().compatibleWith(resourcesToVerify); + } + + private List<Address> createAddressesForHost(Flavor flavor, int hostIndex) { + long numAddresses = Math.max(1, Math.round(flavor.resources().bandwidthGbps())); + return IntStream.range(0, (int) numAddresses) + .mapToObj(i -> new Address("nodename" + hostIndex + "_" + i)) + .collect(Collectors.toList()); + } + + private Node withIpAssigned(Node node) { + if (node.parentHostname().isPresent()) return node; + int hostIndex = Integer.parseInt(node.hostname().replaceAll("^[a-z]+|-\\d+$", "")); + Set<String> addresses = Set.of("::" + hostIndex + ":0"); + Set<String> ipAddressPool = new HashSet<>(); + if (!behaviours.contains(Behaviour.failDnsUpdate)) { + nameResolver.addRecord(node.hostname(), addresses.iterator().next()); + for (int i = 1; i <= 2; i++) { + String ip = "::" + hostIndex + ":" + i; + ipAddressPool.add(ip); + nameResolver.addRecord(node.hostname() + "-" + i, ip); + } + } + + IP.Pool pool = node.ipConfig().pool().withIpAddresses(ipAddressPool); + return node.with(node.ipConfig().withPrimary(addresses).withPool(pool)); + } + + public enum Behaviour { + + /** Fail all calls to {@link MockHostProvisioner#provision(com.yahoo.vespa.hosted.provision.Node, java.util.Set)} */ + failProvisioning, + + /** Fail all calls to {@link MockHostProvisioner#deprovision(com.yahoo.vespa.hosted.provision.Node)} */ + failDeprovisioning, + + /** Fail DNS updates of provisioned hosts */ + failDnsUpdate, + + } + +} diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java index ad6eb6535c2..156542ef1d4 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java @@ -2,7 +2,6 @@ package com.yahoo.vespa.hosted.provision.autoscale; import com.yahoo.collections.Pair; -import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterResources; @@ -21,17 +20,12 @@ import com.yahoo.vespa.hosted.provision.NodeList; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.Nodelike; import com.yahoo.vespa.hosted.provision.applications.Application; -import com.yahoo.vespa.hosted.provision.node.Address; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.IP; -import com.yahoo.vespa.hosted.provision.provisioning.FatalProvisioningException; -import com.yahoo.vespa.hosted.provision.provisioning.HostProvisioner; import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator; -import com.yahoo.vespa.hosted.provision.provisioning.ProvisionedHost; import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester; import java.time.Duration; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; @@ -39,6 +33,9 @@ import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +/** + * @author bratseth + */ class AutoscalingTester { private final ProvisioningTester provisioningTester; @@ -299,45 +296,14 @@ class AutoscalingTester { } - private class MockHostProvisioner implements HostProvisioner { + private class MockHostProvisioner extends com.yahoo.vespa.hosted.provision.testutils.MockHostProvisioner { - private final List<Flavor> hostFlavors; - - public MockHostProvisioner(List<Flavor> hostFlavors) { - this.hostFlavors = hostFlavors; - } - - @Override - public List<ProvisionedHost> provisionHosts(List<Integer> provisionIndexes, NodeResources resources, - ApplicationId applicationId, Version osVersion, - HostSharing sharing) { - Flavor hostFlavor = hostFlavors.stream().filter(f -> matches(f, resources)).findAny() - .orElseThrow(() -> new RuntimeException("No flavor matching " + resources + ". Flavors: " + hostFlavors)); - - List<ProvisionedHost> hosts = new ArrayList<>(); - for (int index : provisionIndexes) { - hosts.add(new ProvisionedHost("host" + index, - "hostname" + index, - hostFlavor, - Optional.empty(), - List.of(new Address("nodename" + index)), - resources, - osVersion)); - } - return hosts; + public MockHostProvisioner(List<Flavor> flavors) { + super(flavors); } @Override - public List<Node> provision(Node host, Set<Node> children) throws FatalProvisioningException { - throw new RuntimeException("Not implemented"); - } - - @Override - public void deprovision(Node host) { - throw new RuntimeException("Not implemented"); - } - - private boolean matches(Flavor flavor, NodeResources resources) { + public boolean compatible(Flavor flavor, NodeResources resources) { NodeResources flavorResources = hostResourcesCalculator.advertisedResourcesOf(flavor); if (flavorResources.storageType() == NodeResources.StorageType.remote && resources.diskGb() <= flavorResources.diskGb()) diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java index 56cf8d02149..43a7be81c88 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java @@ -27,11 +27,9 @@ 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.IP; -import com.yahoo.vespa.hosted.provision.provisioning.FatalProvisioningException; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; -import com.yahoo.vespa.hosted.provision.provisioning.HostProvisioner; -import com.yahoo.vespa.hosted.provision.provisioning.ProvisionedHost; import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester; +import com.yahoo.vespa.hosted.provision.testutils.MockHostProvisioner; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; import com.yahoo.vespa.service.duper.ConfigServerApplication; import com.yahoo.vespa.service.duper.ConfigServerHostApplication; @@ -39,20 +37,15 @@ import org.junit.Test; import java.time.Duration; import java.time.Instant; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; -import java.util.stream.IntStream; import java.util.stream.Stream; -import static com.yahoo.vespa.hosted.provision.maintenance.DynamicProvisioningMaintainerTest.MockHostProvisioner.Behaviour; +import static com.yahoo.vespa.hosted.provision.testutils.MockHostProvisioner.Behaviour; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; /** @@ -115,7 +108,7 @@ public class DynamicProvisioningMaintainerTest { tester.maintainer.maintain(); assertTrue("Failed host is deprovisioned", tester.nodeRepository.nodes().node(failedHost.get().hostname()).isEmpty()); - assertEquals(1, tester.hostProvisioner.deprovisionedHosts); + assertEquals(1, tester.hostProvisioner.deprovisionedHosts()); } @Test @@ -126,7 +119,7 @@ public class DynamicProvisioningMaintainerTest { new ClusterCapacity(1, 16, 24, 100, 1.0)), ClusterCapacity.class); - assertEquals(0, tester.hostProvisioner.provisionedHosts.size()); + assertEquals(0, tester.hostProvisioner.provisionedHosts().size()); assertEquals(11, tester.nodeRepository.nodes().list().size()); assertTrue(tester.nodeRepository.nodes().node("host2").isPresent()); assertTrue(tester.nodeRepository.nodes().node("host2-1").isPresent()); @@ -136,7 +129,7 @@ public class DynamicProvisioningMaintainerTest { tester.maintainer.maintain(); - assertEquals(2, tester.hostProvisioner.provisionedHosts.size()); + assertEquals(2, tester.hostProvisioner.provisionedHosts().size()); assertEquals(2, tester.provisionedHostsMatching(new NodeResources(48, 128, 1000, 10))); NodeList nodesAfter = tester.nodeRepository.nodes().list(); assertEquals(11, nodesAfter.size()); // 2 removed, 2 added @@ -151,13 +144,13 @@ public class DynamicProvisioningMaintainerTest { public void preprovision_with_shared_host() { var tester = new DynamicProvisioningTester().addInitialNodes(); // Makes provisioned hosts 48-128-1000-10 - tester.hostProvisioner.provisionSharedHost("host4"); + tester.hostProvisioner.overrideHostFlavor("host4"); tester.flagSource.withListFlag(PermanentFlags.PREPROVISION_CAPACITY.id(), List.of(new ClusterCapacity(2, 1, 30, 20, 3.0)), ClusterCapacity.class); - assertEquals(0, tester.hostProvisioner.provisionedHosts.size()); + assertEquals(0, tester.hostProvisioner.provisionedHosts().size()); assertEquals(11, tester.nodeRepository.nodes().list().size()); assertTrue(tester.nodeRepository.nodes().node("host2").isPresent()); assertTrue(tester.nodeRepository.nodes().node("host2-1").isPresent()); @@ -196,7 +189,7 @@ public class DynamicProvisioningMaintainerTest { tester.maintainer.maintain(); - assertEquals(2, tester.hostProvisioner.provisionedHosts.size()); + assertEquals(2, tester.hostProvisioner.provisionedHosts().size()); assertEquals(2, tester.provisionedHostsMatching(new NodeResources(48, 128, 1000, 10))); assertEquals(10, tester.nodeRepository.nodes().list().size()); // 3 removed, 2 added assertTrue("preprovision capacity is prefered on shared hosts", tester.nodeRepository.nodes().node("host3").isEmpty()); @@ -212,7 +205,7 @@ public class DynamicProvisioningMaintainerTest { tester.maintainer.maintain(); assertEquals("one provisioned host has been deprovisioned, so there are 2 -> 1 provisioned hosts", - 1, tester.hostProvisioner.provisionedHosts.size()); + 1, tester.hostProvisioner.provisionedHosts().size()); assertEquals(1, tester.provisionedHostsMatching(new NodeResources(48, 128, 1000, 10))); assertEquals(9, tester.nodeRepository.nodes().list().size()); // 4 removed, 2 added if (tester.nodeRepository.nodes().node("hostname100").isPresent()) { @@ -226,7 +219,7 @@ public class DynamicProvisioningMaintainerTest { } private void verifyFirstMaintain(DynamicProvisioningTester tester) { - assertEquals(1, tester.hostProvisioner.provisionedHosts.size()); + assertEquals(1, tester.hostProvisioner.provisionedHosts().size()); assertEquals(1, tester.provisionedHostsMatching(new NodeResources(48, 128, 1000, 10))); assertEquals(10, tester.nodeRepository.nodes().list().size()); // 2 removed, 1 added assertTrue("Failed host 'host2' is deprovisioned", tester.nodeRepository.nodes().node("host2").isEmpty()); @@ -266,17 +259,17 @@ public class DynamicProvisioningMaintainerTest { private void assertWithMinCount(int minCount, int provisionCount, int deprovisionCount) { var tester = new DynamicProvisioningTester().addInitialNodes(); - tester.hostProvisioner.provisionSharedHost("host4"); + tester.hostProvisioner.overrideHostFlavor("host4"); tester.flagSource.withJacksonFlag(PermanentFlags.SHARED_HOST.id(), new SharedHost(null, minCount), SharedHost.class); tester.maintainer.maintain(); - assertEquals(provisionCount, tester.hostProvisioner.provisionedHosts.size()); - assertEquals(deprovisionCount, tester.hostProvisioner.deprovisionedHosts); + assertEquals(provisionCount, tester.hostProvisioner.provisionedHosts().size()); + assertEquals(deprovisionCount, tester.hostProvisioner.deprovisionedHosts()); // Verify next maintain is a no-op tester.maintainer.maintain(); - assertEquals(provisionCount, tester.hostProvisioner.provisionedHosts.size()); - assertEquals(deprovisionCount, tester.hostProvisioner.deprovisionedHosts); + assertEquals(provisionCount, tester.hostProvisioner.provisionedHosts().size()); + assertEquals(deprovisionCount, tester.hostProvisioner.deprovisionedHosts()); } @Test @@ -300,14 +293,14 @@ public class DynamicProvisioningMaintainerTest { // Hosts are provisioned assertEquals(2, tester.provisionedHostsMatching(resources1)); - assertEquals(0, tester.hostProvisioner.deprovisionedHosts); + assertEquals(0, tester.hostProvisioner.deprovisionedHosts()); // Next maintenance run does nothing tester.assertNodesUnchanged(); // Pretend shared-host flag has been set to host4's flavor var sharedHostNodeResources = new NodeResources(48, 128, 1000, 10, NodeResources.DiskSpeed.fast, NodeResources.StorageType.remote); - tester.hostProvisioner.provisionSharedHost("host4"); + tester.hostProvisioner.overrideHostFlavor("host4"); // Next maintenance run does nothing tester.assertNodesUnchanged(); @@ -456,7 +449,7 @@ public class DynamicProvisioningMaintainerTest { public DynamicProvisioningTester(Cloud cloud) { MockNameResolver nameResolver = new MockNameResolver(); - this.hostProvisioner = new MockHostProvisioner(flavors, nameResolver); + this.hostProvisioner = new MockHostProvisioner(flavors.getFlavors(), nameResolver, 0); this.provisioningTester = new ProvisioningTester.Builder().zone(new Zone(cloud, SystemName.defaultSystem(), Environment.defaultEnvironment(), RegionName.defaultName())) @@ -529,9 +522,9 @@ public class DynamicProvisioningMaintainerTest { } private long provisionedHostsMatching(NodeResources resources) { - return hostProvisioner.provisionedHosts.stream() - .filter(host -> host.generateHost().resources().compatibleWith(resources)) - .count(); + return hostProvisioner.provisionedHosts().stream() + .filter(host -> host.generateHost().resources().compatibleWith(resources)) + .count(); } private void assertNodesUnchanged() { @@ -542,113 +535,4 @@ public class DynamicProvisioningMaintainerTest { } - static class MockHostProvisioner implements HostProvisioner { - - private final List<ProvisionedHost> provisionedHosts = new ArrayList<>(); - private final NodeFlavors flavors; - private final MockNameResolver nameResolver; - - private int deprovisionedHosts = 0; - private EnumSet<Behaviour> behaviours = EnumSet.noneOf(Behaviour.class); - private Optional<Flavor> provisionHostFlavor = Optional.empty(); - - public MockHostProvisioner(NodeFlavors flavors, MockNameResolver nameResolver) { - this.flavors = flavors; - this.nameResolver = nameResolver; - } - - public MockHostProvisioner provisionSharedHost(String flavorName) { - provisionHostFlavor = Optional.of(flavors.getFlavorOrThrow(flavorName)); - return this; - } - - @Override - public List<ProvisionedHost> provisionHosts(List<Integer> provisionIndexes, NodeResources resources, - ApplicationId applicationId, Version osVersion, HostSharing sharing) { - Flavor hostFlavor = provisionHostFlavor - .orElseGet(() -> flavors.getFlavors().stream() - .filter(f -> !f.isDocker()) - .filter(f -> f.resources().compatibleWith(resources)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("No host flavor found satisfying " + resources))); - - List<ProvisionedHost> hosts = new ArrayList<>(); - for (int index : provisionIndexes) { - hosts.add(new ProvisionedHost("host" + index, - "hostname" + index, - hostFlavor, - Optional.empty(), - createAddressesForHost(hostFlavor, index), - resources, - osVersion)); - } - provisionedHosts.addAll(hosts); - return hosts; - } - - private List<Address> createAddressesForHost(Flavor flavor, int hostIndex) { - long numAddresses = Math.max(1, Math.round(flavor.resources().bandwidthGbps())); - return IntStream.range(0, (int) numAddresses) - .mapToObj(i -> new Address("nodename" + hostIndex + "_" + i)) - .collect(Collectors.toList()); - } - - @Override - public List<Node> provision(Node host, Set<Node> children) throws FatalProvisioningException { - if (behaviours.contains(Behaviour.failProvisioning)) throw new FatalProvisioningException("Failed to provision node(s)"); - assertSame(Node.State.provisioned, host.state()); - List<Node> result = new ArrayList<>(); - result.add(withIpAssigned(host)); - for (var child : children) { - assertSame(Node.State.reserved, child.state()); - result.add(withIpAssigned(child)); - } - return result; - } - - @Override - public void deprovision(Node host) { - if (behaviours.contains(Behaviour.failDeprovisioning)) throw new FatalProvisioningException("Failed to deprovision node"); - provisionedHosts.removeIf(provisionedHost -> provisionedHost.hostHostname().equals(host.hostname())); - deprovisionedHosts++; - } - - private MockHostProvisioner with(Behaviour first, Behaviour... rest) { - this.behaviours = EnumSet.of(first, rest); - return this; - } - - private MockHostProvisioner without(Behaviour first, Behaviour... rest) { - Set<Behaviour> behaviours = new HashSet<>(this.behaviours); - behaviours.removeAll(EnumSet.of(first, rest)); - this.behaviours = behaviours.isEmpty() ? EnumSet.noneOf(Behaviour.class) : EnumSet.copyOf(behaviours); - return this; - } - - private Node withIpAssigned(Node node) { - if (node.parentHostname().isPresent()) return node; - int hostIndex = Integer.parseInt(node.hostname().replaceAll("^[a-z]+|-\\d+$", "")); - Set<String> addresses = Set.of("::" + hostIndex + ":0"); - Set<String> ipAddressPool = new HashSet<>(); - if (!behaviours.contains(Behaviour.failDnsUpdate)) { - nameResolver.addRecord(node.hostname(), addresses.iterator().next()); - for (int i = 1; i <= 2; i++) { - String ip = "::" + hostIndex + ":" + i; - ipAddressPool.add(ip); - nameResolver.addRecord(node.hostname() + "-" + i, ip); - } - } - - IP.Pool pool = node.ipConfig().pool().withIpAddresses(ipAddressPool); - return node.with(node.ipConfig().withPrimary(addresses).withPool(pool)); - } - - enum Behaviour { - failProvisioning, - failDeprovisioning, - failDnsUpdate, - } - - } - } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java index 131c02015a1..3b8e7075488 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicDockerProvisionTest.java @@ -14,22 +14,20 @@ import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeResources.DiskSpeed; import com.yahoo.config.provision.NodeResources.StorageType; import com.yahoo.config.provision.NodeType; -import com.yahoo.config.provision.OutOfCapacityException; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; -import com.yahoo.vespa.hosted.provision.node.Address; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.IP; import com.yahoo.vespa.hosted.provision.provisioning.HostProvisioner.HostSharing; +import com.yahoo.vespa.hosted.provision.testutils.MockHostProvisioner; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; import org.junit.Test; import java.time.Instant; import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -454,49 +452,4 @@ public class DynamicDockerProvisionTest { }).when(hostProvisioner).provisionHosts(any(), any(), any(), any(), any()); } - private static class MockHostProvisioner implements HostProvisioner { - - private final List<Flavor> hostFlavors; - private final int memoryTaxGb; - - public MockHostProvisioner(List<Flavor> hostFlavors, int memoryTaxGb) { - this.hostFlavors = List.copyOf(hostFlavors); - this.memoryTaxGb = memoryTaxGb; - } - - @Override - public List<ProvisionedHost> provisionHosts(List<Integer> provisionIndexes, NodeResources resources, - ApplicationId applicationId, Version osVersion, HostSharing sharing) { - Optional<Flavor> hostFlavor = hostFlavors.stream().filter(f -> compatible(f, resources)).findFirst(); - if (hostFlavor.isEmpty()) - throw new OutOfCapacityException("No host flavor matches " + resources); - return provisionIndexes.stream() - .map(i -> new ProvisionedHost("id-" + i, "host-" + i, hostFlavor.get(), Optional.empty(), - List.of(new Address("host-" + i + "-1")), resources, osVersion)) - .collect(Collectors.toList()); - } - - private boolean compatible(Flavor hostFlavor, NodeResources resources) { - NodeResources resourcesToVerify = resources.withMemoryGb(resources.memoryGb() - memoryTaxGb); - - if (hostFlavor.resources().storageType() == NodeResources.StorageType.remote - && hostFlavor.resources().diskGb() >= resources.diskGb()) - resourcesToVerify = resourcesToVerify.withDiskGb(hostFlavor.resources().diskGb()); - if (hostFlavor.resources().bandwidthGbps() >= resources.bandwidthGbps()) - resourcesToVerify = resourcesToVerify.withBandwidthGbps(hostFlavor.resources().bandwidthGbps()); - return hostFlavor.resources().compatibleWith(resourcesToVerify); - } - - @Override - public List<Node> provision(Node host, Set<Node> children) throws FatalProvisioningException { - throw new RuntimeException("Not implemented: provision"); - } - - @Override - public void deprovision(Node host) { - throw new RuntimeException("Not implemented: deprovision"); - } - - } - } |