aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java
diff options
context:
space:
mode:
Diffstat (limited to 'controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java')
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java378
1 files changed, 0 insertions, 378 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
deleted file mode 100644
index a4b14755d7d..00000000000
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/NodeRepositoryMock.java
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.integration;
-
-import com.yahoo.collections.Pair;
-import com.yahoo.component.Version;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.CloudAccount;
-import com.yahoo.config.provision.ClusterSpec;
-import com.yahoo.config.provision.HostName;
-import com.yahoo.config.provision.NodeResources;
-import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.TenantName;
-import com.yahoo.config.provision.zone.ZoneId;
-import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
-import com.yahoo.vespa.hosted.controller.api.integration.archive.ArchiveUriUpdate;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.Application;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.ApplicationStats;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.ArchiveUris;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.Load;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeFilter;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepoStats;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.TargetVersions;
-import com.yahoo.vespa.hosted.controller.api.integration.noderepository.ApplicationPatch;
-
-import java.net.URI;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.TreeMap;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.UnaryOperator;
-import java.util.stream.Collectors;
-
-/**
- * @author mpolden
- * @author jonmv
- */
-public class NodeRepositoryMock implements NodeRepository {
-
- private final Map<ZoneId, Map<HostName, Node>> nodeRepository = new ConcurrentHashMap<>();
- private final Map<ZoneId, Map<ApplicationId, Application>> applications = new ConcurrentHashMap<>();
- private final Map<ZoneId, TargetVersions> targetVersions = new ConcurrentHashMap<>();
- private final Map<DeploymentId, Pair<Double, Double>> trafficFractions = new ConcurrentHashMap<>();
- private final Map<DeploymentClusterId, BcpGroupInfo> bcpGroupInfos = new ConcurrentHashMap<>();
- private final Map<ZoneId, ArchiveUris> archiveUris = new ConcurrentHashMap<>();
-
- private boolean allowPatching = true;
- private boolean hasSpareCapacity = false;
-
- @Override
- public void addNodes(ZoneId zone, List<Node> nodes) {
- Map<HostName, Node> existingNodes = nodeRepository.getOrDefault(zone, Map.of());
- for (var node : nodes) {
- if (existingNodes.containsKey(node.hostname())) {
- throw new IllegalArgumentException("Node " + node.hostname() + " already added in zone " + zone);
- }
- }
- putNodes(zone, nodes);
- }
-
- @Override
- public void deleteNode(ZoneId zone, String hostname) {
- require(zone, hostname);
- nodeRepository.get(zone).remove(HostName.of(hostname));
- }
-
- @Override
- public void setState(ZoneId zone, Node.State state, String hostname) {
- Node node = Node.builder(require(zone, hostname))
- .state(Node.State.valueOf(state.name()))
- .build();
- putNodes(zone, node);
- }
-
- @Override
- public Node getNode(ZoneId zone, String hostname) {
- return require(zone, hostname);
- }
-
- @Override
- public List<Node> list(ZoneId zone, NodeFilter filter) {
- return nodeRepository.getOrDefault(zone, Map.of()).values().stream()
- .filter(node -> filter.includeDeprovisioned() || node.state() != Node.State.deprovisioned)
- .filter(node -> filter.applications().isEmpty() ||
- (node.owner().isPresent() && filter.applications().contains(node.owner().get())))
- .filter(node -> filter.hostnames().isEmpty() || filter.hostnames().contains(node.hostname()))
- .filter(node -> filter.states().isEmpty() || filter.states().contains(node.state()))
- .filter(node -> filter.clusterIds().isEmpty() || filter.clusterIds().contains(ClusterSpec.Id.from(node.clusterId())))
- .filter(node -> filter.clusterTypes().isEmpty() || filter.clusterTypes().contains(node.clusterType()))
- .toList();
- }
-
- @Override
- public Application getApplication(ZoneId zone, ApplicationId applicationId) {
- return applications.get(zone).get(applicationId);
- }
-
- @Override
- public void patchApplication(ZoneId zone, ApplicationId application, ApplicationPatch applicationPatch) {
- trafficFractions.put(new DeploymentId(application, zone),
- new Pair<>(applicationPatch.currentReadShare, applicationPatch.maxReadShare));
- if (applicationPatch.clusters != null) {
- for (var cluster : applicationPatch.clusters.entrySet())
- bcpGroupInfos.put(new DeploymentClusterId(new DeploymentId(application, zone), new ClusterSpec.Id(cluster.getKey())),
- new BcpGroupInfo(cluster.getValue().bcpGroupInfo.queryRate,
- cluster.getValue().bcpGroupInfo.growthRateHeadroom,
- cluster.getValue().bcpGroupInfo.cpuCostPerQuery));
- }
- }
-
- @Override
- public NodeRepoStats getStats(ZoneId zone) {
- List<ApplicationStats> applicationStats =
- applications.containsKey(zone)
- ? applications.get(zone).keySet().stream()
- .map(id -> new ApplicationStats(id, Load.zero(), 0, 0))
- .toList()
- : List.of();
-
- return new NodeRepoStats(0.0, 0.0, Load.zero(), Load.zero(), applicationStats);
- }
-
- @Override
- public ArchiveUris getArchiveUris(ZoneId zone) {
- return archiveUris.getOrDefault(zone, ArchiveUris.EMPTY);
- }
-
- @Override
- public void updateArchiveUri(ZoneId zone, ArchiveUriUpdate update) {
- archiveUris.compute(zone, (z, prev) -> {
- prev = prev == null ? ArchiveUris.EMPTY : prev;
- if (update.tenantName().isPresent()) {
- Map<TenantName, URI> updated = new HashMap<>(prev.tenantArchiveUris());
- update.archiveUri().ifPresentOrElse(uri -> updated.put(update.tenantName().get(), uri),
- () -> updated.remove(update.tenantName().get()));
- return new ArchiveUris(updated, prev.accountArchiveUris());
- } else {
- Map<CloudAccount, URI> updated = new HashMap<>(prev.accountArchiveUris());
- update.archiveUri().ifPresentOrElse(uri -> updated.put(update.cloudAccount().get(), uri),
- () -> updated.remove(update.cloudAccount().get()));
- return new ArchiveUris(prev.tenantArchiveUris(), updated);
- }
- });
- }
-
- @Override
- public void upgrade(ZoneId zone, NodeType type, Version version, boolean allowDowngrade) {
- this.targetVersions.compute(zone, (ignored, targetVersions) -> {
- if (targetVersions == null) {
- targetVersions = TargetVersions.EMPTY;
- }
- Optional<Version> current = targetVersions.vespaVersion(type);
- if (current.isPresent() && version.isBefore(current.get()) && !allowDowngrade) {
- throw new IllegalArgumentException("Changing wanted version for " + type + " in " + zone + " from " +
- current.get() + " to " + version +
- ", but downgrade is not allowed");
- }
- return targetVersions.withVespaVersion(type, version);
- });
- // Bump wanted version of each node. This is done by InfrastructureProvisioner in a real node repository.
- nodeRepository.getOrDefault(zone, Map.of()).values()
- .stream()
- .filter(node -> node.type() == type)
- .map(node -> Node.builder(node).wantedVersion(version).build())
- .forEach(node -> putNodes(zone, node));
- }
-
- @Override
- public void upgradeOs(ZoneId zone, NodeType type, Version version, boolean downgrade) {
- this.targetVersions.compute(zone, (ignored, targetVersions) -> {
- if (targetVersions == null) {
- targetVersions = TargetVersions.EMPTY;
- }
- return targetVersions.withOsVersion(type, version);
- });
- // Bump wanted version of each node. This is done by OsUpgradeActivator in a real node repository.
- nodeRepository.getOrDefault(zone, Map.of()).values()
- .stream()
- .filter(node -> node.type() == type)
- .map(node -> Node.builder(node).wantedOsVersion(version).build())
- .forEach(node -> putNodes(zone, node));
- }
-
- @Override
- public TargetVersions targetVersionsOf(ZoneId zone) {
- return targetVersions.getOrDefault(zone, TargetVersions.EMPTY);
- }
-
- @Override
- public void requestFirmwareCheck(ZoneId zone) {
- }
-
- @Override
- public void cancelFirmwareCheck(ZoneId zone) {
- }
-
- @Override
- public void retire(ZoneId zone, String hostname, boolean wantToRetire, boolean wantToDeprovision) {
- patchNodes(zone, hostname, (node) -> Node.builder(node).wantToRetire(wantToRetire).wantToDeprovision(wantToDeprovision).build());
- }
-
- @Override
- public void dropDocuments(ZoneId zoneId, ApplicationId applicationId, Optional<ClusterSpec.Id> clusterId) {
- }
-
- @Override
- public void updateReports(ZoneId zone, String hostname, Map<String, String> reports) {
- Map<String, String> trimmedReports = reports.entrySet().stream()
- // Null value clears a report
- .filter(kv -> kv.getValue() != null)
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
- patchNodes(zone, hostname, (node) -> Node.builder(node).reports(trimmedReports).build());
- }
-
- @Override
- public void updateModel(ZoneId zone, String hostname, String modelName) {
- patchNodes(zone, hostname, (node) -> Node.builder(node).modelName(modelName).build());
- }
-
- @Override
- public void updateSwitchHostname(ZoneId zone, String hostname, String switchHostname) {
- patchNodes(zone, hostname, (node) -> Node.builder(node).switchHostname(switchHostname).build());
- }
-
- @Override
- public void reboot(ZoneId zone, String hostname) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isReplaceable(ZoneId zone, List<HostName> hostnames) {
- return hasSpareCapacity;
- }
-
- /** Add or update given nodes in zone */
- public void putNodes(ZoneId zone, List<Node> nodes) {
- Map<HostName, Node> zoneNodes = nodeRepository.computeIfAbsent(zone, (k) -> new ConcurrentHashMap<>());
- for (var node : nodes) {
- zoneNodes.put(node.hostname(), node);
- }
- }
-
- /** Add or update given node in zone */
- public void putNodes(ZoneId zone, Node node) {
- putNodes(zone, List.of(node));
- }
-
- public void putApplication(ZoneId zone, Application application) {
- applications.computeIfAbsent(zone, (k) -> new TreeMap<>())
- .put(application.id(), application);
- }
-
- public Pair<Double, Double> getTrafficFraction(ApplicationId application, ZoneId zone) {
- return trafficFractions.get(new DeploymentId(application, zone));
- }
-
- public BcpGroupInfo getBcpGroupInfo(ApplicationId application, ZoneId zone, ClusterSpec.Id cluster) {
- return bcpGroupInfos.get(new DeploymentClusterId(new DeploymentId(application, zone), cluster));
- }
-
- /** Remove given nodes from zone */
- public void removeNodes(ZoneId zone, List<Node> nodes) {
- nodes.forEach(node -> nodeRepository.get(zone).remove(node.hostname()));
- }
-
- /** Remove all nodes in all zones */
- public void clear() {
- nodeRepository.clear();
- }
-
- /** Add a fixed set of nodes to given zone */
- public void addFixedNodes(ZoneId zone) {
- var nodeA = Node.builder()
- .hostname(HostName.of("hostA"))
- .parentHostname(HostName.of("parentHostA"))
- .state(Node.State.active)
- .type(NodeType.tenant)
- .owner(ApplicationId.from("tenant1", "app1", "default"))
- .currentVersion(Version.fromString("7.42"))
- .wantedVersion(Version.fromString("7.42"))
- .currentOsVersion(Version.fromString("7.6"))
- .wantedOsVersion(Version.fromString("7.6"))
- .serviceState(Node.ServiceState.expectedUp)
- .resources(new NodeResources(24, 24, 500, 1))
- .clusterId("clusterA")
- .clusterType(Node.ClusterType.container)
- .exclusiveTo(ApplicationId.from("t1", "a1", "i1"))
- .build();
- var nodeB = Node.builder()
- .hostname(HostName.of("hostB"))
- .parentHostname(HostName.of("parentHostB"))
- .state(Node.State.active)
- .type(NodeType.tenant)
- .owner(ApplicationId.from("tenant2", "app2", "default"))
- .currentVersion(Version.fromString("7.42"))
- .wantedVersion(Version.fromString("7.42"))
- .currentOsVersion(Version.fromString("7.6"))
- .wantedOsVersion(Version.fromString("7.6"))
- .serviceState(Node.ServiceState.expectedUp)
- .resources(new NodeResources(40, 24, 500, 1))
- .cost(20)
- .clusterId("clusterB")
- .clusterType(Node.ClusterType.container)
- .build();
- putNodes(zone, List.of(nodeA, nodeB));
- }
-
- public void doUpgrade(DeploymentId deployment, Optional<HostName> hostName, Version version) {
- patchNodes(deployment, hostName, node -> {
- return Node.builder(node)
- .currentVersion(version)
- .currentDockerImage(node.wantedDockerImage())
- .build();
- });
- }
-
- public void requestRestart(DeploymentId deployment, Optional<HostName> hostname) {
- patchNodes(deployment, hostname, node -> Node.builder(node).wantedRestartGeneration(node.wantedRestartGeneration() + 1).build());
- }
-
- public void doRestart(DeploymentId deployment, Optional<HostName> hostname) {
- patchNodes(deployment, hostname, node -> Node.builder(node).restartGeneration(node.restartGeneration() + 1).build());
- }
-
- public void requestReboot(DeploymentId deployment, Optional<HostName> hostname) {
- patchNodes(deployment, hostname, node -> Node.builder(node).wantedRebootGeneration(node.wantedRebootGeneration() + 1).build());
- }
-
- public void doReboot(DeploymentId deployment, Optional<HostName> hostname) {
- patchNodes(deployment, hostname, node -> Node.builder(node).rebootGeneration(node.rebootGeneration() + 1).build());
- }
-
- public NodeRepositoryMock allowPatching(boolean allowPatching) {
- this.allowPatching = allowPatching;
- return this;
- }
-
- public void hasSpareCapacity(boolean hasSpareCapacity) {
- this.hasSpareCapacity = hasSpareCapacity;
- }
-
- private Node require(ZoneId zone, String hostname) {
- return require(zone, HostName.of(hostname));
- }
-
- private Node require(ZoneId zone, HostName hostname) {
- Node node = nodeRepository.getOrDefault(zone, Map.of()).get(hostname);
- if (node == null) throw new IllegalArgumentException("Node not found in " + zone + ": " + hostname);
- return node;
- }
-
- private void patchNodes(ZoneId zone, String hostname, UnaryOperator<Node> patcher) {
- patchNodes(zone, Optional.of(HostName.of(hostname)), patcher);
- }
-
- private void patchNodes(DeploymentId deployment, Optional<HostName> hostname, UnaryOperator<Node> patcher) {
- patchNodes(deployment.zoneId(), hostname, patcher);
- }
-
- private void patchNodes(ZoneId zone, Optional<HostName> hostname, UnaryOperator<Node> patcher) {
- if (!allowPatching) throw new UnsupportedOperationException("Patching is disabled in this mock");
- List<Node> nodes;
- if (hostname.isPresent()) {
- nodes = List.of(require(zone, hostname.get()));
- } else {
- nodes = list(zone, NodeFilter.all());
- }
- putNodes(zone, nodes.stream().map(patcher).toList());
- }
-
- public record DeploymentClusterId(DeploymentId deploymentId, ClusterSpec.Id clusterId) {}
-
- public record BcpGroupInfo(double queryRate, double growthRateHeadroom, double cpuCostPerQuery) {}
-
-}