diff options
author | Jon Bratseth <bratseth@gmail.com> | 2022-10-12 15:55:11 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@gmail.com> | 2022-10-12 15:55:11 +0200 |
commit | 5e0502391c2ca7c4b0bfc9f4f652da2676f26314 (patch) | |
tree | 1fb5c7073f0af7b111d3290e4295a323d0d9ece2 /configserver | |
parent | 08f7a121fff008dd1307b106bd1b7d7a84433fe6 (diff) |
Add instance tags
Diffstat (limited to 'configserver')
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()); |