summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2022-10-27 12:22:48 +0200
committerGitHub <noreply@github.com>2022-10-27 12:22:48 +0200
commitb4f9d149cf6ee11c47f919c4980583983ab75251 (patch)
tree922c0cc9d8c3706795422af2fc3633c428e1cb46
parent5a6b21062b0e20b512206fa49e758bcafa3c83f6 (diff)
parentabdcadc2f31b51d1a0321ef00cd797e4bf586992 (diff)
Merge pull request #24599 from vespa-engine/mpolden/default-cloud-account
Fall back to default cloud account in node spec
-rwxr-xr-xconfig-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java2
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Cloud.java22
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java10
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Zone.java8
-rw-r--r--config-provisioning/src/main/resources/configdefinitions/config.provisioning.cloud.def3
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java17
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java11
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerSpec.java8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DirtyExpirer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostRetirer.java7
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/Rebalancer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java7
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java12
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java7
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java27
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java10
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java3
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java3
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainerTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java7
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java5
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java2
40 files changed, 146 insertions, 99 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
index 560703b6b26..f5f25c65cd4 100755
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
@@ -595,7 +595,7 @@ public abstract class ContainerCluster<CONTAINER extends Container>
builder.system(zone.system().value());
builder.environment(zone.environment().value());
builder.region(zone.region().value());
- builder.cloud(zone.getCloud().name().value());
+ builder.cloud(zone.cloud().name().value());
}
@Override
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Cloud.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Cloud.java
index 4498d8de4c7..6220c73dfd5 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/Cloud.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Cloud.java
@@ -4,7 +4,7 @@ package com.yahoo.config.provision;
import java.util.Objects;
/**
- * Represents a cloud service and its supported features.
+ * Properties of the cloud service where the zone is deployed.
*
* @author mpolden
*/
@@ -14,11 +14,16 @@ public class Cloud {
private final boolean dynamicProvisioning;
private final boolean requireAccessControl;
+ private final CloudAccount account;
- private Cloud(CloudName name, boolean dynamicProvisioning, boolean requireAccessControl) {
+ private Cloud(CloudName name, boolean dynamicProvisioning, boolean requireAccessControl, CloudAccount account) {
this.name = Objects.requireNonNull(name);
this.dynamicProvisioning = dynamicProvisioning;
this.requireAccessControl = requireAccessControl;
+ this.account = Objects.requireNonNull(account);
+ if (name.equals(CloudName.AWS) && account.isEmpty()) {
+ throw new IllegalArgumentException("Account must be non-empty in cloud '" + name + "'");
+ }
}
/** The name of this */
@@ -36,6 +41,11 @@ public class Cloud {
return requireAccessControl;
}
+ /** Returns the default account of this cloud */
+ public CloudAccount account() {
+ return account;
+ }
+
/** For testing purposes only */
public static Cloud defaultCloud() {
return new Builder().build();
@@ -50,6 +60,7 @@ public class Cloud {
private CloudName name = CloudName.DEFAULT;
private boolean dynamicProvisioning = false;
private boolean requireAccessControl = false;
+ private CloudAccount account = CloudAccount.empty;
public Builder() {}
@@ -68,8 +79,13 @@ public class Cloud {
return this;
}
+ public Builder account(CloudAccount account) {
+ this.account = account;
+ return this;
+ }
+
public Cloud build() {
- return new Cloud(name, dynamicProvisioning, requireAccessControl);
+ return new Cloud(name, dynamicProvisioning, requireAccessControl, account);
}
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java b/config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java
index 3609ea4af88..ac237cb1232 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java
@@ -6,14 +6,20 @@ import ai.vespa.validation.PatternedStringWrapper;
import java.util.regex.Pattern;
/**
- * Identifies an account in a public cloud, such as AWS or GCP.
+ * Identifies an account in a public cloud, such as {@link CloudName#AWS} or {@link CloudName#GCP}.
*
* @author mpolden
*/
public class CloudAccount extends PatternedStringWrapper<CloudAccount> {
+ public static final CloudAccount empty = new CloudAccount("");
+
public CloudAccount(String value) {
- super(value, Pattern.compile("^[0-9]{12}$"), "cloud account");
+ super(value, Pattern.compile("^([0-9]{12})?$"), "cloud account");
+ }
+
+ public boolean isEmpty() {
+ return this.equals(empty);
}
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Zone.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Zone.java
index 1f8ba3ce93f..8b662c4f66b 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/Zone.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Zone.java
@@ -27,6 +27,7 @@ public class Zone {
.name(CloudName.from(configserverConfig.cloud()))
.dynamicProvisioning(cloudConfig.dynamicProvisioning())
.requireAccessControl(cloudConfig.requireAccessControl())
+ .account(cloudConfig.account().isEmpty() ? CloudAccount.empty : new CloudAccount(cloudConfig.account()))
.build(),
SystemName.from(configserverConfig.system()),
Environment.from(configserverConfig.environment()),
@@ -51,8 +52,13 @@ public class Zone {
this.region = region;
}
+ // TODO(mpolden): For compatibility with older config models. Remove when versions < 8.76 are gone
+ public Cloud getCloud() {
+ return cloud();
+ }
+
/** Returns the current cloud */
- public Cloud getCloud() { return cloud; }
+ public Cloud cloud() { return cloud; }
/** Returns the current system */
public SystemName system() { return systemName; }
diff --git a/config-provisioning/src/main/resources/configdefinitions/config.provisioning.cloud.def b/config-provisioning/src/main/resources/configdefinitions/config.provisioning.cloud.def
index a5ad0dc9a7c..05ccee34d59 100644
--- a/config-provisioning/src/main/resources/configdefinitions/config.provisioning.cloud.def
+++ b/config-provisioning/src/main/resources/configdefinitions/config.provisioning.cloud.def
@@ -11,3 +11,6 @@ allowHostSharing bool default=true
# Should clusters in this cloud always require access control for both read and write operations?
requireAccessControl bool default=false
+
+# The default account used to provision hosts and load balancers in this zone.
+account string default=""
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
index cb4d5ab3770..6548e8ae16b 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
@@ -29,7 +29,6 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
-import java.util.stream.Collectors;
/**
* A node in the node repository. The identity of a node is given by its id.
@@ -56,7 +55,7 @@ public final class Node implements Nodelike {
private final Optional<ClusterSpec.Type> exclusiveToClusterType;
private final Optional<String> switchHostname;
private final List<TrustStoreItem> trustStoreItems;
- private final Optional<CloudAccount> cloudAccount;
+ private final CloudAccount cloudAccount;
/** Record of the last event of each type happening to this node */
private final History history;
@@ -87,7 +86,7 @@ public final class Node implements Nodelike {
Reports reports, Optional<String> modelName, Optional<TenantName> reservedTo,
Optional<ApplicationId> exclusiveToApplicationId, Optional<ClusterSpec.Type> exclusiveToClusterType,
Optional<String> switchHostname, List<TrustStoreItem> trustStoreItems,
- Optional<CloudAccount> cloudAccount) {
+ CloudAccount cloudAccount) {
this.id = Objects.requireNonNull(id, "A node must have an ID");
this.hostname = requireNonEmptyString(hostname, "A node must have a hostname");
this.ipConfig = Objects.requireNonNull(ipConfig, "A node must a have an IP config");
@@ -104,7 +103,7 @@ public final class Node implements Nodelike {
this.exclusiveToApplicationId = Objects.requireNonNull(exclusiveToApplicationId, "exclusiveToApplicationId cannot be null");
this.exclusiveToClusterType = Objects.requireNonNull(exclusiveToClusterType, "exclusiveToClusterType cannot be null");
this.switchHostname = requireNonEmptyString(switchHostname, "switchHostname cannot be null");
- this.trustStoreItems = Objects.requireNonNull(trustStoreItems).stream().distinct().collect(Collectors.toUnmodifiableList());
+ this.trustStoreItems = Objects.requireNonNull(trustStoreItems).stream().distinct().toList();
this.cloudAccount = Objects.requireNonNull(cloudAccount);
if (state == State.active)
@@ -119,7 +118,7 @@ public final class Node implements Nodelike {
if (!ipConfig.pool().ipSet().isEmpty()) throw new IllegalArgumentException("A child node cannot have an IP address pool");
if (modelName.isPresent()) throw new IllegalArgumentException("A child node cannot have model name set");
if (switchHostname.isPresent()) throw new IllegalArgumentException("A child node cannot have switch hostname set");
- if (cloudAccount().isPresent()) throw new IllegalArgumentException("A child node cannot have cloud account set");
+ if (!cloudAccount.isEmpty()) throw new IllegalArgumentException("A child node cannot have cloud account set");
}
if (type != NodeType.host && reservedTo.isPresent())
@@ -223,8 +222,8 @@ public final class Node implements Nodelike {
return trustStoreItems;
}
- /** Returns the cloud account of this host. This is empty if the host is in the zone's default account */
- public Optional<CloudAccount> cloudAccount() {
+ /** Returns the cloud account of this host */
+ public CloudAccount cloudAccount() {
return cloudAccount;
}
@@ -664,7 +663,7 @@ public final class Node implements Nodelike {
private Reports reports;
private History history;
private List<TrustStoreItem> trustStoreItems;
- private CloudAccount cloudAccount;
+ private CloudAccount cloudAccount = CloudAccount.empty;
private Builder(String id, String hostname, Flavor flavor, State state, NodeType type) {
this.id = id;
@@ -751,7 +750,7 @@ public final class Node implements Nodelike {
Optional.ofNullable(modelName), Optional.ofNullable(reservedTo), Optional.ofNullable(exclusiveToApplicationId),
Optional.ofNullable(exclusiveToClusterType), Optional.ofNullable(switchHostname),
Optional.ofNullable(trustStoreItems).orElseGet(List::of),
- Optional.ofNullable(cloudAccount));
+ cloudAccount);
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
index 21bd0ff99dd..ff156751f5e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
@@ -87,7 +87,7 @@ public class NodeRepository extends AbstractComponent {
metricsDb,
orchestrator,
config.useCuratorClientCache(),
- zone.environment().isProduction() && !zone.getCloud().dynamicProvisioning() && !zone.system().isCd() ? 1 : 0,
+ zone.environment().isProduction() && !zone.cloud().dynamicProvisioning() && !zone.system().isCd() ? 1 : 0,
config.nodeCacheSize());
}
@@ -109,10 +109,10 @@ public class NodeRepository extends AbstractComponent {
boolean useCuratorClientCache,
int spareCount,
long nodeCacheSize) {
- if (provisionServiceProvider.getHostProvisioner().isPresent() != zone.getCloud().dynamicProvisioning())
+ if (provisionServiceProvider.getHostProvisioner().isPresent() != zone.cloud().dynamicProvisioning())
throw new IllegalArgumentException(String.format(
"dynamicProvisioning property must be 1-to-1 with availability of HostProvisioner, was: dynamicProvisioning=%s, hostProvisioner=%s",
- zone.getCloud().dynamicProvisioning(), provisionServiceProvider.getHostProvisioner().map(__ -> "present").orElse("empty")));
+ zone.cloud().dynamicProvisioning(), provisionServiceProvider.getHostProvisioner().map(__ -> "present").orElse("empty")));
this.flagSource = flagSource;
this.db = new CuratorDatabaseClient(flavors, curator, clock, useCuratorClientCache, nodeCacheSize);
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java
index 4a1545cc66c..5ed07153f32 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java
@@ -164,7 +164,7 @@ public class AllocatableClusterResources {
NodeRepository nodeRepository) {
var systemLimits = new NodeResourceLimits(nodeRepository);
boolean exclusive = clusterSpec.isExclusive();
- if ( !clusterSpec.isExclusive() && !nodeRepository.zone().getCloud().dynamicProvisioning()) {
+ if ( !clusterSpec.isExclusive() && !nodeRepository.zone().cloud().dynamicProvisioning()) {
// We decide resources: Add overhead to what we'll request (advertised) to make sure real becomes (at least) cappedNodeResources
var advertisedResources = nodeRepository.resourcesCalculator().realToRequest(wantedResources.nodeResources(), exclusive);
advertisedResources = systemLimits.enlargeToLegal(advertisedResources, clusterSpec.type(), exclusive); // Ask for something legal
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java
index b8e7cfb5441..aa7d388c78f 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java
@@ -23,10 +23,10 @@ public class LoadBalancerInstance {
private final Set<Integer> ports;
private final Set<String> networks;
private final Set<Real> reals;
- private final Optional<CloudAccount> cloudAccount;
+ private final CloudAccount cloudAccount;
public LoadBalancerInstance(Optional<DomainName> hostname, Optional<String> ipAddress, Optional<DnsZone> dnsZone, Set<Integer> ports,
- Set<String> networks, Set<Real> reals, Optional<CloudAccount> cloudAccount) {
+ Set<String> networks, Set<Real> reals, CloudAccount cloudAccount) {
this.hostname = Objects.requireNonNull(hostname, "hostname must be non-null");
this.ipAddress = Objects.requireNonNull(ipAddress, "ip must be non-null");
this.dnsZone = Objects.requireNonNull(dnsZone, "dnsZone must be non-null");
@@ -35,9 +35,10 @@ public class LoadBalancerInstance {
this.reals = ImmutableSortedSet.copyOf(Objects.requireNonNull(reals, "targets must be non-null"));
this.cloudAccount = Objects.requireNonNull(cloudAccount, "cloudAccount must be non-null");
- if (hostname.isEmpty() == ipAddress.isEmpty())
+ if (hostname.isEmpty() == ipAddress.isEmpty()) {
throw new IllegalArgumentException("Exactly 1 of hostname=%s and ipAddress=%s must be set".formatted(
hostname.map(DomainName::value).orElse("<empty>"), ipAddress.orElse("<empty>")));
+ }
}
/** Fully-qualified domain name of this load balancer. This hostname can be used for query and feed */
@@ -70,8 +71,8 @@ public class LoadBalancerInstance {
return reals;
}
- /** Cloud account of this load balancer. This is empty if the load balancer is in the zone's default account */
- public Optional<CloudAccount> cloudAccount() {
+ /** Cloud account of this load balancer */
+ public CloudAccount cloudAccount() {
return cloudAccount;
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerSpec.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerSpec.java
index 19739111415..18c6ed52046 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerSpec.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerSpec.java
@@ -7,7 +7,6 @@ import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.ClusterSpec;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
/**
@@ -20,10 +19,10 @@ public class LoadBalancerSpec {
private final ApplicationId application;
private final ClusterSpec.Id cluster;
private final Set<Real> reals;
- private final Optional<CloudAccount> cloudAccount;
+ private final CloudAccount cloudAccount;
public LoadBalancerSpec(ApplicationId application, ClusterSpec.Id cluster, Set<Real> reals,
- Optional<CloudAccount> cloudAccount) {
+ CloudAccount cloudAccount) {
this.application = Objects.requireNonNull(application);
this.cluster = Objects.requireNonNull(cluster);
this.reals = ImmutableSortedSet.copyOf(Objects.requireNonNull(reals));
@@ -46,7 +45,8 @@ public class LoadBalancerSpec {
}
/** Cloud account to use when satisfying this */
- public Optional<CloudAccount> cloudAccount() {
+ public CloudAccount cloudAccount() {
return cloudAccount;
}
+
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DirtyExpirer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DirtyExpirer.java
index 08898c47129..c4703102f47 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DirtyExpirer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DirtyExpirer.java
@@ -28,7 +28,7 @@ public class DirtyExpirer extends Expirer {
DirtyExpirer(NodeRepository nodeRepository, Duration dirtyTimeout, Metric metric) {
super(Node.State.dirty, History.Event.Type.deallocated, nodeRepository, dirtyTimeout, metric);
// Do not keep allocation in dynamically provisioned zones so that the hosts can be deprovisioned
- this.keepAllocationOnExpiry = ! nodeRepository.zone().getCloud().dynamicProvisioning();
+ this.keepAllocationOnExpiry = ! nodeRepository.zone().cloud().dynamicProvisioning();
}
@Override
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java
index 61589078b69..000809ef5af 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DynamicProvisioningMaintainer.java
@@ -286,7 +286,7 @@ public class DynamicProvisioningMaintainer extends NodeRepositoryMaintainer {
List<Integer> provisionIndices = nodeRepository().database().readProvisionIndices(count);
List<Node> hosts = new ArrayList<>();
hostProvisioner.provisionHosts(provisionIndices, NodeType.host, nodeResources, ApplicationId.defaultId(),
- osVersion, HostSharing.shared, Optional.empty(), Optional.empty(),
+ osVersion, HostSharing.shared, Optional.empty(), nodeRepository().zone().cloud().account(),
provisionedHosts -> {
hosts.addAll(provisionedHosts.stream().map(ProvisionedHost::generateHost).toList());
nodeRepository().nodes().addNodes(hosts, Agent.DynamicProvisioningMaintainer);
@@ -335,7 +335,7 @@ public class DynamicProvisioningMaintainer extends NodeRepositoryMaintainer {
// build() requires a version, even though it is not (should not be) used
.vespaVersion(Vtag.currentVersion)
.build();
- NodeSpec nodeSpec = NodeSpec.from(clusterCapacity.count(), nodeResources, false, true, Optional.empty());
+ NodeSpec nodeSpec = NodeSpec.from(clusterCapacity.count(), nodeResources, false, true, nodeRepository().zone().cloud().account());
int wantedGroups = 1;
NodePrioritizer prioritizer = new NodePrioritizer(nodesAndHosts, applicationId, clusterSpec, nodeSpec, wantedGroups,
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostRetirer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostRetirer.java
index aa3a82d52c9..6667477cad1 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostRetirer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostRetirer.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.maintenance;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.HostEvent;
import com.yahoo.jdisc.Metric;
+import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeList;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.Agent;
@@ -37,12 +38,14 @@ public class HostRetirer extends NodeRepositoryMaintainer {
@Override
protected double maintain() {
- if (!nodeRepository().zone().getCloud().dynamicProvisioning()) return 1.0;
+ if (!nodeRepository().zone().cloud().dynamicProvisioning()) return 1.0;
NodeList candidates = nodeRepository().nodes().list()
.parents()
.not().deprovisioning();
- List<CloudAccount> cloudAccounts = candidates.stream().flatMap(c -> c.cloudAccount().stream())
+ List<CloudAccount> cloudAccounts = candidates.stream()
+ .map(Node::cloudAccount)
+ .filter(cloudAccount -> !cloudAccount.isEmpty())
.distinct()
.collect(Collectors.toList());
Map<String, List<HostEvent>> eventsByHostId = hostProvisioner.hostEventsIn(cloudAccounts).stream()
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
index fbdc8a43c6a..7c748b60527 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
@@ -137,7 +137,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
// Vespa upgrade frequency is higher in CD so (de)activate OS upgrades more frequently as well
osUpgradeActivatorInterval = zone.system().isCd() ? Duration.ofSeconds(30) : Duration.ofMinutes(5);
periodicRedeployInterval = Duration.ofMinutes(60);
- provisionedExpiry = zone.getCloud().dynamicProvisioning() ? Duration.ofMinutes(40) : Duration.ofHours(4);
+ provisionedExpiry = zone.cloud().dynamicProvisioning() ? Duration.ofMinutes(40) : Duration.ofHours(4);
rebalancerInterval = Duration.ofMinutes(120);
redeployMaintainerInterval = Duration.ofMinutes(1);
// Need to be long enough for deployment to be finished for all config model versions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/Rebalancer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/Rebalancer.java
index 3dd0b7d45a5..8f8a332c86a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/Rebalancer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/Rebalancer.java
@@ -37,7 +37,7 @@ public class Rebalancer extends NodeMover<Rebalancer.Move> {
protected double maintain() {
if ( ! nodeRepository().nodes().isWorking()) return 0.0;
- if (nodeRepository().zone().getCloud().dynamicProvisioning()) return 1.0; // Rebalancing not necessary
+ if (nodeRepository().zone().cloud().dynamicProvisioning()) return 1.0; // Rebalancing not necessary
if (nodeRepository().zone().environment().isTest()) return 1.0; // Short lived deployments; no need to rebalance
if (nodeRepository().zone().system().isCd()) return 1.0; // CD tests assert on # of nodes, avoid rebalnacing as it make tests unstable
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainer.java
index 541194af36f..d5b0c3baf19 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainer.java
@@ -71,7 +71,7 @@ public class SpareCapacityMaintainer extends NodeRepositoryMaintainer {
if ( ! nodeRepository().nodes().isWorking()) return 0.0;
// Don't need to maintain spare capacity in dynamically provisioned zones; can provision more on demand.
- if (nodeRepository().zone().getCloud().dynamicProvisioning()) return 1.0;
+ if (nodeRepository().zone().cloud().dynamicProvisioning()) return 1.0;
NodeList allNodes = nodeRepository().nodes().list();
CapacityChecker capacityChecker = new CapacityChecker(allNodes);
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java
index ec3e2539170..016ca8232a2 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java
@@ -510,7 +510,7 @@ public class Nodes {
db.removeNodes(removed, transaction);
} else {
removed = removeChildren(node, force, transaction);
- if (zone.getCloud().dynamicProvisioning()) {
+ if (zone.cloud().dynamicProvisioning()) {
db.removeNodes(List.of(node), transaction);
} else {
move(node.hostname(), Node.State.deprovisioned, Agent.system, false, Optional.empty(), transaction);
@@ -580,7 +580,7 @@ public class Nodes {
* - Node is in parked or failed state
*/
private void requireBreakfixable(Node node) {
- if (zone.getCloud().dynamicProvisioning()) {
+ if (zone.cloud().dynamicProvisioning()) {
illegal("Can not breakfix in zone: " + zone);
}
@@ -736,7 +736,7 @@ public class Nodes {
}
public boolean canAllocateTenantNodeTo(Node host) {
- return canAllocateTenantNodeTo(host, zone.getCloud().dynamicProvisioning());
+ return canAllocateTenantNodeTo(host, zone.cloud().dynamicProvisioning());
}
public boolean canAllocateTenantNodeTo(Node host, boolean dynamicProvisioning) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java
index 91219ed0ce2..a949863b900 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java
@@ -45,7 +45,7 @@ public class OsVersions {
private final Cloud cloud;
public OsVersions(NodeRepository nodeRepository) {
- this(nodeRepository, nodeRepository.zone().getCloud(), MAX_DELEGATED_UPGRADES);
+ this(nodeRepository, nodeRepository.zone().cloud(), MAX_DELEGATED_UPGRADES);
}
OsVersions(NodeRepository nodeRepository, Cloud cloud, int maxDelegatedUpgrades) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java
index 5e0f92bc08a..cfc918ce57b 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java
@@ -70,7 +70,10 @@ public class LoadBalancerSerializer {
realObject.setString(ipAddressField, real.ipAddress());
realObject.setLong(portField, real.port());
}));
- loadBalancer.instance().flatMap(LoadBalancerInstance::cloudAccount).ifPresent(cloudAccount -> root.setString(cloudAccountField, cloudAccount.value()));
+ loadBalancer.instance()
+ .map(LoadBalancerInstance::cloudAccount)
+ .filter(cloudAccount -> !cloudAccount.isEmpty())
+ .ifPresent(cloudAccount -> root.setString(cloudAccountField, cloudAccount.value()));
try {
return SlimeUtils.toJsonBytes(slime);
} catch (IOException e) {
@@ -98,7 +101,7 @@ public class LoadBalancerSerializer {
Optional<DomainName> hostname = optionalString(object.field(hostnameField), Function.identity()).filter(s -> !s.isEmpty()).map(DomainName::of);
Optional<String> ipAddress = optionalString(object.field(lbIpAddressField), Function.identity()).filter(s -> !s.isEmpty());
Optional<DnsZone> dnsZone = optionalString(object.field(dnsZoneField), DnsZone::new);
- Optional<CloudAccount> cloudAccount = optionalString(object.field(cloudAccountField), CloudAccount::new);
+ CloudAccount cloudAccount = optionalString(object.field(cloudAccountField), CloudAccount::new).orElse(CloudAccount.empty);
Optional<LoadBalancerInstance> instance = hostname.isEmpty() && ipAddress.isEmpty() ? Optional.empty() :
Optional.of(new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, cloudAccount));
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
index c0275de5798..d215339efee 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
@@ -194,7 +194,9 @@ public class NodeSerializer {
node.exclusiveToApplicationId().ifPresent(applicationId -> object.setString(exclusiveToApplicationIdKey, applicationId.serializedForm()));
node.exclusiveToClusterType().ifPresent(clusterType -> object.setString(exclusiveToClusterTypeKey, clusterType.name()));
trustedCertificatesToSlime(node.trustedCertificates(), object.setArray(trustedCertificatesKey));
- node.cloudAccount().ifPresent(cloudAccount -> object.setString(cloudAccountKey, cloudAccount.value()));
+ if (!node.cloudAccount().isEmpty()) {
+ object.setString(cloudAccountKey, node.cloudAccount().value());
+ }
}
private void toSlime(Flavor flavor, Cursor object) {
@@ -293,7 +295,7 @@ public class NodeSerializer {
SlimeUtils.optionalString(object.field(exclusiveToClusterTypeKey)).map(ClusterSpec.Type::from),
SlimeUtils.optionalString(object.field(switchHostnameKey)),
trustedCertificatesFromSlime(object),
- SlimeUtils.optionalString(object.field(cloudAccountKey)).map(CloudAccount::new));
+ SlimeUtils.optionalString(object.field(cloudAccountKey)).map(CloudAccount::new).orElse(CloudAccount.empty));
}
private Status statusFromSlime(Inspector object) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
index b98540c6310..33c3ab483f3 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
@@ -70,7 +70,7 @@ public class CapacityPolicies {
if (target.isUnspecified()) return target; // Cannot be modified
// Dev does not cap the cpu or network of containers since usage is spotty: Allocate just a small amount exclusively
- if (zone.environment() == Environment.dev && !zone.getCloud().dynamicProvisioning())
+ if (zone.environment() == Environment.dev && !zone.cloud().dynamicProvisioning())
target = target.withVcpu(0.1).withBandwidthGbps(0.1);
// Allow slow storage in zones which are not performance sensitive
@@ -97,14 +97,14 @@ public class CapacityPolicies {
if (clusterSpec.type() == ClusterSpec.Type.content) {
// TODO: Simplify when no application is on an older version than 8.75
- return zone.getCloud().dynamicProvisioning()
+ return zone.cloud().dynamicProvisioning()
? versioned(clusterSpec, Map.of(new Version(0), new NodeResources(2.0, 8, 50, 0.3),
new Version(8, 75), new NodeResources(2, 16, 300, 0.3)))
: versioned(clusterSpec, Map.of(new Version(0), new NodeResources(1.5, 8, 50, 0.3),
new Version(8, 75), new NodeResources(2, 16, 300, 0.3)));
}
else {
- return zone.getCloud().dynamicProvisioning()
+ return zone.cloud().dynamicProvisioning()
? versioned(clusterSpec, Map.of(new Version(0), new NodeResources(2.0, 8, 50, 0.3)))
: versioned(clusterSpec, Map.of(new Version(0), new NodeResources(1.5, 8, 50, 0.3)));
}
@@ -125,7 +125,7 @@ public class CapacityPolicies {
/** Returns whether an exclusive host is required for given cluster type and exclusivity requirement */
private boolean requiresExclusiveHost(ClusterSpec.Type type, boolean exclusive) {
- return zone.getCloud().dynamicProvisioning() && (exclusive || !sharedHosts.value().isEnabled(type.name()));
+ return zone.cloud().dynamicProvisioning() && (exclusive || !sharedHosts.value().isEnabled(type.name()));
}
/** Returns the resources for the newest version not newer than that requested in the cluster spec. */
@@ -137,14 +137,14 @@ public class CapacityPolicies {
// The lowest amount resources that can be exclusive allocated (i.e. a matching host flavor for this exists)
private NodeResources smallestExclusiveResources() {
- return (zone.getCloud().name().equals(CloudName.GCP))
+ return (zone.cloud().name().equals(CloudName.GCP))
? new NodeResources(1, 4, 50, 0.3)
: new NodeResources(0.5, 4, 50, 0.3);
}
// The lowest amount resources that can be shared (i.e. a matching host flavor for this exists)
private NodeResources smallestSharedResources() {
- return (zone.getCloud().name().equals(CloudName.GCP))
+ return (zone.cloud().name().equals(CloudName.GCP))
? new NodeResources(1, 4, 50, 0.3)
: new NodeResources(0.5, 2, 50, 0.3);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
index e1657ec3358..a8fb0a5e4c2 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
@@ -4,9 +4,9 @@ package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.NodeAllocationException;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.NodeAllocationException;
import com.yahoo.transaction.Mutex;
import com.yahoo.vespa.hosted.provision.LockedNodeList;
import com.yahoo.vespa.hosted.provision.Node;
@@ -159,7 +159,7 @@ public class GroupPreparer {
cluster,
requestedNodes,
wantedGroups,
- nodeRepository.zone().getCloud().dynamicProvisioning(),
+ nodeRepository.zone().cloud().dynamicProvisioning(),
nodeRepository.nameResolver(),
nodeRepository.nodes(),
nodeRepository.resourcesCalculator(),
@@ -169,7 +169,7 @@ public class GroupPreparer {
}
private boolean canProvisionDynamically(NodeType hostType) {
- return nodeRepository.zone().getCloud().dynamicProvisioning() &&
+ return nodeRepository.zone().cloud().dynamicProvisioning() &&
(hostType == NodeType.host || hostType.isConfigServerHostLike());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java
index 1d95cdc09df..eb0877be4d7 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/HostProvisioner.java
@@ -60,7 +60,7 @@ public interface HostProvisioner {
Version osVersion,
HostSharing sharing,
Optional<ClusterSpec.Type> clusterType,
- Optional<CloudAccount> cloudAccount,
+ CloudAccount cloudAccount,
Consumer<List<ProvisionedHost>> provisionedHostConsumer) throws NodeAllocationException;
/**
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java
index a62edec52e4..15c9134d10f 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java
@@ -178,7 +178,7 @@ public class LoadBalancerProvisioner {
return loadBalancerId;
}
- private void prepare(LoadBalancerId id, NodeList nodes, Optional<CloudAccount> cloudAccount) {
+ private void prepare(LoadBalancerId id, NodeList nodes, CloudAccount cloudAccount) {
Instant now = nodeRepository.clock().instant();
Optional<LoadBalancer> loadBalancer = db.readLoadBalancer(id);
Optional<LoadBalancerInstance> instance = provisionInstance(id, nodes, loadBalancer, cloudAccount);
@@ -212,7 +212,7 @@ public class LoadBalancerProvisioner {
/** Provision or reconfigure a load balancer instance, if necessary */
private Optional<LoadBalancerInstance> provisionInstance(LoadBalancerId id, NodeList nodes,
Optional<LoadBalancer> currentLoadBalancer,
- Optional<CloudAccount> cloudAccount) {
+ CloudAccount cloudAccount) {
boolean shouldDeactivateRouting = deactivateRouting.with(FetchVector.Dimension.APPLICATION_ID,
id.application().serializedForm())
.value();
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
index ff24f627aa4..67dbefcdfcd 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
@@ -201,7 +201,7 @@ class NodeAllocation {
if (candidate.parentHostname().isEmpty()) return false;
// In dynamic provisioned zones, exclusivity is violated if...
- if (nodeRepository.zone().getCloud().dynamicProvisioning()) {
+ if (nodeRepository.zone().cloud().dynamicProvisioning()) {
// If either the parent is dedicated to a cluster type different from this cluster
return ! candidate.parent.flatMap(Node::exclusiveToClusterType).map(cluster.type()::equals).orElse(true) ||
// or this cluster is requiring exclusivity, but the host is exclusive to a different owner
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
index ce87abd2dde..59063f1ce85 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
@@ -103,12 +103,13 @@ public class NodeRepositoryProvisioner implements Provisioner {
groups = target.groups();
resources = getNodeResources(cluster, target.nodeResources(), application, exclusive);
- nodeSpec = NodeSpec.from(target.nodes(), resources, exclusive, actual.canFail(), requested.cloudAccount());
+ nodeSpec = NodeSpec.from(target.nodes(), resources, exclusive, actual.canFail(),
+ requested.cloudAccount().orElse(nodeRepository.zone().cloud().account()));
}
else {
groups = 1; // type request with multiple groups is not supported
resources = getNodeResources(cluster, requested.minResources().nodeResources(), application, true);
- nodeSpec = NodeSpec.from(requested.type());
+ nodeSpec = NodeSpec.from(requested.type(), nodeRepository.zone().cloud().account());
}
return asSortedHosts(preparer.prepare(application, cluster, nodeSpec, groups), resources);
}
@@ -259,7 +260,7 @@ public class NodeRepositoryProvisioner implements Provisioner {
private IllegalArgumentException newNoAllocationPossible(ClusterSpec spec, Limits limits) {
StringBuilder message = new StringBuilder("No allocation possible within ").append(limits);
- boolean exclusiveHosts = spec.isExclusive() || nodeRepository.zone().getCloud().dynamicProvisioning();
+ boolean exclusiveHosts = spec.isExclusive() || nodeRepository.zone().cloud().dynamicProvisioning();
if (exclusiveHosts)
message.append(". Nearest allowed node resources: ").append(findNearestNodeResources(limits));
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java
index 310f921367e..bff963c3fec 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java
@@ -5,9 +5,7 @@ import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-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.NodeRepository;
import java.util.Locale;
@@ -64,7 +62,7 @@ public class NodeResourceLimits {
}
private double minAdvertisedVcpu(ClusterSpec.Type clusterType) {
- if (zone().environment() == Environment.dev && !zone().getCloud().dynamicProvisioning()) return 0.1;
+ if (zone().environment() == Environment.dev && !zone().cloud().dynamicProvisioning()) return 0.1;
if (clusterType.isContent() && zone().environment().isProduction()) return 1.0;
if (clusterType == ClusterSpec.Type.admin) return 0.1;
return 0.5;
@@ -81,7 +79,7 @@ public class NodeResourceLimits {
// Note: Assumes node type 'host'
private long reservedDiskSpaceGb(NodeResources.StorageType storageType, boolean exclusive) {
- if (storageType == NodeResources.StorageType.local && zone().getCloud().dynamicProvisioning())
+ if (storageType == NodeResources.StorageType.local && zone().cloud().dynamicProvisioning())
return nodeRepository.resourcesCalculator().reservedDiskSpaceInBase2Gb(NodeType.host, ! exclusive);
else
return 4;
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
index 90cd4a440f2..4ff3342a6c6 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
@@ -69,8 +69,8 @@ public interface NodeSpec {
/** Returns true if nodes with non-active parent hosts should be rejected */
boolean rejectNonActiveParent();
- /** Returns the cloud account to use when fulfilling this spec or empty if none is explicitly requested */
- Optional<CloudAccount> cloudAccount();
+ /** Returns the cloud account to use when fulfilling this spec */
+ CloudAccount cloudAccount();
/**
* Returns true if a node with given current resources and current spare host resources can be resized
@@ -81,12 +81,12 @@ public interface NodeSpec {
return false;
}
- static NodeSpec from(int nodeCount, NodeResources resources, boolean exclusive, boolean canFail, Optional<CloudAccount> cloudAccount) {
+ static NodeSpec from(int nodeCount, NodeResources resources, boolean exclusive, boolean canFail, CloudAccount cloudAccount) {
return new CountNodeSpec(nodeCount, resources, exclusive, canFail, cloudAccount);
}
- static NodeSpec from(NodeType type) {
- return new TypeNodeSpec(type);
+ static NodeSpec from(NodeType type, CloudAccount cloudAccount) {
+ return new TypeNodeSpec(type, cloudAccount);
}
/** A node spec specifying a node count and a flavor */
@@ -96,17 +96,14 @@ public interface NodeSpec {
private final NodeResources requestedNodeResources;
private final boolean exclusive;
private final boolean canFail;
- private final Optional<CloudAccount> cloudAccount;
+ private final CloudAccount cloudAccount;
- private CountNodeSpec(int count, NodeResources resources, boolean exclusive, boolean canFail, Optional<CloudAccount> cloudAccount) {
+ private CountNodeSpec(int count, NodeResources resources, boolean exclusive, boolean canFail, CloudAccount cloudAccount) {
this.count = count;
this.requestedNodeResources = Objects.requireNonNull(resources, "Resources must be specified");
this.exclusive = exclusive;
this.canFail = canFail;
this.cloudAccount = Objects.requireNonNull(cloudAccount);
- if (cloudAccount.isPresent() && !exclusive) {
- throw new IllegalArgumentException("Node spec with custom cloud account requires exclusive=true");
- }
}
@Override
@@ -184,7 +181,7 @@ public interface NodeSpec {
}
@Override
- public Optional<CloudAccount> cloudAccount() {
+ public CloudAccount cloudAccount() {
return cloudAccount;
}
@@ -200,9 +197,11 @@ public interface NodeSpec {
NodeType.controller, 3);
private final NodeType type;
+ private final CloudAccount cloudAccount;
- public TypeNodeSpec(NodeType type) {
+ public TypeNodeSpec(NodeType type, CloudAccount cloudAccount) {
this.type = type;
+ this.cloudAccount = cloudAccount;
}
@Override
@@ -257,8 +256,8 @@ public interface NodeSpec {
}
@Override
- public Optional<CloudAccount> cloudAccount() {
- return Optional.empty(); // Type spec does not support custom cloud accounts
+ public CloudAccount cloudAccount() {
+ return cloudAccount;
}
@Override
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
index 65071ad848d..35b80459168 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisionedHost.java
@@ -35,11 +35,11 @@ public class ProvisionedHost {
private final List<Address> nodeAddresses;
private final NodeResources nodeResources;
private final Version osVersion;
- private final Optional<CloudAccount> cloudAccount;
+ private final CloudAccount cloudAccount;
public ProvisionedHost(String id, String hostHostname, Flavor hostFlavor, NodeType hostType,
Optional<ApplicationId> exclusiveToApplicationId, Optional<ClusterSpec.Type> exclusiveToClusterType,
- List<Address> nodeAddresses, NodeResources nodeResources, Version osVersion, Optional<CloudAccount> cloudAccount) {
+ List<Address> nodeAddresses, NodeResources nodeResources, Version osVersion, CloudAccount cloudAccount) {
this.id = Objects.requireNonNull(id, "Host id must be set");
this.hostHostname = Objects.requireNonNull(hostHostname, "Host hostname must be set");
this.hostFlavor = Objects.requireNonNull(hostFlavor, "Host flavor must be set");
@@ -65,10 +65,10 @@ public class ProvisionedHost {
public Node generateHost() {
Node.Builder builder = Node.create(id, IP.Config.of(Set.of(), Set.of(), nodeAddresses), hostHostname, hostFlavor,
hostType)
- .status(Status.initial().withOsVersion(OsVersion.EMPTY.withCurrent(Optional.of(osVersion))));
+ .status(Status.initial().withOsVersion(OsVersion.EMPTY.withCurrent(Optional.of(osVersion))))
+ .cloudAccount(cloudAccount);
exclusiveToApplicationId.ifPresent(builder::exclusiveToApplicationId);
exclusiveToClusterType.ifPresent(builder::exclusiveToClusterType);
- cloudAccount.ifPresent(builder::cloudAccount);
return builder.build();
}
@@ -86,7 +86,7 @@ public class ProvisionedHost {
public List<Address> nodeAddresses() { return nodeAddresses; }
public NodeResources nodeResources() { return nodeResources; }
public Version osVersion() { return osVersion; }
- public Optional<CloudAccount> cloudAccount() { return cloudAccount; }
+ public CloudAccount cloudAccount() { return cloudAccount; }
public String nodeHostname() { return nodeAddresses.get(0).hostname(); }
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java
index 13489db9f62..712797bb76e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java
@@ -76,7 +76,8 @@ public class LoadBalancersResponse extends SlimeJsonResponse {
});
});
lb.instance()
- .flatMap(LoadBalancerInstance::cloudAccount)
+ .map(LoadBalancerInstance::cloudAccount)
+ .filter(cloudAccount -> !cloudAccount.isEmpty())
.ifPresent(cloudAccount -> lbObject.setString("cloudAccount", cloudAccount.value()));
});
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
index c82cd8fb47f..10f8816134c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
@@ -192,7 +192,9 @@ class NodesResponse extends SlimeJsonResponse {
node.switchHostname().ifPresent(switchHostname -> object.setString("switchHostname", switchHostname));
nodeRepository.archiveUris().archiveUriFor(node).ifPresent(uri -> object.setString("archiveUri", uri));
trustedCertsToSlime(node.trustedCertificates(), object);
- node.cloudAccount().ifPresent(cloudAccount -> object.setString("cloudAccount", cloudAccount.value()));
+ if (!node.cloudAccount().isEmpty()) {
+ object.setString("cloudAccount", node.cloudAccount().value());
+ }
}
private Version resolveVersionFlag(StringFlag flag, Node node, Allocation allocation) {
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
index f9af176fc00..81740accd78 100644
--- 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
@@ -63,7 +63,7 @@ public class MockHostProvisioner implements HostProvisioner {
@Override
public void provisionHosts(List<Integer> provisionIndices, NodeType hostType, NodeResources resources,
ApplicationId applicationId, Version osVersion, HostSharing sharing,
- Optional<ClusterSpec.Type> clusterType, Optional<CloudAccount> cloudAccount,
+ Optional<ClusterSpec.Type> clusterType, CloudAccount cloudAccount,
Consumer<List<ProvisionedHost>> provisionedHostsConsumer) {
Flavor hostFlavor = this.hostFlavor.orElseGet(() -> flavors.stream().filter(f -> compatible(f, resources))
.findFirst()
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 e21c57b3ef5..3d363e8a96b 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
@@ -57,7 +57,7 @@ class AutoscalingTester {
provisioningTester = new ProvisioningTester.Builder().zone(zone)
.flavors(flavors)
.resourcesCalculator(resourcesCalculator)
- .hostProvisioner(zone.getCloud().dynamicProvisioning() ? new MockHostProvisioner(flavors) : null)
+ .hostProvisioner(zone.cloud().dynamicProvisioning() ? new MockHostProvisioner(flavors) : null)
.build();
hostResourcesCalculator = resourcesCalculator;
@@ -217,7 +217,7 @@ class AutoscalingTester {
@Override
public NodeResources realResourcesOf(Nodelike node, NodeRepository nodeRepository) {
- if (zone.getCloud().dynamicProvisioning())
+ if (zone.cloud().dynamicProvisioning())
return node.resources().withMemoryGb(node.resources().memoryGb() - memoryTax);
else
return node.resources();
@@ -225,7 +225,7 @@ class AutoscalingTester {
@Override
public NodeResources advertisedResourcesOf(Flavor flavor) {
- if (zone.getCloud().dynamicProvisioning())
+ if (zone.cloud().dynamicProvisioning())
return flavor.resources().withMemoryGb(flavor.resources().memoryGb() + memoryTax);
else
return flavor.resources();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java
index 1b5fceecbf9..be3216c79a4 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerServiceTest.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.hosted.provision.lb;
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 org.junit.Test;
@@ -26,7 +27,7 @@ public class SharedLoadBalancerServiceTest {
@Test
public void test_create_lb() {
- var lb = loadBalancerService.create(new LoadBalancerSpec(applicationId, clusterId, reals, Optional.empty()), false);
+ var lb = loadBalancerService.create(new LoadBalancerSpec(applicationId, clusterId, reals, CloudAccount.empty), false);
assertEquals(Optional.of(HostName.of("vip.example.com")), lb.hostname());
assertEquals(Optional.empty(), lb.dnsZone());
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 72b49a4794a..bced4daed34 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
@@ -559,14 +559,14 @@ public class DynamicProvisioningMaintainerTest {
tester.maintainer.maintain();
List<ProvisionedHost> newHosts = tester.hostProvisioner.provisionedHosts();
assertEquals(2, newHosts.size());
- assertTrue(newHosts.stream().allMatch(host -> host.cloudAccount().get().equals(cloudAccount)));
+ assertTrue(newHosts.stream().allMatch(host -> host.cloudAccount().equals(cloudAccount)));
for (var host : newHosts) {
provisioningTester.nodeRepository().nodes().setReady(host.hostHostname(), Agent.operator, getClass().getSimpleName());
}
provisioningTester.prepareAndActivateInfraApplication(DynamicProvisioningTester.tenantHostApp, NodeType.host);
NodeList activeHosts = provisioningTester.nodeRepository().nodes().list(Node.State.active).nodeType(NodeType.host);
assertEquals(2, activeHosts.size());
- assertTrue(activeHosts.stream().allMatch(host -> host.cloudAccount().get().equals(cloudAccount)));
+ assertTrue(activeHosts.stream().allMatch(host -> host.cloudAccount().equals(cloudAccount)));
assertEquals(2, provisioningTester.activate(applicationId, prepared).size());
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
index adcd40866d0..8f34b0ae259 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.os;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Cloud;
+import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.HostSpec;
@@ -335,7 +336,11 @@ public class OsVersionsTest {
tester.flagSource().withIntFlag(PermanentFlags.MAX_REBUILDS.id(), maxRebuilds);
tester.flagSource().withBooleanFlag(Flags.SOFT_REBUILD.id(), softRebuild);
- var versions = new OsVersions(tester.nodeRepository(), Cloud.builder().dynamicProvisioning(true).name(CloudName.AWS).build(), Integer.MAX_VALUE);
+ var versions = new OsVersions(tester.nodeRepository(), Cloud.builder()
+ .dynamicProvisioning(true)
+ .name(CloudName.AWS)
+ .account(new CloudAccount("000000000000"))
+ .build(), Integer.MAX_VALUE);
provisionInfraApplication(hostCount, infraApplication, NodeType.host, NodeResources.StorageType.remote);
Supplier<NodeList> hostNodes = () -> tester.nodeRepository().nodes().list().nodeType(NodeType.host);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java
index 5bb9b71a223..8d226899ec4 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java
@@ -43,7 +43,7 @@ public class LoadBalancerSerializerTest {
new Real(DomainName.of("real-2"),
"127.0.0.2",
4080)),
- Optional.of(new CloudAccount("012345678912")))),
+ new CloudAccount("012345678912"))),
LoadBalancer.State.active,
now);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java
index f22abf4c9e3..3f4487e0a34 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializerTest.java
@@ -498,7 +498,7 @@ public class NodeSerializerTest {
.exclusiveToApplicationId(ApplicationId.defaultId())
.build();
node = nodeSerializer.fromJson(State.provisioned, nodeSerializer.toJson(node));
- assertEquals(account, node.cloudAccount().get());
+ assertEquals(account, node.cloudAccount());
}
private byte[] createNodeJson(String hostname, String... ipAddress) {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java
index 94b525cfe3c..0c321159748 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTest.java
@@ -5,6 +5,7 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.Cloud;
+import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.ClusterResources;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
@@ -78,7 +79,7 @@ public class DynamicProvisioningTest {
mockHostProvisioner(hostProvisioner, "large", 3, null); // Provision shared hosts
prepareAndActivate(application1, clusterSpec("mycluster"), 4, 1, resources);
verify(hostProvisioner).provisionHosts(eq(List.of(100, 101, 102, 103)), eq(NodeType.host), eq(resources), eq(application1),
- eq(Version.emptyVersion), eq(HostSharing.any), eq(Optional.of(ClusterSpec.Type.content)), eq(Optional.empty()), any());
+ eq(Version.emptyVersion), eq(HostSharing.any), eq(Optional.of(ClusterSpec.Type.content)), eq(CloudAccount.empty), any());
// Total of 8 nodes should now be in node-repo, 4 active hosts and 4 active nodes
assertEquals(8, tester.nodeRepository().nodes().list().size());
@@ -102,7 +103,7 @@ public class DynamicProvisioningTest {
mockHostProvisioner(hostProvisioner, "large", 3, application3);
prepareAndActivate(application3, clusterSpec("mycluster", true), 4, 1, resources);
verify(hostProvisioner).provisionHosts(eq(List.of(104, 105, 106, 107)), eq(NodeType.host), eq(resources), eq(application3),
- eq(Version.emptyVersion), eq(HostSharing.exclusive), eq(Optional.of(ClusterSpec.Type.content)), eq(Optional.empty()), any());
+ eq(Version.emptyVersion), eq(HostSharing.exclusive), eq(Optional.of(ClusterSpec.Type.content)), eq(CloudAccount.empty), any());
// Total of 20 nodes should now be in node-repo, 8 active hosts and 12 active nodes
assertEquals(20, tester.nodeRepository().nodes().list().size());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java
index 15e07f92292..7706895ebca 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java
@@ -318,7 +318,7 @@ public class LoadBalancerProvisionerTest {
tester.activate(app1, prepare(app1, capacity, clusterRequest(ClusterSpec.Type.container, ClusterSpec.Id.from("c1"))));
LoadBalancerList loadBalancers = tester.nodeRepository().loadBalancers().list();
assertEquals(1, loadBalancers.size());
- assertEquals(cloudAccount, loadBalancers.first().get().instance().get().cloudAccount().get());
+ assertEquals(cloudAccount, loadBalancers.first().get().instance().get().cloudAccount());
}
private void assertReals(ApplicationId application, ClusterSpec.Id cluster, Node.State... states) {