diff options
author | Martin Polden <mpolden@mpolden.no> | 2022-10-27 10:44:19 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2022-10-27 10:49:30 +0200 |
commit | abdcadc2f31b51d1a0321ef00cd797e4bf586992 (patch) | |
tree | 0f6c04729af6bd22384f007a5bf86c9bf4560cd6 | |
parent | a7d5de098525fe51daefd0342763d79075719a97 (diff) |
Less Optional
24 files changed, 84 insertions, 69 deletions
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 a9ebf419783..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 @@ -2,7 +2,6 @@ package com.yahoo.config.provision; import java.util.Objects; -import java.util.Optional; /** * Properties of the cloud service where the zone is deployed. @@ -15,15 +14,15 @@ public class Cloud { private final boolean dynamicProvisioning; private final boolean requireAccessControl; - private final Optional<CloudAccount> account; + private final CloudAccount account; - private Cloud(CloudName name, boolean dynamicProvisioning, boolean requireAccessControl, Optional<CloudAccount> account) { + 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 set in cloud '" + name + "'"); + throw new IllegalArgumentException("Account must be non-empty in cloud '" + name + "'"); } } @@ -42,8 +41,8 @@ public class Cloud { return requireAccessControl; } - /** Returns the default account of this cloud, if any */ - public Optional<CloudAccount> account() { + /** Returns the default account of this cloud */ + public CloudAccount account() { return account; } @@ -61,7 +60,7 @@ public class Cloud { private CloudName name = CloudName.DEFAULT; private boolean dynamicProvisioning = false; private boolean requireAccessControl = false; - private CloudAccount account = null; + private CloudAccount account = CloudAccount.empty; public Builder() {} @@ -86,7 +85,7 @@ public class Cloud { } public Cloud build() { - return new Cloud(name, dynamicProvisioning, requireAccessControl, Optional.ofNullable(account)); + 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 ef46122758a..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,7 +27,7 @@ public class Zone { .name(CloudName.from(configserverConfig.cloud())) .dynamicProvisioning(cloudConfig.dynamicProvisioning()) .requireAccessControl(cloudConfig.requireAccessControl()) - .account(cloudConfig.account().isEmpty() ? null : new CloudAccount(cloudConfig.account())) + .account(cloudConfig.account().isEmpty() ? CloudAccount.empty : new CloudAccount(cloudConfig.account())) .build(), SystemName.from(configserverConfig.system()), Environment.from(configserverConfig.environment()), 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/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/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 10097e76677..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; @@ -42,7 +43,9 @@ public class HostRetirer extends NodeRepositoryMaintainer { 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/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/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/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index 37d3bab11db..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 @@ -104,7 +104,7 @@ 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().or(() -> nodeRepository.zone().cloud().account())); + requested.cloudAccount().orElse(nodeRepository.zone().cloud().account())); } else { groups = 1; // type request with multiple groups is not supported 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 e490080a390..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,11 +81,11 @@ 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, Optional<CloudAccount> cloudAccount) { + static NodeSpec from(NodeType type, CloudAccount cloudAccount) { return new TypeNodeSpec(type, cloudAccount); } @@ -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,9 @@ public interface NodeSpec { NodeType.controller, 3); private final NodeType type; - private final Optional<CloudAccount> cloudAccount; + private final CloudAccount cloudAccount; - public TypeNodeSpec(NodeType type, Optional<CloudAccount> cloudAccount) { + public TypeNodeSpec(NodeType type, CloudAccount cloudAccount) { this.type = type; this.cloudAccount = cloudAccount; } @@ -259,7 +256,7 @@ public interface NodeSpec { } @Override - public Optional<CloudAccount> cloudAccount() { + public CloudAccount cloudAccount() { return cloudAccount; } 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/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/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 3570e56e196..b3716a1a8c6 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; @@ -75,7 +76,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()); @@ -99,7 +100,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) { |