summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjonmv <venstad@gmail.com>2022-12-01 14:12:33 +0100
committerjonmv <venstad@gmail.com>2022-12-01 14:12:33 +0100
commit4226f2d67552c31e07a5be772691be213770a1b7 (patch)
tree8ae23d295a385dd286a6b2b080fc7a8715ab39c8
parent2925f225b34ad7fa3eb515bbddcc8c774e514131 (diff)
Write new settings only on activation
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/AccessLogBuilder.java15
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/InconsistentSchemaAndCodeError.java7
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java11
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java20
-rw-r--r--config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java11
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java13
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java3
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java50
-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/provisioning/LoadBalancerProvisionerTest.java4
14 files changed, 84 insertions, 66 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java b/config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java
index fcad1e20c16..2de7e5a1b37 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/HostSystem.java
@@ -115,7 +115,7 @@ public class HostSystem extends AbstractConfigProducer<Host> {
return hostResource;
}
- /** Returns the hosts owned by the application having this system - i.e all hosts except config servers */
+ /** Returns the hosts owned by the application having this system - i.e. all hosts except config servers */
public List<HostResource> getHosts() {
return hostname2host.values().stream()
.filter(host -> !host.getHost().runsConfigServer())
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/AccessLogBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/AccessLogBuilder.java
index 82b3defa22d..4a264f1eebc 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/AccessLogBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/AccessLogBuilder.java
@@ -99,16 +99,11 @@ public class AccessLogBuilder {
}
private static AccessLogType logTypeFor(AccessLogTypeLiteral typeLiteral) {
- switch (typeLiteral) {
- case DISABLED:
- return null;
- case VESPA:
- return AccessLogType.queryAccessLog;
- case JSON:
- return AccessLogType.jsonAccessLog;
- default:
- throw new InconsistentSchemaAndCodeError();
- }
+ return switch (typeLiteral) {
+ case DISABLED -> null;
+ case VESPA -> AccessLogType.queryAccessLog;
+ case JSON -> AccessLogType.jsonAccessLog;
+ };
}
public static Optional<AccessLogComponent> buildIfNotDisabled(DeployState deployState, ContainerCluster<?> cluster, Element accessLogSpec) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/InconsistentSchemaAndCodeError.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/InconsistentSchemaAndCodeError.java
deleted file mode 100644
index e3744f23964..00000000000
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/InconsistentSchemaAndCodeError.java
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.model.container.xml;
-
-/**
- * @author Tony Vaagenes
- */
-public class InconsistentSchemaAndCodeError extends Error {}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java
index afa3c0a4062..83a2258976e 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java
@@ -21,7 +21,8 @@ public class ClusterMembership {
protected ClusterMembership() {}
- private ClusterMembership(String stringValue, Version vespaVersion, Optional<DockerImage> dockerImageRepo) {
+ private ClusterMembership(String stringValue, Version vespaVersion, Optional<DockerImage> dockerImageRepo,
+ LoadBalancerSettings loadBalancerSettings) {
String[] components = stringValue.split("/");
if (components.length < 4)
throw new RuntimeException("Could not parse '" + stringValue + "' to a cluster membership. " +
@@ -49,6 +50,7 @@ public class ClusterMembership {
.exclusive(exclusive)
.combinedId(combinedId.map(ClusterSpec.Id::from))
.dockerImageRepository(dockerImageRepo)
+ .loadBalancerSettings(loadBalancerSettings)
.stateful(stateful)
.build();
this.index = Integer.parseInt(components[3]);
@@ -123,7 +125,12 @@ public class ClusterMembership {
public String toString() { return stringValue(); }
public static ClusterMembership from(String stringValue, Version vespaVersion, Optional<DockerImage> dockerImageRepo) {
- return new ClusterMembership(stringValue, vespaVersion, dockerImageRepo);
+ return from(stringValue, vespaVersion, dockerImageRepo, LoadBalancerSettings.empty);
+ }
+
+ public static ClusterMembership from(String stringValue, Version vespaVersion, Optional<DockerImage> dockerImageRepo,
+ LoadBalancerSettings loadBalancerSettings) {
+ return new ClusterMembership(stringValue, vespaVersion, dockerImageRepo, loadBalancerSettings);
}
public static ClusterMembership from(ClusterSpec cluster, int index) {
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java b/config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java
index 3973b042bde..01bb0ca45ff 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializer.java
@@ -1,10 +1,12 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.provision.serialization;
+import com.yahoo.component.Version;
import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.HostSpec;
+import com.yahoo.config.provision.LoadBalancerSettings;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.slime.ArrayTraverser;
import com.yahoo.slime.Cursor;
@@ -38,6 +40,8 @@ public class AllocatedHostsSerializer {
private static final String hostSpecKey = "hostSpec";
private static final String hostSpecHostNameKey = "hostName";
private static final String hostSpecMembershipKey = "membership";
+ private static final String loadBalancerSettingsKey = "loadBalancerSettings";
+ private static final String allowedUrnsKey = "allowedUrns";
private static final String realResourcesKey = "realResources";
private static final String advertisedResourcesKey = "advertisedResources";
@@ -81,6 +85,9 @@ public class AllocatedHostsSerializer {
host.membership().ifPresent(membership -> {
object.setString(hostSpecMembershipKey, membership.stringValue());
object.setString(hostSpecVespaVersionKey, membership.cluster().vespaVersion().toFullString());
+ if ( ! membership.cluster().loadBalancerSettings().isEmpty())
+ membership.cluster().loadBalancerSettings().allowedUrns()
+ .forEach(object.setObject(loadBalancerSettingsKey).setArray(allowedUrnsKey)::addString);
membership.cluster().dockerImageRepo().ifPresent(repo -> object.setString(hostSpecDockerImageRepoKey, repo.untagged()));
});
toSlime(host.realResources(), object.setObject(realResourcesKey));
@@ -125,7 +132,7 @@ public class AllocatedHostsSerializer {
nodeResourcesFromSlime(object.field(advertisedResourcesKey)),
optionalNodeResourcesFromSlime(object.field(requestedResourcesKey)), // TODO: Make non-optional when we serialize NodeResources.unspecified()
membershipFromSlime(object),
- optionalString(object.field(hostSpecCurrentVespaVersionKey)).map(com.yahoo.component.Version::new),
+ optionalString(object.field(hostSpecCurrentVespaVersionKey)).map(Version::new),
NetworkPortsSerializer.fromSlime(object.field(hostSpecNetworkPortsKey)),
optionalDockerImage(object.field(hostSpecDockerImageRepoKey)));
}
@@ -211,10 +218,15 @@ public class AllocatedHostsSerializer {
private static ClusterMembership membershipFromSlime(Inspector object) {
return ClusterMembership.from(object.field(hostSpecMembershipKey).asString(),
- com.yahoo.component.Version.fromString(object.field(hostSpecVespaVersionKey).asString()),
+ Version.fromString(object.field(hostSpecVespaVersionKey).asString()),
object.field(hostSpecDockerImageRepoKey).valid()
- ? Optional.of(DockerImage.fromString(object.field(hostSpecDockerImageRepoKey).asString()))
- : Optional.empty());
+ ? Optional.of(DockerImage.fromString(object.field(hostSpecDockerImageRepoKey).asString()))
+ : Optional.empty(),
+ object.field(loadBalancerSettingsKey).valid()
+ ? new LoadBalancerSettings(SlimeUtils.entriesStream(object.field(loadBalancerSettingsKey).field(allowedUrnsKey))
+ .map(Inspector::asString)
+ .toList())
+ : LoadBalancerSettings.empty);
}
private static Optional<String> optionalString(Inspector inspector) {
diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java
index 172e0875767..bcb3b8cd4aa 100644
--- a/config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java
+++ b/config-provisioning/src/test/java/com/yahoo/config/provision/serialization/AllocatedHostsSerializerTest.java
@@ -6,6 +6,7 @@ import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.HostSpec;
+import com.yahoo.config.provision.LoadBalancerSettings;
import com.yahoo.config.provision.NetworkPorts;
import com.yahoo.config.provision.NodeResources;
import org.junit.jupiter.api.Test;
@@ -19,6 +20,7 @@ import java.util.Set;
import static com.yahoo.config.provision.serialization.AllocatedHostsSerializer.fromJson;
import static com.yahoo.config.provision.serialization.AllocatedHostsSerializer.toJson;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
/**
* @author bratseth
@@ -62,6 +64,15 @@ public class AllocatedHostsSerializerTest {
Optional.empty()),
Optional.of(Version.fromString("3.4.5")),
Optional.empty(), Optional.empty()));
+ hosts.add(new HostSpec("with-load-balancer-settings",
+ smallSlowDiskSpeedNode,
+ bigSlowDiskSpeedNode,
+ anyDiskSpeedNode,
+ ClusterMembership.from("container/test/0/0", Version.fromString("6.73.1"),
+ Optional.empty(), new LoadBalancerSettings(List.of("burn"))),
+ Optional.empty(),
+ Optional.empty(),
+ Optional.empty()));
hosts.add(new HostSpec("with-ports",
smallSlowDiskSpeedNode,
bigSlowDiskSpeedNode,
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 36e42fcf541..fde3c85bdab 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
@@ -24,11 +24,11 @@ public class LoadBalancerInstance {
private final Set<Integer> ports;
private final Set<String> networks;
private final Set<Real> reals;
- private final Optional<LoadBalancerSettings> settings;
+ private final LoadBalancerSettings settings;
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<LoadBalancerSettings> settings, CloudAccount cloudAccount) {
+ Set<String> networks, Set<Real> reals, LoadBalancerSettings settings, 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");
@@ -74,8 +74,8 @@ public class LoadBalancerInstance {
return reals;
}
- /** Static user-configured settings of this load balancer, if set */
- public Optional<LoadBalancerSettings> settings() {
+ /** Static user-configured settings of this load balancer */
+ public LoadBalancerSettings settings() {
return settings;
}
@@ -89,11 +89,6 @@ public class LoadBalancerInstance {
return new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, settings, cloudAccount);
}
- /** Returns a copy of this with the given settings */
- public LoadBalancerInstance withSettings(LoadBalancerSettings settings) {
- return new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, Optional.of(settings), cloudAccount);
- }
-
private static Set<Integer> requirePorts(Set<Integer> ports) {
Objects.requireNonNull(ports, "ports must be non-null");
if (ports.isEmpty()) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java
index 2b6f64012b1..a756c1fc01a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.lb;
import ai.vespa.http.DomainName;
import com.google.common.collect.ImmutableSet;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.LoadBalancerSettings;
import com.yahoo.config.provision.NodeType;
import java.util.Collections;
@@ -61,7 +62,7 @@ public class LoadBalancerServiceMock implements LoadBalancerService {
Collections.singleton(4443),
ImmutableSet.of("10.2.3.0/24", "10.4.5.0/24"),
spec.reals(),
- spec.settings(),
+ spec.settings().orElse(LoadBalancerSettings.empty),
spec.cloudAccount());
instances.put(id, instance);
return instance;
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java
index 13407a83f53..97e466827a6 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java
@@ -37,7 +37,7 @@ public class SharedLoadBalancerService implements LoadBalancerService {
Set.of(4443),
Set.of(),
spec.reals(),
- spec.settings(),
+ spec.settings().orElse(LoadBalancerSettings.empty),
spec.cloudAccount());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java
index 0344c05c1c1..0264d0df837 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java
@@ -112,9 +112,9 @@ public class LoadBalancerExpirer extends NodeRepositoryMaintainer {
attempts.add(1);
LOG.log(Level.INFO, () -> "Removing reals from inactive load balancer " + lb.id() + ": " + Sets.difference(lb.instance().get().reals(), reals));
service.create(new LoadBalancerSpec(lb.id().application(), lb.id().cluster(), reals,
- null, lb.instance().get().cloudAccount()),
+ lb.instance().get().settings(), lb.instance().get().cloudAccount()),
true);
- db.writeLoadBalancer(lb.with(lb.instance().map(instance -> instance.withReals(reals).withSettings(lb.instance().get().settings().get()))), lb.state());
+ db.writeLoadBalancer(lb.with(lb.instance().map(instance -> instance.withReals(reals))), lb.state());
} catch (Exception e) {
failed.add(lb.id());
lastException.set(e);
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 22f6ec97107..9eccb21b756 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
@@ -75,8 +75,8 @@ public class LoadBalancerSerializer {
}));
loadBalancer.instance()
.map(LoadBalancerInstance::settings)
- .filter(settings -> ! settings.get().isEmpty())
- .ifPresent(settings -> settings.get().allowedUrns().forEach(root.setObject(settingsField)
+ .filter(settings -> ! settings.isEmpty())
+ .ifPresent(settings -> settings.allowedUrns().forEach(root.setObject(settingsField)
.setArray(allowedUrnsField)::addString));
loadBalancer.instance()
.map(LoadBalancerInstance::cloudAccount)
@@ -112,7 +112,7 @@ public class LoadBalancerSerializer {
LoadBalancerSettings settings = loadBalancerSettings(object.field(settingsField));
CloudAccount cloudAccount = optionalString(object.field(cloudAccountField), CloudAccount::from).orElse(CloudAccount.empty);
Optional<LoadBalancerInstance> instance = hostname.isEmpty() && ipAddress.isEmpty() ? Optional.empty() :
- Optional.of(new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, Optional.of(settings), cloudAccount));
+ Optional.of(new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, settings, cloudAccount));
return new LoadBalancer(LoadBalancerId.fromSerializedForm(object.field(idField).asString()),
instance,
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 17fc83bce80..26a3f231a31 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
@@ -34,6 +34,7 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
@@ -41,6 +42,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
+import static java.util.Objects.requireNonNullElse;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.reducing;
@@ -94,7 +96,7 @@ public class LoadBalancerProvisioner {
ClusterSpec.Id clusterId = effectiveId(cluster);
LoadBalancerId loadBalancerId = requireNonClashing(new LoadBalancerId(application, clusterId));
NodeList nodes = nodesOf(clusterId, application);
- prepare(loadBalancerId, nodes, cluster.loadBalancerSettings(), requestedNodes.cloudAccount());
+ prepare(loadBalancerId, nodes, requestedNodes.cloudAccount());
}
}
@@ -109,18 +111,21 @@ public class LoadBalancerProvisioner {
* Calling this when no load balancer has been prepared for given cluster is a no-op.
*/
public void activate(Set<ClusterSpec> clusters, NodeList newActive, ApplicationTransaction transaction) {
- Set<ClusterSpec.Id> activatingClusters = clusters.stream()
- .map(LoadBalancerProvisioner::effectiveId)
- .collect(Collectors.toSet());
+ Map<ClusterSpec.Id, LoadBalancerSettings> activatingClusters = clusters.stream()
+ .collect(groupingBy(LoadBalancerProvisioner::effectiveId,
+ reducing(LoadBalancerSettings.empty,
+ ClusterSpec::loadBalancerSettings,
+ (o, n) -> o.isEmpty() ? n : o)));
for (var cluster : loadBalancedClustersOf(newActive).entrySet()) {
- if ( ! activatingClusters.contains(cluster.getKey())) continue;
+ if ( ! activatingClusters.containsKey(cluster.getKey()))
+ continue;
Node clusterNode = cluster.getValue().first().get();
if ( ! shouldProvision(transaction.application(), clusterNode.type(), clusterNode.allocation().get().membership().cluster().type())) continue;
- activate(transaction, cluster.getKey(), cluster.getValue());
+ activate(transaction, cluster.getKey(), activatingClusters.get(cluster.getKey()), cluster.getValue());
}
// Deactivate any surplus load balancers, i.e. load balancers for clusters that have been removed
- var surplusLoadBalancers = surplusLoadBalancersOf(transaction.application(), activatingClusters);
+ var surplusLoadBalancers = surplusLoadBalancersOf(transaction.application(), activatingClusters.keySet());
deactivate(surplusLoadBalancers, transaction.nested());
}
@@ -185,10 +190,10 @@ public class LoadBalancerProvisioner {
return loadBalancerId;
}
- private void prepare(LoadBalancerId id, NodeList nodes, LoadBalancerSettings loadBalancerSettings, 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, loadBalancerSettings, cloudAccount, false);
+ Optional<LoadBalancerInstance> instance = provisionInstance(id, nodes, loadBalancer, null, cloudAccount);
LoadBalancer newLoadBalancer;
LoadBalancer.State fromState = null;
if (loadBalancer.isEmpty()) {
@@ -207,17 +212,14 @@ public class LoadBalancerProvisioner {
requireInstance(id, instance, cloudAccount);
}
- private void activate(ApplicationTransaction transaction, ClusterSpec.Id cluster, NodeList nodes) {
+ private void activate(ApplicationTransaction transaction, ClusterSpec.Id cluster, LoadBalancerSettings settings, NodeList nodes) {
Instant now = nodeRepository.clock().instant();
LoadBalancerId id = new LoadBalancerId(transaction.application(), cluster);
Optional<LoadBalancer> loadBalancer = db.readLoadBalancer(id);
if (loadBalancer.isEmpty()) throw new IllegalArgumentException("Could not activate load balancer that was never prepared: " + id);
if (loadBalancer.get().instance().isEmpty()) throw new IllegalArgumentException("Activating " + id + ", but prepare never provisioned a load balancer instance");
- Optional<LoadBalancerInstance> instance = provisionInstance(id, nodes, loadBalancer,
- loadBalancer.get().instance().get().settings().orElseThrow(),
- loadBalancer.get().instance().get().cloudAccount(),
- true);
+ Optional<LoadBalancerInstance> instance = provisionInstance(id, nodes, loadBalancer, settings, loadBalancer.get().instance().get().cloudAccount());
LoadBalancer.State state = instance.isPresent() ? LoadBalancer.State.active : loadBalancer.get().state();
LoadBalancer newLoadBalancer = loadBalancer.get().with(instance).with(state, now);
db.writeLoadBalancers(List.of(newLoadBalancer), loadBalancer.get().state(), transaction.nested());
@@ -228,8 +230,7 @@ public class LoadBalancerProvisioner {
private Optional<LoadBalancerInstance> provisionInstance(LoadBalancerId id, NodeList nodes,
Optional<LoadBalancer> currentLoadBalancer,
LoadBalancerSettings loadBalancerSettings,
- CloudAccount cloudAccount,
- boolean activate) {
+ CloudAccount cloudAccount) {
boolean shouldDeactivateRouting = deactivateRouting.with(FetchVector.Dimension.APPLICATION_ID,
id.application().serializedForm())
.value();
@@ -239,14 +240,17 @@ public class LoadBalancerProvisioner {
} else {
reals = realsOf(nodes);
}
- LoadBalancerSettings settingsToUse = activate ? loadBalancerSettings : null;
- if (isUpToDate(currentLoadBalancer, reals, settingsToUse))
- return currentLoadBalancer.get().instance().map(instance -> instance.withSettings(loadBalancerSettings));
+ if (isUpToDate(currentLoadBalancer, reals, loadBalancerSettings))
+ return currentLoadBalancer.get().instance();
log.log(Level.INFO, () -> "Provisioning instance for " + id + ", targeting: " + reals);
try {
- return Optional.of(service.create(new LoadBalancerSpec(id.application(), id.cluster(), reals, settingsToUse, cloudAccount),
- shouldDeactivateRouting || allowEmptyReals(currentLoadBalancer))
- .withSettings(loadBalancerSettings));
+ // Override settings at activation, otherwise keep existing ones.
+ LoadBalancerSettings settings = loadBalancerSettings != null ? loadBalancerSettings
+ : currentLoadBalancer.flatMap(LoadBalancer::instance)
+ .map(LoadBalancerInstance::settings)
+ .orElse(null);
+ return Optional.of(service.create(new LoadBalancerSpec(id.application(), id.cluster(), reals, settings, cloudAccount),
+ shouldDeactivateRouting || allowEmptyReals(currentLoadBalancer)));
} catch (Exception e) {
log.log(Level.WARNING, e, () -> "Could not (re)configure " + id + ", targeting: " +
reals + ". The operation will be retried on next deployment");
@@ -306,7 +310,7 @@ public class LoadBalancerProvisioner {
if (loadBalancer.isEmpty()) return false;
if (loadBalancer.get().instance().isEmpty()) return false;
return loadBalancer.get().instance().get().reals().equals(reals)
- && (loadBalancerSettings == null || loadBalancer.get().instance().get().settings().get().equals(loadBalancerSettings));
+ && (loadBalancerSettings == null || loadBalancer.get().instance().get().settings().equals(loadBalancerSettings));
}
/** Returns whether to allow given load balancer to have no reals */
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 307c9db38c6..1e0385d152a 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
@@ -45,7 +45,7 @@ public class LoadBalancerSerializerTest {
new Real(DomainName.of("real-2"),
"127.0.0.2",
4080)),
- Optional.of(new LoadBalancerSettings(List.of("123"))),
+ new LoadBalancerSettings(List.of("123")),
CloudAccount.from("012345678912"))),
LoadBalancer.State.active,
now);
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 a19f986a177..c7a2c94783b 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
@@ -320,14 +320,14 @@ 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(LoadBalancerSettings.empty, loadBalancers.first().get().instance().get().settings().get());
+ assertEquals(LoadBalancerSettings.empty, loadBalancers.first().get().instance().get().settings());
// Next deployment contains new settings
LoadBalancerSettings settings = new LoadBalancerSettings(List.of("alice", "bob"));
tester.activate(app1, prepare(app1, capacity, clusterRequest(ClusterSpec.Type.container, ClusterSpec.Id.from("c1"), Optional.empty(), settings)));
loadBalancers = tester.nodeRepository().loadBalancers().list();
assertEquals(1, loadBalancers.size());
- assertEquals(settings, loadBalancers.first().get().instance().get().settings().get());
+ assertEquals(settings, loadBalancers.first().get().instance().get().settings());
}