diff options
author | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2018-08-10 13:19:25 +0200 |
---|---|---|
committer | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2018-08-10 13:19:25 +0200 |
commit | 4440482a69a96282eab9117df1e2d9917f67e672 (patch) | |
tree | fb7110578284e4c13aee5a78974be96a12221126 /controller-server | |
parent | 490b6146a42868379d620d77789ed9a6da6ae27c (diff) |
Modifiable ConfigChangeActions, mock provisioning and re(boot)|(start)
Diffstat (limited to 'controller-server')
3 files changed, 111 insertions, 9 deletions
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java index b0bd1029db8..fe4cac08e4b 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java @@ -6,11 +6,13 @@ import com.yahoo.component.AbstractComponent; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.HostName; +import com.yahoo.config.provision.NodeType; import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions; import com.yahoo.vespa.hosted.controller.api.application.v4.model.EndpointStatus; import com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbindings.ConfigChangeActions; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import com.yahoo.vespa.hosted.controller.api.identifiers.Hostname; +import com.yahoo.vespa.hosted.controller.api.identifiers.Identifier; import com.yahoo.vespa.hosted.controller.api.identifiers.TenantId; import com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServer; import com.yahoo.vespa.hosted.controller.api.integration.configserver.Log; @@ -51,12 +53,27 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer private Version lastPrepareVersion = null; private RuntimeException prepareException = null; + private ConfigChangeActions configChangeActions = null; @Inject public ConfigServerMock(ZoneRegistryMock zoneRegistry) { bootstrap(zoneRegistry.zones().all().ids(), SystemApplication.all()); } + public void setConfigChangeActions(ConfigChangeActions configChangeActions) { + this.configChangeActions = configChangeActions; + } + + /** Assigns a reserved tenant node to the given deployment, with initial versions. */ + public void provision(ZoneId zone, ApplicationId application) { + nodeRepository().putByHostname(zone, new Node(HostName.from("host-" + application.serializedForm()), + Node.State.reserved, + NodeType.tenant, + Optional.of(application), + initialVersion, + initialVersion)); + } + public void bootstrap(List<ZoneId> zones, SystemApplication... applications) { bootstrap(zones, Arrays.asList(applications)); } @@ -135,6 +152,9 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer } applications.put(deployment.applicationId(), new Application(deployment.applicationId(), lastPrepareVersion)); + if (nodeRepository().list(deployment.zoneId(), deployment.applicationId()).isEmpty()) + provision(deployment.zoneId(), deployment.applicationId()); + return new PreparedApplication() { @Override @@ -160,18 +180,20 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer Application application = applications.get(deployment.applicationId()); application.activate(); for (Node node : nodeRepository.list(deployment.zoneId(), deployment.applicationId())) { - nodeRepository.add(deployment.zoneId(), new Node(node.hostname(), - node.state(), node.type(), - node.owner(), - node.currentVersion(), - application.version().get())); + nodeRepository.putByHostname(deployment.zoneId(), new Node(node.hostname(), + node.state(), node.type(), + node.owner(), + node.currentVersion(), + application.version().get())); } serviceStatus.remove(deployment); // Deployment is no longer converging after new deployment PrepareResponse prepareResponse = new PrepareResponse(); prepareResponse.message = "foo"; - prepareResponse.configChangeActions = new ConfigChangeActions(Collections.emptyList(), - Collections.emptyList()); + prepareResponse.configChangeActions = configChangeActions != null + ? configChangeActions + : new ConfigChangeActions(Collections.emptyList(), + Collections.emptyList()); prepareResponse.tenant = new TenantId("tenant"); return prepareResponse; } @@ -181,11 +203,14 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer @Override public void restart(DeploymentId deployment, Optional<Hostname> hostname) { + nodeRepository().requestRestart(deployment, hostname.map(Identifier::id).map(HostName::from)); } @Override public void deactivate(DeploymentId deployment) { applications.remove(deployment.applicationId()); + nodeRepository().removeByHostname(deployment.zoneId(), + nodeRepository().list(deployment.zoneId(), deployment.applicationId())); } // Returns a canned example response 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 49d342ea10b..2bb3cddf291 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 @@ -5,6 +5,7 @@ import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node; import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository; import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneId; @@ -13,6 +14,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Optional; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; /** @@ -41,6 +46,14 @@ public class NodeRepositoryMock implements NodeRepository { nodeRepository.clear(); } + public Node require(HostName hostName) { + return nodeRepository.values().stream() + .map(zoneNodes -> zoneNodes.get(hostName)) + .filter(Objects::nonNull) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("No node with the hostname " + hostName + " is known.")); + } + @Override public List<Node> list(ZoneId zone, ApplicationId application) { return nodeRepository.getOrDefault(zone, Collections.emptyMap()).values().stream() @@ -55,7 +68,71 @@ public class NodeRepositoryMock implements NodeRepository { .filter(node -> node.type() == type) .map(node -> new Node(node.hostname(), node.state(), node.type(), node.owner(), node.currentVersion(), version)) - .forEach(node -> add(zone, node)); + .forEach(node -> putByHostname(zone, node)); + } + + public void modifyNodes(DeploymentId deployment, Optional<HostName> hostname, UnaryOperator<Node> modification) { + List<Node> nodes = hostname.map(host -> require(host)) + .map(Collections::singletonList) + .orElse(list(deployment.zoneId(), deployment.applicationId())); + putByHostname(deployment.zoneId(), + nodes.stream().map(modification).collect(Collectors.toList())); + } + + public void requestRestart(DeploymentId deployment, Optional<HostName> hostname) { + modifyNodes(deployment, hostname, node -> new Node(node.hostname(), + node.state(), + node.type(), + node.owner(), + node.currentVersion(), + node.wantedVersion(), + node.serviceState(), + node.restartGeneration(), + node.wantedRestartGeneration() + 1, + node.rebootGeneration(), + node.wantedRebootGeneration())); + } + + public void doRestart(DeploymentId deployment, Optional<HostName> hostname) { + modifyNodes(deployment, hostname, node -> new Node(node.hostname(), + node.state(), + node.type(), + node.owner(), + node.currentVersion(), + node.wantedVersion(), + node.serviceState(), + node.restartGeneration() + 1, + node.wantedRestartGeneration(), + node.rebootGeneration(), + node.wantedRebootGeneration())); + } + + public void requestReboot(DeploymentId deployment, Optional<HostName> hostname) { + modifyNodes(deployment, hostname, node -> new Node(node.hostname(), + node.state(), + node.type(), + node.owner(), + node.currentVersion(), + node.wantedVersion(), + node.serviceState(), + node.restartGeneration(), + node.wantedRestartGeneration(), + node.rebootGeneration(), + node.wantedRebootGeneration() + 1)); + } + + public void doReboot(DeploymentId deployment, Optional<HostName> hostname) { + modifyNodes(deployment, hostname, node -> new Node(node.hostname(), + node.state(), + node.type(), + node.owner(), + node.currentVersion(), + node.wantedVersion(), + node.serviceState(), + node.restartGeneration(), + node.wantedRestartGeneration(), + node.rebootGeneration() + 1, + node.wantedRebootGeneration())); } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java index 45513c2294f..4ab42248b6d 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java @@ -338,7 +338,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST a 'restart application' command with a host filter (other filters not supported yet) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/restart?hostname=host1", POST) .screwdriverIdentity(SCREWDRIVER_ID), - "Requested restart of tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default"); + "{\"error-code\":\"INTERNAL_SERVER_ERROR\",\"message\":\"No node with the hostname host1 is known.\"}", 500); // GET services tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/service", GET) |