diff options
author | Øyvind Grønnesby <oyving@verizonmedia.com> | 2020-12-03 19:33:21 +0100 |
---|---|---|
committer | Øyvind Grønnesby <oyving@verizonmedia.com> | 2020-12-03 19:33:21 +0100 |
commit | 2b01b49d4f9fa0338c00a113daf7e61e10041646 (patch) | |
tree | 2c970f2cae118746977147fbaca49e5f0c02c09a /controller-server/src/test/java/com/yahoo | |
parent | f0771b2201f06684f66c7261c528167adb8f4c7b (diff) | |
parent | 5ad34990803dc859ee107ba46b3e60ef877898ca (diff) |
Merge remote-tracking branch 'origin/master' into ogronnesby/trial-tenant-limit
Conflicts:
controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java
controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControl.java
flags/src/main/java/com/yahoo/vespa/flags/Flags.java
Diffstat (limited to 'controller-server/src/test/java/com/yahoo')
7 files changed, 136 insertions, 12 deletions
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 61bd7858da2..ca478905893 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 @@ -41,6 +41,8 @@ public class NodeRepositoryMock implements NodeRepository { private final Map<ZoneId, TargetVersions> targetVersions = new HashMap<>(); private final Map<Integer, Duration> osUpgradeBudgets = new HashMap<>(); + private boolean allowPatching = false; + /** Add or update given nodes in zone */ public void putNodes(ZoneId zone, List<Node> nodes) { nodeRepository.putIfAbsent(zone, new HashMap<>()); @@ -230,7 +232,14 @@ public class NodeRepositoryMock implements NodeRepository { @Override public void patchNode(ZoneId zoneId, String hostName, NodeRepositoryNode node) { - throw new UnsupportedOperationException(); + if (!allowPatching) throw new UnsupportedOperationException(); + List<Node> existing = list(zoneId, List.of(HostName.from(hostName))); + if (existing.size() != 1) throw new IllegalArgumentException("Node " + hostName + " not found in " + zoneId); + + // Note: Only supports switchHostname + Node newNode = new Node.Builder(existing.get(0)).switchHostname(node.getSwitchHostname()) + .build(); + putNodes(zoneId, newNode); } @Override @@ -280,4 +289,9 @@ public class NodeRepositoryMock implements NodeRepository { nodeRepository.get(zoneId).get(hostName).reports().put(reportId, report); } + public NodeRepositoryMock allowPatching(boolean allowPatching) { + this.allowPatching = allowPatching; + return this; + } + } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java index ea31667d249..96eb4b39510 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java @@ -15,7 +15,6 @@ import com.yahoo.vespa.hosted.controller.api.integration.aws.ResourceTagger; import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController; import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController; import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateMock; -import com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServer; import com.yahoo.vespa.hosted.controller.api.integration.dns.MemoryNameService; import com.yahoo.vespa.hosted.controller.api.integration.entity.MemoryEntityService; import com.yahoo.vespa.hosted.controller.api.integration.organization.MockContactRetriever; @@ -81,7 +80,7 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg } @Override - public ConfigServer configServer() { + public ConfigServerMock configServer() { return configServerMock; } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/HostSwitchUpdaterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/HostSwitchUpdaterTest.java new file mode 100644 index 00000000000..4dcacb3934b --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/HostSwitchUpdaterTest.java @@ -0,0 +1,110 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.maintenance; + +import com.yahoo.config.provision.HostName; +import com.yahoo.config.provision.NodeType; +import com.yahoo.config.provision.zone.ZoneId; +import com.yahoo.vespa.hosted.controller.ControllerTester; +import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node; +import com.yahoo.vespa.hosted.controller.api.integration.entity.NodeEntity; +import org.junit.Test; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author mpolden + */ +public class HostSwitchUpdaterTest { + + @Test + public void maintain() { + ControllerTester tester = new ControllerTester(); + tester.serviceRegistry().configServer().nodeRepository().allowPatching(true); + addNodeEntities(tester); + + // First iteration patches all hosts + HostSwitchUpdater maintainer = new HostSwitchUpdater(tester.controller(), Duration.ofDays(1)); + maintainer.maintain(); + List<Node> nodes = allNodes(tester); + assertFalse(nodes.isEmpty()); + for (var node : nodes) { + assertEquals("Node " + node.hostname().value() + (node.type().isHost() ? " has" : " does not have") + + " switch hostname", node.type().isHost(), node.switchHostname().isPresent()); + if (node.type().isHost()) { + assertEquals("tor-" + node.hostname().value(), node.switchHostname().get()); + } + } + + // Second iteration does not patch anything as all switch information is current + tester.serviceRegistry().configServer().nodeRepository().allowPatching(false); + maintainer.maintain(); + + // One host is moved to a different switch + Node host = allNodes(tester).stream().filter(node -> node.type().isHost()).findFirst().get(); + String newSwitch = "tor2-" + host.hostname().value(); + NodeEntity nodeEntity = new NodeEntity(host.hostname().value(), "", "", newSwitch); + tester.serviceRegistry().entityService().addNodeEntity(nodeEntity); + + // Host is updated + tester.serviceRegistry().configServer().nodeRepository().allowPatching(true); + maintainer.maintain(); + assertEquals(newSwitch, getNode(host.hostname(), tester).switchHostname().get()); + + // Host keeps old switch hostname if removed from the node entity + nodeEntity = new NodeEntity(host.hostname().value(), "", "", ""); + tester.serviceRegistry().entityService().addNodeEntity(nodeEntity); + maintainer.maintain(); + assertEquals(newSwitch, getNode(host.hostname(), tester).switchHostname().get()); + + // Updates node registered under a different hostname + ZoneId zone = tester.zoneRegistry().zones().controllerUpgraded().all().ids().get(0); + String hostnameSuffix = ".prod." + zone.value(); + Node configNode = new Node.Builder().hostname(HostName.from("cfg3" + hostnameSuffix)) + .type(NodeType.config) + .build(); + Node configHost = new Node.Builder().hostname(HostName.from("cfghost3" + hostnameSuffix)) + .type(NodeType.confighost) + .build(); + tester.serviceRegistry().configServer().nodeRepository().putNodes(zone, List.of(configNode, configHost)); + String switchHostname = switchHostname(configHost); + NodeEntity configNodeEntity = new NodeEntity("cfg3" + hostnameSuffix, "", "", switchHostname); + tester.serviceRegistry().entityService().addNodeEntity(configNodeEntity); + maintainer.maintain(); + assertEquals(switchHostname, getNode(configHost.hostname(), tester).switchHostname().get()); + assertTrue("Switch hostname is not set for non-host", getNode(configNode.hostname(), tester).switchHostname().isEmpty()); + } + + private static Node getNode(HostName hostname, ControllerTester tester) { + return allNodes(tester).stream() + .filter(node -> node.hostname().equals(hostname)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("No such node: " + hostname)); + } + + private static List<Node> allNodes(ControllerTester tester) { + List<Node> nodes = new ArrayList<>(); + for (var zone : tester.zoneRegistry().zones().controllerUpgraded().all().ids()) { + nodes.addAll(tester.serviceRegistry().configServer().nodeRepository().list(zone)); + } + return nodes; + } + + private static String switchHostname(Node node) { + return "tor-" + node.hostname().value(); + } + + private static void addNodeEntities(ControllerTester tester) { + for (var node : allNodes(tester)) { + if (!node.type().isHost()) continue; + NodeEntity nodeEntity = new NodeEntity(node.hostname().value(), "", "", switchHostname(node)); + tester.serviceRegistry().entityService().addNodeEntity(nodeEntity); + } + } + +} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java index 1da7bdeca19..f327851f902 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java @@ -2,10 +2,9 @@ package com.yahoo.vespa.hosted.controller.restapi.application; import com.yahoo.config.provision.ApplicationName; -import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; +import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.controller.ControllerTester; import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; import com.yahoo.vespa.hosted.controller.api.role.Role; @@ -25,8 +24,8 @@ import java.util.Collections; import java.util.Set; import static com.yahoo.application.container.handler.Request.Method.GET; -import static com.yahoo.application.container.handler.Request.Method.PUT; import static com.yahoo.application.container.handler.Request.Method.POST; +import static com.yahoo.application.container.handler.Request.Method.PUT; import static com.yahoo.vespa.hosted.controller.restapi.application.ApplicationApiTest.createApplicationSubmissionData; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -45,7 +44,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { public void before() { tester = new ContainerTester(container, responseFiles); ((InMemoryFlagSource) tester.controller().flagSource()) - .withBooleanFlag(Flags.ENABLE_PUBLIC_SIGNUP_FLOW.id(), true); + .withBooleanFlag(PermanentFlags.ENABLE_PUBLIC_SIGNUP_FLOW.id(), true); deploymentTester = new DeploymentTester(new ControllerTester(tester)); deploymentTester.controllerTester().computeVersionStatus(); setupTenantAndApplication(); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java index c061bfed21a..5523ce8dd9f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java @@ -6,8 +6,8 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.test.ManualClock; -import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; +import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshot; import com.yahoo.vespa.hosted.controller.auditlog.AuditLogger; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; @@ -42,7 +42,7 @@ public class ControllerApiTest extends ControllerContainerTest { public void testControllerApi() { tester.assertResponse(authenticatedRequest("http://localhost:8080/controller/v1/", "", Request.Method.GET), new File("root.json")); - ((InMemoryFlagSource) tester.controller().flagSource()).withListFlag(Flags.INACTIVE_MAINTENANCE_JOBS.id(), List.of("DeploymentExpirer"), String.class); + ((InMemoryFlagSource) tester.controller().flagSource()).withListFlag(PermanentFlags.INACTIVE_MAINTENANCE_JOBS.id(), List.of("DeploymentExpirer"), String.class); // GET a list of all maintenance jobs tester.assertResponse(authenticatedRequest("http://localhost:8080/controller/v1/maintenance/", "", Request.Method.GET), diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json index c1ee1489cd4..5ab087aab17 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json @@ -34,6 +34,9 @@ "name": "HostRepairMaintainer" }, { + "name": "HostSwitchUpdater" + }, + { "name": "JobRunner" }, { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java index 0ed30871ded..547ce769e87 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java @@ -4,8 +4,8 @@ package com.yahoo.vespa.hosted.controller.restapi.user; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; +import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.controller.ControllerTester; import com.yahoo.vespa.hosted.controller.api.integration.user.User; import com.yahoo.vespa.hosted.controller.api.role.Role; @@ -19,7 +19,6 @@ import java.util.Set; import static com.yahoo.application.container.handler.Request.Method.DELETE; import static com.yahoo.application.container.handler.Request.Method.POST; -import static com.yahoo.application.container.handler.Request.Method.PUT; import static org.junit.Assert.assertEquals; /** @@ -203,7 +202,7 @@ public class UserApiTest extends ControllerContainerCloudTest { public void userMetadataTest() { ContainerTester tester = new ContainerTester(container, responseFiles); ((InMemoryFlagSource) tester.controller().flagSource()) - .withBooleanFlag(Flags.ENABLE_PUBLIC_SIGNUP_FLOW.id(), true); + .withBooleanFlag(PermanentFlags.ENABLE_PUBLIC_SIGNUP_FLOW.id(), true); ControllerTester controller = new ControllerTester(tester); Set<Role> operator = Set.of(Role.hostedOperator(), Role.hostedSupporter(), Role.hostedAccountant()); User user = new User("dev@domail", "Joe Developer", "dev", null); |