aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@yahooinc.com>2023-10-26 16:20:34 +0200
committerHåkon Hallingstad <hakon@yahooinc.com>2023-10-26 16:20:34 +0200
commit9f18ca064bf95f0706bb83d9c22fb6fa2993173c (patch)
treea4355ba0cad6ca5544b97ed6676738c4d4bd28e7
parent7dcf21422fc3e3616524342d23bf8cf197fdb6ed (diff)
Set tenant, instance ID, and Vespa version dimensions of make-exclusive
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java10
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java2
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java7
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/Flags.java9
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java23
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java6
8 files changed, 38 insertions, 28 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
index 96153f8075e..7e54c5164f7 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
@@ -312,7 +312,7 @@ public class ModelContextImpl implements ModelContext {
private static <V> V flagValue(FlagSource source, ApplicationId appId, Version vespaVersion, UnboundFlag<? extends V, ?, ?> flag) {
return flag.bindTo(source)
.with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm())
- .with(FetchVector.Dimension.APPLICATION_ID, appId.toSerializedFormWithoutInstance())
+ .with(FetchVector.Dimension.APPLICATION, appId.toSerializedFormWithoutInstance())
.with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString())
.with(FetchVector.Dimension.TENANT_ID, appId.tenant().value())
.boxedValue();
@@ -325,7 +325,7 @@ public class ModelContextImpl implements ModelContext {
UnboundFlag<? extends V, ?, ?> flag) {
return flag.bindTo(source)
.with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm())
- .with(FetchVector.Dimension.APPLICATION_ID, appId.toSerializedFormWithoutInstance())
+ .with(FetchVector.Dimension.APPLICATION, appId.toSerializedFormWithoutInstance())
.with(FetchVector.Dimension.CLUSTER_TYPE, clusterType.name())
.with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString())
.boxedValue();
@@ -338,7 +338,7 @@ public class ModelContextImpl implements ModelContext {
UnboundFlag<? extends V, ?, ?> flag) {
return flag.bindTo(source)
.with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm())
- .with(FetchVector.Dimension.APPLICATION_ID, appId.toSerializedFormWithoutInstance())
+ .with(FetchVector.Dimension.APPLICATION, appId.toSerializedFormWithoutInstance())
.with(FetchVector.Dimension.CLUSTER_ID, clusterId.value())
.with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString())
.boxedValue();
@@ -416,7 +416,7 @@ public class ModelContextImpl implements ModelContext {
this.secretStore = secretStore;
this.jvmGCOptionsFlag = PermanentFlags.JVM_GC_OPTIONS.bindTo(flagSource)
.with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm())
- .with(FetchVector.Dimension.APPLICATION_ID, applicationId.toSerializedFormWithoutInstance());
+ .with(FetchVector.Dimension.APPLICATION, applicationId.toSerializedFormWithoutInstance());
this.allowDisableMtls = flagValue(flagSource, applicationId, PermanentFlags.ALLOW_DISABLE_MTLS);
this.operatorCertificates = operatorCertificates;
this.tlsCiphersOverride = flagValue(flagSource, applicationId, PermanentFlags.TLS_CIPHERS_OVERRIDE);
@@ -528,7 +528,7 @@ public class ModelContextImpl implements ModelContext {
private static <V> V flagValue(FlagSource source, ApplicationId appId, UnboundFlag<? extends V, ?, ?> flag) {
return flag.bindTo(source)
.with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm())
- .with(FetchVector.Dimension.APPLICATION_ID, appId.toSerializedFormWithoutInstance())
+ .with(FetchVector.Dimension.APPLICATION, appId.toSerializedFormWithoutInstance())
.boxedValue();
}
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java
index b55157b90be..02bb669417c 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java
@@ -5,7 +5,6 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.fasterxml.jackson.databind.node.TextNode;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
@@ -192,7 +191,7 @@ public class SystemFlagsDataArchive {
flagData.rules().forEach(rule -> rule.conditions().forEach(condition -> {
int force_switch_expression_dummy = switch (condition.type()) {
case RELATIONAL -> switch (condition.dimension()) {
- case APPLICATION_ID, CLOUD, CLOUD_ACCOUNT, CLUSTER_ID, CLUSTER_TYPE, CONSOLE_USER_EMAIL,
+ case APPLICATION, CLOUD, CLOUD_ACCOUNT, CLUSTER_ID, CLUSTER_TYPE, CONSOLE_USER_EMAIL,
ENVIRONMENT, HOSTNAME, INSTANCE_ID, NODE_TYPE, SYSTEM, TENANT_ID, ZONE_ID ->
throw new FlagValidationException(condition.type().toWire() + " " +
DimensionHelper.toWire(condition.dimension()) +
@@ -207,7 +206,7 @@ public class SystemFlagsDataArchive {
};
case WHITELIST, BLACKLIST -> switch (condition.dimension()) {
- case APPLICATION_ID -> validateConditionValues(condition, SystemFlagsDataArchive::validateTenantApplication);
+ case APPLICATION -> validateConditionValues(condition, SystemFlagsDataArchive::validateTenantApplication);
case CONSOLE_USER_EMAIL -> validateConditionValues(condition, email -> {
if (!email.contains("@"))
throw new FlagValidationException("Invalid email address: " + email);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java
index f11d67762ad..5dec1449507 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java
@@ -127,7 +127,7 @@ public class RoutingController {
/** Returns the endpoint config to use for given instance */
public EndpointConfig endpointConfig(ApplicationId instance) {
String flagValue = endpointConfig.with(FetchVector.Dimension.TENANT_ID, instance.tenant().value())
- .with(FetchVector.Dimension.APPLICATION_ID, TenantAndApplicationId.from(instance).serialized())
+ .with(FetchVector.Dimension.APPLICATION, TenantAndApplicationId.from(instance).serialized())
.with(FetchVector.Dimension.INSTANCE_ID, instance.serializedForm())
.value();
return switch (flagValue) {
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java b/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java
index 4c4bada7552..b5a944430f3 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java
@@ -22,8 +22,11 @@ public class FetchVector {
* Note: If this enum is changed, you must also change {@link DimensionHelper}.
*/
public enum Dimension {
- /** Application id from ApplicationId::toSerializedForm(TenantName, ApplicationName) on the form tenant:applicationName. */
- APPLICATION_ID,
+ /**
+ * Application from ApplicationId::toSerializedFormWithoutInstance() of the form tenant:applicationName.
+ * <p><em>WARNING: NOT ApplicationId</em> - see {@link #INSTANCE_ID}.</p>
+ */
+ APPLICATION,
/**
* Cloud from com.yahoo.config.provision.CloudName::value, e.g. yahoo, aws, gcp.
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
index fb667d60ab0..0f1815e44b6 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
@@ -13,7 +13,7 @@ import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Predicate;
-import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID;
+import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION;
import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLOUD_ACCOUNT;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_ID;
@@ -345,7 +345,8 @@ public class Flags {
"make-exclusive", false,
List.of("hakonhall"), "2023-10-20", "2023-12-20",
"Allow an exclusive allocation to a non-exclusive host, but if so, make the host exclusive.",
- "Takes immediate effect on any following preparation of clusters");
+ "Takes immediate effect on any following preparation of clusters",
+ INSTANCE_ID, TENANT_ID, VESPA_VERSION);
public static final UnboundBooleanFlag WRITE_CONFIG_SERVER_SESSION_DATA_AS_ONE_BLOB = defineFeatureFlag(
"write-config-server-session-data-as-blob", false,
@@ -414,14 +415,14 @@ public class Flags {
List.of("bjorncs", "baldersheim"), "2023-10-01", "2024-01-01",
"Adjust search handler threadpool size",
"Takes effect at redeployment",
- APPLICATION_ID);
+ APPLICATION);
public static final UnboundStringFlag ENDPOINT_CONFIG = defineStringFlag(
"endpoint-config", "legacy",
List.of("mpolden", "tokle"), "2023-10-06", "2024-02-01",
"Set the endpoint config to use for an application. Must be 'legacy', 'combined' or 'generated'. See EndpointConfig for further details",
"Takes effect on next deployment through controller",
- TENANT_ID, APPLICATION_ID, INSTANCE_ID);
+ TENANT_ID, APPLICATION, INSTANCE_ID);
public static final UnboundBooleanFlag CLOUD_TRIAL_NOTIFICATIONS = defineFeatureFlag(
"cloud-trial-notifications", false,
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java b/flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java
index 4323af5a4fd..7298f090be2 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java
@@ -4,8 +4,6 @@ package com.yahoo.vespa.flags.json;
import com.yahoo.vespa.flags.FetchVector;
import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -19,7 +17,7 @@ public class DimensionHelper {
static {
// WARNING: If you ever change the serialized form of a dimension, ensure the new serialized
// flag data are pushed out everywhere before removing support for old format, see VESPA-27760.
- serializedDimensions.put(FetchVector.Dimension.APPLICATION_ID, "application");
+ serializedDimensions.put(FetchVector.Dimension.APPLICATION, "application");
serializedDimensions.put(FetchVector.Dimension.CLOUD, "cloud");
serializedDimensions.put(FetchVector.Dimension.CLOUD_ACCOUNT, "cloud-account");
serializedDimensions.put(FetchVector.Dimension.CLUSTER_ID, "cluster-id");
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java
index be6c420c63b..3c42972ee0b 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java
@@ -14,6 +14,7 @@ import com.yahoo.jdisc.Metric;
import com.yahoo.lang.MutableInteger;
import com.yahoo.transaction.Mutex;
import com.yahoo.vespa.flags.BooleanFlag;
+import com.yahoo.vespa.flags.FetchVector;
import com.yahoo.vespa.flags.FlagSource;
import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.flags.ListFlag;
@@ -191,7 +192,11 @@ public class HostCapacityMaintainer extends NodeRepositoryMaintainer {
*/
private List<Node> provisionUntilNoDeficit(NodeList nodeList) {
List<ClusterCapacity> preprovisionCapacity = preprovisionCapacityFlag.value();
- boolean makeExclusive = makeExclusiveFlag.value();
+ ApplicationId application = ApplicationId.defaultId();
+ boolean makeExclusive = makeExclusiveFlag.with(FetchVector.Dimension.TENANT_ID, application.tenant().value())
+ .with(FetchVector.Dimension.INSTANCE_ID, application.serializedForm())
+ .with(FetchVector.Dimension.VESPA_VERSION, Vtag.currentVersion.toFullString())
+ .value();
// Worst-case each ClusterCapacity in preprovisionCapacity will require an allocation.
int maxProvisions = preprovisionCapacity.size();
@@ -199,7 +204,7 @@ public class HostCapacityMaintainer extends NodeRepositoryMaintainer {
var nodesPlusProvisioned = new ArrayList<>(nodeList.asList());
for (int numProvisions = 0;; ++numProvisions) {
var nodesPlusProvisionedPlusAllocated = new ArrayList<>(nodesPlusProvisioned);
- Optional<ClusterCapacity> deficit = allocatePreprovisionCapacity(preprovisionCapacity, nodesPlusProvisionedPlusAllocated, makeExclusive);
+ Optional<ClusterCapacity> deficit = allocatePreprovisionCapacity(application, preprovisionCapacity, nodesPlusProvisionedPlusAllocated, makeExclusive);
if (deficit.isEmpty()) {
return nodesPlusProvisionedPlusAllocated;
}
@@ -258,13 +263,14 @@ public class HostCapacityMaintainer extends NodeRepositoryMaintainer {
* they are added to {@code mutableNodes}
* @return the part of a cluster capacity it was unable to allocate, if any
*/
- private Optional<ClusterCapacity> allocatePreprovisionCapacity(List<ClusterCapacity> preprovisionCapacity,
+ private Optional<ClusterCapacity> allocatePreprovisionCapacity(ApplicationId application,
+ List<ClusterCapacity> preprovisionCapacity,
ArrayList<Node> mutableNodes,
boolean makeExclusive) {
for (int clusterIndex = 0; clusterIndex < preprovisionCapacity.size(); ++clusterIndex) {
ClusterCapacity clusterCapacity = preprovisionCapacity.get(clusterIndex);
LockedNodeList allNodes = new LockedNodeList(mutableNodes, () -> {});
- List<Node> candidates = findCandidates(clusterCapacity, clusterIndex, allNodes, makeExclusive);
+ List<Node> candidates = findCandidates(application, clusterCapacity, clusterIndex, allNodes, makeExclusive);
int deficit = Math.max(0, clusterCapacity.count() - candidates.size());
if (deficit > 0) {
return Optional.of(clusterCapacity.withCount(deficit));
@@ -277,25 +283,24 @@ public class HostCapacityMaintainer extends NodeRepositoryMaintainer {
return Optional.empty();
}
- private List<Node> findCandidates(ClusterCapacity clusterCapacity, int clusterIndex, LockedNodeList allNodes, boolean makeExclusive) {
+ private List<Node> findCandidates(ApplicationId application, ClusterCapacity clusterCapacity, int clusterIndex, LockedNodeList allNodes, boolean makeExclusive) {
NodeResources nodeResources = toNodeResources(clusterCapacity);
// We'll allocate each ClusterCapacity as a unique cluster in a dummy application
- ApplicationId applicationId = ApplicationId.defaultId();
ClusterSpec cluster = asSpec(Optional.ofNullable(clusterCapacity.clusterType()), clusterIndex);
NodeSpec nodeSpec = NodeSpec.from(clusterCapacity.count(), 1, nodeResources, false, true,
nodeRepository().zone().cloud().account(), Duration.ZERO);
var allocationContext = IP.Allocation.Context.from(nodeRepository().zone().cloud().name(),
nodeSpec.cloudAccount().isExclave(nodeRepository().zone()),
nodeRepository().nameResolver());
- NodePrioritizer prioritizer = new NodePrioritizer(allNodes, applicationId, cluster, nodeSpec,
+ NodePrioritizer prioritizer = new NodePrioritizer(allNodes, application, cluster, nodeSpec,
true, false, allocationContext, nodeRepository().nodes(),
nodeRepository().resourcesCalculator(), nodeRepository().spareCount(),
nodeRepository().exclusiveAllocation(cluster), makeExclusive);
List<NodeCandidate> nodeCandidates = prioritizer.collect()
.stream()
.filter(node -> node.violatesExclusivity(cluster,
- applicationId,
+ application,
nodeRepository().exclusiveAllocation(cluster),
false,
nodeRepository().zone().cloud().allowHostSharing(),
@@ -308,7 +313,7 @@ public class HostCapacityMaintainer extends NodeRepositoryMaintainer {
.stream()
.limit(clusterCapacity.count())
.map(candidate -> candidate.toNode()
- .allocate(applicationId,
+ .allocate(application,
ClusterMembership.from(cluster, index.next()),
nodeResources,
nodeRepository().clock().instant()))
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
index 270fda8314e..83afe92d025 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
@@ -14,6 +14,7 @@ import com.yahoo.text.internal.SnippetGenerator;
import com.yahoo.transaction.Mutex;
import com.yahoo.vespa.applicationmodel.InfrastructureApplication;
import com.yahoo.vespa.flags.BooleanFlag;
+import com.yahoo.vespa.flags.FetchVector;
import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.hosted.provision.LockedNodeList;
import com.yahoo.vespa.hosted.provision.Node;
@@ -76,7 +77,10 @@ public class Preparer {
loadBalancerProvisioner.ifPresent(provisioner -> provisioner.prepare(application, cluster, requested));
- boolean makeExclusive = makeExclusiveFlag.value();
+ boolean makeExclusive = makeExclusiveFlag.with(FetchVector.Dimension.TENANT_ID, application.tenant().value())
+ .with(FetchVector.Dimension.INSTANCE_ID, application.serializedForm())
+ .with(FetchVector.Dimension.VESPA_VERSION, cluster.vespaVersion().toFullString())
+ .value();
// Try preparing in memory without global unallocated lock. Most of the time there should be no changes,
// and we can return nodes previously allocated.
LockedNodeList allNodes = nodeRepository.nodes().list(PROBE_LOCK);