summaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2022-10-12 15:55:11 +0200
committerJon Bratseth <bratseth@gmail.com>2022-10-12 15:55:11 +0200
commit5e0502391c2ca7c4b0bfc9f4f652da2676f26314 (patch)
tree1fb5c7073f0af7b111d3290e4295a323d0d9ece2 /configserver
parent08f7a121fff008dd1307b106bd1b7d7a84433fe6 (diff)
Add instance tags
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java16
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java11
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java61
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java9
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java19
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java27
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java16
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java9
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java15
12 files changed, 151 insertions, 40 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index f832c504526..589dfa775ae 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -23,6 +23,7 @@ import com.yahoo.config.provision.InfraDeployer;
import com.yahoo.config.provision.Provisioner;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
import com.yahoo.config.provision.exception.ActivationConflictException;
@@ -357,8 +358,11 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
}
private PrepareResult deploy(File applicationDir, PrepareParams prepareParams, DeployHandlerLogger logger) {
- ApplicationId applicationId = prepareParams.getApplicationId();
- long sessionId = createSession(applicationId, prepareParams.getTimeoutBudget(), applicationDir, logger);
+ long sessionId = createSession(prepareParams.getApplicationId(),
+ prepareParams.tags(),
+ prepareParams.getTimeoutBudget(),
+ applicationDir,
+ logger);
Deployment deployment = prepare(sessionId, prepareParams, logger);
if ( ! prepareParams.isDryRun())
@@ -821,21 +825,21 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
return sessionRepository.createSessionFromExisting(fromSession, internalRedeploy, timeoutBudget, deployLogger).getSessionId();
}
- public long createSession(ApplicationId applicationId, TimeoutBudget timeoutBudget, InputStream in,
+ public long createSession(ApplicationId applicationId, Tags tags, TimeoutBudget timeoutBudget, InputStream in,
String contentType, DeployLogger logger) {
File tempDir = uncheck(() -> Files.createTempDirectory("deploy")).toFile();
long sessionId;
try {
- sessionId = createSession(applicationId, timeoutBudget, decompressApplication(in, contentType, tempDir), logger);
+ sessionId = createSession(applicationId, tags, timeoutBudget, decompressApplication(in, contentType, tempDir), logger);
} finally {
cleanupTempDirectory(tempDir, logger);
}
return sessionId;
}
- public long createSession(ApplicationId applicationId, TimeoutBudget timeoutBudget, File applicationDirectory, DeployLogger deployLogger) {
+ public long createSession(ApplicationId applicationId, Tags tags, TimeoutBudget timeoutBudget, File applicationDirectory, DeployLogger deployLogger) {
SessionRepository sessionRepository = getTenant(applicationId).getSessionRepository();
- Session session = sessionRepository.createSessionFromApplicationPackage(applicationDirectory, applicationId, timeoutBudget, deployLogger);
+ Session session = sessionRepository.createSessionFromApplicationPackage(applicationDirectory, applicationId, tags, timeoutBudget, deployLogger);
return session.getSessionId();
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java
index f29b05b66af..71702e2926c 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java
@@ -6,6 +6,7 @@ import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.InstanceName;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
@@ -46,7 +47,7 @@ public class SessionCreateHandler extends SessionHandler {
@Override
protected HttpResponse handlePOST(HttpRequest request) {
- final TenantName tenantName = Utils.getTenantNameFromSessionRequest(request);
+ TenantName tenantName = Utils.getTenantNameFromSessionRequest(request);
Utils.checkThatTenantExists(applicationRepository.tenantRepository(), tenantName);
TimeoutBudget timeoutBudget = SessionHandler.getTimeoutBudget(request, zookeeperBarrierTimeout);
boolean verbose = request.getBooleanProperty("verbose");
@@ -62,8 +63,12 @@ public class SessionCreateHandler extends SessionHandler {
logger = DeployHandlerLogger.forTenant(tenantName, verbose);
// TODO: Avoid using application id here at all
ApplicationId applicationId = ApplicationId.from(tenantName, ApplicationName.defaultName(), InstanceName.defaultName());
- sessionId = applicationRepository.createSession(applicationId, timeoutBudget, request.getData(),
- request.getHeader(ApplicationApiHandler.contentTypeHeader), logger);
+ sessionId = applicationRepository.createSession(applicationId,
+ Tags.empty(),
+ timeoutBudget,
+ request.getData(),
+ request.getHeader(ApplicationApiHandler.contentTypeHeader),
+ logger);
}
return new SessionCreateResponse(logger.slime(), tenantName, request.getHost(), request.getPort(), sessionId);
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
index 175b6f6457f..ec673377af9 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
@@ -10,6 +10,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.DockerImage;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.security.X509CertificateUtils;
@@ -41,6 +42,7 @@ public final class PrepareParams {
static final String APPLICATION_NAME_PARAM_NAME = "applicationName";
static final String INSTANCE_PARAM_NAME = "instance";
+ static final String TAGS_PARAM_NAME = "tags";
static final String IGNORE_VALIDATION_PARAM_NAME = "ignoreValidationErrors";
static final String DRY_RUN_PARAM_NAME = "dryRun";
static final String VERBOSE_PARAM_NAME = "verbose";
@@ -57,6 +59,7 @@ public final class PrepareParams {
static final String CLOUD_ACCOUNT = "cloudAccount";
private final ApplicationId applicationId;
+ private final Tags tags;
private final TimeoutBudget timeoutBudget;
private final boolean ignoreValidationErrors;
private final boolean dryRun;
@@ -74,16 +77,27 @@ public final class PrepareParams {
private final List<X509Certificate> operatorCertificates;
private final Optional<CloudAccount> cloudAccount;
- private PrepareParams(ApplicationId applicationId, TimeoutBudget timeoutBudget, boolean ignoreValidationErrors,
- boolean dryRun, boolean verbose, boolean isBootstrap, Optional<Version> vespaVersion,
+ private PrepareParams(ApplicationId applicationId,
+ Tags tags,
+ TimeoutBudget timeoutBudget,
+ boolean ignoreValidationErrors,
+ boolean dryRun,
+ boolean verbose,
+ boolean isBootstrap,
+ Optional<Version> vespaVersion,
List<ContainerEndpoint> containerEndpoints,
Optional<EndpointCertificateMetadata> endpointCertificateMetadata,
- Optional<DockerImage> dockerImageRepository, Optional<AthenzDomain> athenzDomain,
- Optional<Quota> quota, List<TenantSecretStore> tenantSecretStores,
- boolean force, boolean waitForResourcesInPrepare, List<X509Certificate> operatorCertificates,
+ Optional<DockerImage> dockerImageRepository,
+ Optional<AthenzDomain> athenzDomain,
+ Optional<Quota> quota,
+ List<TenantSecretStore> tenantSecretStores,
+ boolean force,
+ boolean waitForResourcesInPrepare,
+ List<X509Certificate> operatorCertificates,
Optional<CloudAccount> cloudAccount) {
this.timeoutBudget = timeoutBudget;
this.applicationId = Objects.requireNonNull(applicationId);
+ this.tags = tags;
this.ignoreValidationErrors = ignoreValidationErrors;
this.dryRun = dryRun;
this.verbose = verbose;
@@ -110,6 +124,7 @@ public final class PrepareParams {
private boolean force = false;
private boolean waitForResourcesInPrepare = false;
private ApplicationId applicationId = null;
+ private Tags tags = Tags.empty();
private TimeoutBudget timeoutBudget = new TimeoutBudget(Clock.systemUTC(), Duration.ofSeconds(60));
private Optional<Version> vespaVersion = Optional.empty();
private List<ContainerEndpoint> containerEndpoints = null;
@@ -128,6 +143,11 @@ public final class PrepareParams {
return this;
}
+ public Builder tags(Tags tags) {
+ this.tags = tags;
+ return this;
+ }
+
public Builder ignoreValidationErrors(boolean ignoreValidationErrors) {
this.ignoreValidationErrors = ignoreValidationErrors;
return this;
@@ -258,11 +278,24 @@ public final class PrepareParams {
}
public PrepareParams build() {
- return new PrepareParams(applicationId, timeoutBudget, ignoreValidationErrors, dryRun,
- verbose, isBootstrap, vespaVersion, containerEndpoints,
- endpointCertificateMetadata, dockerImageRepository, athenzDomain,
- quota, tenantSecretStores, force, waitForResourcesInPrepare,
- operatorCertificates, cloudAccount);
+ return new PrepareParams(applicationId,
+ tags,
+ timeoutBudget,
+ ignoreValidationErrors,
+ dryRun,
+ verbose,
+ isBootstrap,
+ vespaVersion,
+ containerEndpoints,
+ endpointCertificateMetadata,
+ dockerImageRepository,
+ athenzDomain,
+ quota,
+ tenantSecretStores,
+ force,
+ waitForResourcesInPrepare,
+ operatorCertificates,
+ cloudAccount);
}
}
@@ -273,6 +306,7 @@ public final class PrepareParams {
.verbose(request.getBooleanProperty(VERBOSE_PARAM_NAME))
.timeoutBudget(SessionHandler.getTimeoutBudget(request, barrierTimeout))
.applicationId(createApplicationId(request, tenant))
+ .tags(Tags.fromString(request.getProperty(TAGS_PARAM_NAME)))
.vespaVersion(request.getProperty(VESPA_VERSION_PARAM_NAME))
.containerEndpoints(request.getProperty(CONTAINER_ENDPOINTS_PARAM_NAME))
.endpointCertificateMetadata(request.getProperty(ENDPOINT_CERTIFICATE_METADATA_PARAM_NAME))
@@ -295,6 +329,7 @@ public final class PrepareParams {
.verbose(booleanValue(params, VERBOSE_PARAM_NAME))
.timeoutBudget(SessionHandler.getTimeoutBudget(getTimeout(params, barrierTimeout)))
.applicationId(createApplicationId(params, tenant))
+ .tags(Tags.fromString(params.field(TAGS_PARAM_NAME).asString()))
.vespaVersion(SlimeUtils.optionalString(params.field(VESPA_VERSION_PARAM_NAME)).orElse(null))
.containerEndpointList(deserialize(params.field(CONTAINER_ENDPOINTS_PARAM_NAME), ContainerEndpointSerializer::endpointListFromSlime, List.of()))
.endpointCertificateMetadata(deserialize(params.field(ENDPOINT_CERTIFICATE_METADATA_PARAM_NAME), EndpointCertificateMetadataSerializer::fromSlime))
@@ -367,9 +402,9 @@ public final class PrepareParams {
return applicationId.application().value();
}
- public ApplicationId getApplicationId() {
- return applicationId;
- }
+ public ApplicationId getApplicationId() { return applicationId; }
+
+ public Tags tags() { return tags; }
/** Returns the Vespa version the nodes running the prepared system should have, or empty to use the system version */
public Optional<Version> vespaVersion() { return vespaVersion; }
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java
index 82faeae01e8..e4bbe120c11 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java
@@ -12,6 +12,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.DockerImage;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.path.Path;
import com.yahoo.transaction.Transaction;
@@ -119,6 +120,10 @@ public abstract class Session implements Comparable<Session> {
sessionZooKeeperClient.writeApplicationId(applicationId);
}
+ public void setTags(Tags tags) {
+ sessionZooKeeperClient.writeTags(tags);
+ }
+
void setApplicationPackageReference(FileReference applicationPackageReference) {
sessionZooKeeperClient.writeApplicationPackageReference(Optional.ofNullable(applicationPackageReference));
}
@@ -153,6 +158,10 @@ public abstract class Session implements Comparable<Session> {
.orElseThrow(() -> new RuntimeException("Unable to read application id for session " + sessionId));
}
+ public Tags getTags() {
+ return sessionZooKeeperClient.readTags();
+ }
+
/** Returns application id read from ZooKeeper. Will return Optional.empty() if not found */
public Optional<ApplicationId> getOptionalApplicationId() {
try {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
index 71df5a8829e..8d023cac88a 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
@@ -24,6 +24,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.DockerImage;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.Zone;
import com.yahoo.container.jdisc.secretstore.SecretStore;
import com.yahoo.net.HostName;
@@ -157,6 +158,7 @@ public class SessionPreparer {
final PrepareParams params;
final ApplicationId applicationId;
+ final Tags tags;
/** The repository part of docker image to be used for this deployment */
final Optional<DockerImage> dockerImageRepository;
@@ -188,6 +190,7 @@ public class SessionPreparer {
this.applicationPackage = applicationPackage;
this.sessionZooKeeperClient = sessionZooKeeperClient;
this.applicationId = params.getApplicationId();
+ this.tags = params.tags();
this.dockerImageRepository = params.dockerImageRepository();
this.vespaVersion = params.vespaVersion().orElse(Vtag.currentVersion);
this.containerEndpointsCache = new ContainerEndpointsCache(tenantPath, curator);
@@ -224,7 +227,7 @@ public class SessionPreparer {
if (! timeoutBudget.hasTimeLeft(step)) {
String used = timeoutBudget.timesUsed();
throw new UncheckedTimeoutException("prepare timed out " + used + " after " + step +
- " step (timeout " + timeoutBudget.timeout() + "): " + applicationId);
+ " step (timeout " + timeoutBudget.timeout() + "): " + applicationId);
}
}
@@ -248,7 +251,7 @@ public class SessionPreparer {
this.preprocessedApplicationPackage = applicationPackage.preprocess(zone, logger);
} catch (IOException | RuntimeException e) {
throw new IllegalArgumentException("Error preprocessing application package for " + applicationId +
- ", session " + sessionZooKeeperClient.sessionId(), e);
+ ", session " + sessionZooKeeperClient.sessionId(), e);
}
checkTimeout("preprocess");
}
@@ -318,10 +321,11 @@ public class SessionPreparer {
void vespaPreprocess(File appDir, File inputXml, ApplicationMetaData metaData) {
try {
new XmlPreProcessor(appDir,
- inputXml,
- metaData.getApplicationId().instance(),
- zone.environment(),
- zone.region())
+ inputXml,
+ metaData.getApplicationId().instance(),
+ zone.environment(),
+ zone.region(),
+ metaData.getTags())
.run();
} catch (ParserConfigurationException | IOException | SAXException | TransformerException e) {
throw new RuntimeException(e);
@@ -346,6 +350,7 @@ public class SessionPreparer {
writeStateToZooKeeper(sessionZooKeeperClient,
preprocessedApplicationPackage,
applicationId,
+ tags,
filereference,
dockerImageRepository,
vespaVersion,
@@ -387,6 +392,7 @@ public class SessionPreparer {
private void writeStateToZooKeeper(SessionZooKeeperClient zooKeeperClient,
ApplicationPackage applicationPackage,
ApplicationId applicationId,
+ Tags tags,
FileReference fileReference,
Optional<DockerImage> dockerImageRepository,
Version vespaVersion,
@@ -403,6 +409,7 @@ public class SessionPreparer {
zkDeployer.deploy(applicationPackage, fileRegistryMap, allocatedHosts);
// Note: When changing the below you need to also change similar calls in SessionRepository.createSessionFromExisting()
zooKeeperClient.writeApplicationId(applicationId);
+ zooKeeperClient.writeTags(tags);
zooKeeperClient.writeApplicationPackageReference(Optional.of(fileReference));
zooKeeperClient.writeVespaVersion(vespaVersion);
zooKeeperClient.writeDockerImageRepository(dockerImageRepository);
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 9e7af5a44a3..e686b17a1ae 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
@@ -13,6 +13,7 @@ import com.yahoo.config.model.api.ConfigDefinitionRepo;
import com.yahoo.config.model.application.provider.DeployData;
import com.yahoo.config.model.application.provider.FilesApplicationPackage;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
import com.yahoo.container.jdisc.secretstore.SecretStore;
@@ -282,10 +283,17 @@ public class SessionRepository {
TimeoutBudget timeoutBudget,
DeployLogger deployLogger) {
ApplicationId existingApplicationId = existingSession.getApplicationId();
+ Tags existingTags = existingSession.getTags();
File existingApp = getSessionAppDir(existingSession.getSessionId());
- LocalSession session = createSessionFromApplication(existingApp, existingApplicationId, internalRedeploy, timeoutBudget, deployLogger);
+ LocalSession session = createSessionFromApplication(existingApp,
+ existingApplicationId,
+ existingTags,
+ internalRedeploy,
+ timeoutBudget,
+ deployLogger);
// Note: Setters below need to be kept in sync with calls in SessionPreparer.writeStateToZooKeeper()
session.setApplicationId(existingApplicationId);
+ session.setTags(existingTags);
session.setApplicationPackageReference(existingSession.getApplicationPackageReference());
session.setVespaVersion(existingSession.getVespaVersion());
session.setDockerImageRepository(existingSession.getDockerImageRepository());
@@ -306,19 +314,20 @@ public class SessionRepository {
*/
public LocalSession createSessionFromApplicationPackage(File applicationDirectory,
ApplicationId applicationId,
+ Tags tags,
TimeoutBudget timeoutBudget,
DeployLogger deployLogger) {
applicationRepo.createApplication(applicationId);
- return createSessionFromApplication(applicationDirectory, applicationId, false, timeoutBudget, deployLogger);
+ return createSessionFromApplication(applicationDirectory, applicationId, tags, false, timeoutBudget, deployLogger);
}
/**
* Creates a local session based on a remote session and the distributed application package.
* Does not wait for session being created on other servers.
*/
- private void createLocalSession(File applicationFile, ApplicationId applicationId, long sessionId) {
+ private void createLocalSession(File applicationFile, ApplicationId applicationId, Tags tags, long sessionId) {
try {
- ApplicationPackage applicationPackage = createApplicationPackage(applicationFile, applicationId, sessionId, false, Optional.empty());
+ ApplicationPackage applicationPackage = createApplicationPackage(applicationFile, applicationId, tags, sessionId, false, Optional.empty());
createLocalSession(sessionId, applicationPackage);
} catch (Exception e) {
throw new RuntimeException("Error creating session " + sessionId, e);
@@ -706,12 +715,13 @@ public class SessionRepository {
private ApplicationPackage createApplication(File userDir,
File configApplicationDir,
ApplicationId applicationId,
+ Tags tags,
long sessionId,
Optional<Long> currentlyActiveSessionId,
boolean internalRedeploy,
Optional<DeployLogger> deployLogger) {
long deployTimestamp = System.currentTimeMillis();
- DeployData deployData = new DeployData(userDir.getAbsolutePath(), applicationId, deployTimestamp, internalRedeploy,
+ DeployData deployData = new DeployData(userDir.getAbsolutePath(), applicationId, tags, deployTimestamp, internalRedeploy,
sessionId, currentlyActiveSessionId.orElse(nonExistingActiveSessionId));
FilesApplicationPackage app = FilesApplicationPackage.fromFileWithDeployData(configApplicationDir, deployData);
validateFileExtensions(applicationId, deployLogger, app);
@@ -739,13 +749,14 @@ public class SessionRepository {
private LocalSession createSessionFromApplication(File applicationDirectory,
ApplicationId applicationId,
+ Tags tags,
boolean internalRedeploy,
TimeoutBudget timeoutBudget,
DeployLogger deployLogger) {
long sessionId = getNextSessionId();
try {
ensureSessionPathDoesNotExist(sessionId);
- ApplicationPackage app = createApplicationPackage(applicationDirectory, applicationId, sessionId, internalRedeploy, Optional.of(deployLogger));
+ ApplicationPackage app = createApplicationPackage(applicationDirectory, applicationId, tags, sessionId, internalRedeploy, Optional.of(deployLogger));
log.log(Level.FINE, () -> TenantRepository.logPre(tenantName) + "Creating session " + sessionId + " in ZooKeeper");
SessionZooKeeperClient sessionZKClient = createSessionZooKeeperClient(sessionId);
sessionZKClient.createNewSession(clock.instant());
@@ -761,6 +772,7 @@ public class SessionRepository {
private ApplicationPackage createApplicationPackage(File applicationDirectory,
ApplicationId applicationId,
+ Tags tags,
long sessionId,
boolean internalRedeploy,
Optional<DeployLogger> deployLogger) throws IOException {
@@ -773,6 +785,7 @@ public class SessionRepository {
ApplicationPackage applicationPackage = createApplication(applicationDirectory,
userApplicationDir,
applicationId,
+ tags,
sessionId,
activeSessionId,
internalRedeploy,
@@ -884,7 +897,7 @@ public class SessionRepository {
ApplicationId applicationId = sessionZKClient.readApplicationId()
.orElseThrow(() -> new RuntimeException("Could not find application id for session " + sessionId));
log.log(Level.FINE, () -> "Creating local session for tenant '" + tenantName + "' with session id " + sessionId);
- createLocalSession(sessionDir, applicationId, sessionId);
+ createLocalSession(sessionDir, applicationId, sessionZKClient.readTags(), sessionId);
}
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
index 988d13b1978..9218b03af1e 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
@@ -14,6 +14,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.DockerImage;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.path.Path;
import com.yahoo.slime.SlimeUtils;
@@ -57,6 +58,7 @@ public class SessionZooKeeperClient {
// NOTE: Any state added here MUST also be propagated in com.yahoo.vespa.config.server.deploy.Deployment.prepare()
static final String APPLICATION_ID_PATH = "applicationId";
+ static final String TAGS_PATH = "tags";
static final String APPLICATION_PACKAGE_REFERENCE_PATH = "applicationPackageReference";
private static final String VERSION_PATH = "version";
private static final String CREATE_TIME_PATH = "createTime";
@@ -171,6 +173,20 @@ public class SessionZooKeeperClient {
return curator.getData(applicationIdPath()).map(d -> ApplicationId.fromSerializedForm(Utf8.toString(d)));
}
+ private Path tagsPath() {
+ return sessionPath.append(TAGS_PATH);
+ }
+
+ public void writeTags(Tags tags) {
+ curator.set(tagsPath(), Utf8.toBytes(tags.asString()));
+ }
+
+ public Tags readTags() {
+ Optional<byte[]> data = curator.getData(tagsPath());
+ if (data.isEmpty()) return Tags.empty();
+ return Tags.fromString(Utf8.toString(data.get()));
+ }
+
void writeApplicationPackageReference(Optional<FileReference> applicationPackageReference) {
applicationPackageReference.ifPresent(
reference -> curator.set(applicationPackageReferencePath(), Utf8.toBytes(reference.value())));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
index 4f7be104b9c..4f14d57d748 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
@@ -17,6 +17,7 @@ import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NetworkPorts;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.exception.ActivationConflictException;
import com.yahoo.container.jdisc.HttpResponse;
@@ -849,7 +850,7 @@ public class ApplicationRepositoryTest {
}
private long createSession(ApplicationId applicationId, TimeoutBudget timeoutBudget, File app) {
- return applicationRepository.createSession(applicationId, timeoutBudget, app, new BaseDeployLogger());
+ return applicationRepository.createSession(applicationId, Tags.empty(), timeoutBudget, app, new BaseDeployLogger());
}
private long createSessionFromExisting(ApplicationId applicationId, TimeoutBudget timeoutBudget) {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
index fd6440a9632..653753c97e7 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
@@ -13,6 +13,7 @@ import com.yahoo.config.model.application.provider.MockFileRegistry;
import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.HostSpec;
+import com.yahoo.config.provision.Tags;
import com.yahoo.path.Path;
import com.yahoo.text.Utf8;
import com.yahoo.vespa.config.server.zookeeper.ZKApplicationPackage;
@@ -59,6 +60,7 @@ public class ZooKeeperClientTest {
ApplicationPackage app = FilesApplicationPackage.fromFileWithDeployData(new File("src/test/apps/zkfeed"),
new DeployData("/bar/baz",
ApplicationId.from("default", "appName", "default"),
+ Tags.fromString("tag1 tag2"),
1345L,
true,
3L,
@@ -121,6 +123,7 @@ public class ZooKeeperClientTest {
assertTrue(metaData.getChecksum().length() > 0);
assertTrue(metaData.isInternalRedeploy());
assertEquals("/bar/baz", metaData.getDeployPath());
+ assertEquals(Tags.fromString("tag1 tag2"), metaData.getTags());
assertEquals(1345, metaData.getDeployTimestamp().longValue());
assertEquals(3, metaData.getGeneration().longValue());
assertEquals(2, metaData.getPreviousActiveGeneration());
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
index 1c71ef0b7fb..816f7e3dcec 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
@@ -6,6 +6,7 @@ import com.yahoo.component.Version;
import com.yahoo.config.application.api.ApplicationMetaData;
import com.yahoo.config.model.application.provider.BaseDeployLogger;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
import com.yahoo.container.jdisc.HttpResponse;
@@ -131,6 +132,7 @@ public class SessionActiveHandlerTest {
void invoke() {
long sessionId = applicationRepository.createSession(applicationId(),
+ Tags.empty(),
new TimeoutBudget(clock, Duration.ofSeconds(10)),
testApp,
new BaseDeployLogger());
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
index 2b07cffffce..74c6febb7e6 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
@@ -10,6 +10,7 @@ import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeAllocationException;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.jdisc.http.HttpRequest;
@@ -187,7 +188,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
}
@Test
- public void require_that_preparing_with_multiple_tenants_work() throws Exception {
+ public void prepare_with_multiple_tenants() throws Exception {
SessionHandler handler = createHandler();
TenantName defaultTenant = TenantName.from("test2");
@@ -206,7 +207,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
assertEquals(sessionId, sessionId2); // Want to test when they are equal (but for different tenants)
pathPrefix = "/application/v2/tenant/" + tenant + "/session/" + sessionId2 +
- "/prepared?applicationName=" + applicationName;
+ "/prepared?applicationName=" + applicationName;
response = handler.handle(SessionHandlerTest.createTestRequest(pathPrefix));
assertNotNull(response);
assertEquals(SessionHandlerTest.getRenderedString(response), OK, response.getStatus());
@@ -214,7 +215,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
ApplicationId applicationId3 = ApplicationId.from(tenant.value(), applicationName, "quux");
long sessionId3 = createSession(applicationId3);
pathPrefix = "/application/v2/tenant/" + tenant + "/session/" + sessionId3 +
- "/prepared?applicationName=" + applicationName + "&instance=quux";
+ "/prepared?applicationName=" + applicationName + "&instance=quux";
response = handler.handle(SessionHandlerTest.createTestRequest(pathPrefix));
assertNotNull(response);
assertEquals(SessionHandlerTest.getRenderedString(response), OK, response.getStatus());
@@ -324,7 +325,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
}
private long createSession(ApplicationId applicationId) {
- return applicationRepository.createSession(applicationId, timeoutBudget, app, new BaseDeployLogger());
+ return applicationRepository.createSession(applicationId, Tags.empty(), timeoutBudget, app, new BaseDeployLogger());
}
private static class FailingSessionPrepareHandler extends SessionPrepareHandler {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
index e5b550fdc1a..34921db1bb7 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
@@ -7,6 +7,7 @@ import com.yahoo.config.model.api.EndpointCertificateMetadata;
import com.yahoo.config.model.api.TenantSecretStore;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.CloudAccount;
+import com.yahoo.config.provision.Tags;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
@@ -62,6 +63,7 @@ public class PrepareParamsTest {
PrepareParams prepareParams = createParams("http://foo:19071/application/v2/", TenantName.defaultName());
assertEquals(ApplicationId.defaultId(), prepareParams.getApplicationId());
+ assertTrue(prepareParams.tags().isEmpty());
assertFalse(prepareParams.isDryRun());
assertFalse(prepareParams.isVerbose());
assertFalse(prepareParams.ignoreValidationErrors());
@@ -72,6 +74,18 @@ public class PrepareParamsTest {
}
@Test
+ public void testTagsParsing() throws IOException {
+ var prepareParams = createParams(request + "&" + PrepareParams.TAGS_PARAM_NAME + "=tag1%20tag2", TenantName.from("foo"));
+ assertEquals(Tags.fromString("tag1 tag2"), prepareParams.tags());
+
+ // Verify using json object
+ var slime = SlimeUtils.jsonToSlime(json);
+ slime.get().setString(PrepareParams.TAGS_PARAM_NAME, "tag1 tag2");
+ PrepareParams prepareParamsJson = PrepareParams.fromJson(SlimeUtils.toJsonBytes(slime), TenantName.from("foo"), Duration.ofSeconds(60));
+ assertPrepareParamsEqual(prepareParams, prepareParamsJson);
+ }
+
+ @Test
public void testCorrectParsingWithContainerEndpoints() throws IOException {
var endpoints = List.of(new ContainerEndpoint("qrs1", ApplicationClusterEndpoint.Scope.global,
List.of("c1.example.com",
@@ -207,6 +221,7 @@ public class PrepareParamsTest {
assertEquals(urlParams.force(), jsonParams.force());
assertEquals(urlParams.waitForResourcesInPrepare(), jsonParams.waitForResourcesInPrepare());
assertEquals(urlParams.getApplicationId(), jsonParams.getApplicationId());
+ assertEquals(urlParams.tags(), jsonParams.tags());
assertEquals(urlParams.getTimeoutBudget().timeout(), jsonParams.getTimeoutBudget().timeout());
assertEquals(urlParams.vespaVersion(), jsonParams.vespaVersion());
assertEquals(urlParams.containerEndpoints(), jsonParams.containerEndpoints());