aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java8
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java18
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java4
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java16
-rw-r--r--controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java7
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/certificate/EndpointCertificatesHandler.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializer.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java14
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java6
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java2
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/Flags.java78
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java72
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java52
-rw-r--r--flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java6
-rw-r--r--flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java4
-rw-r--r--flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java29
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java29
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java1
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java1
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java11
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java2
-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/NodeResourceLimits.java2
-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.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java4
37 files changed, 237 insertions, 183 deletions
diff --git a/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java b/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java
index 3c4c99e0337..4f8d42e895b 100644
--- a/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java
+++ b/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java
@@ -34,7 +34,7 @@ public class FlagsHandlerTest {
"id1", false, List.of("joe"), "2010-01-01", "2030-01-01", "desc1", "mod1");
private static final UnboundBooleanFlag FLAG2 = Flags.defineFeatureFlag(
"id2", true, List.of("joe"), "2010-01-01", "2030-01-01", "desc2", "mod2",
- FetchVector.Dimension.HOSTNAME, FetchVector.Dimension.APPLICATION_ID);
+ FetchVector.Dimension.HOSTNAME, FetchVector.Dimension.INSTANCE_ID);
private final FlagsDb flagsDb = new FlagsDbImpl(new MockCurator());
private final FlagsHandler handler = new FlagsHandler(FlagsHandler.testContext(), flagsDb);
@@ -111,7 +111,7 @@ public class FlagsHandlerTest {
},
{
"type": "blacklist",
- "dimension": "application",
+ "dimension": "instance",
"values": [ "app1", "app2" ]
}
],
@@ -127,7 +127,7 @@ public class FlagsHandlerTest {
// GET on id2 should now return what was put
verifySuccessfulRequest(Method.GET, "/data/" + FLAG2.id(), "",
- "{\"id\":\"id2\",\"rules\":[{\"conditions\":[{\"type\":\"whitelist\",\"dimension\":\"hostname\",\"values\":[\"host1\",\"host2\"]},{\"type\":\"blacklist\",\"dimension\":\"application\",\"values\":[\"app1\",\"app2\"]}],\"value\":true}],\"attributes\":{\"zone\":\"zone1\"}}");
+ "{\"id\":\"id2\",\"rules\":[{\"conditions\":[{\"type\":\"whitelist\",\"dimension\":\"hostname\",\"values\":[\"host1\",\"host2\"]},{\"type\":\"blacklist\",\"dimension\":\"instance\",\"values\":[\"app1\",\"app2\"]}],\"value\":true}],\"attributes\":{\"zone\":\"zone1\"}}");
// The list of flag data should return id1 and id2
verifySuccessfulRequest(Method.GET, "/data",
@@ -153,7 +153,7 @@ public class FlagsHandlerTest {
// Get all recursivelly displays all flag data
verifySuccessfulRequest(Method.GET, "/data?recursive=true", "",
- "{\"flags\":[{\"id\":\"id1\",\"rules\":[{\"value\":false}]},{\"id\":\"id2\",\"rules\":[{\"conditions\":[{\"type\":\"whitelist\",\"dimension\":\"hostname\",\"values\":[\"host1\",\"host2\"]},{\"type\":\"blacklist\",\"dimension\":\"application\",\"values\":[\"app1\",\"app2\"]}],\"value\":true}],\"attributes\":{\"zone\":\"zone1\"}}]}");
+ "{\"flags\":[{\"id\":\"id1\",\"rules\":[{\"value\":false}]},{\"id\":\"id2\",\"rules\":[{\"conditions\":[{\"type\":\"whitelist\",\"dimension\":\"hostname\",\"values\":[\"host1\",\"host2\"]},{\"type\":\"blacklist\",\"dimension\":\"instance\",\"values\":[\"app1\",\"app2\"]}],\"value\":true}],\"attributes\":{\"zone\":\"zone1\"}}]}");
// Deleting both flags
verifySuccessfulRequest(Method.DELETE, "/data/" + FLAG1.id(), "", "");
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
index 296e31ce801..693252da43a 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
@@ -50,7 +50,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import static com.yahoo.vespa.curator.Curator.CompletionWaiter;
-import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID;
+import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID;
import static java.util.stream.Collectors.toSet;
/**
@@ -418,7 +418,7 @@ public class TenantApplications implements RequestHandler, HostValidator {
if (vespaVersion.isEmpty()) return true;
Version wantedVersion = applicationMapper.getForVersion(application, Optional.empty(), clock.instant())
.getModel().wantedNodeVersion();
- return VersionCompatibility.fromVersionList(incompatibleVersions.with(APPLICATION_ID, application.serializedForm()).value())
+ return VersionCompatibility.fromVersionList(incompatibleVersions.with(INSTANCE_ID, application.serializedForm()).value())
.accept(vespaVersion.get(), wantedVersion);
}
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 bab2e666d0a..142f98e13e3 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
@@ -296,7 +296,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.APPLICATION_ID, appId.serializedForm())
+ .with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm())
.with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString())
.with(FetchVector.Dimension.TENANT_ID, appId.tenant().value())
.boxedValue();
@@ -308,7 +308,7 @@ public class ModelContextImpl implements ModelContext {
ClusterSpec.Type clusterType,
UnboundFlag<? extends V, ?, ?> flag) {
return flag.bindTo(source)
- .with(FetchVector.Dimension.APPLICATION_ID, appId.serializedForm())
+ .with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm())
.with(FetchVector.Dimension.CLUSTER_TYPE, clusterType.name())
.with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString())
.boxedValue();
@@ -320,7 +320,7 @@ public class ModelContextImpl implements ModelContext {
ClusterSpec.Id clusterId,
UnboundFlag<? extends V, ?, ?> flag) {
return flag.bindTo(source)
- .with(FetchVector.Dimension.APPLICATION_ID, appId.serializedForm())
+ .with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm())
.with(FetchVector.Dimension.CLUSTER_ID, clusterId.value())
.with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString())
.boxedValue();
@@ -397,21 +397,21 @@ public class ModelContextImpl implements ModelContext {
this.tenantSecretStores = tenantSecretStores;
this.secretStore = secretStore;
this.jvmGCOptionsFlag = PermanentFlags.JVM_GC_OPTIONS.bindTo(flagSource)
- .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm());
+ .with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm());
this.allowDisableMtls = PermanentFlags.ALLOW_DISABLE_MTLS.bindTo(flagSource)
- .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value();
+ .with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm()).value();
this.operatorCertificates = operatorCertificates;
this.tlsCiphersOverride = PermanentFlags.TLS_CIPHERS_OVERRIDE.bindTo(flagSource)
- .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value();
+ .with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm()).value();
this.zoneDnsSuffixes = configserverConfig.zoneDnsSuffixes();
this.environmentVariables = PermanentFlags.ENVIRONMENT_VARIABLES.bindTo(flagSource)
- .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value();
+ .with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm()).value();
this.cloudAccount = cloudAccount;
this.allowUserFilters = PermanentFlags.ALLOW_USER_FILTERS.bindTo(flagSource)
- .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value();
+ .with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm()).value();
this.endpointConnectionTtl = Duration.ofSeconds(
PermanentFlags.ENDPOINT_CONNECTION_TTL.bindTo(flagSource)
- .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value());
+ .with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm()).value());
this.dataplaneTokens = dataplaneTokens;
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
index 44a656a1579..3b57945b21d 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
@@ -82,7 +82,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import static com.yahoo.vespa.curator.Curator.CompletionWaiter;
-import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID;
+import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID;
import static java.nio.file.Files.readAttributes;
/**
@@ -728,7 +728,7 @@ public class SessionRepository {
} catch (IllegalArgumentException e) {
if (configserverConfig.hostedVespa()) {
UnboundStringFlag flag = PermanentFlags.APPLICATION_FILES_WITH_UNKNOWN_EXTENSION;
- String value = flag.bindTo(flagSource).with(APPLICATION_ID, applicationId.serializedForm()).value();
+ String value = flag.bindTo(flagSource).with(INSTANCE_ID, applicationId.serializedForm()).value();
switch (value) {
case "FAIL" -> throw new InvalidApplicationException(e);
case "LOG" -> deployLogger.ifPresent(logger -> logger.logApplicationPackage(Level.WARNING, e.getMessage()));
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 fa8a0ddcba1..856af9f4132 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,6 +5,7 @@ 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.CloudAccount;
@@ -190,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 INSTANCE_ID, CLOUD, CLOUD_ACCOUNT, CLUSTER_ID, CLUSTER_TYPE, CONSOLE_USER_EMAIL,
ENVIRONMENT, HOSTNAME, NODE_TYPE, SYSTEM, TENANT_ID, ZONE_ID ->
throw new FlagValidationException(condition.type().toWire() + " " +
DimensionHelper.toWire(condition.dimension()) +
@@ -205,7 +206,7 @@ public class SystemFlagsDataArchive {
};
case WHITELIST, BLACKLIST -> switch (condition.dimension()) {
- case APPLICATION_ID -> validateConditionValues(condition, ApplicationId::fromSerializedForm);
+ case INSTANCE_ID -> validateConditionValues(condition, ApplicationId::fromSerializedForm);
case CONSOLE_USER_EMAIL -> validateConditionValues(condition, email -> {
if (!email.contains("@"))
throw new FlagValidationException("Invalid email address: " + email);
@@ -255,6 +256,17 @@ public class SystemFlagsDataArchive {
final JsonNode root;
try {
root = mapper.readTree(fileContent);
+ // TODO (mortent): Remove this after completing migration of APPLICATION_ID dimension
+ // replace "application" with "instance" for all dimension fields
+ List<JsonNode> dimensionParents = root.findParents("dimension");
+ for (JsonNode parentNode : dimensionParents) {
+ JsonNode dimension = parentNode.get("dimension");
+ if (dimension.isTextual() && "application".equals(dimension.textValue())) {
+ ObjectNode parent = (ObjectNode) parentNode;
+ parent.remove("dimension");
+ parent.put("dimension", "instance");
+ }
+ }
} catch (JsonProcessingException e) {
throw new FlagValidationException("Invalid JSON: " + e.getMessage());
}
diff --git a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java
index 759f21579d4..373f8ba9de2 100644
--- a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java
+++ b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java
@@ -245,7 +245,7 @@ public class SystemFlagsDataArchiveTest {
"conditions": [
{
"type": "whitelist",
- "dimension": "application",
+ "dimension": "instance",
"values": [ "f:o:o" ]
}
],
@@ -287,7 +287,7 @@ public class SystemFlagsDataArchiveTest {
{
"comment": "bar",
"type": "whitelist",
- "dimension": "application",
+ "dimension": "instance",
"values": [ "f:o:o" ]
}
],
@@ -308,6 +308,7 @@ public class SystemFlagsDataArchiveTest {
@Test
void normalize_json_succeed_on_valid_values() {
addFile(Condition.Type.WHITELIST, "application", "a:b:c");
+ addFile(Condition.Type.WHITELIST, "instance", "a:b:c");
addFile(Condition.Type.WHITELIST, "cloud", "yahoo");
addFile(Condition.Type.WHITELIST, "cloud", "aws");
addFile(Condition.Type.WHITELIST, "cloud", "gcp");
@@ -361,7 +362,7 @@ public class SystemFlagsDataArchiveTest {
@Test
void normalize_json_fail_on_invalid_values() {
- failAddFile(Condition.Type.WHITELIST, "application", "a.b.c", "In file flags/temporary/foo/default.json: Invalid application 'a.b.c' in whitelist condition: Application ids must be on the form tenant:application:instance, but was a.b.c");
+ failAddFile(Condition.Type.WHITELIST, "application", "a.b.c", "In file flags/temporary/foo/default.json: Invalid instance 'a.b.c' in whitelist condition: Application ids must be on the form tenant:application:instance, but was a.b.c");
failAddFile(Condition.Type.WHITELIST, "cloud", "foo", "In file flags/temporary/foo/default.json: Unknown cloud: foo");
// cluster-id: any String is valid
failAddFile(Condition.Type.WHITELIST, "cluster-type", "foo", "In file flags/temporary/foo/default.json: Invalid cluster-type 'foo' in whitelist condition: Illegal cluster type 'foo'");
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
index 2f7b9f92316..90653d85aed 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
@@ -113,7 +113,7 @@ import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID;
+import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID;
import static com.yahoo.vespa.hosted.controller.api.integration.configserver.Node.State.active;
import static com.yahoo.vespa.hosted.controller.api.integration.configserver.Node.State.reserved;
import static com.yahoo.vespa.hosted.controller.versions.VespaVersion.Confidence.broken;
@@ -676,7 +676,7 @@ public class ApplicationController {
Optional<DockerImage> dockerImageRepo = Optional.ofNullable(
dockerImageRepoFlag
.with(FetchVector.Dimension.ZONE_ID, zone.value())
- .with(APPLICATION_ID, application.serializedForm())
+ .with(INSTANCE_ID, application.serializedForm())
.value())
.filter(s -> !s.isBlank())
.map(DockerImage::fromString);
@@ -962,7 +962,7 @@ public class ApplicationController {
}
public VersionCompatibility versionCompatibility(ApplicationId id) {
- return VersionCompatibility.fromVersionList(incompatibleVersions.with(APPLICATION_ID, id.serializedForm()).value());
+ return VersionCompatibility.fromVersionList(incompatibleVersions.with(INSTANCE_ID, id.serializedForm()).value());
}
/**
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 b50915253fb..3917fb23971 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
@@ -521,7 +521,7 @@ public class RoutingController {
}
public boolean generatedEndpointsEnabled(ApplicationId instance) {
- return randomizedEndpoints.with(FetchVector.Dimension.APPLICATION_ID, instance.serializedForm()).value();
+ return randomizedEndpoints.with(FetchVector.Dimension.INSTANCE_ID, instance.serializedForm()).value();
}
private static void requireGeneratedEndpoints(GeneratedEndpointList generatedEndpoints, boolean declared) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java
index b16d09f974f..e01da00a27e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java
@@ -234,8 +234,8 @@ public class EndpointCertificates {
.forEach(requiredNames::addAll);
log.log(Level.INFO, String.format("Requesting new endpoint certificate from Cameo for application %s", deployment.applicationId().serializedForm()));
- String algo = this.endpointCertificateAlgo.with(FetchVector.Dimension.APPLICATION_ID, deployment.applicationId().serializedForm()).value();
- boolean useAlternativeProvider = useAlternateCertProvider.with(FetchVector.Dimension.APPLICATION_ID, deployment.applicationId().serializedForm()).value();
+ String algo = this.endpointCertificateAlgo.with(FetchVector.Dimension.INSTANCE_ID, deployment.applicationId().serializedForm()).value();
+ boolean useAlternativeProvider = useAlternateCertProvider.with(FetchVector.Dimension.INSTANCE_ID, deployment.applicationId().serializedForm()).value();
String keyPrefix = deployment.applicationId().toFullString();
var t0 = Instant.now();
EndpointCertificate endpointCertificate = certificateProvider.requestCaSignedCertificate(keyPrefix, List.copyOf(requiredNames), currentCert, algo, useAlternativeProvider);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
index 0773c95e1f2..1c417e750e3 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
@@ -155,7 +155,7 @@ public class JobController {
}
public boolean isDisabled(JobId id) {
- return disabledZones.with(Dimension.APPLICATION_ID, id.application().serializedForm()).value().contains(id.type().zone().value());
+ return disabledZones.with(Dimension.INSTANCE_ID, id.application().serializedForm()).value().contains(id.type().zone().value());
}
/** Returns all entries currently logged for the given run. */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
index e130e73cef1..c90fcb81c71 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
@@ -283,7 +283,7 @@ public class EndpointCertificateMaintainer extends ControllerMaintainer {
assignedCertificates.stream()
.filter(c -> c.instance().isPresent())
.filter(c -> c.certificate().randomizedId().isEmpty())
- .filter(c -> assignRandomizedId.with(FetchVector.Dimension.APPLICATION_ID, c.application().instance(c.instance().get()).serializedForm()).value())
+ .filter(c -> assignRandomizedId.with(FetchVector.Dimension.INSTANCE_ID, c.application().instance(c.instance().get()).serializedForm()).value())
.filter(c -> controller().applications().getApplication(c.application()).isPresent()) // In case application has been deleted, but certificate is pending deletion
.limit(assignRandomizedIdRate.value())
.forEach(c -> assignRandomizedId(c.application(), c.instance().get()));
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/certificate/EndpointCertificatesHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/certificate/EndpointCertificatesHandler.java
index 2835c36c320..912bd051a31 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/certificate/EndpointCertificatesHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/certificate/EndpointCertificatesHandler.java
@@ -80,8 +80,8 @@ public class EndpointCertificatesHandler extends ThreadedHttpRequestHandler {
AssignedCertificate assignedCertificate = curator.readAssignedCertificate(applicationId)
.orElseThrow(() -> new RestApiException.NotFound("No certificate found for application " + applicationId.serializedForm()));
- String algo = this.endpointCertificateAlgo.with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value();
- boolean useAlternativeProvider = useAlternateCertProvider.with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value();
+ String algo = this.endpointCertificateAlgo.with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm()).value();
+ boolean useAlternativeProvider = useAlternateCertProvider.with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm()).value();
String keyPrefix = applicationId.toFullString();
EndpointCertificate cert = endpointCertificateProvider.requestCaSignedCertificate(
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializer.java
index 54a24360b5a..c3acf01a53e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializer.java
@@ -20,7 +20,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
@@ -72,7 +71,7 @@ public class UserFlagsSerializer {
// For the other dimensions, filter the values down to an allowed subset
switch (condition.dimension()) {
case TENANT_ID: return valueSubset(condition, tenant -> isOperator || authorizedForTenantNames.contains(TenantName.from(tenant)));
- case APPLICATION_ID: return valueSubset(condition, appId -> isOperator || authorizedForTenantNames.stream().anyMatch(tenant -> appId.startsWith(tenant.value() + ":")));
+ case INSTANCE_ID: return valueSubset(condition, appId -> isOperator || authorizedForTenantNames.stream().anyMatch(tenant -> appId.startsWith(tenant.value() + ":")));
default: throw new IllegalArgumentException("Dimension " + condition.dimension() + " is not supported for user flags");
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java
index ed7d02d0047..eb3f9daef53 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java
@@ -26,7 +26,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID;
+import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CONSOLE_USER_EMAIL;
import static com.yahoo.vespa.flags.FetchVector.Dimension.TENANT_ID;
@@ -42,7 +42,7 @@ public class UserFlagsSerializerTest {
try (Flags.Replacer ignored = Flags.clearFlagsForTesting()) {
Flags.defineStringFlag("string-id", "default value", List.of("owner"), "1970-01-01", "2100-01-01", "desc", "mod", CONSOLE_USER_EMAIL);
- Flags.defineIntFlag("int-id", 123, List.of("owner"), "1970-01-01", "2100-01-01", "desc", "mod", CONSOLE_USER_EMAIL, TENANT_ID, APPLICATION_ID);
+ Flags.defineIntFlag("int-id", 123, List.of("owner"), "1970-01-01", "2100-01-01", "desc", "mod", CONSOLE_USER_EMAIL, TENANT_ID, INSTANCE_ID);
Flags.defineDoubleFlag("double-id", 3.14d, List.of("owner"), "1970-01-01", "2100-01-01", "desc", "mod");
Flags.defineListFlag("list-id", List.of("a"), String.class, List.of("owner"), "1970-01-01", "2100-01-01", "desc", "mod", CONSOLE_USER_EMAIL);
Flags.defineJacksonFlag("jackson-id", new ExampleJacksonClass(123, "abc"), ExampleJacksonClass.class,
@@ -52,9 +52,9 @@ public class UserFlagsSerializerTest {
flagData("string-id", rule("\"value1\"", condition(CONSOLE_USER_EMAIL, Condition.Type.WHITELIST, email1))),
flagData("int-id", rule("456")),
flagData("list-id",
- rule("[\"value1\"]", condition(CONSOLE_USER_EMAIL, Condition.Type.WHITELIST, email1), condition(APPLICATION_ID, Condition.Type.BLACKLIST, "tenant1:video:default", "tenant1:video:default", "tenant2:music:default")),
+ rule("[\"value1\"]", condition(CONSOLE_USER_EMAIL, Condition.Type.WHITELIST, email1), condition(INSTANCE_ID, Condition.Type.BLACKLIST, "tenant1:video:default", "tenant1:video:default", "tenant2:music:default")),
rule("[\"value2\"]", condition(CONSOLE_USER_EMAIL, Condition.Type.WHITELIST, email2)),
- rule("[\"value1\",\"value3\"]", condition(APPLICATION_ID, Condition.Type.BLACKLIST, "tenant1:video:default", "tenant1:video:default", "tenant2:music:default"))),
+ rule("[\"value1\",\"value3\"]", condition(INSTANCE_ID, Condition.Type.BLACKLIST, "tenant1:video:default", "tenant1:video:default", "tenant2:music:default"))),
flagData("jackson-id", rule("{\"integer\":456,\"string\":\"xyz\"}", condition(CONSOLE_USER_EMAIL, Condition.Type.WHITELIST, email1), condition(TENANT_ID, Condition.Type.WHITELIST, "tenant1", "tenant3")))
).collect(Collectors.toMap(FlagData::id, fd -> fd));
@@ -63,7 +63,7 @@ public class UserFlagsSerializerTest {
"{\"id\":\"int-id\",\"rules\":[{\"value\":456}]}," + // Default from DB
"{\"id\":\"jackson-id\",\"rules\":[{\"conditions\":[{\"type\":\"whitelist\",\"dimension\":\"tenant\"}],\"value\":{\"integer\":456,\"string\":\"xyz\"}},{\"value\":{\"integer\":123,\"string\":\"abc\"}}]}," + // Resolved for email
// Resolved for email, but conditions are empty since this user is not authorized for any tenants
- "{\"id\":\"list-id\",\"rules\":[{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"application\"}],\"value\":[\"value1\"]},{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"application\"}],\"value\":[\"value1\",\"value3\"]},{\"value\":[\"a\"]}]}," +
+ "{\"id\":\"list-id\",\"rules\":[{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"instance\"}],\"value\":[\"value1\"]},{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"instance\"}],\"value\":[\"value1\",\"value3\"]},{\"value\":[\"a\"]}]}," +
"{\"id\":\"string-id\",\"rules\":[{\"value\":\"value1\"}]}]}", // resolved for email
flagData, Set.of(), false, email1);
@@ -72,7 +72,7 @@ public class UserFlagsSerializerTest {
"{\"id\":\"int-id\",\"rules\":[{\"value\":456}]}," + // Default from DB
"{\"id\":\"jackson-id\",\"rules\":[{\"conditions\":[{\"type\":\"whitelist\",\"dimension\":\"tenant\",\"values\":[\"tenant1\"]}],\"value\":{\"integer\":456,\"string\":\"xyz\"}},{\"value\":{\"integer\":123,\"string\":\"abc\"}}]}," + // Resolved for email
// Resolved for email, but conditions have filtered out tenant2
- "{\"id\":\"list-id\",\"rules\":[{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"application\",\"values\":[\"tenant1:video:default\",\"tenant1:video:default\"]}],\"value\":[\"value1\"]},{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"application\",\"values\":[\"tenant1:video:default\",\"tenant1:video:default\"]}],\"value\":[\"value1\",\"value3\"]},{\"value\":[\"a\"]}]}," +
+ "{\"id\":\"list-id\",\"rules\":[{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"instance\",\"values\":[\"tenant1:video:default\",\"tenant1:video:default\"]}],\"value\":[\"value1\"]},{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"instance\",\"values\":[\"tenant1:video:default\",\"tenant1:video:default\"]}],\"value\":[\"value1\",\"value3\"]},{\"value\":[\"a\"]}]}," +
"{\"id\":\"string-id\",\"rules\":[{\"value\":\"value1\"}]}]}", // resolved for email
flagData, Set.of("tenant1"), false, email1);
@@ -81,7 +81,7 @@ public class UserFlagsSerializerTest {
"{\"id\":\"int-id\",\"rules\":[{\"value\":456}]}," + // Default from DB
"{\"id\":\"jackson-id\",\"rules\":[{\"value\":{\"integer\":123,\"string\":\"abc\"}}]}," + // Default from code, no DB values match
// Includes last value from DB which is not conditioned on email and the default from code
- "{\"id\":\"list-id\",\"rules\":[{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"application\",\"values\":[\"tenant1:video:default\",\"tenant1:video:default\",\"tenant2:music:default\"]}],\"value\":[\"value1\",\"value3\"]},{\"value\":[\"a\"]}]}," +
+ "{\"id\":\"list-id\",\"rules\":[{\"conditions\":[{\"type\":\"blacklist\",\"dimension\":\"instance\",\"values\":[\"tenant1:video:default\",\"tenant1:video:default\",\"tenant2:music:default\"]}],\"value\":[\"value1\",\"value3\"]},{\"value\":[\"a\"]}]}," +
"{\"id\":\"string-id\",\"rules\":[{\"value\":\"default value\"}]}]}", // Default from code
flagData, Set.of(), true, "operator@domain.tld");
}
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 7af1661cf0c..b16d26a04a4 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java
@@ -22,9 +22,6 @@ public class FetchVector {
* Note: If this enum is changed, you must also change {@link DimensionHelper}.
*/
public enum Dimension {
- /** Value from ApplicationId::serializedForm of the form tenant:applicationName:instance. */
- APPLICATION_ID,
-
/**
* Cloud from com.yahoo.config.provision.CloudName::value, e.g. yahoo, aws, gcp.
*
@@ -59,6 +56,9 @@ public class FetchVector {
*/
HOSTNAME,
+ /** Value from ApplicationId::serializedForm of the form tenant:applicationName:instance. */
+ INSTANCE_ID,
+
/** Node type from com.yahoo.config.provision.NodeType::name, e.g. tenant, host, confighost, controller, etc. */
NODE_TYPE,
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java b/flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java
index 1773a03feb1..451f45ec792 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java
@@ -77,7 +77,7 @@ public class FlagDefinition {
if (dimensions.contains(FetchVector.Dimension.CONSOLE_USER_EMAIL)) {
Set<FetchVector.Dimension> disallowedCombinations = EnumSet.allOf(FetchVector.Dimension.class);
disallowedCombinations.remove(FetchVector.Dimension.CONSOLE_USER_EMAIL);
- disallowedCombinations.remove(FetchVector.Dimension.APPLICATION_ID);
+ disallowedCombinations.remove(FetchVector.Dimension.INSTANCE_ID);
disallowedCombinations.remove(FetchVector.Dimension.TENANT_ID);
disallowedCombinations.retainAll(dimensions);
if (!disallowedCombinations.isEmpty())
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 de14d4e7b00..2e158f0f3ef 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.INSTANCE_ID;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLOUD_ACCOUNT;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_ID;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_TYPE;
@@ -35,7 +35,7 @@ import static com.yahoo.vespa.flags.FetchVector.Dimension.VESPA_VERSION;
* an unbound flag to a flag source produces a (bound) flag, e.g. {@link BooleanFlag} and {@link StringFlag}.</li>
* <li>If you would like your flag value to be dependent on e.g. the application ID, then 1. you should
* declare this in the unbound flag definition in this file (referring to
- * {@link FetchVector.Dimension#APPLICATION_ID}), and 2. specify the application ID when retrieving the value, e.g.
+ * {@link FetchVector.Dimension#INSTANCE_ID}), and 2. specify the application ID when retrieving the value, e.g.
* {@link BooleanFlag#with(FetchVector.Dimension, String)}. See {@link FetchVector} for more info.</li>
* </ol>
*
@@ -53,7 +53,7 @@ public class Flags {
List.of("baldersheim"), "2020-12-02", "2023-12-31",
"Default limit for when to apply termwise query evaluation",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundStringFlag QUERY_DISPATCH_POLICY = defineStringFlag(
"query-dispatch-policy", "adaptive",
@@ -61,62 +61,62 @@ public class Flags {
"Select query dispatch policy, valid values are adaptive, round-robin, best-of-random-2," +
" latency-amortized-over-requests, latency-amortized-over-time",
"Takes effect at redeployment (requires restart)",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundStringFlag SUMMARY_DECODE_POLICY = defineStringFlag(
"summary-decode-policy", "eager",
List.of("baldersheim"), "2023-03-30", "2023-12-31",
"Select summary decoding policy, valid values are eager and on-demand/ondemand.",
"Takes effect at redeployment (requires restart)",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundStringFlag FEED_SEQUENCER_TYPE = defineStringFlag(
"feed-sequencer-type", "THROUGHPUT",
List.of("baldersheim"), "2020-12-02", "2023-12-31",
"Selects type of sequenced executor used for feeding in proton, valid values are LATENCY, ADAPTIVE, THROUGHPUT",
"Takes effect at redeployment (requires restart)",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MAX_UNCOMMITTED_MEMORY = defineIntFlag(
"max-uncommitted-memory", 130000,
List.of("geirst, baldersheim"), "2021-10-21", "2023-12-31",
"Max amount of memory holding updates to an attribute before we do a commit.",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundStringFlag RESPONSE_SEQUENCER_TYPE = defineStringFlag(
"response-sequencer-type", "ADAPTIVE",
List.of("baldersheim"), "2020-12-02", "2023-12-31",
"Selects type of sequenced executor used for mbus responses, valid values are LATENCY, ADAPTIVE, THROUGHPUT",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag RESPONSE_NUM_THREADS = defineIntFlag(
"response-num-threads", 2,
List.of("baldersheim"), "2020-12-02", "2023-12-31",
"Number of threads used for mbus responses, default is 2, negative number = numcores/4",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag USE_ASYNC_MESSAGE_HANDLING_ON_SCHEDULE = defineFeatureFlag(
"async-message-handling-on-schedule", false,
List.of("baldersheim"), "2020-12-02", "2023-12-31",
"Optionally deliver async messages in own thread",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundDoubleFlag FEED_CONCURRENCY = defineDoubleFlag(
"feed-concurrency", 0.5,
List.of("baldersheim"), "2020-12-02", "2023-12-31",
"How much concurrency should be allowed for feed",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundDoubleFlag FEED_NICENESS = defineDoubleFlag(
"feed-niceness", 0.0,
List.of("baldersheim"), "2022-06-24", "2023-12-31",
"How nice feeding shall be",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MBUS_JAVA_NUM_TARGETS = defineIntFlag(
@@ -124,71 +124,71 @@ public class Flags {
List.of("baldersheim"), "2022-07-05", "2023-12-31",
"Number of rpc targets per service",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MBUS_CPP_NUM_TARGETS = defineIntFlag(
"mbus-cpp-num-targets", 2,
List.of("baldersheim"), "2022-07-05", "2023-12-31",
"Number of rpc targets per service",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag RPC_NUM_TARGETS = defineIntFlag(
"rpc-num-targets", 2,
List.of("baldersheim"), "2022-07-05", "2023-12-31",
"Number of rpc targets per content node",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MBUS_JAVA_EVENTS_BEFORE_WAKEUP = defineIntFlag(
"mbus-java-events-before-wakeup", 1,
List.of("baldersheim"), "2022-07-05", "2023-12-31",
"Number write events before waking up transport thread",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MBUS_CPP_EVENTS_BEFORE_WAKEUP = defineIntFlag(
"mbus-cpp-events-before-wakeup", 1,
List.of("baldersheim"), "2022-07-05", "2023-12-31",
"Number write events before waking up transport thread",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag RPC_EVENTS_BEFORE_WAKEUP = defineIntFlag(
"rpc-events-before-wakeup", 1,
List.of("baldersheim"), "2022-07-05", "2023-12-31",
"Number write events before waking up transport thread",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MBUS_NUM_NETWORK_THREADS = defineIntFlag(
"mbus-num-network-threads", 1,
List.of("baldersheim"), "2022-07-01", "2023-12-31",
"Number of threads used for mbus network",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag SHARED_STRING_REPO_NO_RECLAIM = defineFeatureFlag(
"shared-string-repo-no-reclaim", false,
List.of("baldersheim"), "2022-06-14", "2023-12-31",
"Controls whether we do track usage and reclaim unused enum values in shared string repo",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag CONTAINER_DUMP_HEAP_ON_SHUTDOWN_TIMEOUT = defineFeatureFlag(
"container-dump-heap-on-shutdown-timeout", false,
List.of("baldersheim"), "2021-09-25", "2023-12-31",
"Will trigger a heap dump during if container shutdown times out",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag LOAD_CODE_AS_HUGEPAGES = defineFeatureFlag(
"load-code-as-hugepages", false,
List.of("baldersheim"), "2022-05-13", "2023-12-31",
"Will try to map the code segment with huge (2M) pages",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundDoubleFlag CONTAINER_SHUTDOWN_TIMEOUT = defineDoubleFlag(
"container-shutdown-timeout", 50.0,
List.of("baldersheim"), "2021-09-25", "2023-12-31",
"Timeout for shutdown of a jdisc container",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
// TODO: Move to a permanent flag
public static final UnboundListFlag<String> ALLOWED_ATHENZ_PROXY_IDENTITIES = defineListFlag(
@@ -203,14 +203,14 @@ public class Flags {
"Allows replicas in up to N content groups to not be activated " +
"for query visibility if they are out of sync with a majority of other replicas",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundDoubleFlag MIN_NODE_RATIO_PER_GROUP = defineDoubleFlag(
"min-node-ratio-per-group", 0.0,
List.of("geirst", "vekterli"), "2021-07-16", "2023-12-01",
"Minimum ratio of nodes that have to be available (i.e. not Down) in any hierarchic content cluster group for the group to be Up",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundStringFlag SYSTEM_MEMORY_HIGH = defineStringFlag(
"system-memory-high", "",
@@ -243,28 +243,28 @@ public class Flags {
List.of("arnej"), "2021-11-15", "2023-12-31",
"Use Vespa 8 types and formats for geographical positions",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MAX_COMPACT_BUFFERS = defineIntFlag(
"max-compact-buffers", 1,
List.of("baldersheim", "geirst", "toregge"), "2021-12-15", "2023-12-31",
"Upper limit of buffers to compact in a data store at the same time for each reason (memory usage, address space usage)",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag ENABLE_PROXY_PROTOCOL_MIXED_MODE = defineFeatureFlag(
"enable-proxy-protocol-mixed-mode", true,
List.of("tokle"), "2022-05-09", "2023-10-01",
"Enable or disable proxy protocol mixed mode",
"Takes effect on redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundStringFlag LOG_FILE_COMPRESSION_ALGORITHM = defineStringFlag(
"log-file-compression-algorithm", "",
List.of("arnej"), "2022-06-14", "2024-12-31",
"Which algorithm to use for compressing log files. Valid values: empty string (default), gzip, zstd",
"Takes effect immediately",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag SEPARATE_METRIC_CHECK_CONFIG = defineFeatureFlag(
"separate-metric-check-config", false,
@@ -278,7 +278,7 @@ public class Flags {
List.of("bjorncs", "vekterli"), "2022-07-21", "2024-01-01",
"Configure Vespa TLS capability enforcement mode",
"Takes effect on restart of Docker container",
- APPLICATION_ID,HOSTNAME,NODE_TYPE,TENANT_ID,VESPA_VERSION
+ INSTANCE_ID,HOSTNAME,NODE_TYPE,TENANT_ID,VESPA_VERSION
);
public static final UnboundBooleanFlag ENABLE_OTELCOL = defineFeatureFlag(
@@ -286,7 +286,7 @@ public class Flags {
List.of("olaa"), "2022-09-23", "2023-12-01",
"Whether an OpenTelemetry collector should be enabled",
"Takes effect at next tick",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundStringFlag CORE_ENCRYPTION_PUBLIC_KEY_ID = defineStringFlag(
"core-encryption-public-key-id", "",
@@ -300,7 +300,7 @@ public class Flags {
List.of("arnej", "bjorncs"), "2023-02-28", "2024-01-10",
"Enable global phase ranking",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag ENABLE_CROWDSTRIKE = defineFeatureFlag(
"enable-crowdstrike", true, List.of("andreer"), "2023-04-13", "2023-10-14",
@@ -311,7 +311,7 @@ public class Flags {
"randomized-endpoint-names", false, List.of("andreer"), "2023-04-26", "2023-10-14",
"Whether to use randomized endpoint names",
"Takes effect on application deployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag ENABLE_THE_ONE_THAT_SHOULD_NOT_BE_NAMED = defineFeatureFlag(
"enable-the-one-that-should-not-be-named", false, List.of("hmusum"), "2023-05-08", "2023-10-01",
@@ -329,14 +329,14 @@ public class Flags {
List.of("baldersheim"), "2023-06-29", "2023-12-31",
"Should we enable proper nested multivalue grouping",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag USE_RECONFIGURABLE_DISPATCHER = defineFeatureFlag(
"use-reconfigurable-dispatcher", false,
List.of("jonmv"), "2023-07-14", "2023-10-01",
"Whether to set up a ReconfigurableDispatcher with config self-sub for backend nodes",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag WRITE_CONFIG_SERVER_SESSION_DATA_AS_ONE_BLOB = defineFeatureFlag(
"write-config-server-session-data-as-blob", false,
@@ -382,21 +382,21 @@ public class Flags {
List.of("freva"), "2023-09-08", "2023-11-01",
"Minimum amount of advertised memory for exclusive nodes",
"Takes effect immediately",
- APPLICATION_ID, CLUSTER_ID, CLUSTER_TYPE);
+ INSTANCE_ID, CLUSTER_ID, CLUSTER_TYPE);
public static final UnboundBooleanFlag ASSIGN_RANDOMIZED_ID = defineFeatureFlag(
"assign-randomized-id", false,
List.of("mortent"), "2023-08-31", "2024-02-01",
"Whether to assign randomized id to the application",
"Takes effect immediately",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag ASSIGNED_RANDOMIZED_ID_RATE = defineIntFlag(
"assign-randomized-id-rate", 5,
List.of("mortent"), "2023-09-11", "2024-02-01",
"Rate for requesting assigned ids for existing certificates. Rate is per maintainer cycle.",
"Takes effect immediately",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag CONTENT_LAYER_METADATA_FEATURE_LEVEL = defineIntFlag(
"content-layer-metadata-feature-level", 0,
@@ -404,7 +404,7 @@ public class Flags {
"Value semantics: 0) legacy behavior, 1) operation cancellation, 2) operation " +
"cancellation and ephemeral content node sequence numbers for bucket replicas",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
/** WARNING: public for testing: All flags should be defined in {@link Flags}. */
public static UnboundBooleanFlag defineFeatureFlag(String flagId, boolean defaultValue, List<String> owners,
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
index f856ebeb456..629636afb68 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
@@ -13,7 +13,7 @@ import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;
-import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID;
+import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_ID;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_TYPE;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CONSOLE_USER_EMAIL;
@@ -43,19 +43,19 @@ public class PermanentFlags {
"jvm-gc-options", "",
"Sets default jvm gc options",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag HEAP_SIZE_PERCENTAGE = defineIntFlag(
"heap-size-percentage", 70,
"Sets default jvm heap size percentage",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundDoubleFlag QUERY_DISPATCH_WARMUP = defineDoubleFlag(
"query-dispatch-warmup", 5,
"Warmup duration for query dispatcher",
"Takes effect at redeployment (requires restart)",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag FLEET_CANARY = defineFeatureFlag(
"fleet-canary", false,
@@ -86,13 +86,13 @@ public class PermanentFlags {
"host-flavor", "",
"Specifies the Vespa flavor name that the hosts of the matching nodes should have.",
"Takes effect on next deployment (including internal redeployment).",
- APPLICATION_ID, CLUSTER_TYPE, CLUSTER_ID);
+ INSTANCE_ID, CLUSTER_TYPE, CLUSTER_ID);
public static final UnboundBooleanFlag SKIP_MAINTENANCE_DEPLOYMENT = defineFeatureFlag(
"node-repository-skip-maintenance-deployment", false,
"Whether PeriodicApplicationMaintainer should skip deployment for an application",
"Takes effect at next run of maintainer",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundListFlag<String> INACTIVE_MAINTENANCE_JOBS = defineListFlag(
"inactive-maintenance-jobs", List.of(), String.class,
@@ -120,19 +120,19 @@ public class PermanentFlags {
"Hard limit on how many CPUs a container may use. This value is multiplied by CPU allocated to node, so " +
"to cap CPU at 200%, set this to 2, etc. 0 disables the cap to allow unlimited CPU.",
"Takes effect on next node agent tick. Change is orchestrated, but does NOT require container restart",
- HOSTNAME, APPLICATION_ID, CLUSTER_ID, CLUSTER_TYPE);
+ HOSTNAME, INSTANCE_ID, CLUSTER_ID, CLUSTER_TYPE);
public static final UnboundIntFlag MIN_DISK_THROUGHPUT_MB_S = defineIntFlag(
"min-disk-throughput-mb-s", 0,
"Minimum required disk throughput performance, 0 = default, Only when using remote disk",
"Takes effect when node is provisioned",
- APPLICATION_ID, TENANT_ID, CLUSTER_ID, CLUSTER_TYPE);
+ INSTANCE_ID, TENANT_ID, CLUSTER_ID, CLUSTER_TYPE);
public static final UnboundIntFlag MIN_DISK_IOPS_K = defineIntFlag(
"min-disk-iops-k", 0,
"Minimum required disk I/O operations per second, unit is kilo, 0 = default, Only when using remote disk",
"Takes effect when node is provisioned",
- APPLICATION_ID, TENANT_ID, CLUSTER_ID, CLUSTER_TYPE);
+ INSTANCE_ID, TENANT_ID, CLUSTER_ID, CLUSTER_TYPE);
public static final UnboundListFlag<String> DISABLED_HOST_ADMIN_TASKS = defineListFlag(
"disabled-host-admin-tasks", List.of(), String.class,
@@ -145,13 +145,13 @@ public class PermanentFlags {
"docker-image-repo", "",
"Override default docker image repo. Docker image version will be Vespa version.",
"Takes effect on next deployment from controller",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag SEND_LIMITED_METRIC_SET = defineFeatureFlag(
"send-limited-metric-set", true,
"Whether a limited metric set should be fetched from metrics-proxy (CD systems only)",
"Takes effect on next host admin tick",
- APPLICATION_ID);
+ INSTANCE_ID);
private static final String VERSION_QUALIFIER_REGEX = "[a-zA-Z0-9_-]+";
private static final Pattern QUALIFIER_PATTERN = Pattern.compile("^" + VERSION_QUALIFIER_REGEX + "$");
@@ -164,13 +164,13 @@ public class PermanentFlags {
"Otherwise a '.' + the flag value will be appended.",
"Takes effect on the next host admin tick. The upgrade to the new wanted docker image is orchestrated.",
value -> value.isEmpty() || QUALIFIER_PATTERN.matcher(value).find() || VERSION_PATTERN.matcher(value).find(),
- HOSTNAME, NODE_TYPE, TENANT_ID, APPLICATION_ID, CLUSTER_TYPE, CLUSTER_ID, VESPA_VERSION);
+ HOSTNAME, NODE_TYPE, TENANT_ID, INSTANCE_ID, CLUSTER_TYPE, CLUSTER_ID, VESPA_VERSION);
public static final UnboundStringFlag ZOOKEEPER_SERVER_VERSION = defineStringFlag(
"zookeeper-server-version", "3.8.0",
"ZooKeeper server version, a jar file zookeeper-server-<ZOOKEEPER_SERVER_VERSION>-jar-with-dependencies.jar must exist",
"Takes effect on restart of Docker container",
- NODE_TYPE, APPLICATION_ID, HOSTNAME);
+ NODE_TYPE, INSTANCE_ID, HOSTNAME);
public static final UnboundBooleanFlag ENABLE_PUBLIC_SIGNUP_FLOW = defineFeatureFlag(
"enable-public-signup-flow", false,
@@ -188,7 +188,7 @@ public class PermanentFlags {
"jvm-omit-stack-trace-in-fast-throw", true,
"Controls JVM option OmitStackTraceInFastThrow (default feature flag value is true, which is the default JVM option value as well)",
"takes effect on JVM restart",
- CLUSTER_TYPE, APPLICATION_ID);
+ CLUSTER_TYPE, INSTANCE_ID);
public static final UnboundIntFlag MAX_TRIAL_TENANTS = defineIntFlag(
"max-trial-tenants", -1,
@@ -200,7 +200,7 @@ public class PermanentFlags {
"allow-disable-mtls", true,
"Allow application to disable client authentication",
"Takes effect on redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MAX_OS_UPGRADES = defineIntFlag(
"max-os-upgrades", 30,
@@ -219,7 +219,7 @@ public class PermanentFlags {
"tls-ciphers-override", List.of(), String.class,
"Override TLS ciphers enabled for port 4443 on hosted application containers",
"Takes effect on redeployment",
- APPLICATION_ID
+ INSTANCE_ID
);
public static final UnboundStringFlag ENDPOINT_CERTIFICATE_ALGORITHM = defineStringFlag(
@@ -227,20 +227,20 @@ public class PermanentFlags {
// Acceptable values are: "rsa_4096", "ecdsa_p256"
"Selects algorithm used for an applications endpoint certificate",
"Takes effect when a new endpoint certificate is requested (on first deployment or deployment adding new endpoints)",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundDoubleFlag RESOURCE_LIMIT_DISK = defineDoubleFlag(
"resource-limit-disk", 0.75,
"Resource limit (between 0.0 and 1.0) for disk usage on content nodes, used by cluster controller for when to block feed",
"Takes effect on next deployment",
- APPLICATION_ID
+ INSTANCE_ID
);
public static final UnboundDoubleFlag RESOURCE_LIMIT_MEMORY = defineDoubleFlag(
"resource-limit-memory", 0.8,
"Resource limit (between 0.0 and 1.0) for memory usage on content nodes, used by cluster controller for when to block feed",
"Takes effect on next deployment",
- APPLICATION_ID
+ INSTANCE_ID
);
public static final UnboundListFlag<String> LOGCTL_OVERRIDE = defineListFlag(
@@ -248,7 +248,7 @@ public class PermanentFlags {
"A list of vespa-logctl statements that are run on container startup. " +
"Each item should be on the form <service>:<component> <level>=on",
"Takes effect on container restart",
- APPLICATION_ID, HOSTNAME
+ INSTANCE_ID, HOSTNAME
);
public static final UnboundListFlag<String> ENVIRONMENT_VARIABLES = defineListFlag(
@@ -256,14 +256,14 @@ public class PermanentFlags {
"A list of environment variables set for all services. " +
"Each item should be on the form <ENV_VAR>=<VALUE>",
"Takes effect on service restart",
- APPLICATION_ID
+ INSTANCE_ID
);
public static final UnboundStringFlag CONFIG_PROXY_JVM_ARGS = defineStringFlag(
"config-proxy-jvm-args", "",
"Sets jvm args for config proxy (added at the end of startup command, will override existing ones)",
"Takes effect on restart of Docker container",
- APPLICATION_ID
+ INSTANCE_ID
);
// This must be set in a feature flag to avoid flickering between the new and old value during config server upgrade
@@ -277,20 +277,20 @@ public class PermanentFlags {
"forward-issues-as-errors", true,
"When the backend detects a problematic issue with a query, it will by default send it as an error message to the QRS, which adds it in an ErrorHit in the result. May be disabled using this flag.",
"Takes effect immediately",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag DEACTIVATE_ROUTING = defineFeatureFlag(
"deactivate-routing", false,
"Deactivates routing for an application by removing all reals from its load balancers. Used in " +
"cases where we immediately need to stop serving an application, i.e. in case of service violations",
"Takes effect on next redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundListFlag<String> IGNORED_HTTP_USER_AGENTS = defineListFlag(
"ignored-http-user-agents", List.of(), String.class,
"List of user agents to ignore (crawlers etc)",
"Takes effect immediately.",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundListFlag<String> INCOMPATIBLE_VERSIONS = defineListFlag(
"incompatible-versions", List.of("8"), String.class,
@@ -305,7 +305,7 @@ public class PermanentFlags {
"The config server will refuse to serve config to nodes running a version which is incompatible with their " +
"current wanted node version, i.e., nodes about to upgrade to a version which is incompatible with the current.",
"Takes effect immediately",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundStringFlag ADMIN_CLUSTER_NODE_ARCHITECTURE = defineStringFlag(
"admin-cluster-node-architecture", "x86_64",
@@ -313,7 +313,7 @@ public class PermanentFlags {
"(logserver and clustercontroller clusters).",
"Takes effect on next redeployment",
value -> Set.of("any", "arm64", "x86_64").contains(value),
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundListFlag<String> CLOUD_ACCOUNTS = defineListFlag(
"cloud-accounts", List.of(), String.class,
@@ -325,20 +325,20 @@ public class PermanentFlags {
"fail-deployment-for-files-with-unknown-extension", "FAIL",
"Whether to log or fail for deployments when app has a file with unknown extension (valid values: LOG, FAIL)",
"Takes effect at redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundListFlag<String> DISABLED_DEPLOYMENT_ZONES = defineListFlag(
"disabled-deployment-zones", List.of(), String.class,
"The zones, e.g., prod.norway-71, where deployments jobs are currently disabled",
"Takes effect immediately",
- APPLICATION_ID
+ INSTANCE_ID
);
public static final UnboundBooleanFlag ALLOW_USER_FILTERS = defineFeatureFlag(
"allow-user-filters", true,
"Allow user filter (chains) in application",
"Takes effect on next redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundLongFlag CONFIG_SERVER_SESSION_EXPIRY_TIME = defineLongFlag(
"config-server-session-expiry-time", 3600,
@@ -357,27 +357,27 @@ public class PermanentFlags {
"keep-file-references-days", 30,
"How many days to keep file references on tenant nodes (based on last modification time)",
"Takes effect on restart of Docker container",
- APPLICATION_ID
+ INSTANCE_ID
);
public static final UnboundIntFlag KEEP_FILE_REFERENCES_COUNT = defineIntFlag(
"keep-file-references-count", 20,
"How many file references to keep on tenant nodes (no matter what last modification time is)",
"Takes effect on restart of Docker container",
- ZONE_ID, APPLICATION_ID
+ ZONE_ID, INSTANCE_ID
);
public static final UnboundIntFlag ENDPOINT_CONNECTION_TTL = defineIntFlag(
"endpoint-connection-ttl", 45,
"Time to live for connections to endpoints in seconds",
"Takes effect on next redeployment",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundBooleanFlag AUTOSCALING = defineFeatureFlag(
"autoscaling", true,
"Whether to enable autoscaling",
"Takes effect immediately",
- APPLICATION_ID);
+ INSTANCE_ID);
public static final UnboundIntFlag MAX_HOSTS_PER_HOUR = defineIntFlag(
"max-hosts-per-hour", 40,
@@ -392,7 +392,7 @@ public class PermanentFlags {
"Takes effect on next tick",
// The application ID is the exclusive application ID associated with the host,
// if any, or otherwise hosted-vespa:tenant-host:default.
- APPLICATION_ID, TENANT_ID, CLUSTER_ID, CLUSTER_TYPE);
+ INSTANCE_ID, TENANT_ID, CLUSTER_ID, CLUSTER_TYPE);
public static final UnboundIntFlag DROP_DENTRIES = defineIntFlag(
"drop-dentries", -1,
@@ -401,7 +401,7 @@ public class PermanentFlags {
"Takes effect on next tick",
// The application ID is the exclusive application ID associated with the host,
// if any, or otherwise hosted-vespa:tenant-host:default.
- APPLICATION_ID, TENANT_ID, CLUSTER_ID, CLUSTER_TYPE);
+ INSTANCE_ID, TENANT_ID, CLUSTER_ID, CLUSTER_TYPE);
public static final UnboundIntFlag CERT_POOL_SIZE = defineIntFlag(
"cert-pool-size", 0,
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 2193d70ec47..8fb48c8a82f 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,30 +4,31 @@ 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;
/**
* @author hakonhall
*/
public class DimensionHelper {
- private static final Map<FetchVector.Dimension, String> serializedDimensions = new HashMap<>();
+ private static final Map<FetchVector.Dimension, List<String>> serializedDimensions = new HashMap<>();
static {
- serializedDimensions.put(FetchVector.Dimension.APPLICATION_ID, "application");
- serializedDimensions.put(FetchVector.Dimension.CLOUD, "cloud");
- serializedDimensions.put(FetchVector.Dimension.CLOUD_ACCOUNT, "cloud-account");
- serializedDimensions.put(FetchVector.Dimension.CLUSTER_ID, "cluster-id");
- serializedDimensions.put(FetchVector.Dimension.CLUSTER_TYPE, "cluster-type");
- serializedDimensions.put(FetchVector.Dimension.CONSOLE_USER_EMAIL, "console-user-email");
- serializedDimensions.put(FetchVector.Dimension.ENVIRONMENT, "environment");
- serializedDimensions.put(FetchVector.Dimension.HOSTNAME, "hostname");
- serializedDimensions.put(FetchVector.Dimension.NODE_TYPE, "node-type");
- serializedDimensions.put(FetchVector.Dimension.SYSTEM, "system");
- serializedDimensions.put(FetchVector.Dimension.TENANT_ID, "tenant");
- serializedDimensions.put(FetchVector.Dimension.VESPA_VERSION, "vespa-version");
- serializedDimensions.put(FetchVector.Dimension.ZONE_ID, "zone");
+ serializedDimensions.put(FetchVector.Dimension.CLOUD, List.of("cloud"));
+ serializedDimensions.put(FetchVector.Dimension.CLOUD_ACCOUNT, List.of("cloud-account"));
+ serializedDimensions.put(FetchVector.Dimension.CLUSTER_ID, List.of("cluster-id"));
+ serializedDimensions.put(FetchVector.Dimension.CLUSTER_TYPE, List.of("cluster-type"));
+ serializedDimensions.put(FetchVector.Dimension.CONSOLE_USER_EMAIL, List.of("console-user-email"));
+ serializedDimensions.put(FetchVector.Dimension.ENVIRONMENT, List.of("environment"));
+ serializedDimensions.put(FetchVector.Dimension.HOSTNAME, List.of("hostname"));
+ serializedDimensions.put(FetchVector.Dimension.INSTANCE_ID, List.of("instance", "application"));
+ serializedDimensions.put(FetchVector.Dimension.NODE_TYPE, List.of("node-type"));
+ serializedDimensions.put(FetchVector.Dimension.SYSTEM, List.of("system"));
+ serializedDimensions.put(FetchVector.Dimension.TENANT_ID, List.of("tenant"));
+ serializedDimensions.put(FetchVector.Dimension.VESPA_VERSION, List.of("vespa-version"));
+ serializedDimensions.put(FetchVector.Dimension.ZONE_ID, List.of("zone"));
if (serializedDimensions.size() != FetchVector.Dimension.values().length) {
throw new IllegalStateException(FetchVectorHelper.class.getName() + " is not in sync with " +
@@ -35,16 +36,27 @@ public class DimensionHelper {
}
}
- private static final Map<String, FetchVector.Dimension> deserializedDimensions = serializedDimensions.
- entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
+ private static final Map<String, FetchVector.Dimension> deserializedDimensions = reverseMapping(serializedDimensions);
+
+ private static Map<String, FetchVector.Dimension> reverseMapping(Map<FetchVector.Dimension, List<String>> mapping) {
+ Map<String, FetchVector.Dimension> reverseMapping = new LinkedHashMap<>();
+ mapping.forEach((dimension, serializedDimensions) -> {
+ serializedDimensions.forEach(serializedDimension -> {
+ if (reverseMapping.put(serializedDimension, dimension) != null) {
+ throw new IllegalStateException("Duplicate serialized dimension: '" + serializedDimension + "'");
+ }
+ });
+ });
+ return Map.copyOf(reverseMapping);
+ }
public static String toWire(FetchVector.Dimension dimension) {
- String serializedDimension = serializedDimensions.get(dimension);
- if (serializedDimension == null) {
+ List<String> serializedDimension = serializedDimensions.get(dimension);
+ if (serializedDimension == null || serializedDimension.isEmpty()) {
throw new IllegalArgumentException("Unsupported dimension (please add it): '" + dimension + "'");
}
- return serializedDimension;
+ return serializedDimension.get(0);
}
public static FetchVector.Dimension fromWire(String serializedDimension) {
diff --git a/flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java b/flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java
index 3edde140de8..dd332be6627 100644
--- a/flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java
+++ b/flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java
@@ -50,7 +50,7 @@ public class FlagsTest {
// zone is set because it was set on the unbound flag above
assertThat(vector.getValue().getValue(FetchVector.Dimension.ZONE_ID), is(Optional.of("a-zone")));
// application and node type are not set
- assertThat(vector.getValue().getValue(FetchVector.Dimension.APPLICATION_ID), is(Optional.empty()));
+ assertThat(vector.getValue().getValue(FetchVector.Dimension.INSTANCE_ID), is(Optional.empty()));
assertThat(vector.getValue().getValue(FetchVector.Dimension.NODE_TYPE), is(Optional.empty()));
RawFlag rawFlag = mock(RawFlag.class);
@@ -58,11 +58,11 @@ public class FlagsTest {
when(rawFlag.asJsonNode()).thenReturn(BooleanNode.getTrue());
// raw flag deserializes to true
- assertThat(booleanFlag.with(FetchVector.Dimension.APPLICATION_ID, "an-app").value(), equalTo(true));
+ assertThat(booleanFlag.with(FetchVector.Dimension.INSTANCE_ID, "an-app").value(), equalTo(true));
verify(source, times(2)).fetch(any(), vector.capture());
// application was set on the (bound) flag.
- assertThat(vector.getValue().getValue(FetchVector.Dimension.APPLICATION_ID), is(Optional.of("an-app")));
+ assertThat(vector.getValue().getValue(FetchVector.Dimension.INSTANCE_ID), is(Optional.of("an-app")));
}
@Test
diff --git a/flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java b/flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java
index 4da66bd5cc1..084ad3b9395 100644
--- a/flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java
+++ b/flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java
@@ -18,7 +18,7 @@ public class ConditionTest {
var params = new Condition.CreateParams(FetchVector.Dimension.HOSTNAME).withValues(hostname1);
Condition condition = WhitelistCondition.create(params);
assertFalse(condition.test(new FetchVector()));
- assertFalse(condition.test(new FetchVector().with(FetchVector.Dimension.APPLICATION_ID, "foo")));
+ assertFalse(condition.test(new FetchVector().with(FetchVector.Dimension.INSTANCE_ID, "foo")));
assertFalse(condition.test(new FetchVector().with(FetchVector.Dimension.HOSTNAME, "bar")));
assertTrue(condition.test(new FetchVector().with(FetchVector.Dimension.HOSTNAME, hostname1)));
}
@@ -29,7 +29,7 @@ public class ConditionTest {
var params = new Condition.CreateParams(FetchVector.Dimension.HOSTNAME).withValues(hostname1);
Condition condition = BlacklistCondition.create(params);
assertTrue(condition.test(new FetchVector()));
- assertTrue(condition.test(new FetchVector().with(FetchVector.Dimension.APPLICATION_ID, "foo")));
+ assertTrue(condition.test(new FetchVector().with(FetchVector.Dimension.INSTANCE_ID, "foo")));
assertTrue(condition.test(new FetchVector().with(FetchVector.Dimension.HOSTNAME, "bar")));
assertFalse(condition.test(new FetchVector().with(FetchVector.Dimension.HOSTNAME, hostname1)));
}
diff --git a/flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java b/flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java
index 3ca7f59c759..ed81afc8054 100644
--- a/flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java
+++ b/flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java
@@ -52,6 +52,8 @@ public class FlagDataTest {
}
}""";
+ private final String json_with_instance = json.replace("application", "instance");
+
private final FetchVector vector = new FetchVector();
@Test
@@ -62,16 +64,16 @@ public class FlagDataTest {
// First rule matches only if both conditions match
verify(Optional.of("false"), vector
.with(FetchVector.Dimension.HOSTNAME, "host1")
- .with(FetchVector.Dimension.APPLICATION_ID, "app2"));
+ .with(FetchVector.Dimension.INSTANCE_ID, "app2"));
verify(Optional.of("true"), vector
.with(FetchVector.Dimension.HOSTNAME, "host1")
- .with(FetchVector.Dimension.APPLICATION_ID, "app3"));
+ .with(FetchVector.Dimension.INSTANCE_ID, "app3"));
// Verify unsetting a dimension with null works.
verify(Optional.of("true"), vector
.with(FetchVector.Dimension.HOSTNAME, "host1")
- .with(FetchVector.Dimension.APPLICATION_ID, "app3")
- .with(FetchVector.Dimension.APPLICATION_ID, null));
+ .with(FetchVector.Dimension.INSTANCE_ID, "app3")
+ .with(FetchVector.Dimension.INSTANCE_ID, null));
// No rules apply if zone is overridden to an unknown zone
verify(Optional.empty(), vector.with(FetchVector.Dimension.ZONE_ID, "unknown zone"));
@@ -81,7 +83,7 @@ public class FlagDataTest {
void testPartialResolve() {
FlagData data = FlagData.deserialize(json);
assertEquals(data.partialResolve(vector), data);
- assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.APPLICATION_ID, "app1")),
+ assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app1")),
FlagData.deserialize("""
{
"id": "id1",
@@ -102,7 +104,7 @@ public class FlagDataTest {
}
}"""));
- assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.APPLICATION_ID, "app1")),
+ assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app1")),
FlagData.deserialize("""
{
"id": "id1",
@@ -123,7 +125,7 @@ public class FlagDataTest {
}
}"""));
- assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.APPLICATION_ID, "app3")),
+ assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3")),
FlagData.deserialize("""
{
"id": "id1",
@@ -154,7 +156,7 @@ public class FlagDataTest {
}
}"""));
- assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.APPLICATION_ID, "app3")
+ assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3")
.with(FetchVector.Dimension.HOSTNAME, "host1")),
FlagData.deserialize("""
{
@@ -169,7 +171,7 @@ public class FlagDataTest {
}
}"""));
- assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.APPLICATION_ID, "app3")
+ assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3")
.with(FetchVector.Dimension.HOSTNAME, "host3")),
FlagData.deserialize("""
{
@@ -191,7 +193,7 @@ public class FlagDataTest {
}
}"""));
- assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.APPLICATION_ID, "app3")
+ assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3")
.with(FetchVector.Dimension.HOSTNAME, "host3")
.with(FetchVector.Dimension.ZONE_ID, "zone2")),
FlagData.deserialize("""
@@ -204,7 +206,7 @@ public class FlagDataTest {
]
}"""));
- FlagData fullyResolved = data.partialResolve(vector.with(FetchVector.Dimension.APPLICATION_ID, "app3")
+ FlagData fullyResolved = data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3")
.with(FetchVector.Dimension.HOSTNAME, "host3")
.with(FetchVector.Dimension.ZONE_ID, "zone3"));
assertEquals(fullyResolved, FlagData.deserialize("""
@@ -271,6 +273,11 @@ public class FlagDataTest {
}
private void verify(Optional<String> expectedValue, FetchVector vector) {
+ verify(json, expectedValue, vector);
+ verify(json_with_instance, expectedValue, vector);
+ }
+
+ private void verify(String json, Optional<String> expectedValue, FetchVector vector) {
FlagData data = FlagData.deserialize(json);
assertEquals("id1", data.id().toString());
Optional<RawFlag> rawFlag = data.resolve(vector);
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java
index 466ee65fcc1..98252a696f2 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java
@@ -40,7 +40,7 @@ import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
-import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID;
+import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_ID;
import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_TYPE;
import static com.yahoo.vespa.flags.FetchVector.Dimension.HOSTNAME;
@@ -416,7 +416,7 @@ public class NodeAgentImpl implements NodeAgent {
private ContainerResources getContainerResources(NodeAgentContext context) {
double cpuCap = context.vcpuOnThisHost() * containerCpuCap
- .with(APPLICATION_ID, context.node().owner().map(ApplicationId::serializedForm))
+ .with(INSTANCE_ID, context.node().owner().map(ApplicationId::serializedForm))
.with(CLUSTER_ID, context.node().membership().map(NodeMembership::clusterId))
.with(CLUSTER_TYPE, context.node().membership().map(membership -> membership.type().value()))
.with(HOSTNAME, context.node().hostname())
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 e228d31384c..f42d1ce9bd3 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
@@ -21,7 +21,8 @@ import java.util.Set;
public class LoadBalancerInstance {
private final Optional<DomainName> hostname;
- private final Optional<String> ipAddress;
+ private final Optional<String> ip4Address;
+ private final Optional<String> ip6Address;
private final Optional<DnsZone> dnsZone;
private final Set<Integer> ports;
private final Set<String> networks;
@@ -30,11 +31,12 @@ public class LoadBalancerInstance {
private final List<PrivateServiceId> serviceIds;
private final CloudAccount cloudAccount;
- public LoadBalancerInstance(Optional<DomainName> hostname, Optional<String> ipAddress,
+ public LoadBalancerInstance(Optional<DomainName> hostname, Optional<String> ip4Address, Optional<String> ip6Address,
Optional<DnsZone> dnsZone, Set<Integer> ports, Set<String> networks, Set<Real> reals,
ZoneEndpoint settings, List<PrivateServiceId> serviceIds, CloudAccount cloudAccount) {
this.hostname = Objects.requireNonNull(hostname, "hostname must be non-null");
- this.ipAddress = Objects.requireNonNull(ipAddress, "ip must be non-null");
+ this.ip4Address = Objects.requireNonNull(ip4Address, "ip4Address must be non-null");
+ this.ip6Address = Objects.requireNonNull(ip6Address, "ip6Address must be non-null");
this.dnsZone = Objects.requireNonNull(dnsZone, "dnsZone must be non-null");
this.ports = ImmutableSortedSet.copyOf(requirePorts(ports));
this.networks = ImmutableSortedSet.copyOf(Objects.requireNonNull(networks, "networks must be non-null"));
@@ -43,9 +45,9 @@ public class LoadBalancerInstance {
this.serviceIds = List.copyOf(Objects.requireNonNull(serviceIds, "private service id must be non-null"));
this.cloudAccount = Objects.requireNonNull(cloudAccount, "cloudAccount must be non-null");
- 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>")));
+ if (hostname.isEmpty() == ip4Address.isEmpty()) {
+ throw new IllegalArgumentException("Exactly 1 of hostname=%s and ip4Address=%s must be set".formatted(
+ hostname.map(DomainName::value).orElse("<empty>"), ip4Address.orElse("<empty>")));
}
}
@@ -54,9 +56,14 @@ public class LoadBalancerInstance {
return hostname;
}
- /** IP address of this (public) load balancer */
- public Optional<String> ipAddress() {
- return ipAddress;
+ /** IPv4 address of this (public) load balancer */
+ public Optional<String> ip4Address() {
+ return ip4Address;
+ }
+
+ /** IPv6 address of this (public) load balancer */
+ public Optional<String> ip6Address() {
+ return ip6Address;
}
/** ID of the DNS zone associated with this */
@@ -114,7 +121,7 @@ public class LoadBalancerInstance {
public LoadBalancerInstance with(Set<Real> reals, ZoneEndpoint settings, Optional<PrivateServiceId> serviceId) {
List<PrivateServiceId> ids = new ArrayList<>(serviceIds);
serviceId.filter(id -> ! ids.contains(id)).ifPresent(ids::add);
- return new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks,
+ return new LoadBalancerInstance(hostname, ip4Address, ip6Address, dnsZone, ports, networks,
reals, settings, ids,
cloudAccount);
}
@@ -123,7 +130,7 @@ public class LoadBalancerInstance {
public LoadBalancerInstance withServiceIds(List<PrivateServiceId> serviceIds) {
List<PrivateServiceId> ids = new ArrayList<>(serviceIds);
for (PrivateServiceId id : this.serviceIds) if ( ! ids.contains(id)) ids.add(id);
- return new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, settings, ids, cloudAccount);
+ return new LoadBalancerInstance(hostname, ip4Address, ip6Address, dnsZone, ports, networks, reals, settings, ids, cloudAccount);
}
}
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 a79766a577d..c79ccc2aece 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
@@ -57,6 +57,7 @@ public class LoadBalancerServiceMock implements LoadBalancerService {
var instance = new LoadBalancerInstance(
Optional.of(DomainName.of("lb-" + spec.application().toShortString() + "-" + spec.cluster().value())),
Optional.empty(),
+ Optional.empty(),
Optional.of(new DnsZone("zone-id-1")),
Collections.singleton(4443),
ImmutableSet.of("10.2.3.0/24", "10.4.5.0/24"),
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 e49d1b302cf..073662b39fe 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
@@ -45,6 +45,7 @@ public class SharedLoadBalancerService implements LoadBalancerService {
return new LoadBalancerInstance(Optional.of(DomainName.of(vipHostname)),
Optional.empty(),
Optional.empty(),
+ Optional.empty(),
Set.of(4443),
Set.of(),
spec.reals(),
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
index 8638087c5cd..eb290d9ec2a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
@@ -59,7 +59,7 @@ public class AutoscalingMaintainer extends NodeRepositoryMaintainer {
int failures = 0;
outer:
for (var applicationNodes : activeNodesByApplication().entrySet()) {
- boolean enabled = enabledFlag.with(FetchVector.Dimension.APPLICATION_ID,
+ boolean enabled = enabledFlag.with(FetchVector.Dimension.INSTANCE_ID,
applicationNodes.getKey().serializedForm()).value();
if (!enabled) continue;
for (var clusterNodes : nodesByCluster(applicationNodes.getValue()).entrySet()) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java
index 14693c75436..9cbf1778b3b 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java
@@ -58,7 +58,7 @@ public class PeriodicApplicationMaintainer extends ApplicationMaintainer {
private boolean shouldMaintain(ApplicationId id) {
BooleanFlag skipMaintenanceDeployment = PermanentFlags.SKIP_MAINTENANCE_DEPLOYMENT.bindTo(flagSource)
- .with(FetchVector.Dimension.APPLICATION_ID, id.serializedForm());
+ .with(FetchVector.Dimension.INSTANCE_ID, id.serializedForm());
return ! skipMaintenanceDeployment.value();
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java
index 3c3868bfeb8..8ad975f5334 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java
@@ -47,6 +47,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
import static com.yahoo.stream.CustomCollectors.toLinkedMap;
import static java.util.stream.Collectors.collectingAndThen;
@@ -456,7 +457,12 @@ public class CuratorDb {
transaction.onCommitted(() -> {
for (var lb : loadBalancers) {
if (lb.state() == fromState) continue;
- Optional<String> target = lb.instance().flatMap(instance -> instance.hostname().map(DomainName::value).or(instance::ipAddress));
+ Optional<String> target = lb.instance()
+ .flatMap(instance -> instance.hostname()
+ .map(DomainName::value)
+ .or(() -> Optional.of(Stream.concat(instance.ip4Address().stream(),
+ instance.ip6Address().stream())
+ .collect(Collectors.joining(",")))));
if (fromState == null) {
log.log(Level.INFO, () -> "Creating " + lb.id() + target.map(t -> " (" + t + ")").orElse("") +
" in " + lb.state());
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 b85d96c6b54..d329676f842 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
@@ -45,6 +45,7 @@ public class LoadBalancerSerializer {
private static final String idField = "id";
private static final String hostnameField = "hostname";
private static final String lbIpAddressField = "ipAddress";
+ private static final String lbIp6AddressField = "ip6Address";
private static final String stateField = "state";
private static final String changedAtField = "changedAt";
private static final String dnsZoneField = "dnsZone";
@@ -69,7 +70,8 @@ public class LoadBalancerSerializer {
root.setString(idField, loadBalancer.id().serializedForm());
loadBalancer.instance().flatMap(LoadBalancerInstance::hostname).ifPresent(hostname -> root.setString(hostnameField, hostname.value()));
- loadBalancer.instance().flatMap(LoadBalancerInstance::ipAddress).ifPresent(ip -> root.setString(lbIpAddressField, ip));
+ loadBalancer.instance().flatMap(LoadBalancerInstance::ip4Address).ifPresent(ip -> root.setString(lbIpAddressField, ip));
+ loadBalancer.instance().flatMap(LoadBalancerInstance::ip6Address).ifPresent(ip -> root.setString(lbIp6AddressField, ip));
root.setString(stateField, asString(loadBalancer.state()));
root.setLong(changedAtField, loadBalancer.changedAt().toEpochMilli());
loadBalancer.instance().flatMap(LoadBalancerInstance::dnsZone).ifPresent(dnsZone -> root.setString(dnsZoneField, dnsZone.id()));
@@ -123,7 +125,8 @@ public class LoadBalancerSerializer {
object.field(networksField).traverse((ArrayTraverser) (i, network) -> networks.add(network.asString()));
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<String> ip4Address = optionalString(object.field(lbIpAddressField), Function.identity()).filter(s -> !s.isEmpty());
+ Optional<String> ip6Address = optionalString(object.field(lbIp6AddressField), Function.identity()).filter(s -> !s.isEmpty());
Optional<DnsZone> dnsZone = optionalString(object.field(dnsZoneField), DnsZone::new);
ZoneEndpoint settings = zoneEndpoint(object.field(settingsField));
Optional<PrivateServiceId> serviceId = optionalString(object.field(serviceIdField), PrivateServiceId::of);
@@ -131,9 +134,9 @@ public class LoadBalancerSerializer {
object.field(serviceIdsField).traverse((ArrayTraverser) (__, serviceIdObject) -> serviceIds.add(PrivateServiceId.of(serviceIdObject.asString())));
if (serviceIds.isEmpty()) serviceId.ifPresent(serviceIds::add); // TODO: remove after winter vacation '23
CloudAccount cloudAccount = optionalString(object.field(cloudAccountField), CloudAccount::from).orElse(CloudAccount.empty);
- Optional<LoadBalancerInstance> instance = hostname.isEmpty() && ipAddress.isEmpty()
+ Optional<LoadBalancerInstance> instance = hostname.isEmpty() && ip4Address.isEmpty() && ip6Address.isEmpty()
? Optional.empty()
- : Optional.of(new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, settings, serviceIds, cloudAccount));
+ : Optional.of(new LoadBalancerInstance(hostname, ip4Address, ip6Address, dnsZone, ports, networks, reals, settings, serviceIds, 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/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
index 4236f78336b..e5599ac3d18 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
@@ -18,7 +18,7 @@ import java.util.Map;
import java.util.TreeMap;
import static com.yahoo.config.provision.NodeResources.Architecture;
-import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION_ID;
+import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID;
import static java.util.Objects.requireNonNull;
/**
@@ -146,7 +146,7 @@ public class CapacityPolicies {
}
private Architecture adminClusterArchitecture(ApplicationId instance) {
- return Architecture.valueOf(adminClusterNodeArchitecture.with(APPLICATION_ID, instance.serializedForm()).value());
+ return Architecture.valueOf(adminClusterNodeArchitecture.with(INSTANCE_ID, instance.serializedForm()).value());
}
/** Returns the resources for the newest version not newer than that requested in the cluster spec. */
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 c414c70f315..22909122079 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
@@ -273,7 +273,7 @@ public class LoadBalancerProvisioner {
LoadBalancer currentLoadBalancer,
ZoneEndpoint zoneEndpoint,
CloudAccount cloudAccount) {
- boolean shouldDeactivateRouting = deactivateRouting.with(FetchVector.Dimension.APPLICATION_ID,
+ boolean shouldDeactivateRouting = deactivateRouting.with(FetchVector.Dimension.INSTANCE_ID,
id.application().serializedForm())
.value();
Set<Real> reals = shouldDeactivateRouting ? Set.of() : realsOf(nodes, cloudAccount);
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 b289a965567..ca170d2af6b 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
@@ -94,7 +94,7 @@ class NodeAllocation {
this.nextIndex = nextIndex;
this.nodeRepository = nodeRepository;
this.requiredHostFlavor = Optional.of(PermanentFlags.HOST_FLAVOR.bindTo(nodeRepository.flagSource())
- .with(FetchVector.Dimension.APPLICATION_ID, application.serializedForm())
+ .with(FetchVector.Dimension.INSTANCE_ID, application.serializedForm())
.with(FetchVector.Dimension.CLUSTER_TYPE, cluster.type().name())
.with(FetchVector.Dimension.CLUSTER_ID, cluster.id().value())
.value())
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 06ab9eb1a10..ab222c45252 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
@@ -88,7 +88,7 @@ public class NodeResourceLimits {
if (cluster.type() == ClusterSpec.Type.admin) return 1;
if (!exclusive) return 4;
return minExclusiveAdvertisedMemoryGbFlag
- .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm())
+ .with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm())
.with(FetchVector.Dimension.CLUSTER_ID, cluster.id().value())
.with(FetchVector.Dimension.CLUSTER_TYPE, cluster.type().name())
.value();
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 09f947503f6..20aa7d8181e 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
@@ -57,7 +57,8 @@ public class LoadBalancersResponse extends SlimeJsonResponse {
lbObject.setString("instance", lb.id().application().instance().value());
lbObject.setString("cluster", lb.id().cluster().value());
lb.instance().flatMap(LoadBalancerInstance::hostname).ifPresent(hostname -> lbObject.setString("hostname", hostname.value()));
- lb.instance().flatMap(LoadBalancerInstance::ipAddress).ifPresent(ipAddress -> lbObject.setString("ipAddress", ipAddress));
+ lb.instance().flatMap(LoadBalancerInstance::ip4Address).ifPresent(ip -> lbObject.setString("ipAddress", ip));
+ lb.instance().flatMap(LoadBalancerInstance::ip6Address).ifPresent(ip -> lbObject.setString("ip6Address", ip));
lb.instance().flatMap(LoadBalancerInstance::dnsZone).ifPresent(dnsZone -> lbObject.setString("dnsZone", dnsZone.id()));
Cursor networkArray = lbObject.setArray("networks");
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 2b908efde94..a8f526544d7 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
@@ -201,7 +201,7 @@ class NodesResponse extends SlimeJsonResponse {
.with(FetchVector.Dimension.HOSTNAME, node.hostname())
.with(FetchVector.Dimension.NODE_TYPE, node.type().name())
.with(FetchVector.Dimension.TENANT_ID, allocation.owner().tenant().value())
- .with(FetchVector.Dimension.APPLICATION_ID, allocation.owner().serializedForm())
+ .with(FetchVector.Dimension.INSTANCE_ID, allocation.owner().serializedForm())
.with(FetchVector.Dimension.CLUSTER_TYPE, allocation.membership().cluster().type().name())
.with(FetchVector.Dimension.CLUSTER_ID, allocation.membership().cluster().id().value())
.with(FetchVector.Dimension.VESPA_VERSION, allocation.membership().cluster().vespaVersion().toFullString())
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 6dc681ae5c8..b5257e23d9e 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
@@ -40,6 +40,7 @@ public class LoadBalancerSerializerTest {
Optional.of(new LoadBalancerInstance(
Optional.of(DomainName.of("lb-host")),
Optional.empty(),
+ Optional.empty(),
Optional.of(new DnsZone("zone-id-1")),
Set.of(4080, 4443),
Set.of("10.2.3.4/24"),
@@ -73,6 +74,7 @@ public class LoadBalancerSerializerTest {
Optional.of(new LoadBalancerInstance(
Optional.empty(),
Optional.of("1.2.3.4"),
+ Optional.of("fd00::1"),
Optional.of(new DnsZone("zone-id-1")),
Set.of(4443),
Set.of("10.2.3.4/24", "12.3.2.1/30"),
@@ -86,6 +88,8 @@ public class LoadBalancerSerializerTest {
var serialized = LoadBalancerSerializer.fromJson(LoadBalancerSerializer.toJson(loadBalancer));
assertEquals(loadBalancer.id(), serialized.id());
assertEquals(loadBalancer.instance().get().hostname(), serialized.instance().get().hostname());
+ assertEquals(loadBalancer.instance().get().ip4Address(), serialized.instance().get().ip4Address());
+ assertEquals(loadBalancer.instance().get().ip6Address(), serialized.instance().get().ip6Address());
assertEquals(loadBalancer.instance().get().dnsZone(), serialized.instance().get().dnsZone());
assertEquals(loadBalancer.instance().get().ports(), serialized.instance().get().ports());
assertEquals(loadBalancer.instance().get().networks(), serialized.instance().get().networks());