diff options
author | Jon Bratseth <jonbratseth@yahoo.com> | 2016-07-08 15:16:01 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-08 15:16:01 +0200 |
commit | a2d774f4d8412862b425de61d7c8ac8d82c6e593 (patch) | |
tree | dc521c2f68afea0d1a137bd97cbd81c6c3da8895 /configserver | |
parent | f85ca3c2afdb7e909e7814a6f1f34a8b32d7019c (diff) | |
parent | c990441c379cb20e5049c7dae842b1f03c4624c1 (diff) |
Merge pull request #342 from yahoo/bratseth/transactional-application-remove
Bratseth/transactional application remove
Diffstat (limited to 'configserver')
138 files changed, 1160 insertions, 604 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java index 00a036df9d5..c32fef58b01 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java @@ -1,32 +1,40 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.deploy; +package com.yahoo.vespa.config.server; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Provisioner; -import com.yahoo.vespa.config.server.ActivateLock; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; -import com.yahoo.vespa.config.server.TimeoutBudget; +import com.yahoo.log.LogLevel; +import com.yahoo.transaction.NestedTransaction; +import com.yahoo.vespa.config.server.application.TenantApplications; +import com.yahoo.vespa.config.server.deploy.Deployment; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.session.LocalSession; import com.yahoo.vespa.config.server.session.LocalSessionRepo; import com.yahoo.vespa.config.server.session.SilentDeployLogger; +import com.yahoo.vespa.config.server.tenant.ActivateLock; +import com.yahoo.vespa.config.server.tenant.Rotations; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.curator.Curator; import java.time.Clock; import java.time.Duration; import java.util.Optional; +import java.util.logging.Logger; /** - * The API for deploying applications. - * A class which needs to deploy applications can have an instance of this injected. + * The API for managing applications. * * @author bratseth */ -public class Deployer implements com.yahoo.config.provision.Deployer { +// TODO: Move logic for dealing with applications here from the HTTP layer and make this the persistent component +// owning the rest of the state +public class ApplicationRepository implements com.yahoo.config.provision.Deployer { + private static final Logger log = Logger.getLogger(ApplicationRepository.class.getName()); + private final Tenants tenants; private final Optional<Provisioner> hostProvisioner; private final ConfigserverConfig configserverConfig; @@ -34,8 +42,8 @@ public class Deployer implements com.yahoo.config.provision.Deployer { private final Clock clock; private final DeployLogger logger = new SilentDeployLogger(); - public Deployer(Tenants tenants, HostProvisionerProvider hostProvisionerProvider, - ConfigserverConfig configserverConfig, Curator curator) { + public ApplicationRepository(Tenants tenants, HostProvisionerProvider hostProvisionerProvider, + ConfigserverConfig configserverConfig, Curator curator) { this.tenants = tenants; this.hostProvisioner = hostProvisionerProvider.getHostProvisioner(); this.configserverConfig = configserverConfig; @@ -77,4 +85,39 @@ public class Deployer implements com.yahoo.config.provision.Deployer { timeout, clock); } + /** + * Removes a previously deployed application + * + * @return true if the application was found and removed, false if it was not present + * @throws RuntimeException if the remove transaction fails. This method is exception safe. + */ + public boolean remove(ApplicationId applicationId) { + Optional<Tenant> owner = Optional.ofNullable(tenants.tenantsCopy().get(applicationId.tenant())); + if ( ! owner.isPresent()) return false; + + TenantApplications tenantApplications = owner.get().getApplicationRepo(); + if ( ! tenantApplications.listApplications().contains(applicationId)) return false; + + // TODO: Push lookup logic down + long sessionId = tenantApplications.getSessionIdForApplication(applicationId); + LocalSessionRepo localSessionRepo = owner.get().getLocalSessionRepo(); + LocalSession session = localSessionRepo.getSession(sessionId); + if (session == null) return false; + + NestedTransaction transaction = new NestedTransaction(); + localSessionRepo.removeSession(session.getSessionId(), transaction); + session.delete(transaction); // TODO: Not tested + + transaction.add(new Rotations(owner.get().getCurator(), owner.get().getPath()).delete(applicationId)); // TODO: Not tested + + transaction.add(tenantApplications.deleteApplication(applicationId)); + + if (hostProvisioner.isPresent()) + hostProvisioner.get().remove(transaction, applicationId); + transaction.onCommitted(() -> log.log(LogLevel.INFO, "Deleted " + applicationId)); + transaction.commit(); + + return true; + } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java index b4a0f6135c3..ddf318eed9f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java @@ -5,6 +5,8 @@ import com.google.inject.Inject; import com.yahoo.component.AbstractComponent; import com.yahoo.config.provision.Deployer; import com.yahoo.log.LogLevel; +import com.yahoo.vespa.config.server.rpc.RpcServer; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.version.VersionState; /** diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerSpec.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerSpec.java index a84985d738c..8db2f05e0a9 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerSpec.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerSpec.java @@ -10,6 +10,7 @@ import java.util.List; * @author tonytv */ public class ConfigServerSpec implements com.yahoo.config.model.api.ConfigServerSpec { + private final String hostName; private final int configServerPort; private final int httpPort; @@ -70,4 +71,5 @@ public class ConfigServerSpec implements com.yahoo.config.model.api.ConfigServer public String toString() { return "hostname=" + hostName + ", rpc port=" + configServerPort + ", http port=" + httpPort + ", zookeeper port=" + zooKeeperPort; } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigContext.java b/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigContext.java index e27a1c56dc3..2b1a2f0142e 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigContext.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigContext.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.config.server; import com.yahoo.vespa.config.protocol.Trace; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.config.server.tenant.Tenants; /** * Contains the context for serving getconfig requests so that this information does not have to be looked up multiple times. diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java index 7ea65173a53..a1ee3da6703 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java @@ -6,9 +6,11 @@ import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.provision.Provisioner; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; +import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.vespa.config.server.session.SessionPreparer; +import com.yahoo.vespa.config.server.tenant.TenantListener; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; import com.yahoo.vespa.curator.Curator; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java index fd5529cdffd..25e17398082 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java @@ -7,10 +7,13 @@ import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.provision.Provisioner; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; +import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; +import com.yahoo.vespa.config.server.rpc.RpcServer; import com.yahoo.vespa.config.server.session.SessionPreparer; +import com.yahoo.vespa.config.server.tenant.TenantListener; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; import com.yahoo.vespa.curator.Curator; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/PathProvider.java b/configserver/src/main/java/com/yahoo/vespa/config/server/PathProvider.java index ca715d66a05..3e70f8ffa9b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/PathProvider.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/PathProvider.java @@ -11,13 +11,12 @@ import com.yahoo.path.Path; * * @since 5.1.24 */ public class PathProvider { + private final Path root; // Path for Vespa-related data stored in Zookeeper (subpaths are relative to this path) // NOTE: This should not be exposed, as this path can be different in testing, depending on how we configure it. private static final String APPS_ZK_NODE = "sessions"; private static final String VESPA_ZK_PATH = "/vespa/config"; - //private static final String VESPA_ZK_PATH = "/config/v2/tenants/default"; - private static final String LIVEAPP_ZK_NODE = "liveapp"; @Inject public PathProvider() { @@ -40,7 +39,4 @@ public class PathProvider { return getSessionDirs().append(String.valueOf(sessionId)); } - public Path getLiveApp() { - return root.append(LIVEAPP_ZK_NODE); - } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java index 8d7eb8a9d7c..9d8142b4db2 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.config.server; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.config.server.application.ApplicationSet; /** * Interface representing a reload handler. @@ -10,17 +11,19 @@ import com.yahoo.config.provision.ApplicationId; * @since 5.1.24 */ public interface ReloadHandler { + /** * Reload config with the one contained in the application. * * @param applicationSet The set of applications to set as active. */ - public void reloadConfig(ApplicationSet applicationSet); + void reloadConfig(ApplicationSet applicationSet); /** * Remove an application and resources related to it. * * @param applicationId to be removed */ - public void removeApplication(ApplicationId applicationId); + void removeApplication(ApplicationId applicationId); + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadListener.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadListener.java index f519a656c8f..277e5d1e848 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadListener.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadListener.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.config.server; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.config.server.application.ApplicationSet; import java.util.Collection; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/RotationsCache.java b/configserver/src/main/java/com/yahoo/vespa/config/server/RotationsCache.java deleted file mode 100644 index b1a2988109d..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/RotationsCache.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.Rotation; -import com.yahoo.path.Path; - -import com.yahoo.vespa.curator.Curator; - -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Rotations for an application. Persisted in ZooKeeper. - * - * @author hmusum - */ -public class RotationsCache { - - private final Path path; - private final Curator curator; - - public RotationsCache(Curator curator, Path tenantPath) { - this.curator = curator; - this.path = tenantPath.append("rotationsCache/"); - } - - public Set<Rotation> readRotationsFromZooKeeper(ApplicationId applicationId) { - ObjectMapper objectMapper = new ObjectMapper(); - Path fullPath = path.append(applicationId.serializedForm()); - Set<Rotation> ret = new LinkedHashSet<>(); - try { - if (curator != null && curator.exists(fullPath)) { - byte[] data = curator.framework().getData().forPath(fullPath.getAbsolute()); - if (data.length > 0) { - Set<String> rotationIds = objectMapper.readValue(data, new TypeReference<Set<String>>() { - }); - ret.addAll(rotationIds.stream().map(Rotation::new).collect(Collectors.toSet())); - } - } - } catch (Exception e) { - throw new RuntimeException("Error reading rotations from ZooKeeper (" + fullPath + ")", e); - } - return ret; - } - - public void writeRotationsToZooKeeper(ApplicationId applicationId, Set<Rotation> rotations) { - if (rotations.size() > 0) { - final ObjectMapper objectMapper = new ObjectMapper(); - final Path cachePath = path.append(applicationId.serializedForm()); - final String absolutePath = cachePath.getAbsolute(); - try { - curator.create(cachePath); - final Set<String> rotationIds = rotations.stream().map(Rotation::getId).collect(Collectors.toSet()); - final byte[] data = objectMapper.writeValueAsBytes(rotationIds); - curator.framework().setData().forPath(absolutePath, data); - } catch (Exception e) { - throw new RuntimeException("Error writing rotations to ZooKeeper (" + absolutePath + ")", e); - } - } - } - - public void deleteRotationFromZooKeeper(ApplicationId applicationId) { - curator.delete(path.append(applicationId.serializedForm())); - } -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelController.java b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelController.java index 4b94d4c21cc..88489aaa17b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelController.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelController.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server; +import com.google.inject.Inject; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.config.ConfigInstance; import com.yahoo.config.model.api.ConfigDefinitionRepo; @@ -14,7 +15,10 @@ import com.yahoo.vespa.config.server.application.Application; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; import com.yahoo.vespa.config.GenerationCounter; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.model.SuperModel; +import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory; +import com.yahoo.vespa.config.server.rpc.ConfigResponseFactoryFactory; import java.io.IOException; import java.util.Collections; @@ -40,7 +44,12 @@ public class SuperModelController implements RequestHandler { private final ConfigResponseFactory responseFactory; private volatile boolean enabled = false; - + /** + * Creates a supermodel controller + * + * @param generationCounter this will be the SuperModelGenerationCounter in production + */ + @Inject public SuperModelController(GenerationCounter generationCounter, ConfigDefinitionRepo configDefinitionRepo, ConfigserverConfig configserverConfig) { this.generationCounter = generationCounter; this.configDefinitionRepo = configDefinitionRepo; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelGenerationCounter.java b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelGenerationCounter.java index 589363467b0..0527fc288f6 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelGenerationCounter.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelGenerationCounter.java @@ -2,10 +2,14 @@ package com.yahoo.vespa.config.server; import com.yahoo.path.Path; +import com.yahoo.transaction.AbstractTransaction; +import com.yahoo.transaction.Transaction; import com.yahoo.vespa.config.GenerationCounter; import com.yahoo.vespa.curator.recipes.CuratorCounter; import com.yahoo.vespa.curator.Curator; +import java.util.logging.Logger; + /** * Distributed global generation counter for the super model. * @@ -37,4 +41,55 @@ public class SuperModelGenerationCounter implements GenerationCounter { public synchronized long get() { return counter.get(); } + + /** Returns a transaction which increments this */ + public IncrementTransaction incrementTransaction() { + return new IncrementTransaction(counter); + } + + /** An increment transaction */ + public static class IncrementTransaction extends AbstractTransaction { + + /** Creates a counting curator transaction containing a single increment operation */ + public IncrementTransaction(CuratorCounter counter) { + add(new IncrementOperation(counter)); + } + + @Override + public void prepare() { } + + @Override + public void commit() { + for (Operation operation : operations()) + ((IncrementOperation)operation).commit(); + } + + @Override + public void rollbackOrLog() { + for (Operation operation : operations()) + ((IncrementOperation)operation).rollback(); + } + + public static class IncrementOperation implements Transaction.Operation { + + private static final Logger log = Logger.getLogger(IncrementOperation.class.getName()); + private final CuratorCounter counter; + + public IncrementOperation(CuratorCounter counter) { + this.counter = counter; + } + + public void commit() { + counter.next(); + } + + public void rollback() { + // ok; we're just losing a generation number + } + + public String toString() { return "increment " + counterPath + " operation"; } + + } + + } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java index c745379f9cb..b08ac0827a1 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java @@ -15,6 +15,7 @@ import com.yahoo.vespa.config.buildergen.ConfigDefinition; import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.protocol.DefContent; import com.yahoo.vespa.config.server.model.SuperModel; +import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory; import java.io.IOException; import java.io.StringReader; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/Application.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/Application.java index 7116dda7322..1b3da039145 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/Application.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/Application.java @@ -15,10 +15,10 @@ import com.yahoo.vespa.config.GetConfigRequest; import com.yahoo.vespa.config.buildergen.ConfigDefinition; import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.protocol.DefContent; -import com.yahoo.vespa.config.server.ConfigResponseFactory; +import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory; import com.yahoo.vespa.config.server.ServerCache; -import com.yahoo.vespa.config.server.Tenants; -import com.yahoo.vespa.config.server.UncompressedConfigResponseFactory; +import com.yahoo.vespa.config.server.tenant.Tenants; +import com.yahoo.vespa.config.server.rpc.UncompressedConfigResponseFactory; import com.yahoo.vespa.config.server.UnknownConfigDefinitionException; import com.yahoo.vespa.config.server.modelfactory.ModelResult; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationMapper.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java index 6ff0fa49593..af458b913cf 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationMapper.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.application; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Version; @@ -8,12 +8,12 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import com.yahoo.vespa.config.server.application.Application; import com.yahoo.vespa.config.server.http.NotFoundException; /** * Used during config request handling to route to the right config model * based on application id and version. + * * @author Vegard Sjonfjell */ public final class ApplicationMapper { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationSet.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationSet.java index dd41ef2d489..4c383f7b16e 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationSet.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationSet.java @@ -1,9 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.application; import com.yahoo.config.model.api.HostInfo; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Version; -import com.yahoo.vespa.config.server.application.Application; import java.util.*; import java.util.stream.Collectors; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationRepo.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java index a9296f26eeb..4bf0956d01c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationRepo.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java @@ -3,23 +3,24 @@ package com.yahoo.vespa.config.server.application; import com.yahoo.config.provision.ApplicationId; import com.yahoo.transaction.Transaction; +import com.yahoo.vespa.curator.transaction.CuratorTransaction; import java.util.List; /** - * Manages the list of active applications in a config server. + * The applications of a tenant * * @author lulf * @since 5.1 */ -public interface ApplicationRepo { +public interface TenantApplications { /** - * List the active applications in this config server. + * List the active applications of a tenant in this config server. * * @return a list of {@link com.yahoo.config.provision.ApplicationId}s that are active. */ - public List<ApplicationId> listApplications(); + List<ApplicationId> listApplications(); /** * Register active application and adds it to the repo. If it already exists it is overwritten. @@ -39,11 +40,11 @@ public interface ApplicationRepo { long getSessionIdForApplication(ApplicationId applicationId); /** - * Deletes an application from the repo if it exists. + * Returns a transaction which deletes this application * * @param applicationId an {@link ApplicationId} to delete. */ - void deleteApplication(ApplicationId applicationId); + Transaction deleteApplication(ApplicationId applicationId); /** * Closes the application repo. Once a repo has been closed, it should not be used again. diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/VersionDoesNotExistException.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/VersionDoesNotExistException.java index d6a329491e6..09707c81cd2 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/VersionDoesNotExistException.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/VersionDoesNotExistException.java @@ -1,11 +1,13 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.application; /** * @author Vegard Sjonfjell */ public final class VersionDoesNotExistException extends RuntimeException { + public VersionDoesNotExistException(String message) { super(message); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKApplicationRepo.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java index 6567f8439a5..09762e53a2e 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKApplicationRepo.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ZKTenantApplications.java @@ -9,7 +9,7 @@ import com.yahoo.path.Path; import com.yahoo.text.Utf8; import com.yahoo.transaction.Transaction; import com.yahoo.vespa.config.server.ReloadHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.transaction.CuratorOperations; import com.yahoo.vespa.curator.transaction.CuratorTransaction; @@ -25,35 +25,46 @@ import java.util.concurrent.Executors; import java.util.logging.Logger; /** - * Application repo backed by zookeeper. + * The applications of a tenant, backed by ZooKeeper. + * Each application is stored as a single file, named the same as the application id and containing the id + * of the session storing the content of the application. * * @author lulf * @since 5.1 */ -public class ZKApplicationRepo implements ApplicationRepo, PathChildrenCacheListener { +// TODO: Merge into interface and separate out curator layer instead +public class ZKTenantApplications implements TenantApplications, PathChildrenCacheListener { - private static final Logger log = Logger.getLogger(ZKApplicationRepo.class.getName()); + private static final Logger log = Logger.getLogger(ZKTenantApplications.class.getName()); private final Curator curator; - private final Path root; - private final ExecutorService pathChildrenExecutor = Executors.newFixedThreadPool(1, ThreadFactoryFactory.getThreadFactory(ZKApplicationRepo.class.getName())); + private final Path tenantRoot; + private final ExecutorService pathChildrenExecutor = Executors.newFixedThreadPool(1, ThreadFactoryFactory.getThreadFactory(ZKTenantApplications.class.getName())); private final Curator.DirectoryCache directoryCache; private final ReloadHandler reloadHandler; private final TenantName tenant; - private ZKApplicationRepo(Curator curator, Path root, ReloadHandler reloadHandler, TenantName tenant) throws Exception { + private ZKTenantApplications(Curator curator, Path tenantRoot, ReloadHandler reloadHandler, TenantName tenant) throws Exception { this.curator = curator; - this.root = root; + this.tenantRoot = tenantRoot; this.reloadHandler = reloadHandler; this.tenant = tenant; rewriteApplicationIds(); - this.directoryCache = curator.createDirectoryCache(root.getAbsolute(), false, false, pathChildrenExecutor); + this.directoryCache = curator.createDirectoryCache(tenantRoot.getAbsolute(), false, false, pathChildrenExecutor); this.directoryCache.start(); this.directoryCache.addListener(this); } + public static TenantApplications create(Curator curator, Path root, ReloadHandler reloadHandler, TenantName tenant) { + try { + return new ZKTenantApplications(curator, root, reloadHandler, tenant); + } catch (Exception e) { + throw new RuntimeException(Tenants.logPre(tenant) + "Error creating application repo", e); + } + } + private void rewriteApplicationIds() { try { - List<String> appNodes = curator.framework().getChildren().forPath(root.getAbsolute()); + List<String> appNodes = curator.framework().getChildren().forPath(tenantRoot.getAbsolute()); for (String appNode : appNodes) { Optional<ApplicationId> appId = parseApplication(appNode); appId.filter(id -> shouldBeRewritten(appNode, id)) @@ -65,7 +76,7 @@ public class ZKApplicationRepo implements ApplicationRepo, PathChildrenCacheList } private long readSessionId(ApplicationId appId, String appNode) { - String path = root.append(appNode).getAbsolute(); + String path = tenantRoot.append(appNode).getAbsolute(); try { return Long.parseLong(Utf8.toString(curator.framework().getData().forPath(path))); } catch (Exception e) { @@ -78,8 +89,8 @@ public class ZKApplicationRepo implements ApplicationRepo, PathChildrenCacheList } private void rewriteApplicationId(ApplicationId appId, String origNode, long sessionId) { - String newPath = root.append(appId.serializedForm()).getAbsolute(); - String oldPath = root.append(origNode).getAbsolute(); + String newPath = tenantRoot.append(appId.serializedForm()).getAbsolute(); + String oldPath = tenantRoot.append(origNode).getAbsolute(); try (CuratorTransaction transaction = new CuratorTransaction(curator)) { if (curator.framework().checkExists().forPath(newPath) == null) { transaction.add(CuratorOperations.create(newPath, Utf8.toAsciiBytes(sessionId))); @@ -91,18 +102,10 @@ public class ZKApplicationRepo implements ApplicationRepo, PathChildrenCacheList } } - public static ApplicationRepo create(Curator curator, Path root, ReloadHandler reloadHandler, TenantName tenant) { - try { - return new ZKApplicationRepo(curator, root, reloadHandler, tenant); - } catch (Exception e) { - throw new RuntimeException(Tenants.logPre(tenant)+"Error creating application repo", e); - } - } - @Override public List<ApplicationId> listApplications() { try { - List<String> appNodes = curator.framework().getChildren().forPath(root.getAbsolute()); + List<String> appNodes = curator.framework().getChildren().forPath(tenantRoot.getAbsolute()); List<ApplicationId> applicationIds = new ArrayList<>(); for (String appNode : appNodes) { parseApplication(appNode).ifPresent(applicationIds::add); @@ -125,9 +128,9 @@ public class ZKApplicationRepo implements ApplicationRepo, PathChildrenCacheList @Override public Transaction createPutApplicationTransaction(ApplicationId applicationId, long sessionId) { if (listApplications().contains(applicationId)) { - return new CuratorTransaction(curator).add(CuratorOperations.setData(root.append(applicationId.serializedForm()).getAbsolute(), Utf8.toAsciiBytes(sessionId))); + return new CuratorTransaction(curator).add(CuratorOperations.setData(tenantRoot.append(applicationId.serializedForm()).getAbsolute(), Utf8.toAsciiBytes(sessionId))); } else { - return new CuratorTransaction(curator).add(CuratorOperations.create(root.append(applicationId.serializedForm()).getAbsolute(), Utf8.toAsciiBytes(sessionId))); + return new CuratorTransaction(curator).add(CuratorOperations.create(tenantRoot.append(applicationId.serializedForm()).getAbsolute(), Utf8.toAsciiBytes(sessionId))); } } @@ -137,9 +140,9 @@ public class ZKApplicationRepo implements ApplicationRepo, PathChildrenCacheList } @Override - public void deleteApplication(ApplicationId applicationId) { - Path path = root.append(applicationId.serializedForm()); - curator.delete(path); + public CuratorTransaction deleteApplication(ApplicationId applicationId) { + Path path = tenantRoot.append(applicationId.serializedForm()); + return CuratorTransaction.from(CuratorOperations.delete(path.getAbsolute()), curator); } @Override @@ -163,10 +166,11 @@ public class ZKApplicationRepo implements ApplicationRepo, PathChildrenCacheList private void applicationRemoved(ApplicationId applicationId) { reloadHandler.removeApplication(applicationId); - log.log(LogLevel.DEBUG, Tenants.logPre(applicationId)+"Application removed: " + applicationId); + log.log(LogLevel.DEBUG, Tenants.logPre(applicationId) + "Application removed: " + applicationId); } private void applicationAdded(ApplicationId applicationId) { - log.log(LogLevel.DEBUG, Tenants.logPre(applicationId)+"Application " + applicationId + " was added to repo"); + log.log(LogLevel.DEBUG, Tenants.logPre(applicationId) + "Application added: " + applicationId); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/counter/package-info.java b/configserver/src/main/java/com/yahoo/vespa/config/server/counter/package-info.java deleted file mode 100644 index 219e1008f3a..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/counter/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * @author andreer - */ -@ExportPackage -package com.yahoo.vespa.config.server.counter; - -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/DeployHandlerLogger.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLogger.java index 2c652d74b97..957e6a0f3d8 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/DeployHandlerLogger.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLogger.java @@ -1,11 +1,12 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.deploy; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.provision.ApplicationId; import com.yahoo.log.LogLevel; import com.yahoo.slime.Cursor; import com.yahoo.slime.Slime; +import com.yahoo.vespa.config.server.tenant.Tenants; import java.util.logging.Level; import java.util.logging.Logger; @@ -17,6 +18,7 @@ import java.util.logging.Logger; * @since 5.1 */ public class DeployHandlerLogger implements DeployLogger { + private static final Logger log = Logger.getLogger(DeployHandlerLogger.class.getName()); private final Cursor logroot; @@ -37,7 +39,7 @@ public class DeployHandlerLogger implements DeployLogger { !verbose) { return; } - String fullMsg = Tenants.logPre(app)+message; + String fullMsg = Tenants.logPre(app) + message; Cursor entry = logroot.addObject(); entry.setLong("time", System.currentTimeMillis()); entry.setString("level", level.getName()); @@ -45,4 +47,5 @@ public class DeployHandlerLogger implements DeployLogger { // Also tee to a normal log, Vespa log for example, but use level fine log.log(LogLevel.FINE, fullMsg); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java index cf366fd21f7..4a00081f0ab 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java @@ -2,7 +2,6 @@ package com.yahoo.vespa.config.server.deploy; import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.config.application.api.ApplicationMetaData; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.provision.HostFilter; import com.yahoo.config.provision.Provisioner; @@ -11,7 +10,8 @@ import com.yahoo.log.LogLevel; import com.yahoo.path.Path; import com.yahoo.transaction.NestedTransaction; import com.yahoo.transaction.Transaction; -import com.yahoo.vespa.config.server.ActivateLock; +import com.yahoo.vespa.config.server.tenant.ActivateLock; +import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.http.InternalServerException; import com.yahoo.vespa.config.server.session.LocalSession; @@ -27,7 +27,7 @@ import java.util.logging.Logger; /** * The process of deploying an application. - * Deployments are created by a {@link Deployer}. + * Deployments are created by a {@link ApplicationRepository}. * Instances of this are not multithread safe. * * @author lulf @@ -69,16 +69,16 @@ public class Deployment implements com.yahoo.config.provision.Deployment { this.prepared = prepared; } - static Deployment unprepared(LocalSession session, LocalSessionRepo localSessionRepo, Path tenantPath, ConfigserverConfig configserverConfig, - Optional<Provisioner> hostProvisioner, ActivateLock activateLock, - Duration timeout, Clock clock) { + public static Deployment unprepared(LocalSession session, LocalSessionRepo localSessionRepo, Path tenantPath, ConfigserverConfig configserverConfig, + Optional<Provisioner> hostProvisioner, ActivateLock activateLock, + Duration timeout, Clock clock) { return new Deployment(session, localSessionRepo, tenantPath, configserverConfig, hostProvisioner, activateLock, timeout, clock, false); } - static Deployment prepared(LocalSession session, LocalSessionRepo localSessionRepo, - Optional<Provisioner> hostProvisioner, ActivateLock activateLock, - Duration timeout, Clock clock) { + public static Deployment prepared(LocalSession session, LocalSessionRepo localSessionRepo, + Optional<Provisioner> hostProvisioner, ActivateLock activateLock, + Duration timeout, Clock clock) { return new Deployment(session, localSessionRepo, null, null, hostProvisioner, activateLock, timeout, clock, true); } @@ -132,8 +132,8 @@ public class Deployment implements com.yahoo.config.provision.Deployment { } finally { activateLock.release(); } - final ApplicationMetaData metaData = session.getMetaData(); - log.log(LogLevel.INFO, session.logPre() + "Session " + sessionId + " activated successfully. Config generation " + metaData.getGeneration()); + log.log(LogLevel.INFO, session.logPre() + "Session " + sessionId + + " activated successfully. Config generation " + session.getMetaData().getGeneration()); } /** 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 9a6f373a807..a753db90a7a 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 @@ -21,6 +21,7 @@ import java.util.Set; * @author lulf */ public class ModelContextImpl implements ModelContext { + private final ApplicationPackage applicationPackage; private final Optional<Model> previousModel; private final Optional<ApplicationPackage> permanentApplicationPackage; @@ -157,4 +158,5 @@ public class ModelContextImpl implements ModelContext { return rotations; } } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/HostRegistries.java b/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistries.java index 117f807c309..c107a671eef 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/HostRegistries.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistries.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.host; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/HostRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistry.java index a62e0059c2a..dfa72b03126 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/HostRegistry.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostRegistry.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.host; import java.util.*; import java.util.concurrent.ConcurrentHashMap; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/HostValidator.java b/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostValidator.java index 67292e281bb..fc024c10302 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/HostValidator.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/host/HostValidator.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.host; import java.util.Collection; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/CompressedApplicationInputStream.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStream.java index b8da2448c5b..b83d8383f44 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/CompressedApplicationInputStream.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStream.java @@ -1,12 +1,9 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.http; import com.google.common.io.ByteStreams; import com.google.common.io.Files; import com.yahoo.log.LogLevel; -import com.yahoo.vespa.config.server.http.BadRequestException; -import com.yahoo.vespa.config.server.http.InternalServerException; -import com.yahoo.vespa.config.server.http.SessionCreate; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; @@ -23,6 +20,7 @@ import java.util.zip.GZIPInputStream; * @since 5.1 */ public class CompressedApplicationInputStream implements AutoCloseable { + private static final Logger log = Logger.getLogger(CompressedApplicationInputStream.class.getPackage().getName()); private final ArchiveInputStream ais; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandler.java index 50a1a3877ef..8cf995207aa 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandler.java @@ -8,7 +8,7 @@ import com.yahoo.container.logging.AccessLog; import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.server.RequestHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.config.provision.ApplicationId; import java.util.Optional; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandler.java index a6e2c5bf050..3352b878994 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandler.java @@ -10,7 +10,7 @@ import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.server.RequestHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.config.provision.ApplicationId; import java.io.IOException; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpListNamedConfigsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpListNamedConfigsHandler.java index 31d6e84860d..1a31ab67545 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpListNamedConfigsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpListNamedConfigsHandler.java @@ -9,7 +9,7 @@ import com.yahoo.container.logging.AccessLog; import com.yahoo.jdisc.application.BindingMatch; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.server.RequestHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.config.provision.ApplicationId; import java.util.Optional; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/NotFoundException.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/NotFoundException.java index 6a49188a14c..40d04ff9fa6 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/NotFoundException.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/NotFoundException.java @@ -12,5 +12,6 @@ public class NotFoundException extends RuntimeException { public NotFoundException(String message) { super(message); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerBase.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerBase.java index 53133b49c8a..cc4689682dd 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerBase.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerBase.java @@ -4,9 +4,9 @@ package com.yahoo.vespa.config.server.http; import com.yahoo.config.provision.Provisioner; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.logging.AccessLog; -import com.yahoo.vespa.config.server.ActivateLock; +import com.yahoo.vespa.config.server.tenant.ActivateLock; import com.yahoo.vespa.config.server.TimeoutBudget; -import com.yahoo.vespa.config.server.deploy.Deployer; +import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.deploy.Deployment; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.session.LocalSession; @@ -30,10 +30,10 @@ public class SessionActiveHandlerBase extends SessionHandler { TimeoutBudget timeoutBudget, Optional<Provisioner> hostProvisioner, LocalSession localSession) { - // TODO: Use an injected deployer from the callers of this instead + // TODO: Use an injected applicationRepository from the callers of this instead // TODO: And then get rid of the activateLock and localSessionRepo arguments in deployFromPreparedSession - Deployer deployer = new Deployer(null, HostProvisionerProvider.from(hostProvisioner), null, null); - Deployment deployment = deployer.deployFromPreparedSession(localSession, activateLock, localSessionRepo, timeoutBudget.timeLeft()); + ApplicationRepository applicationRepository = new ApplicationRepository(null, HostProvisionerProvider.from(hostProvisioner), null, null); + Deployment deployment = applicationRepository.deployFromPreparedSession(localSession, activateLock, localSessionRepo, timeoutBudget.timeLeft()); deployment.setIgnoreLockFailure(shouldIgnoreLockFailure(request)); deployment.setIgnoreSessionStaleFailure(shouldIgnoreSessionStaleFailure(request)); deployment.activate(); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionCreate.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionCreate.java index fdafd5a7b16..72e7146af3c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionCreate.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionCreate.java @@ -10,7 +10,6 @@ import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.io.IOUtils; import com.yahoo.log.LogLevel; import com.yahoo.slime.Slime; -import com.yahoo.vespa.config.server.CompressedApplicationInputStream; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.session.LocalSession; import com.yahoo.vespa.config.server.session.LocalSessionRepo; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java index db1cb7dc202..3bbd2528453 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java @@ -6,7 +6,7 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.logging.AccessLog; import com.yahoo.jdisc.application.BindingMatch; import com.yahoo.slime.Slime; -import com.yahoo.vespa.config.server.DeployHandlerLogger; +import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.session.Session; import com.yahoo.vespa.config.server.session.SessionRepo; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/Utils.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/Utils.java index e1159ba8e64..b21dcf18a0e 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/Utils.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/Utils.java @@ -5,8 +5,8 @@ import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.jdisc.application.BindingMatch; import com.yahoo.jdisc.application.UriPattern; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import java.net.URI; @@ -16,6 +16,7 @@ import java.net.URI; * @author hmusum * @since 5.1.14 */ +// TODO: Dissolve into callers public class Utils { /** diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java index 28c2df7377d..c0482ad5d99 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java @@ -1,27 +1,38 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.http.v2; -import com.yahoo.config.provision.*; +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.ApplicationName; +import com.yahoo.config.provision.HostFilter; +import com.yahoo.config.provision.Provisioner; +import com.yahoo.config.provision.TenantName; +import com.yahoo.config.provision.Zone; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.jdisc.Response; import com.yahoo.jdisc.application.BindingMatch; -import com.yahoo.log.LogLevel; -import com.yahoo.vespa.config.server.RotationsCache; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.vespa.config.server.application.ApplicationConvergenceChecker; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.application.LogServerLogGrabber; -import com.yahoo.vespa.config.server.http.*; +import com.yahoo.vespa.config.server.ApplicationRepository; +import com.yahoo.vespa.config.server.http.ContentHandler; +import com.yahoo.vespa.config.server.http.HttpErrorResponse; +import com.yahoo.vespa.config.server.http.HttpHandler; +import com.yahoo.vespa.config.server.http.JSONResponse; +import com.yahoo.vespa.config.server.http.NotFoundException; +import com.yahoo.vespa.config.server.http.SessionHandler; +import com.yahoo.vespa.config.server.http.Utils; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.session.LocalSession; -import com.yahoo.vespa.config.server.session.LocalSessionRepo; import com.yahoo.vespa.config.server.session.RemoteSession; import com.yahoo.vespa.config.server.session.RemoteSessionRepo; +import com.yahoo.vespa.curator.Curator; import java.io.IOException; import java.time.Clock; @@ -36,6 +47,7 @@ import java.util.concurrent.Executor; * @author hmusum * @since 5.4 */ +// TODO: Move business logic out of the http layer public class ApplicationHandler extends HttpHandler { private static final String REQUEST_PROPERTY_TIMEOUT = "timeout"; @@ -45,40 +57,28 @@ public class ApplicationHandler extends HttpHandler { private final ApplicationConvergenceChecker convergeChecker; private final Zone zone; private final LogServerLogGrabber logServerLogGrabber; + private final ApplicationRepository applicationRepository; public ApplicationHandler(Executor executor, AccessLog accessLog, Tenants tenants, HostProvisionerProvider hostProvisionerProvider, Zone zone, ApplicationConvergenceChecker convergeChecker, - LogServerLogGrabber logServerLogGrabber) { + LogServerLogGrabber logServerLogGrabber, + ConfigserverConfig configserverConfig, Curator curator) { super(executor, accessLog); this.tenants = tenants; this.hostProvisioner = hostProvisionerProvider.getHostProvisioner(); this.zone = zone; this.convergeChecker = convergeChecker; this.logServerLogGrabber = logServerLogGrabber; + this.applicationRepository = new ApplicationRepository(tenants, hostProvisionerProvider, configserverConfig, curator); } @Override public HttpResponse handleDELETE(HttpRequest request) { ApplicationId applicationId = getApplicationIdFromRequest(request); - Tenant tenant = verifyTenantAndApplication(applicationId); - ApplicationRepo applicationRepo = tenant.getApplicationRepo(); - final long sessionId = applicationRepo.getSessionIdForApplication(applicationId); - final LocalSessionRepo localSessionRepo = tenant.getLocalSessionRepo(); - final LocalSession session = localSessionRepo.getSession(sessionId); - if (session == null) { - return HttpErrorResponse.notFoundError("Unable to delete " + applicationId + " (session id " + sessionId + "):" + - "No local deployment for this application found on this config server"); - } - log.log(LogLevel.INFO, "Deleting " + applicationId); - localSessionRepo.removeSession(session.getSessionId()); - session.delete(); - RotationsCache rotationsCache = new RotationsCache(tenant.getCurator(), tenant.getPath()); - rotationsCache.deleteRotationFromZooKeeper(applicationId); - applicationRepo.deleteApplication(applicationId); - if (hostProvisioner.isPresent()) { - hostProvisioner.get().removed(applicationId); - } + boolean removed = applicationRepository.remove(applicationId); + if ( ! removed) + return HttpErrorResponse.notFoundError("Unable to delete " + applicationId + ": Not found"); return new DeleteApplicationResponse(Response.Status.OK, applicationId); } @@ -126,7 +126,7 @@ public class ApplicationHandler extends HttpHandler { private HttpResponse handlePostRestart(HttpRequest request, ApplicationId applicationId) { if (getBindingMatch(request).groupCount() != 7) throw new NotFoundException("Illegal POST restart request '" + request.getUri() + - "': Must have 6 arguments but had " + ( getBindingMatch(request).groupCount()-1 ) ); + "': Must have 6 arguments but had " + ( getBindingMatch(request).groupCount()-1 ) ); if (hostProvisioner.isPresent()) hostProvisioner.get().restart(applicationId, hostFilterFrom(request)); return new JSONResponse(Response.Status.OK); // return empty @@ -165,7 +165,7 @@ public class ApplicationHandler extends HttpHandler { } private Application getApplication(Tenant tenant, ApplicationId applicationId) { - ApplicationRepo applicationRepo = tenant.getApplicationRepo(); + TenantApplications applicationRepo = tenant.getApplicationRepo(); RemoteSessionRepo remoteSessionRepo = tenant.getRemoteSessionRepo(); long sessionId = applicationRepo.getSessionIdForApplication(applicationId); RemoteSession session = remoteSessionRepo.getSession(sessionId, 0); @@ -173,7 +173,7 @@ public class ApplicationHandler extends HttpHandler { } private List<ApplicationId> listApplicationIds(Tenant tenant) { - ApplicationRepo applicationRepo = tenant.getApplicationRepo(); + TenantApplications applicationRepo = tenant.getApplicationRepo(); return applicationRepo.listApplications(); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java index 03c0c7d7fc9..8429bc1e043 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java @@ -11,8 +11,8 @@ import com.yahoo.jdisc.Response; import com.yahoo.jdisc.application.BindingMatch; import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.server.GlobalComponentRegistry; -import com.yahoo.vespa.config.server.HostRegistries; -import com.yahoo.vespa.config.server.HostRegistry; +import com.yahoo.vespa.config.server.host.HostRegistries; +import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.vespa.config.server.http.*; import java.util.concurrent.Executor; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpConfigRequests.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpConfigRequests.java index b63c52a26bb..ca0fceef5e7 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpConfigRequests.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpConfigRequests.java @@ -8,8 +8,8 @@ import com.yahoo.jdisc.application.BindingMatch; import com.yahoo.jdisc.application.UriPattern; import com.yahoo.jdisc.application.UriPattern.Match; import com.yahoo.vespa.config.server.RequestHandler; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.http.NotFoundException; /** diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandler.java index 6c872578324..d5313db1495 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandler.java @@ -8,7 +8,7 @@ import com.yahoo.container.logging.AccessLog; import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.server.RequestHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.http.HttpConfigRequest; import com.yahoo.vespa.config.server.http.HttpConfigResponse; import com.yahoo.vespa.config.server.http.HttpHandler; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandler.java index 0358a9a7046..44832a8dc44 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandler.java @@ -16,7 +16,7 @@ import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.server.RequestHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.config.server.http.HttpConfigResponse; import com.yahoo.vespa.config.server.http.HttpHandler; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListNamedConfigsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListNamedConfigsHandler.java index ed4accb386b..543b90198c1 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListNamedConfigsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListNamedConfigsHandler.java @@ -12,7 +12,7 @@ import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.server.RequestHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.config.server.http.HttpConfigRequest; import com.yahoo.vespa.config.server.http.HttpHandler; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandler.java index e77c3928f11..8b7c138642a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandler.java @@ -9,10 +9,10 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.jdisc.Response; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.http.HttpHandler; import com.yahoo.vespa.config.server.http.Utils; @@ -52,7 +52,7 @@ public class ListApplicationsHandler extends HttpHandler { private List<ApplicationId> listApplicationIds(TenantName tenantName) { Tenant tenant = Utils.checkThatTenantExists(tenants, tenantName); - ApplicationRepo applicationRepo = tenant.getApplicationRepo(); + TenantApplications applicationRepo = tenant.getApplicationRepo(); return applicationRepo.listApplications(); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListTenantsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListTenantsHandler.java index 0fd456b6bd0..c2065249ad1 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListTenantsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListTenantsHandler.java @@ -7,7 +7,7 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.vespa.config.server.http.HttpHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; /** * Handler to list tenants in the configserver diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java index ee926f39cad..89463a0b8ee 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java @@ -12,8 +12,8 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.log.LogLevel; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.http.SessionActiveHandlerBase; import com.yahoo.vespa.config.server.http.SessionHandler; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandler.java index 669ec049770..1c8f026aef1 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandler.java @@ -7,8 +7,8 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.log.LogLevel; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.http.ContentHandler; import com.yahoo.vespa.config.server.http.NotFoundException; import com.yahoo.vespa.config.server.http.SessionHandler; 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 c4f4a5139b5..9778048dbf0 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 @@ -11,10 +11,10 @@ import com.yahoo.container.logging.AccessLog; import com.yahoo.jdisc.application.UriPattern; import com.yahoo.log.LogLevel; import com.yahoo.slime.Slime; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.TimeoutBudget; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.http.BadRequestException; import com.yahoo.vespa.config.server.http.SessionCreate; import com.yahoo.vespa.config.server.http.SessionHandler; @@ -66,7 +66,7 @@ public class SessionCreateHandler extends SessionHandler { } private static LocalSession getExistingSession(Tenant tenant, HttpRequest request) { - ApplicationRepo applicationRepo = tenant.getApplicationRepo(); + TenantApplications applicationRepo = tenant.getApplicationRepo(); LocalSessionRepo localSessionRepo = tenant.getLocalSessionRepo(); ApplicationId applicationId = getFromProperty(request); return SessionHandler.getSessionFromRequest(localSessionRepo, applicationRepo.getSessionIdForApplication(applicationId)); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateResponseV2.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateResponseV2.java index 30c7e98e2da..22ca1a8fe70 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateResponseV2.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateResponseV2.java @@ -4,9 +4,9 @@ package com.yahoo.vespa.config.server.http.v2; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.slime.Cursor; import com.yahoo.slime.Slime; -import com.yahoo.vespa.config.server.Tenant; import com.yahoo.vespa.config.server.http.SessionCreateResponse; import com.yahoo.vespa.config.server.http.SessionResponse; +import com.yahoo.vespa.config.server.tenant.Tenant; /** * Creates a response for SessionCreateHandler (v2). diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandler.java index cf2094933c1..6e3f4ea246f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandler.java @@ -11,10 +11,10 @@ import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.log.LogLevel; import com.yahoo.slime.Slime; -import com.yahoo.vespa.config.server.ApplicationSet; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.configchange.RefeedActions; import com.yahoo.vespa.config.server.configchange.RefeedActionsFormatter; @@ -34,7 +34,9 @@ import java.util.logging.Logger; * @author hmusum * @since 5.1.29 */ +// TODO: Move business logic out of the HTTP layer and delegate to a ApplicationRepository public class SessionPrepareHandler extends SessionHandler { + private static final Logger log = Logger.getLogger(SessionPrepareHandler.class.getName()); private final Tenants tenants; @@ -99,7 +101,7 @@ public class SessionPrepareHandler extends SessionHandler { private static Optional<ApplicationSet> getCurrentActiveApplicationSet(Tenant tenant, ApplicationId appId) { Optional<ApplicationSet> currentActiveApplicationSet = Optional.empty(); - ApplicationRepo applicationRepo = tenant.getApplicationRepo(); + TenantApplications applicationRepo = tenant.getApplicationRepo(); try { long currentActiveSessionId = applicationRepo.getSessionIdForApplication(appId); final RemoteSession currentActiveSession = tenant.getRemoteSessionRepo().getSession(currentActiveSessionId); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareResponse.java index c46d0e063b3..bf4db5524f3 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareResponse.java @@ -3,11 +3,11 @@ package com.yahoo.vespa.config.server.http.v2; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.slime.Slime; -import com.yahoo.vespa.config.server.Tenant; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.configchange.ConfigChangeActionsSlimeConverter; import com.yahoo.vespa.config.server.http.SessionResponse; import com.yahoo.vespa.config.server.session.Session; +import com.yahoo.vespa.config.server.tenant.Tenant; /** * Creates a response for SessionPrepareHandler. diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java index e373eb4478f..e409181f4c6 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java @@ -9,14 +9,14 @@ import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; +import com.yahoo.vespa.config.server.tenant.Tenant; import com.yahoo.yolean.Exceptions; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.http.BadRequestException; import com.yahoo.vespa.config.server.http.HttpHandler; import com.yahoo.vespa.config.server.http.InternalServerException; import com.yahoo.vespa.config.server.http.Utils; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; /** * Handler to create, get and delete a tenant. @@ -37,7 +37,7 @@ public class TenantHandler extends HttpHandler { protected HttpResponse handlePUT(HttpRequest request) { TenantName tenant = getAndValidateTenantFromRequest(request); try { - tenants.createTenant(tenant); + tenants.writeTenantPath(tenant); } catch (Exception e) { throw new InternalServerException(Exceptions.toMessageString(e)); } @@ -73,7 +73,7 @@ public class TenantHandler extends HttpHandler { protected HttpResponse handleDELETE(HttpRequest request) { TenantName tenantName = getExistingTenant(request); Tenant tenant = Utils.checkThatTenantExists(tenants, tenantName); - ApplicationRepo applicationRepo = tenant.getApplicationRepo(); + TenantApplications applicationRepo = tenant.getApplicationRepo(); final List<ApplicationId> activeApplications = applicationRepo.listApplications(); if (activeApplications.isEmpty()) { try { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/model/RoutingProducer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/model/RoutingProducer.java index 6a63269ae6e..6a63269ae6e 100755..100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/model/RoutingProducer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/model/RoutingProducer.java diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/model/SuperModel.java b/configserver/src/main/java/com/yahoo/vespa/config/server/model/SuperModel.java index c6aa5ed7f8e..c6aa5ed7f8e 100755..100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/model/SuperModel.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/model/SuperModel.java diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java index c3046887b0e..3b15da0fbea 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java @@ -17,9 +17,9 @@ import com.yahoo.config.provision.Version; import com.yahoo.config.provision.Zone; import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.server.GlobalComponentRegistry; -import com.yahoo.vespa.config.server.RotationsCache; +import com.yahoo.vespa.config.server.tenant.Rotations; import com.yahoo.vespa.config.server.ServerCache; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.deploy.ModelContextImpl; @@ -120,7 +120,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { applicationId, configserverConfig, zone, - new RotationsCache(curator, Tenants.getTenantPath(tenant)).readRotationsFromZooKeeper(applicationId)); + new Rotations(curator, Tenants.getTenantPath(tenant)).readRotationsFromZooKeeper(applicationId)); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java index 0d6170909a7..70333ce83a4 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java @@ -18,11 +18,11 @@ import com.yahoo.config.provision.Version; import com.yahoo.config.provision.Zone; import com.yahoo.log.LogLevel; import com.yahoo.path.Path; -import com.yahoo.vespa.config.server.ApplicationSet; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.ConfigServerSpec; import com.yahoo.vespa.config.server.GlobalComponentRegistry; -import com.yahoo.vespa.config.server.HostValidator; -import com.yahoo.vespa.config.server.RotationsCache; +import com.yahoo.vespa.config.server.host.HostValidator; +import com.yahoo.vespa.config.server.tenant.Rotations; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.deploy.ModelContextImpl; import com.yahoo.vespa.config.server.filedistribution.FileDistributionProvider; @@ -60,8 +60,8 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P private final HostProvisionerProvider hostProvisionerProvider; private final Optional<ApplicationSet> currentActiveApplicationSet; private final ApplicationId applicationId; - private final RotationsCache rotationsCache; - private final Set<Rotation> rotations; + private final Rotations rotations; + private final Set<Rotation> rotationsSet; private final ModelContext.Properties properties; /** Construct from global component registry */ @@ -89,13 +89,13 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P this.currentActiveApplicationSet = currentActiveApplicationSet; this.applicationId = params.getApplicationId(); - this.rotationsCache = new RotationsCache(curator, tenantPath); - this.rotations = getRotations(params.rotations()); + this.rotations = new Rotations(curator, tenantPath); + this.rotationsSet = getRotations(params.rotations()); this.properties = createModelContextProperties( params.getApplicationId(), configserverConfig, zone, - rotations); + rotationsSet); } /** Construct with all dependencies passed separately */ @@ -128,15 +128,15 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P this.currentActiveApplicationSet = currentActiveApplicationSet; this.applicationId = params.getApplicationId(); - this.rotationsCache = new RotationsCache(curator, tenantPath); - this.rotations = getRotations(params.rotations()); + this.rotations = new Rotations(curator, tenantPath); + this.rotationsSet = getRotations(params.rotations()); this.properties = new ModelContextImpl.Properties( params.getApplicationId(), configserverConfig.multitenant(), ConfigServerSpec.fromConfig(configserverConfig), configserverConfig.hostedVespa(), zone, - rotations); + rotationsSet); } @Override @@ -187,7 +187,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P private Set<Rotation> getRotations(Set<Rotation> rotations) { if (rotations == null || rotations.isEmpty()) { - rotations = rotationsCache.readRotationsFromZooKeeper(applicationId); + rotations = this.rotations.readRotationsFromZooKeeper(applicationId); } return rotations; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/Metrics.java b/configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/Metrics.java index d0984baefc2..ab62ae3ad2f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/Metrics.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/Metrics.java @@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentHashMap; * @since 4.2 */ public class Metrics extends TimerTask implements MetricUpdaterFactory { + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(Metrics.class.getName()); private static final String METRIC_REQUESTS = getMetricName("requests"); private static final String METRIC_FAILED_REQUESTS = getMetricName("failedRequests"); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigResponseFactory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/ConfigResponseFactory.java index 3fc3c0ff8aa..1abc4393c55 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigResponseFactory.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/ConfigResponseFactory.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.config.codegen.InnerCNode; import com.yahoo.vespa.config.ConfigPayload; @@ -13,6 +13,7 @@ import com.yahoo.vespa.config.protocol.ConfigResponse; * @since 5.19 */ public interface ConfigResponseFactory { + /** * Create a {@link ConfigResponse} for a given payload and generation. * @param payload The {@link com.yahoo.vespa.config.ConfigPayload} to put in the response. @@ -20,4 +21,5 @@ public interface ConfigResponseFactory { * @param generation The payload generation. @return A {@link ConfigResponse} that can be sent to the client. */ ConfigResponse createResponse(ConfigPayload payload, InnerCNode defFile, long generation); + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigResponseFactoryFactory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/ConfigResponseFactoryFactory.java index 309f9052a71..547a58663f3 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigResponseFactoryFactory.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/ConfigResponseFactoryFactory.java @@ -1,7 +1,10 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory; +import com.yahoo.vespa.config.server.rpc.LZ4ConfigResponseFactory; +import com.yahoo.vespa.config.server.rpc.UncompressedConfigResponseFactory; /** * Logic to select the appropriate response factory based on config. @@ -11,6 +14,7 @@ import com.yahoo.cloud.config.ConfigserverConfig; * @since 5.20 */ public class ConfigResponseFactoryFactory { + public static ConfigResponseFactory createFactory(ConfigserverConfig configserverConfig) { switch (configserverConfig.payloadCompressionType()) { case LZ4: @@ -21,4 +25,5 @@ public class ConfigResponseFactoryFactory { throw new IllegalArgumentException("Unknown payload compression type " + configserverConfig.payloadCompressionType()); } } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/DelayedConfigResponses.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/DelayedConfigResponses.java index 204ab214199..e1bad224b8c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/DelayedConfigResponses.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/DelayedConfigResponses.java @@ -1,14 +1,16 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.concurrent.ThreadFactoryFactory; import com.yahoo.jrt.Target; import com.yahoo.jrt.TargetWatcher; import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.protocol.JRTServerConfigRequest; +import com.yahoo.vespa.config.server.GetConfigContext; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.config.server.tenant.Tenants; import java.util.*; import java.util.concurrent.*; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigProcessor.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java index 1861965947c..acd640002fa 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigProcessor.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.cloud.config.SentinelConfig; import com.yahoo.config.provision.TenantName; @@ -11,6 +11,9 @@ import com.yahoo.vespa.config.ConfigPayload; import com.yahoo.vespa.config.ErrorCode; import com.yahoo.vespa.config.UnknownConfigIdException; import com.yahoo.vespa.config.protocol.*; +import com.yahoo.vespa.config.server.GetConfigContext; +import com.yahoo.vespa.config.server.UnknownConfigDefinitionException; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.util.ConfigUtils; import java.util.Optional; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/LZ4ConfigResponseFactory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/LZ4ConfigResponseFactory.java index 66a2dc32eea..e5568f9eaf2 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/LZ4ConfigResponseFactory.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/LZ4ConfigResponseFactory.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.config.codegen.InnerCNode; import com.yahoo.text.Utf8Array; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/RpcServer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java index a1c17a93022..cdb5a3453ef 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/RpcServer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.google.inject.Inject; import com.yahoo.cloud.config.ConfigserverConfig; @@ -23,8 +23,18 @@ import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.protocol.JRTServerConfigRequest; import com.yahoo.vespa.config.protocol.JRTServerConfigRequestV3; import com.yahoo.vespa.config.protocol.Trace; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.GetConfigContext; +import com.yahoo.vespa.config.server.host.HostRegistries; +import com.yahoo.vespa.config.server.host.HostRegistry; +import com.yahoo.vespa.config.server.ReloadListener; +import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.SuperModelController; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import com.yahoo.vespa.config.server.monitoring.MetricUpdaterFactory; +import com.yahoo.vespa.config.server.tenant.TenantHandlerProvider; +import com.yahoo.vespa.config.server.tenant.TenantListener; +import com.yahoo.vespa.config.server.tenant.Tenants; import java.util.Collection; import java.util.Collections; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/UncompressedConfigResponseFactory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/UncompressedConfigResponseFactory.java index 73e7acb5a88..1e545edf02b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/UncompressedConfigResponseFactory.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/UncompressedConfigResponseFactory.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.config.codegen.InnerCNode; import com.yahoo.text.Utf8Array; @@ -17,6 +17,7 @@ import com.yahoo.vespa.config.util.ConfigUtils; * @since 5.19 */ public class UncompressedConfigResponseFactory implements ConfigResponseFactory { + @Override public ConfigResponse createResponse(ConfigPayload payload, InnerCNode defFile, long generation) { Utf8Array rawPayload = payload.toUtf8Array(true); @@ -24,4 +25,5 @@ public class UncompressedConfigResponseFactory implements ConfigResponseFactory CompressionInfo info = CompressionInfo.create(CompressionType.UNCOMPRESSED, rawPayload.getByteLength()); return new SlimeConfigResponse(rawPayload, defFile, generation, configMd5, info); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java index d2857068885..8ea92d2eb8d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java @@ -6,14 +6,18 @@ import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.ApplicationMetaData; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.provision.ProvisionInfo; +import com.yahoo.transaction.AbstractTransaction; +import com.yahoo.transaction.NestedTransaction; import com.yahoo.transaction.Transaction; import com.yahoo.io.IOUtils; import com.yahoo.path.Path; import com.yahoo.vespa.config.server.*; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.curator.Curator; import java.io.File; @@ -27,10 +31,12 @@ import java.util.Optional; * @author lulf * @since 5.1 */ +// This is really the store of an application, whether it is active or in an edit session +// TODO: Separate the "application store" and "session" aspects - the latter belongs in the HTTP layer public class LocalSession extends Session implements Comparable<LocalSession> { private final ApplicationPackage applicationPackage; - private final ApplicationRepo applicationRepo; + private final TenantApplications applicationRepo; private final SessionZooKeeperClient zooKeeperClient; private final SessionPreparer sessionPreparer; private final SessionContext sessionContext; @@ -114,15 +120,21 @@ public class LocalSession extends Session implements Comparable<LocalSession> { return getSessionId() > sessionId; } - /** - * Deletes this session from ZooKeeper and filesystem, as well as making sure the supermodel generation counter is incremented. - */ + /** Delete this session */ + // TODO: Use transactional delete instead public void delete() { superModelGenerationCounter.increment(); IOUtils.recursiveDeleteDir(serverDB); zooKeeperClient.delete(); } + /** Add transactions to delete this session to the given nested transaction */ + public void delete(NestedTransaction transaction) { + transaction.add(zooKeeperClient.deleteTransaction(), FileTransaction.class); + transaction.add(FileTransaction.from(FileOperations.delete(serverDB.getAbsolutePath())), SuperModelGenerationCounter.IncrementTransaction.class); + transaction.add(superModelGenerationCounter.incrementTransaction()); + } + @Override public int compareTo(LocalSession rhs) { Long lhsId = getSessionId(); @@ -167,4 +179,62 @@ public class LocalSession extends Session implements Comparable<LocalSession> { return Tenants.logPre(getApplicationId()); } } + + // The rest of this class should be moved elsewhere ... + + private static class FileTransaction extends AbstractTransaction { + + public static FileTransaction from(FileOperation operation) { + FileTransaction transaction = new FileTransaction(); + transaction.add(operation); + return transaction; + } + + @Override + public void prepare() { } + + @Override + public void commit() { + for (Operation operation : operations()) + ((FileOperation)operation).commit(); + } + + } + + /** Factory for file operations */ + private static class FileOperations { + + /** Creates an operation which recursively deletes the given path */ + public static DeleteOperation delete(String pathToDelete) { + return new DeleteOperation(pathToDelete); + } + + } + + private interface FileOperation extends Transaction.Operation { + + void commit(); + + } + + /** + * Recursively deletes this path and everything below. + * Succeeds with no action if the path does not exist. + */ + private static class DeleteOperation implements FileOperation { + + private final String pathToDelete; + + public DeleteOperation(String pathToDelete) { + this.pathToDelete = pathToDelete; + } + + @Override + public void commit() { + // TODO: Check delete access in prepare() + IOUtils.recursiveDeleteDir(new File(pathToDelete)); + } + + } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java index 8f39d0b96d1..7114768c760 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionRepo.java @@ -3,7 +3,7 @@ package com.yahoo.vespa.config.server.session; import com.yahoo.log.LogLevel; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs; import java.io.File; @@ -32,10 +32,10 @@ public class LocalSessionRepo extends SessionRepo<LocalSession> { }; private final long sessionLifetime; // in seconds - private final ApplicationRepo applicationRepo; + private final TenantApplications applicationRepo; private final Clock clock; - public LocalSessionRepo(TenantFileSystemDirs tenantFileSystemDirs, LocalSessionLoader loader, ApplicationRepo applicationRepo, Clock clock, long sessionLifeTime) { + public LocalSessionRepo(TenantFileSystemDirs tenantFileSystemDirs, LocalSessionLoader loader, TenantApplications applicationRepo, Clock clock, long sessionLifeTime) { this(applicationRepo, clock, sessionLifeTime); loadSessions(tenantFileSystemDirs.path(), loader); } @@ -68,13 +68,13 @@ public class LocalSessionRepo extends SessionRepo<LocalSession> { } // Constructor only for testing - public LocalSessionRepo(ApplicationRepo applicationRepo, Clock clock, long sessionLifetime) { + public LocalSessionRepo(TenantApplications applicationRepo, Clock clock, long sessionLifetime) { this.applicationRepo = applicationRepo; this.sessionLifetime = sessionLifetime; this.clock = clock; } - public LocalSessionRepo(ApplicationRepo applicationRepo) { + public LocalSessionRepo(TenantApplications applicationRepo) { this(applicationRepo, Clock.systemUTC(), TimeUnit.DAYS.toMillis(1)); } @@ -108,7 +108,7 @@ public class LocalSessionRepo extends SessionRepo<LocalSession> { } private void deleteSession(LocalSession candidate) { - removeSession(candidate.getSessionId()); + removeSessionOrThrow(candidate.getSessionId()); candidate.delete(); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java index 2ce378d0464..9b8dcd58464 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java @@ -4,7 +4,9 @@ package com.yahoo.vespa.config.server.session; import com.yahoo.config.provision.*; import com.yahoo.vespa.config.server.*; import com.yahoo.log.LogLevel; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.modelfactory.ActivatedModelsBuilder; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.curator.Curator; import java.util.*; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionRepo.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionRepo.java index 78d7704506f..771099ef163 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionRepo.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionRepo.java @@ -10,12 +10,13 @@ import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; import com.yahoo.log.LogLevel; import com.yahoo.path.Path; -import com.yahoo.vespa.config.server.ApplicationSet; +import com.yahoo.transaction.NestedTransaction; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.curator.Curator; import com.yahoo.yolean.Exceptions; import com.yahoo.vespa.config.server.ReloadHandler; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; @@ -42,13 +43,13 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> implements Nod private final ReloadHandler reloadHandler; private final MetricUpdater metrics; private final Curator.DirectoryCache directoryCache; - private final ApplicationRepo applicationRepo; + private final TenantApplications applicationRepo; public static RemoteSessionRepo create(Curator curator, RemoteSessionFactory remoteSessionFactory, ReloadHandler reloadHandler, Path sessionsPath, - ApplicationRepo applicationRepo, + TenantApplications applicationRepo, MetricUpdater metrics, ExecutorService executorService) throws Exception { return new RemoteSessionRepo(curator, remoteSessionFactory, reloadHandler, sessionsPath, applicationRepo, metrics, executorService); @@ -60,7 +61,7 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> implements Nod * @param remoteSessionFactory a {@link com.yahoo.vespa.config.server.session.RemoteSessionFactory} * @param reloadHandler a {@link com.yahoo.vespa.config.server.ReloadHandler} * @param sessionsPath a {@link com.yahoo.path.Path} to the sessions dir. - * @param applicationRepo an {@link com.yahoo.vespa.config.server.application.ApplicationRepo} object. + * @param applicationRepo an {@link TenantApplications} object. * @param executorService an {@link ExecutorService} to run callbacks from ZooKeeper. * @throws java.lang.Exception if creating the repo fails */ @@ -68,7 +69,7 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> implements Nod RemoteSessionFactory remoteSessionFactory, ReloadHandler reloadHandler, Path sessionsPath, - ApplicationRepo applicationRepo, + TenantApplications applicationRepo, MetricUpdater metricUpdater, ExecutorService executorService) throws Exception { this.curator = curator; @@ -80,9 +81,44 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> implements Nod this.directoryCache = curator.createDirectoryCache(sessionsPath.getAbsolute(), false, false, executorService); this.directoryCache.start(); this.directoryCache.addListener(this); - sessionsChanged(getSessionList(directoryCache.getCurrentData())); + sessionsChanged(); } + //---------- START overrides to keep sessions changed in sync + + @Override + public synchronized void addSession(RemoteSession session) { + super.addSession(session); + sessionAdded(session.getSessionId()); + } + + @Override + public synchronized void removeSessionOrThrow(long id) { + super.removeSessionOrThrow(id); + sessionRemoved(id); + } + + /** + * Removes a session + * + * @param id the id of the session to remove + * @return the removed session, or null if none was found + */ + @Override + public synchronized RemoteSession removeSession(long id) { + RemoteSession session = super.removeSession(id); + sessionRemoved(id); + return session; + } + + @Override + public void removeSession(long id, NestedTransaction transaction) { + super.removeSession(id, transaction); + transaction.onCommitted(() -> sessionRemoved(id)); + } + + //---------- END overrides to keep sessions changed in sync + private void loadActiveSession(RemoteSession session) { tryReload(session.ensureApplicationLoaded(), session.logPre()); } @@ -115,30 +151,22 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> implements Nod return sessions; } - synchronized void sessionsChanged(List<Long> sessions) throws NumberFormatException { + synchronized void sessionsChanged() throws NumberFormatException { + List<Long> sessions = getSessionList(directoryCache.getCurrentData()); checkForRemovedSessions(sessions); checkForAddedSessions(sessions); } private void checkForRemovedSessions(List<Long> sessions) { - for (RemoteSession session : listSessions()) { - if (!sessions.contains(session.getSessionId())) { - SessionStateWatcher watcher = sessionStateWatchers.remove(session.getSessionId()); - watcher.close(); - removeSession(session.getSessionId()); - metrics.incRemovedSessions(); - } - } + for (RemoteSession session : listSessions()) + if ( ! sessions.contains(session.getSessionId())) + sessionRemoved(session.getSessionId()); } - + private void checkForAddedSessions(List<Long> sessions) { - for (Long sessionId : sessions) { - if (getSession(sessionId) == null) { - log.log(LogLevel.DEBUG, "Loading session id " + sessionId); - newSession(sessionId); - metrics.incAddedSessions(); - } - } + for (Long sessionId : sessions) + if (getSession(sessionId) == null) + sessionAdded(sessionId); } /** @@ -146,7 +174,7 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> implements Nod * * @param sessionId session id for the new session */ - private void newSession(long sessionId) { + private void sessionAdded(long sessionId) { try { log.log(LogLevel.DEBUG, "Adding session to RemoteSessionRepo: " + sessionId); RemoteSession session = remoteSessionFactory.createSession(sessionId); @@ -155,12 +183,20 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> implements Nod fileCache.addListener(this); loadSessionIfActive(session); sessionStateWatchers.put(sessionId, new SessionStateWatcher(fileCache, reloadHandler, session, metrics)); - addSession(session); + internalAddSession(session); + metrics.incAddedSessions(); } catch (Exception e) { - log.log(Level.WARNING, "Failed loading session " + sessionId + " (no config for this session can be served) : " + Exceptions.toMessageString(e)); + log.log(Level.WARNING, "Failed loading session " + sessionId + ": No config for this session can be served", e); } } + private void sessionRemoved(long sessionId) { + SessionStateWatcher watcher = sessionStateWatchers.remove(sessionId); + watcher.close(); + internalRemoveSessionOrThrow(sessionId); + metrics.incRemovedSessions(); + } + private void loadSessionIfActive(RemoteSession session) { for (ApplicationId applicationId : applicationRepo.listApplications()) { try { @@ -206,11 +242,11 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> implements Nod } switch (event.getType()) { case CHILD_ADDED: - sessionsChanged(getSessionList(directoryCache.getCurrentData())); + sessionsChanged(); synchronizeOnNew(getSessionList(Collections.singletonList(event.getData()))); break; case CHILD_REMOVED: - sessionsChanged(getSessionList(directoryCache.getCurrentData())); + sessionsChanged(); break; } } 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 961f9d10a60..74f3de18ffc 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 @@ -2,7 +2,7 @@ package com.yahoo.vespa.config.server.session; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.tenant.Tenants; /** * A session represents an instance of an application that can be edited, prepared and activated. This diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java index dd908eaa559..c3111c09527 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionContext.java @@ -2,10 +2,10 @@ package com.yahoo.vespa.config.server.session; import com.yahoo.config.application.api.ApplicationPackage; -import com.yahoo.vespa.config.server.HostValidator; +import com.yahoo.vespa.config.server.host.HostValidator; import com.yahoo.vespa.config.server.SuperModelGenerationCounter; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import java.io.File; @@ -20,12 +20,12 @@ public class SessionContext { private final ApplicationPackage applicationPackage; private final SessionZooKeeperClient sessionZooKeeperClient; private final File serverDBSessionDir; - private final ApplicationRepo applicationRepo; + private final TenantApplications applicationRepo; private final HostValidator<ApplicationId> hostRegistry; private final SuperModelGenerationCounter superModelGenerationCounter; public SessionContext(ApplicationPackage applicationPackage, SessionZooKeeperClient sessionZooKeeperClient, - File serverDBSessionDir, ApplicationRepo applicationRepo, + File serverDBSessionDir, TenantApplications applicationRepo, HostValidator<ApplicationId> hostRegistry, SuperModelGenerationCounter superModelGenerationCounter) { this.applicationPackage = applicationPackage; this.sessionZooKeeperClient = sessionZooKeeperClient; @@ -47,7 +47,7 @@ public class SessionContext { return serverDBSessionDir; } - public ApplicationRepo getApplicationRepo() { + public TenantApplications getApplicationRepo() { return applicationRepo; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java index 3ef6f23b84e..951bb66f206 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java @@ -12,8 +12,10 @@ import com.yahoo.path.Path; import com.yahoo.vespa.config.server.*; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs; +import com.yahoo.vespa.config.server.host.HostValidator; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.zookeeper.SessionCounter; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; import com.yahoo.vespa.curator.Curator; @@ -39,7 +41,7 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { private final Curator curator; private final ConfigCurator configCurator; private final SessionCounter sessionCounter; - private final ApplicationRepo applicationRepo; + private final TenantApplications applicationRepo; private final Path sessionsPath; private final TenantFileSystemDirs tenantFileSystemDirs; private final HostValidator<ApplicationId> hostRegistry; @@ -51,7 +53,7 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { public SessionFactoryImpl(GlobalComponentRegistry globalComponentRegistry, SessionCounter sessionCounter, Path sessionsPath, - ApplicationRepo applicationRepo, + TenantApplications applicationRepo, TenantFileSystemDirs tenantFileSystemDirs, HostValidator<ApplicationId> hostRegistry, TenantName tenant) { this.hostRegistry = hostRegistry; this.tenant = tenant; @@ -134,11 +136,9 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { IOUtils.copyDirectory(applicationFile, userApplicationDir); ApplicationPackage applicationPackage = createApplication(applicationFile, userApplicationDir, applicationName, sessionId, currentlyActiveSession); applicationPackage.writeMetaData(); - logger.log(LogLevel.SPAM, "Application package is written to disk"); return createSessionFromApplication(applicationPackage, sessionId, sessionZooKeeperClient, timeoutBudget); } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException("Error creating session: " + e.getMessage(), e); + throw new RuntimeException("Error creating session " + sessionIdPath, e); } } 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 4057d010b15..747b38f554f 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 @@ -11,11 +11,11 @@ import com.yahoo.config.model.api.ModelContext; import com.yahoo.config.provision.*; import com.yahoo.log.LogLevel; import com.yahoo.path.Path; -import com.yahoo.vespa.config.server.ApplicationSet; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.ConfigServerSpec; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; -import com.yahoo.vespa.config.server.RotationsCache; +import com.yahoo.vespa.config.server.tenant.Rotations; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.deploy.ModelContextImpl; import com.yahoo.vespa.config.server.deploy.ZooKeeperDeployer; @@ -113,8 +113,8 @@ public class SessionPreparer { final Optional<ApplicationSet> currentActiveApplicationSet; final Path tenantPath; final ApplicationId applicationId; - final RotationsCache rotationsCache; - final Set<Rotation> rotations; + final Rotations rotations; + final Set<Rotation> rotationsSet; final ModelContext.Properties properties; private ApplicationPackage applicationPackage; @@ -132,14 +132,14 @@ public class SessionPreparer { this.tenantPath = tenantPath; this.applicationId = params.getApplicationId(); - this.rotationsCache = new RotationsCache(curator, tenantPath); - this.rotations = getRotations(params.rotations()); + this.rotations = new Rotations(curator, tenantPath); + this.rotationsSet = getRotations(params.rotations()); this.properties = new ModelContextImpl.Properties(params.getApplicationId(), configserverConfig.multitenant(), ConfigServerSpec.fromConfig(configserverConfig), configserverConfig.hostedVespa(), zone, - rotations); + rotationsSet); this.preparedModelsBuilder = new PreparedModelsBuilder(modelFactoryRegistry, permanentApplicationPackage, configserverConfig, @@ -192,7 +192,7 @@ public class SessionPreparer { } void writeRotZK() { - rotationsCache.writeRotationsToZooKeeper(applicationId, rotations); + rotations.writeRotationsToZooKeeper(applicationId, rotationsSet); checkTimeout("write rotations to zookeeper"); } @@ -215,7 +215,7 @@ public class SessionPreparer { private Set<Rotation> getRotations(Set<Rotation> rotations) { if (rotations == null || rotations.isEmpty()) { - rotations = rotationsCache.readRotationsFromZooKeeper(applicationId); + rotations = this.rotations.readRotationsFromZooKeeper(applicationId); } return rotations; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepo.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepo.java index 872e6117637..1d8113f66ad 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepo.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepo.java @@ -1,6 +1,9 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.session; +import com.yahoo.transaction.AbstractTransaction; +import com.yahoo.transaction.NestedTransaction; +import com.yahoo.transaction.Transaction; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.http.NotFoundException; @@ -16,25 +19,47 @@ import java.util.HashMap; * @author lulf * @since 5.1 */ +// TODO: This is a ZK cache. We should probably remove it, or make that explicit public class SessionRepo<SESSIONTYPE extends Session> { private final HashMap<Long, SESSIONTYPE> sessions = new HashMap<>(); public synchronized void addSession(SESSIONTYPE session) { - final long sessionId = session.getSessionId(); - if (sessions.containsKey(sessionId)) { - throw new IllegalArgumentException("There already exists a session with id '" + sessionId + "'"); - } - sessions.put(sessionId, session); + internalAddSession(session); + } + + /** Why is this needed? Because of implementation inheritance - see RemoveSessionRepo */ + protected synchronized final void internalAddSession(SESSIONTYPE session) { + if (sessions.containsKey(session.getSessionId())) + throw new IllegalArgumentException("There already exists a session with id '" + session.getSessionId() + "'"); + sessions.put(session.getSessionId(), session); } - public synchronized void removeSession(long id) { - if ( ! sessions.containsKey(id)) { + public synchronized void removeSessionOrThrow(long id) { + internalRemoveSessionOrThrow(id); + } + + /** Why is this needed? Because of implementation inheritance - see RemoveSessionRepo */ + protected synchronized final void internalRemoveSessionOrThrow(long id) { + if ( ! sessions.containsKey(id)) throw new IllegalArgumentException("No such session exists '" + id + "'"); - } sessions.remove(id); } + /** + * Removes a session in a transaction + * + * @param id the id of the session to remove + * @return the removed session, or null if none was found + */ + public synchronized SESSIONTYPE removeSession(long id) { return sessions.remove(id); } + + public void removeSession(long id, NestedTransaction nestedTransaction) { + SessionRepoTransaction transaction = new SessionRepoTransaction(); + transaction.addRemoveOperation(id); + nestedTransaction.add(transaction); + } + /** * Gets a Session * @@ -75,4 +100,60 @@ public class SessionRepo<SESSIONTYPE extends Session> { public synchronized Collection<SESSIONTYPE> listSessions() { return new ArrayList<>(sessions.values()); } + + public class SessionRepoTransaction extends AbstractTransaction { + + public void addRemoveOperation(long sessionIdToRemove) { + add(new RemoveOperation(sessionIdToRemove)); + } + + @Override + public void prepare() { } + + @Override + @SuppressWarnings("unchecked") + public void commit() { + for (Operation operation : operations()) + ((SessionOperation)operation).commit(); + } + + @Override + @SuppressWarnings("unchecked") + public void rollbackOrLog() { + for (Operation operation : operations()) + ((SessionOperation)operation).rollback(); + } + + public abstract class SessionOperation implements Transaction.Operation { + + abstract void commit(); + + abstract void rollback(); + + } + + public class RemoveOperation extends SessionOperation { + + private final long sessionIdToRemove; + private SESSIONTYPE removed = null; + + public RemoveOperation(long sessionIdToRemove) { + this.sessionIdToRemove = sessionIdToRemove; + } + + @Override + public void commit() { + removed = removeSession(sessionIdToRemove); + } + + @Override + public void rollback() { + if (removed != null) + addSession(removed); + } + + } + + } + } 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 e17667c2a5a..da1fda43f9f 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 @@ -102,12 +102,9 @@ public class SessionZooKeeperClient { return rootPath.append(barrierName); } + /** Returns the number of node members needed in a barrier */ private int getNumberOfMembers() { - /* - * The number of members required in a barrier is the majority of servers. - */ - int numServers = curator.serverCount(); - return (numServers / 2) + 1; + return (curator.serverCount() / 2) + 1; // majority } private Curator.CompletionWaiter createCompletionWaiter(String waiterNode) { @@ -127,6 +124,11 @@ public class SessionZooKeeperClient { } } + /** Returns a transaction deleting this session on commit */ + public CuratorTransaction deleteTransaction() { + return CuratorTransaction.from(CuratorOperations.deleteAll(rootPath.getAbsolute(), curator), curator); + } + public ApplicationPackage loadApplicationPackage() { return new ZKApplicationPackage(configCurator, rootPath); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ActivateLock.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ActivateLock.java index bcc920614ec..7581509722f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ActivateLock.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ActivateLock.java @@ -1,7 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.yahoo.path.Path; +import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.recipes.CuratorLock; @@ -14,6 +15,7 @@ import java.util.concurrent.TimeUnit; * @since 5.1 */ public class ActivateLock { + private static final String ACTIVATE_LOCK_NAME = "activateLock"; private final CuratorLock curatorLock; @@ -36,4 +38,5 @@ public class ActivateLock { curatorLock.unlock(); } } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Rotations.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Rotations.java new file mode 100644 index 00000000000..4f5d80e570e --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Rotations.java @@ -0,0 +1,70 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.tenant; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.Rotation; +import com.yahoo.path.Path; + +import com.yahoo.vespa.curator.Curator; +import com.yahoo.vespa.curator.transaction.CuratorOperations; +import com.yahoo.vespa.curator.transaction.CuratorTransaction; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Rotations for an application. Persisted in ZooKeeper. + * + * @author hmusum + * @author bratseth + */ +// TODO: This should be owned by the correct Tenant object +public class Rotations { + + private final Path path; + private final Curator curator; + + public Rotations(Curator curator, Path tenantPath) { + this.curator = curator; + this.path = tenantPath.append("rotationsCache/"); + } + + public Set<Rotation> readRotationsFromZooKeeper(ApplicationId application) { + try { + Optional<byte[]> data = curator.getData(rotationsOf(application)); + if ( ! data.isPresent() || data.get().length == 0) return Collections.emptySet(); + Set<String> rotationIds = new ObjectMapper().readValue(data.get(), new TypeReference<Set<String>>() {}); + return rotationIds.stream().map(Rotation::new).collect(Collectors.toSet()); + } catch (Exception e) { + throw new RuntimeException("Error reading rotations of " + application, e); + } + } + + public void writeRotationsToZooKeeper(ApplicationId application, Set<Rotation> rotations) { + if (rotations.isEmpty()) return; + try { + Set<String> rotationIds = rotations.stream().map(Rotation::getId).collect(Collectors.toSet()); + byte[] data = new ObjectMapper().writeValueAsBytes(rotationIds); + curator.set(rotationsOf(application), data); + } catch (Exception e) { + throw new RuntimeException("Could not write rotations of " + application, e); + } + } + + /** Returns a transaction which deletes these rotations if they exist */ + public CuratorTransaction delete(ApplicationId application) { + if ( ! curator.exists(rotationsOf(application))) return CuratorTransaction.empty(curator); + return CuratorTransaction.from(CuratorOperations.delete(rotationsOf(application).getAbsolute()), curator); + } + + /** Returns the path storing the rotations data for an application */ + private Path rotationsOf(ApplicationId application) { + return path.append(application.serializedForm()); + } + +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/Tenant.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java index cabf4bed323..4ae7f59796a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/Tenant.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java @@ -1,12 +1,13 @@ -// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Deployer; import com.yahoo.config.provision.TenantName; import com.yahoo.log.LogLevel; import com.yahoo.path.Path; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.ReloadHandler; +import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs; import com.yahoo.vespa.config.server.session.LocalSessionRepo; import com.yahoo.vespa.config.server.session.RemoteSessionRepo; @@ -27,15 +28,15 @@ import java.util.logging.Logger; public class Tenant implements TenantHandlerProvider { private static final Logger log = Logger.getLogger(Tenant.class.getName()); - static final String SESSIONS = "sessions"; - static final String APPLICATIONS = "applications"; + public static final String SESSIONS = "sessions"; + public static final String APPLICATIONS = "applications"; private final TenantName name; private final RemoteSessionRepo remoteSessionRepo; private final Path path; private final SessionFactory sessionFactory; private final LocalSessionRepo localSessionRepo; - private final ApplicationRepo applicationRepo; + private final TenantApplications applicationRepo; private final ActivateLock activateLock; private final RequestHandler requestHandler; private final ReloadHandler reloadHandler; @@ -49,7 +50,7 @@ public class Tenant implements TenantHandlerProvider { RemoteSessionRepo remoteSessionRepo, RequestHandler requestHandler, ReloadHandler reloadHandler, - ApplicationRepo applicationRepo, + TenantApplications applicationRepo, Curator curator, TenantFileSystemDirs tenantFileSystemDirs) { this.name = name; @@ -121,7 +122,7 @@ public class Tenant implements TenantHandlerProvider { return getName().value(); } - public ApplicationRepo getApplicationRepo() { + public TenantApplications getApplicationRepo() { return applicationRepo; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java index 78ec368f2fb..07b68d8ab90 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java @@ -1,12 +1,17 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.yahoo.concurrent.ThreadFactoryFactory; import com.yahoo.path.Path; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.config.server.application.ApplicationRepo; -import com.yahoo.vespa.config.server.application.ZKApplicationRepo; +import com.yahoo.vespa.config.server.rpc.ConfigResponseFactoryFactory; +import com.yahoo.vespa.config.server.GlobalComponentRegistry; +import com.yahoo.vespa.config.server.host.HostValidator; +import com.yahoo.vespa.config.server.ReloadHandler; +import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.application.TenantApplications; +import com.yahoo.vespa.config.server.application.ZKTenantApplications; import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.vespa.config.server.session.*; @@ -34,7 +39,7 @@ public class TenantBuilder { private LocalSessionRepo localSessionRepo; private SessionFactory sessionFactory; private LocalSessionLoader localSessionLoader; - private ApplicationRepo applicationRepo; + private TenantApplications applicationRepo; private SessionCounter sessionCounter; private ReloadHandler reloadHandler; private RequestHandler requestHandler; @@ -68,7 +73,7 @@ public class TenantBuilder { return this; } - public TenantBuilder withApplicationRepo(ApplicationRepo applicationRepo) { + public TenantBuilder withApplicationRepo(TenantApplications applicationRepo) { this.applicationRepo = applicationRepo; return this; } @@ -99,15 +104,15 @@ public class TenantBuilder { createSessionFactory(); createLocalSessionRepo(); return new Tenant(tenant, - tenantPath, - sessionFactory, - localSessionRepo, - remoteSessionRepo, - requestHandler, - reloadHandler, - applicationRepo, - componentRegistry.getCurator(), - tenantFileSystemDirs); + tenantPath, + sessionFactory, + localSessionRepo, + remoteSessionRepo, + requestHandler, + reloadHandler, + applicationRepo, + componentRegistry.getCurator(), + tenantFileSystemDirs); } private void createLocalSessionRepo() { @@ -130,7 +135,7 @@ public class TenantBuilder { private void createApplicationRepo() { if (applicationRepo == null) { - applicationRepo = ZKApplicationRepo.create(componentRegistry.getCurator(), tenantPath.append(Tenant.APPLICATIONS), reloadHandler, tenant); + applicationRepo = ZKTenantApplications.create(componentRegistry.getCurator(), tenantPath.append(Tenant.APPLICATIONS), reloadHandler, tenant); } } @@ -143,10 +148,10 @@ public class TenantBuilder { private void createTenantRequestHandler() { if (requestHandler == null || reloadHandler == null) { TenantRequestHandler impl = new TenantRequestHandler(componentRegistry.getMetrics(), - tenant, - Collections.singletonList(componentRegistry.getReloadListener()), - ConfigResponseFactoryFactory.createFactory(componentRegistry.getConfigserverConfig()), - componentRegistry.getHostRegistries()); + tenant, + Collections.singletonList(componentRegistry.getReloadListener()), + ConfigResponseFactoryFactory.createFactory(componentRegistry.getConfigserverConfig()), + componentRegistry.getHostRegistries()); if (hostValidator == null) { this.hostValidator = impl; } @@ -195,7 +200,7 @@ public class TenantBuilder { return localSessionRepo; } - public ApplicationRepo getApplicationRepo() { + public TenantApplications getApplicationRepo() { return applicationRepo; } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantDebugger.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantDebugger.java index ab5bf6db7b9..aa0b78fa091 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantDebugger.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantDebugger.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.yahoo.log.LogLevel; import com.yahoo.vespa.curator.Curator; @@ -16,6 +16,7 @@ import java.util.logging.Logger; * @author lulf */ public class TenantDebugger implements TreeCacheListener { + private final TreeCache cache; private static final Logger log = Logger.getLogger(TenantDebugger.class.getName()); @@ -35,4 +36,5 @@ public class TenantDebugger implements TreeCacheListener { break; } } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantHandlerProvider.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantHandlerProvider.java index a9321709dd3..9a28cba7fab 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantHandlerProvider.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantHandlerProvider.java @@ -1,5 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; + +import com.yahoo.vespa.config.server.ReloadHandler; +import com.yahoo.vespa.config.server.RequestHandler; /** * Represents something that can provide request and reload handlers of a tenant. diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantListener.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantListener.java index 7037e24ff5d..2ba93373f93 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantListener.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantListener.java @@ -1,7 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.config.server.tenant.TenantHandlerProvider; /** * Interface for something that listens for created and deleted tenants. diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java index c4e77abc6e9..88659798575 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/TenantRequestHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import java.util.*; @@ -7,6 +7,16 @@ import com.yahoo.config.provision.Version; import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.*; import com.yahoo.vespa.config.protocol.ConfigResponse; +import com.yahoo.vespa.config.server.application.ApplicationMapper; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory; +import com.yahoo.vespa.config.server.host.HostRegistries; +import com.yahoo.vespa.config.server.host.HostRegistry; +import com.yahoo.vespa.config.server.host.HostValidator; +import com.yahoo.vespa.config.server.ReloadHandler; +import com.yahoo.vespa.config.server.ReloadListener; +import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.application.VersionDoesNotExistException; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; @@ -74,7 +84,7 @@ public class TenantRequestHandler implements RequestHandler, ReloadHandler, Host /** * Activates the config of the given app. Notifies listeners - * @param applicationSet the {@link com.yahoo.vespa.config.server.ApplicationSet} to be reloaded + * @param applicationSet the {@link ApplicationSet} to be reloaded */ public void reloadConfig(ApplicationSet applicationSet) { setLiveApp(applicationSet); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/Tenants.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java index 63ae8d1f743..6ff16c0c0fa 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/Tenants.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.google.inject.Inject; import com.yahoo.concurrent.ThreadFactoryFactory; @@ -8,6 +8,7 @@ import com.yahoo.config.provision.Deployer; import com.yahoo.config.provision.TenantName; import com.yahoo.log.LogLevel; import com.yahoo.path.Path; +import com.yahoo.vespa.config.server.GlobalComponentRegistry; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.vespa.curator.Curator; @@ -42,7 +43,7 @@ import java.util.logging.Logger; * implemented support for it). * * This instance is called from two different threads, the http handler threads and the zookeeper watcher threads. - * To create or delete a tenant, the handler calls {@link Tenants#createTenant} and {@link Tenants#deleteTenant} methods. + * To create or delete a tenant, the handler calls {@link Tenants#writeTenantPath} and {@link Tenants#deleteTenant} methods. * This will delete shared state from zookeeper, and return, so it does not mean a tenant is immediately deleted. * * Once a tenant is deleted from zookeeper, the zookeeper watcher thread will get notified on all configservers, and @@ -123,7 +124,7 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen // Pre-condition: tenants path needs to exist in zk private LinkedHashMap<TenantName, Tenant> addTenants(Collection<Tenant> newTenants) { - final LinkedHashMap<TenantName, Tenant> sessionTenants = new LinkedHashMap<>(); + LinkedHashMap<TenantName, Tenant> sessionTenants = new LinkedHashMap<>(); for (Tenant t : newTenants) { sessionTenants.put(t.getName(), t); } @@ -131,6 +132,11 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen metricUpdater.setTenants(tenants.size()); return sessionTenants; } + + public synchronized void addTenant(Tenant tenant) { + tenants.put(tenant.getName(), tenant); + metricUpdater.setTenants(tenants.size()); + } /** * Reads the set of tenants in patch cache. @@ -164,8 +170,7 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen } } - private void checkForAddedTenants(Set<TenantName> newTenants) - throws Exception { + private void checkForAddedTenants(Set<TenantName> newTenants) throws Exception { ExecutorService executor = Executors.newFixedThreadPool(globalComponentRegistry.getConfigserverConfig().numParallelTenantLoaders()); Map<TenantName, Tenant> addedTenants = new ConcurrentHashMap<>(); for (TenantName tenantName : newTenants) { @@ -193,6 +198,7 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen * * @return tenant list */ + // TODO: Replace by something idiomatic public synchronized Map<TenantName, Tenant> tenantsCopy() { return new LinkedHashMap<>(tenants); } @@ -226,7 +232,7 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen public synchronized void createSystemTenants() { for (final TenantName tenantName : SYSTEM_TENANT_NAMES) { try { - createTenant(tenantName); + writeTenantPath(tenantName); } catch (RuntimeException e) { // Do nothing if we get NodeExistsException if (e.getCause().getClass() != KeeperException.NodeExistsException.class) { @@ -237,12 +243,12 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen } /** - * Writes the given tenant into ZooKeeper, for watchers to react on + * Writes the path of the given tenant into ZooKeeper, for watchers to react on * * @param name name of the tenant * @return this Tenants */ - public synchronized Tenants createTenant(TenantName name) { + public synchronized Tenants writeTenantPath(TenantName name) { Path tenantPath = getTenantPath(name); curator.createAtomically(tenantPath, tenantPath.append(Tenant.SESSIONS), tenantPath.append(Tenant.APPLICATIONS)); return this; @@ -355,4 +361,5 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen public static Path getTenantPath(TenantName tenantName) { return tenantsPath.append(tenantName.value()); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/version/VersionState.java b/configserver/src/main/java/com/yahoo/vespa/config/server/version/VersionState.java index 2a09e46d821..21dd0b17d7a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/version/VersionState.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/version/VersionState.java @@ -58,4 +58,5 @@ public class VersionState { public String toString() { return String.format("Current version:%s, stored version:%s", currentVersion(), storedVersion()); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationFile.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationFile.java index 4aedb487352..629c045f5f2 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationFile.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationFile.java @@ -19,6 +19,7 @@ import java.util.logging.Logger; * @since 5.1 */ class ZKApplicationFile extends ApplicationFile { + private static final Logger log = Logger.getLogger("ZKApplicationFile"); private final ZKLiveApp zkApp; private final ObjectMapper mapper = new ObjectMapper(); @@ -172,4 +173,5 @@ class ZKApplicationFile extends ApplicationFile { if (other == this) return 0; return this.getPath().getName().compareTo((other).getPath().getName()); } + } diff --git a/configserver/src/main/resources/configserver-app/services.xml b/configserver/src/main/resources/configserver-app/services.xml index 1b86aed3983..5fd8f9429a7 100644 --- a/configserver/src/main/resources/configserver-app/services.xml +++ b/configserver/src/main/resources/configserver-app/services.xml @@ -6,7 +6,7 @@ <component id="com.yahoo.vespa.config.server.ConfigServerBootstrap" bundle="configserver" /> <component id="com.yahoo.vespa.config.server.monitoring.Metrics" bundle="configserver" /> <component id="com.yahoo.vespa.zookeeper.ZooKeeperServer" bundle="zkfacade" /> - <component id="com.yahoo.vespa.config.server.RpcServer" bundle="configserver" /> + <component id="com.yahoo.vespa.config.server.rpc.RpcServer" bundle="configserver" /> <component id="com.yahoo.vespa.config.server.ConfigServerDB" bundle="configserver" /> <component id="com.yahoo.vespa.config.server.session.FileDistributionFactory" bundle="configserver" /> <component id="com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry" bundle="configserver" /> @@ -17,10 +17,10 @@ <component id="com.yahoo.vespa.config.server.provision.HostProvisionerProvider" bundle="configserver" /> <component id="com.yahoo.vespa.curator.Curator" bundle="configserver" /> <component id="com.yahoo.vespa.config.server.InjectedGlobalComponentRegistry" bundle="configserver" /> - <component id="com.yahoo.vespa.config.server.Tenants" bundle="configserver" /> + <component id="com.yahoo.vespa.config.server.tenant.Tenants" bundle="configserver" /> <component id="com.yahoo.vespa.config.server.application.PermanentApplicationPackage" bundle="configserver" /> - <component id="com.yahoo.vespa.config.server.HostRegistries" bundle="configserver" /> - <component id="com.yahoo.vespa.config.server.deploy.Deployer" bundle="configserver" /> + <component id="com.yahoo.vespa.config.server.host.HostRegistries" bundle="configserver" /> + <component id="com.yahoo.vespa.config.server.ApplicationRepository" bundle="configserver" /> <component id="com.yahoo.vespa.config.server.version.VersionState" bundle="configserver" /> <component id="com.yahoo.vespa.config.server.zookeeper.ConfigCurator" bundle="configserver" /> <component id="com.yahoo.container.jdisc.metric.state.StateMetricConsumerFactory" bundle="container-disc" /> diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java index 6f5b51e7914..29d3273a527 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java @@ -4,7 +4,11 @@ package com.yahoo.vespa.config.server; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.config.provision.TenantName; import com.yahoo.io.IOUtils; +import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.monitoring.Metrics; +import com.yahoo.vespa.config.server.rpc.UncompressedConfigResponseFactory; +import com.yahoo.vespa.config.server.tenant.TenantRequestHandler; +import com.yahoo.vespa.config.server.tenant.TestWithTenant; import com.yahoo.vespa.config.server.version.VersionState; import org.junit.Rule; import org.junit.Test; @@ -69,7 +73,7 @@ public class ConfigServerBootstrapTest extends TestWithTenant { } } - public static class MockRpc extends com.yahoo.vespa.config.server.MockRpc { + public static class MockRpc extends com.yahoo.vespa.config.server.rpc.MockRpc { public volatile boolean started = false; public volatile boolean stopped = false; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java index 09576d18b32..0e3359b363f 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java @@ -7,10 +7,12 @@ import com.yahoo.config.model.NullConfigModelRegistry; import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; +import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.http.v2.SessionActiveHandlerTest; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; +import com.yahoo.vespa.config.server.rpc.RpcServer; import com.yahoo.vespa.config.server.session.*; import com.yahoo.vespa.curator.mock.MockCurator; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockReloadHandler.java b/configserver/src/test/java/com/yahoo/vespa/config/server/MockReloadHandler.java index d705203b5af..6af557d9fe3 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/MockReloadHandler.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/MockReloadHandler.java @@ -2,14 +2,15 @@ package com.yahoo.vespa.config.server; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.config.server.application.ApplicationSet; /** * @author lulf * @since 5.1.24 */ public class MockReloadHandler implements ReloadHandler { + public ApplicationSet current = null; - public ReloadListener listener = null; public volatile ApplicationId lastRemoved = null; @Override @@ -21,4 +22,5 @@ public class MockReloadHandler implements ReloadHandler { public void removeApplication(ApplicationId applicationId) { lastRemoved = applicationId; } + } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelControllerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelControllerTest.java index 68bdf3150ab..9077b3fdac9 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelControllerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelControllerTest.java @@ -7,6 +7,7 @@ import com.yahoo.config.provision.Version; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import com.yahoo.vespa.curator.mock.MockCurator; import com.yahoo.vespa.model.VespaModel; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java index e5c839abb01..65d6611112c 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java @@ -15,6 +15,7 @@ import com.yahoo.vespa.config.protocol.Trace; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.vespa.config.server.model.SuperModel; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; +import com.yahoo.vespa.config.server.rpc.UncompressedConfigResponseFactory; import com.yahoo.vespa.model.VespaModel; import org.junit.Before; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java index d202f55e38a..d3092b94de4 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java @@ -8,12 +8,16 @@ import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.provision.Provisioner; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; +import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.session.FileDistributionFactory; import com.yahoo.vespa.config.server.session.MockFileDistributionFactory; import com.yahoo.vespa.config.server.session.SessionPreparer; +import com.yahoo.vespa.config.server.tenant.MockTenantListener; +import com.yahoo.vespa.config.server.tenant.TenantListener; +import com.yahoo.vespa.config.server.tenant.TenantRequestHandlerTest; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.mock.MockCurator; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationMapperTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationMapperTest.java index e5d98bda7b5..db13e67072e 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationMapperTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationMapperTest.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.application; import java.util.ArrayList; import java.util.Arrays; @@ -7,7 +7,7 @@ import java.util.Optional; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Version; -import com.yahoo.vespa.config.server.application.Application; +import com.yahoo.vespa.config.server.ModelStub; import com.yahoo.vespa.config.server.http.NotFoundException; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import org.junit.Before; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationSetTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationSetTest.java index fce6139e18e..3d4f4c005b0 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationSetTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationSetTest.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.application; import java.util.ArrayList; import java.util.Arrays; @@ -8,7 +8,7 @@ import java.util.Optional; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Version; -import com.yahoo.vespa.config.server.application.Application; +import com.yahoo.vespa.config.server.ModelStub; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import org.junit.Before; import org.junit.Test; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/MemoryApplicationRepo.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/MemoryTenantApplications.java index c725775e467..8a4ca32fa12 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/MemoryApplicationRepo.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/MemoryTenantApplications.java @@ -11,12 +11,13 @@ import java.util.List; import java.util.Map; /** - * In memory {@link ApplicationRepo} to be used when testing. + * In memory {@link TenantApplications} to be used when testing. * * @author lulf * @since 5.1 */ -public class MemoryApplicationRepo implements ApplicationRepo { +public class MemoryTenantApplications implements TenantApplications { + private final Map<ApplicationId, Long> applications = new LinkedHashMap<>(); private boolean isOpen = true; @@ -43,8 +44,10 @@ public class MemoryApplicationRepo implements ApplicationRepo { } @Override - public void deleteApplication(ApplicationId id) { - applications.remove(id); + public Transaction deleteApplication(ApplicationId id) { + return new DummyTransaction().add((DummyTransaction.RunnableOperation) () -> { + applications.remove(id); + }); } @Override diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationRepoTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java index eea951e5c9c..82953b7e2ad 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationRepoTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java @@ -21,14 +21,14 @@ import static org.junit.Assert.*; * @author lulf * @since 5.1 */ -public class ApplicationRepoTest extends TestWithCurator { +public class TenantApplicationsTest extends TestWithCurator { @Test public void require_that_applications_are_read_from_zookeeper() throws Exception { curatorFramework.create().creatingParentsIfNeeded().forPath("/foo:dev:baz:bim", Utf8.toAsciiBytes(3)); curatorFramework.create().creatingParentsIfNeeded().forPath("/bar:test:bim:quux", Utf8.toAsciiBytes(4)); curatorFramework.create().creatingParentsIfNeeded().forPath("/bario:staging:bala:bong", Utf8.toAsciiBytes(5)); - ApplicationRepo repo = createZKAppRepo(); + TenantApplications repo = createZKAppRepo(); List<ApplicationId> applications = repo.listApplications(); assertThat(applications.size(), is(3)); assertThat(applications.get(0).application().value(), is("bario")); @@ -43,7 +43,7 @@ public class ApplicationRepoTest extends TestWithCurator { public void require_that_legacy_application_ids_are_rewritten() throws Exception { curatorFramework.create().creatingParentsIfNeeded().forPath("/foo:default:baz:bim", Utf8.toAsciiBytes(3)); curatorFramework.create().creatingParentsIfNeeded().forPath("/bar:test:bim:quux", Utf8.toAsciiBytes(4)); - ApplicationRepo repo = createZKAppRepo(); + TenantApplications repo = createZKAppRepo(); List<ApplicationId> applications = repo.listApplications(); assertThat(applications.size(), is(2)); assertThat(applications.get(0).application().value(), is("bar")); @@ -61,7 +61,7 @@ public class ApplicationRepoTest extends TestWithCurator { curatorFramework.create().creatingParentsIfNeeded().forPath("/foo:default:baz:bim", Utf8.toAsciiBytes(3)); curatorFramework.create().creatingParentsIfNeeded().forPath("/foo:prod:baz:bim", Utf8.toAsciiBytes(3)); curatorFramework.create().creatingParentsIfNeeded().forPath("/bar:test:bim:quux", Utf8.toAsciiBytes(4)); - ApplicationRepo repo = createZKAppRepo(); + TenantApplications repo = createZKAppRepo(); List<ApplicationId> applications = repo.listApplications(); assertThat(applications.size(), is(2)); assertThat(repo.getSessionIdForApplication(applications.get(0)), is(4l)); @@ -72,7 +72,7 @@ public class ApplicationRepoTest extends TestWithCurator { public void require_that_invalid_entries_are_skipped() throws Exception { curatorFramework.create().creatingParentsIfNeeded().forPath("/foo:dev:baz:bim"); curatorFramework.create().creatingParentsIfNeeded().forPath("/invalid"); - ApplicationRepo repo = createZKAppRepo(); + TenantApplications repo = createZKAppRepo(); List<ApplicationId> applications = repo.listApplications(); assertThat(applications.size(), is(1)); assertThat(applications.get(0).application().value(), is("foo")); @@ -81,7 +81,7 @@ public class ApplicationRepoTest extends TestWithCurator { @Test(expected = IllegalArgumentException.class) public void require_that_requesting_session_for_unknown_application_throws_exception() throws Exception { curatorFramework.create().creatingParentsIfNeeded().forPath("/foo:dev:baz:bim"); - ApplicationRepo repo = createZKAppRepo(); + TenantApplications repo = createZKAppRepo(); repo.getSessionIdForApplication(new ApplicationId.Builder() .tenant("exist") .applicationName("tenant").instanceName("here").build()); @@ -90,7 +90,7 @@ public class ApplicationRepoTest extends TestWithCurator { @Test(expected = IllegalArgumentException.class) public void require_that_requesting_session_for_empty_application_throws_exception() throws Exception { curatorFramework.create().creatingParentsIfNeeded().forPath("/foo:dev:baz:bim"); - ApplicationRepo repo = createZKAppRepo(); + TenantApplications repo = createZKAppRepo(); repo.getSessionIdForApplication(new ApplicationId.Builder() .tenant("tenant") .applicationName("foo").instanceName("bim").build()); @@ -98,7 +98,7 @@ public class ApplicationRepoTest extends TestWithCurator { @Test public void require_that_application_ids_can_be_written() throws Exception { - ApplicationRepo repo = createZKAppRepo(); + TenantApplications repo = createZKAppRepo(); repo.createPutApplicationTransaction(createAppplicationId("myapp"), 3l).commit(); String path = "/mytenant:myapp:myinst"; assertTrue(curatorFramework.checkExists().forPath(path) != null); @@ -110,25 +110,23 @@ public class ApplicationRepoTest extends TestWithCurator { @Test public void require_that_application_ids_can_be_deleted() throws Exception { - ApplicationRepo repo = createZKAppRepo(); + TenantApplications repo = createZKAppRepo(); ApplicationId id1 = createAppplicationId("myapp"); ApplicationId id2 = createAppplicationId("myapp2"); repo.createPutApplicationTransaction(id1, 1).commit(); repo.createPutApplicationTransaction(id2, 1).commit(); assertThat(repo.listApplications().size(), is(2)); - repo.deleteApplication(id1); + repo.deleteApplication(id1).commit(); assertThat(repo.listApplications().size(), is(1)); - repo.deleteApplication(id2); - assertThat(repo.listApplications().size(), is(0)); - repo.deleteApplication(id2); + repo.deleteApplication(id2).commit(); assertThat(repo.listApplications().size(), is(0)); } @Test public void require_that_repos_behave_similarly() throws Exception { - ApplicationRepo zkRepo = createZKAppRepo(); - ApplicationRepo memRepo = new MemoryApplicationRepo(); - for (ApplicationRepo repo : Arrays.asList(zkRepo, memRepo)) { + TenantApplications zkRepo = createZKAppRepo(); + TenantApplications memRepo = new MemoryTenantApplications(); + for (TenantApplications repo : Arrays.asList(zkRepo, memRepo)) { ApplicationId id1 = createAppplicationId("myapp"); ApplicationId id2 = createAppplicationId("myapp2"); repo.createPutApplicationTransaction(id1, 4).commit(); @@ -148,11 +146,9 @@ public class ApplicationRepoTest extends TestWithCurator { assertThat(lst.get(1).application(), is(id2.application())); assertThat(repo.getSessionIdForApplication(id1), is(6l)); assertThat(repo.getSessionIdForApplication(id2), is(5l)); - repo.deleteApplication(id1); + repo.deleteApplication(id1).commit(); assertThat(repo.listApplications().size(), is(1)); - repo.deleteApplication(id2); - assertThat(repo.listApplications().size(), is(0)); - repo.deleteApplication(id2); + repo.deleteApplication(id2).commit(); } } @@ -162,11 +158,12 @@ public class ApplicationRepoTest extends TestWithCurator { curatorFramework.create().creatingParentsIfNeeded().forPath("/bar:dev:bim:quux", Utf8.toAsciiBytes(4)); curatorFramework.create().creatingParentsIfNeeded().forPath("/bario:staging:bala:bong", Utf8.toAsciiBytes(5)); MockReloadHandler reloadHandler = new MockReloadHandler(); - ApplicationRepo repo = createZKAppRepo(reloadHandler); + TenantApplications repo = createZKAppRepo(reloadHandler); assertNull(reloadHandler.lastRemoved); repo.deleteApplication(new ApplicationId.Builder() .tenant("mytenant") - .applicationName("bar").instanceName("quux").build()); + .applicationName("bar").instanceName("quux").build()) + .commit(); long endTime = System.currentTimeMillis() + 60_000; while (System.currentTimeMillis() < endTime && reloadHandler.lastRemoved == null) { Thread.sleep(100); @@ -175,12 +172,12 @@ public class ApplicationRepoTest extends TestWithCurator { assertThat(reloadHandler.lastRemoved.serializedForm(), is("mytenant:bar:quux")); } - private ApplicationRepo createZKAppRepo() { + private TenantApplications createZKAppRepo() { return createZKAppRepo(new MockReloadHandler()); } - private ApplicationRepo createZKAppRepo(MockReloadHandler reloadHandler) { - return ZKApplicationRepo.create(curator, Path.createRoot(), reloadHandler, TenantName.from("mytenant")); + private TenantApplications createZKAppRepo(MockReloadHandler reloadHandler) { + return ZKTenantApplications.create(curator, Path.createRoot(), reloadHandler, TenantName.from("mytenant")); } private static ApplicationId createAppplicationId(String name) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/DeployHandlerLoggerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLoggerTest.java index b34881bcba8..4e095b3324e 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/DeployHandlerLoggerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLoggerTest.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.deploy; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.provision.ApplicationId; @@ -8,6 +8,7 @@ import com.yahoo.slime.Cursor; import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; +import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger; import org.junit.Test; import java.io.ByteArrayOutputStream; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java index fbd4f791f83..12f69ec1dc6 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java @@ -15,7 +15,8 @@ import com.yahoo.config.provision.ProvisionLogger; import com.yahoo.config.provision.Provisioner; import com.yahoo.path.Path; import com.yahoo.transaction.NestedTransaction; -import com.yahoo.vespa.config.server.TestWithTenant; +import com.yahoo.vespa.config.server.ApplicationRepository; +import com.yahoo.vespa.config.server.tenant.TestWithTenant; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.session.LocalSession; @@ -46,10 +47,10 @@ public class HostedDeployTest extends TestWithTenant { public void testRedeploy() throws InterruptedException, IOException { ApplicationId id = deployApp(); - Deployer deployer = new Deployer(tenants, HostProvisionerProvider.withProvisioner(createHostProvisioner()), - new ConfigserverConfig(new ConfigserverConfig.Builder()), curator); + ApplicationRepository applicationRepository = new ApplicationRepository(tenants, HostProvisionerProvider.withProvisioner(createHostProvisioner()), + new ConfigserverConfig(new ConfigserverConfig.Builder()), curator); - Optional<com.yahoo.config.provision.Deployment> deployment = deployer.deployFromLocalActive(id, Duration.ofSeconds(60)); + Optional<com.yahoo.config.provision.Deployment> deployment = applicationRepository.deployFromLocalActive(id, Duration.ofSeconds(60)); assertTrue(deployment.isPresent()); deployment.get().prepare(); deployment.get().activate(); @@ -90,7 +91,7 @@ public class HostedDeployTest extends TestWithTenant { } @Override - public void removed(ApplicationId application) { + public void remove(NestedTransaction transaction, ApplicationId application) { // noop } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java index 6175e8cf1fc..b06069d98af 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java @@ -7,7 +7,8 @@ import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.TenantName; import com.yahoo.path.Path; -import com.yahoo.vespa.config.server.TestWithTenant; +import com.yahoo.vespa.config.server.ApplicationRepository; +import com.yahoo.vespa.config.server.tenant.TestWithTenant; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.session.LocalSession; @@ -40,10 +41,10 @@ public class RedeployTest extends TestWithTenant { public void testRedeploy() throws InterruptedException, IOException { ApplicationId id = deployApp(); - Deployer deployer = new Deployer(tenants, HostProvisionerProvider.empty(), - new ConfigserverConfig(new ConfigserverConfig.Builder()), curator); + ApplicationRepository applicationRepository = new ApplicationRepository(tenants, HostProvisionerProvider.empty(), + new ConfigserverConfig(new ConfigserverConfig.Builder()), curator); - Optional<com.yahoo.config.provision.Deployment> deployment = deployer.deployFromLocalActive(id, Duration.ofSeconds(60)); + Optional<com.yahoo.config.provision.Deployment> deployment = applicationRepository.deployFromLocalActive(id, Duration.ofSeconds(60)); assertTrue(deployment.isPresent()); long activeSessionIdBefore = tenant.getLocalSessionRepo().getActiveSession(id).getSessionId(); assertEquals(id, tenant.getLocalSessionRepo().getSession(activeSessionIdBefore).getApplicationId()); @@ -61,10 +62,10 @@ public class RedeployTest extends TestWithTenant { ApplicationName.from("default"), InstanceName.from("default")); - Deployer deployer = new Deployer(tenants, HostProvisionerProvider.empty(), - new ConfigserverConfig(new ConfigserverConfig.Builder()), curator); + ApplicationRepository applicationRepository = new ApplicationRepository(tenants, HostProvisionerProvider.empty(), + new ConfigserverConfig(new ConfigserverConfig.Builder()), curator); - assertFalse(deployer.deployFromLocalActive(id, Duration.ofSeconds(60)).isPresent()); + assertFalse(applicationRepository.deployFromLocalActive(id, Duration.ofSeconds(60)).isPresent()); } /** diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/HostRegistryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/host/HostRegistryTest.java index 1147d2d4c0d..68fbe3d6b61 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/HostRegistryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/host/HostRegistryTest.java @@ -1,11 +1,12 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.host; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import com.yahoo.vespa.config.server.host.HostRegistry; import org.junit.Test; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/CompressedApplicationInputStreamTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java index 5dd0f889431..8d85258f221 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/CompressedApplicationInputStreamTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java @@ -1,7 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.http; import com.google.common.io.ByteStreams; +import com.yahoo.vespa.config.server.http.CompressedApplicationInputStream; import org.apache.commons.compress.archivers.ArchiveOutputStream; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HandlerTest.java index 6f4ca93fb07..6f69b135972 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HandlerTest.java @@ -16,6 +16,7 @@ import static org.junit.Assert.*; * @since 5.1.14 */ public class HandlerTest { + public static void assertHttpStatusCodeErrorCodeAndMessage(HttpResponse response, int statusCode, HttpErrorResponse.errorCodes errorCode, String message) throws IOException { assertNotNull(response); String renderedString = SessionHandlerTest.getRenderedString(response); @@ -32,4 +33,5 @@ public class HandlerTest { public static void assertHttpStatusCodeAndMessage(HttpResponse response, int statusCode, String message) throws IOException { assertHttpStatusCodeErrorCodeAndMessage(response, statusCode, null, message); } + } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandlerTest.java index d1c4c5e5e2e..6957e5018b9 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandlerTest.java @@ -10,7 +10,7 @@ import com.yahoo.container.logging.AccessLog; import com.yahoo.text.StringUtilities; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.ConfigPayload; -import com.yahoo.vespa.config.server.MockRequestHandler; +import com.yahoo.vespa.config.server.rpc.MockRequestHandler; import com.yahoo.vespa.config.protocol.SlimeConfigResponse; import com.yahoo.config.provision.ApplicationId; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandlerTest.java index ad917c5db6d..a01f6bbbded 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandlerTest.java @@ -5,7 +5,7 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.vespa.config.ConfigKey; -import com.yahoo.vespa.config.server.MockRequestHandler; +import com.yahoo.vespa.config.server.rpc.MockRequestHandler; import com.yahoo.vespa.config.server.http.HttpListConfigsHandler.ListConfigsResponse; import org.junit.Before; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java index 2e5576869b5..3d1f9b5766a 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionActiveHandlerTestBase.java @@ -20,7 +20,7 @@ import com.yahoo.config.provision.*; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.SuperModelGenerationCounter; import com.yahoo.vespa.config.server.TestComponentRegistry; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs; import com.yahoo.vespa.config.server.deploy.ZooKeeperClient; import com.yahoo.vespa.config.server.session.*; @@ -37,7 +37,7 @@ import com.yahoo.config.model.application.provider.BaseDeployLogger; import com.yahoo.config.model.application.provider.DeployData; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.jdisc.http.HttpRequest; -import com.yahoo.vespa.config.server.HostRegistry; +import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.vespa.config.server.PathProvider; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; @@ -51,7 +51,7 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest { protected RemoteSessionRepo remoteSessionRepo; protected LocalSessionRepo localRepo; protected PathProvider pathProvider; - protected ApplicationRepo applicationRepo; + protected TenantApplications applicationRepo; protected String activatedMessage = " activated."; protected String tenantMessage = ""; @@ -159,9 +159,7 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest { private LocalSessionRepo addLocalSession(long sessionId, DeployData deployData, SessionZooKeeperClient zkc) { writeApplicationId(zkc, deployData.getApplicationName()); TenantFileSystemDirs tenantFileSystemDirs = TenantFileSystemDirs.createTestDirs(tenant); - ApplicationPackage app = FilesApplicationPackage.fromFileWithDeployData(testApp, - deployData - ); + ApplicationPackage app = FilesApplicationPackage.fromFileWithDeployData(testApp, deployData); localRepo.addSession(new LocalSession(tenant, sessionId, new SessionTest.MockSessionPreparer(), new SessionContext(app, zkc, new File(tenantFileSystemDirs.path(), String.valueOf(sessionId)), applicationRepo, new HostRegistry<>(), new SuperModelGenerationCounter(curator)))); return localRepo; } @@ -173,7 +171,8 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest { protected abstract RemoteSession activateAndAssertOK(long sessionId, long previousSessionId) throws Exception; protected ActivateRequest activateAndAssertOKPut(long sessionId, long previousSessionId, String subPath) throws Exception { - ActivateRequest activateRequest = new ActivateRequest(sessionId, previousSessionId, subPath).invoke(); + ActivateRequest activateRequest = new ActivateRequest(sessionId, previousSessionId, subPath); + activateRequest.invoke(); HttpResponse actResponse = activateRequest.getActResponse(); String message = getRenderedString(actResponse); assertThat(message, actResponse.getStatus(), is(OK)); @@ -188,7 +187,8 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest { protected abstract void activateAndAssertError(long sessionId, long previousSessionId, HttpErrorResponse.errorCodes errorCode, String expectedError) throws Exception; protected ActivateRequest activateAndAssertErrorPut(long sessionId, long previousSessionId, HttpErrorResponse.errorCodes errorCode, String expectedError) throws Exception { - ActivateRequest activateRequest = new ActivateRequest(sessionId, previousSessionId, "").invoke(); + ActivateRequest activateRequest = new ActivateRequest(sessionId, previousSessionId, ""); + activateRequest.invoke(); HttpResponse actResponse = activateRequest.getActResponse(); RemoteSession session = activateRequest.getSession(); assertThat(actResponse.getStatus(), is(BAD_REQUEST)); @@ -206,6 +206,7 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest { } protected class ActivateRequest { + private long sessionId; private RemoteSession session; private SessionHandler handler; @@ -251,7 +252,8 @@ public abstract class SessionActiveHandlerTestBase extends SessionHandlerTest { } public ActivateRequest invoke(boolean createLocalSession) throws Exception { - SessionZooKeeperClient zkClient = new MockSessionZKClient(curator, pathProvider.getSessionDirs().append(String.valueOf(sessionId)), Optional.of(ProvisionInfo.withHosts(Collections.singleton(new HostSpec("bar", Collections.emptyList()))))); + SessionZooKeeperClient zkClient = new MockSessionZKClient(curator, pathProvider.getSessionDirs().append(String.valueOf(sessionId)), + Optional.of(ProvisionInfo.withHosts(Collections.singleton(new HostSpec("bar", Collections.emptyList()))))); session = createRemoteSession(sessionId, initialStatus, zkClient); if (createLocalSession) { LocalSessionRepo repo = addLocalSession(sessionId, deployData, zkClient); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionCreateHandlerTestBase.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionCreateHandlerTestBase.java index 74211196174..52237235580 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionCreateHandlerTestBase.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionCreateHandlerTestBase.java @@ -7,9 +7,8 @@ import com.yahoo.config.model.application.provider.FilesApplicationPackage; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.io.IOUtils; -import com.yahoo.vespa.config.server.CompressedApplicationInputStreamTest; import com.yahoo.vespa.config.server.TimeoutBudget; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.session.LocalSession; import com.yahoo.vespa.config.server.session.LocalSessionRepo; import com.yahoo.vespa.config.server.session.SessionFactory; @@ -48,7 +47,7 @@ public abstract class SessionCreateHandlerTestBase extends SessionHandlerTest { public File testApp = new File("src/test/apps/app"); public LocalSessionRepo localSessionRepo; - public ApplicationRepo applicationRepo; + public TenantApplications applicationRepo; static { postHeaders.put(SessionCreate.contentTypeHeader, SessionCreate.APPLICATION_X_GZIP); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java index da5283aeecd..1f1791fd70f 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java @@ -5,13 +5,14 @@ import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.model.test.MockApplicationPackage; +import com.yahoo.transaction.NestedTransaction; import com.yahoo.transaction.Transaction; import com.yahoo.log.LogLevel; import com.yahoo.path.Path; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.vespa.config.server.ApplicationSet; -import com.yahoo.vespa.config.server.HostRegistry; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; @@ -44,6 +45,10 @@ public class SessionHandlerTest { return createTestRequest(path, method, cmd, id, ""); } + public static HttpRequest createTestRequest(String path, com.yahoo.jdisc.http.HttpRequest.Method method) { + return HttpRequest.createTestRequest("http://" + hostname + ":" + port + path, method); + } + public static HttpRequest createTestRequest(String path) { return HttpRequest.createTestRequest("http://" + hostname + ":" + port + path, com.yahoo.jdisc.http.HttpRequest.Method.PUT); } @@ -144,15 +149,19 @@ public class SessionHandlerTest { @Override public void delete() { } + + @Override + public void delete(NestedTransaction transaction) { } + } - public static enum Cmd { + public enum Cmd { PREPARED("prepared"), ACTIVE("active"), CONTENT("content"); private final String name; - private Cmd(String s) { + Cmd(String s) { this.name = s; } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java index 1e1bf1a644c..f92bfa7d866 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java @@ -51,7 +51,7 @@ public class ApplicationContentHandlerTest extends ContentHandlerTestBase { testTenantBuilder.tenants().get(tenant2).getLocalSessionRepo().addSession(new MockSession(3l, FilesApplicationPackage.fromFile(new File("src/test/apps/content2")))); testTenantBuilder.tenants().get(tenant1).getApplicationRepo().createPutApplicationTransaction(idTenant1, 2l).commit(); testTenantBuilder.tenants().get(tenant2).getApplicationRepo().createPutApplicationTransaction(idTenant2, 3l).commit(); - handler = new ApplicationHandler(command -> command.run(), AccessLog.voidAccessLog(), testTenantBuilder.createTenants(), HostProvisionerProvider.empty(), Zone.defaultZone(), null, null); + handler = new ApplicationHandler(command -> command.run(), AccessLog.voidAccessLog(), testTenantBuilder.createTenants(), HostProvisionerProvider.empty(), Zone.defaultZone(), null, null, null, null); pathPrefix = createPath(idTenant1, Zone.defaultZone()); baseUrl = baseServer + pathPrefix; } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java index 5171277c873..a1a4a3413ba 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java @@ -14,10 +14,20 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.jdisc.Response; +import com.yahoo.path.Path; +import com.yahoo.vespa.config.server.GlobalComponentRegistry; import com.yahoo.vespa.config.server.MockReloadHandler; +import com.yahoo.vespa.config.server.SuperModelGenerationCounter; +import com.yahoo.vespa.config.server.application.TenantApplications; +import com.yahoo.vespa.config.server.application.ZKTenantApplications; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; -import com.yahoo.vespa.config.server.Tenant; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.monitoring.Metrics; +import com.yahoo.vespa.config.server.session.LocalSession; +import com.yahoo.vespa.config.server.session.SessionContext; +import com.yahoo.vespa.config.server.session.SessionZooKeeperClient; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.application.ApplicationConvergenceChecker; import com.yahoo.vespa.config.server.application.LogServerLogGrabber; @@ -25,10 +35,8 @@ import com.yahoo.vespa.config.server.http.HandlerTest; import com.yahoo.vespa.config.server.http.HttpErrorResponse; import com.yahoo.vespa.config.server.http.SessionHandlerTest; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; -import com.yahoo.vespa.config.server.session.LocalSessionRepo; import com.yahoo.vespa.config.server.session.MockSessionZKClient; import com.yahoo.vespa.config.server.session.RemoteSession; -import com.yahoo.vespa.config.server.session.RemoteSessionRepo; import com.yahoo.vespa.curator.mock.MockCurator; import com.yahoo.vespa.model.VespaModelFactory; import org.junit.Assert; @@ -46,6 +54,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -57,9 +66,9 @@ public class ApplicationHandlerTest { private static File testApp = new File("src/test/apps/app"); - private ApplicationHandler handler; + private ApplicationHandler mockHandler; private ListApplicationsHandler listApplicationsHandler; - private final static TenantName mytenant = TenantName.from("mytenant"); + private final static TenantName mytenantName = TenantName.from("mytenant"); private final static TenantName foobar = TenantName.from("foobar"); private Tenants tenants; private SessionActiveHandlerTest.MockProvisioner provisioner; @@ -68,18 +77,18 @@ public class ApplicationHandlerTest { @Before public void setup() throws Exception { TestTenantBuilder testBuilder = new TestTenantBuilder(); - testBuilder.createTenant(mytenant).withReloadHandler(new MockReloadHandler()); + testBuilder.createTenant(mytenantName).withReloadHandler(new MockReloadHandler()); testBuilder.createTenant(foobar).withReloadHandler(new MockReloadHandler()); tenants = testBuilder.createTenants(); provisioner = new SessionActiveHandlerTest.MockProvisioner(); - handler = createApplicationHandler( + mockHandler = createMockApplicationHandler( provisioner, new ApplicationConvergenceChecker(stateApiFactory), new LogServerLogGrabber()); listApplicationsHandler = new ListApplicationsHandler( Runnable::run, AccessLog.voidAccessLog(), tenants, Zone.defaultZone()); } - private ApplicationHandler createApplicationHandler( + private ApplicationHandler createMockApplicationHandler( Provisioner provisioner, ApplicationConvergenceChecker convergeChecker, LogServerLogGrabber logServerLogGrabber) { @@ -90,55 +99,89 @@ public class ApplicationHandlerTest { HostProvisionerProvider.withProvisioner(provisioner), Zone.defaultZone(), convergeChecker, - logServerLogGrabber); + logServerLogGrabber, + null, + null); + } + + private ApplicationHandler createApplicationHandler(Tenants tenants) { + return new ApplicationHandler( + Runnable::run, + AccessLog.voidAccessLog(), + tenants, + HostProvisionerProvider.withProvisioner(provisioner), + Zone.defaultZone(), + new ApplicationConvergenceChecker(stateApiFactory), + new LogServerLogGrabber(), + null, + null); } @Test public void testDelete() throws Exception { - ApplicationId defaultId = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenant).build(); - assertApplicationExists(mytenant, null, Zone.defaultZone()); + ApplicationId defaultId = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build(); + assertApplicationExists(mytenantName, null, Zone.defaultZone()); long sessionId = 1; - addApplication(tenants.tenantsCopy().get(mytenant), defaultId, sessionId); - assertApplicationExists(mytenant, defaultId, Zone.defaultZone()); - assertFalse(provisioner.removed); - deleteAndAssertOKResponse(defaultId); - assertTrue(provisioner.removed); - assertThat(provisioner.lastApplicationId.tenant(), is(mytenant)); - assertThat(provisioner.lastApplicationId, is(defaultId)); - sessionId++; - addApplication(tenants.tenantsCopy().get(mytenant), defaultId, sessionId); - deleteAndAssertOKResponse(defaultId, true); - - ApplicationId fooId = new ApplicationId.Builder() - .tenant(mytenant) - .applicationName("foo").instanceName("quux").build(); + { + // This block is a real test of the interplay of (most of) the components of the config server + // TODO: Extract it to ApplicationRepositoryTest, rewrite to bypass the HTTP layer and extend + // as login is moved from the HTTP layer into ApplicationRepository + Tenants tenants = addApplication(defaultId, sessionId); + ApplicationHandler handler = createApplicationHandler(tenants); + Tenant mytenant = tenants.tenantsCopy().get(defaultId.tenant()); + LocalSession applicationData = mytenant.getLocalSessionRepo().getSession(sessionId); + assertNotNull(applicationData); + assertNotNull(applicationData.getApplicationId()); + assertFalse(provisioner.removed); + + deleteAndAssertOKResponse(handler, mytenant, defaultId); + assertTrue(provisioner.removed); + assertThat(provisioner.lastApplicationId.tenant(), is(mytenantName)); + assertThat(provisioner.lastApplicationId, is(defaultId)); + + assertNull(mytenant.getLocalSessionRepo().getSession(sessionId)); + assertNull(mytenant.getRemoteSessionRepo().getSession(sessionId)); + } + sessionId++; - addApplication(tenants.tenantsCopy().get(mytenant), fooId, sessionId); - addApplication(tenants.tenantsCopy().get(foobar), fooId, sessionId); - assertApplicationExists(mytenant, fooId, Zone.defaultZone()); - assertApplicationExists(foobar, fooId, Zone.defaultZone()); - deleteAndAssertOKResponse(fooId, true); - assertThat(provisioner.lastApplicationId.tenant(), is(mytenant)); - assertThat(provisioner.lastApplicationId, is(fooId)); - assertApplicationExists(mytenant, null, Zone.defaultZone()); - assertApplicationExists(foobar, fooId, Zone.defaultZone()); - + { + addMockApplication(tenants.tenantsCopy().get(mytenantName), defaultId, sessionId); + deleteAndAssertOKResponseMocked(defaultId, true); + + ApplicationId fooId = new ApplicationId.Builder() + .tenant(mytenantName) + .applicationName("foo").instanceName("quux").build(); + + sessionId++; + + addMockApplication(tenants.tenantsCopy().get(mytenantName), fooId, sessionId); + addMockApplication(tenants.tenantsCopy().get(foobar), fooId, sessionId); + assertApplicationExists(mytenantName, fooId, Zone.defaultZone()); + assertApplicationExists(foobar, fooId, Zone.defaultZone()); + deleteAndAssertOKResponseMocked(fooId, true); + assertThat(provisioner.lastApplicationId.tenant(), is(mytenantName)); + assertThat(provisioner.lastApplicationId, is(fooId)); + assertApplicationExists(mytenantName, null, Zone.defaultZone()); + assertApplicationExists(foobar, fooId, Zone.defaultZone()); + } sessionId++; - ApplicationId baliId = new ApplicationId.Builder() - .tenant(mytenant) - .applicationName("bali").instanceName("quux").build(); - addApplication(tenants.tenantsCopy().get(mytenant), baliId, sessionId); - deleteAndAssertOKResponse(baliId, true); - assertApplicationExists(mytenant, null, Zone.defaultZone()); + { + ApplicationId baliId = new ApplicationId.Builder() + .tenant(mytenantName) + .applicationName("bali").instanceName("quux").build(); + addMockApplication(tenants.tenantsCopy().get(mytenantName), baliId, sessionId); + deleteAndAssertOKResponseMocked(baliId, true); + assertApplicationExists(mytenantName, null, Zone.defaultZone()); + } } @Test public void testGet() throws Exception { long sessionId = 1; - ApplicationId defaultId = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenant).build(); - addApplication(tenants.tenantsCopy().get(mytenant), defaultId, sessionId); + ApplicationId defaultId = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build(); + addMockApplication(tenants.tenantsCopy().get(mytenantName), defaultId, sessionId); assertApplicationGeneration(defaultId, Zone.defaultZone(), 1, true); assertApplicationGeneration(defaultId, Zone.defaultZone(), 1, false); } @@ -146,8 +189,8 @@ public class ApplicationHandlerTest { @Test public void testRestart() throws Exception { long sessionId = 1; - ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenant).build(); - addApplication(tenants.tenantsCopy().get(mytenant), application, sessionId); + ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build(); + addMockApplication(tenants.tenantsCopy().get(mytenantName), application, sessionId); assertFalse(provisioner.restarted); restart(application, Zone.defaultZone()); assertTrue(provisioner.restarted); @@ -157,8 +200,8 @@ public class ApplicationHandlerTest { @Test public void testConverge() throws Exception { long sessionId = 1; - ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenant).build(); - addApplication(tenants.tenantsCopy().get(mytenant), application, sessionId); + ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build(); + addMockApplication(tenants.tenantsCopy().get(mytenantName), application, sessionId); assertFalse(stateApiFactory.createdApi); converge(application, Zone.defaultZone()); assertTrue(stateApiFactory.createdApi); @@ -173,55 +216,105 @@ public class ApplicationHandlerTest { @Ignore public void testFailingProvisioner() throws Exception { provisioner = new SessionActiveHandlerTest.FailingMockProvisioner(); - handler = createApplicationHandler( + mockHandler = createMockApplicationHandler( provisioner, new ApplicationConvergenceChecker(stateApiFactory), new LogServerLogGrabber()); final ApplicationId applicationId = ApplicationId.defaultId(); - addApplication(tenants.tenantsCopy().get(mytenant), applicationId, 1); - assertApplicationExists(mytenant, applicationId, Zone.defaultZone()); + addMockApplication(tenants.tenantsCopy().get(mytenantName), applicationId, 1); + assertApplicationExists(mytenantName, applicationId, Zone.defaultZone()); provisioner.activated = true; - String url = "http://myhost:14000/application/v2/tenant/" + mytenant + "/application/" + applicationId.application(); - deleteAndAssertResponse(url, 500, null, "{\"message\":\"Cannot remove application\"}", com.yahoo.jdisc.http.HttpRequest.Method.DELETE); - assertApplicationExists(mytenant, applicationId, Zone.defaultZone()); + String url = "http://myhost:14000/application/v2/tenant/" + mytenantName + "/application/" + applicationId.application(); + deleteAndAssertResponse(mockHandler, url, 500, null, "{\"message\":\"Cannot remove application\"}", com.yahoo.jdisc.http.HttpRequest.Method.DELETE); + assertApplicationExists(mytenantName, applicationId, Zone.defaultZone()); Assert.assertTrue(provisioner.activated); } - static void addApplication(Tenant tenant, ApplicationId applicationId, long sessionId) throws Exception { + static void addMockApplication(Tenant tenant, ApplicationId applicationId, long sessionId) throws Exception { tenant.getApplicationRepo().createPutApplicationTransaction(applicationId, sessionId).commit(); ApplicationPackage app = FilesApplicationPackage.fromFile(testApp); - addLocalSession(tenant, app, sessionId, applicationId); - addRemoteSession(tenant, app, sessionId); + tenant.getLocalSessionRepo().addSession(new SessionHandlerTest.MockSession(sessionId, app, applicationId)); + tenant.getRemoteSessionRepo().addSession(new RemoteSession(tenant.getName(), sessionId, + new TestComponentRegistry(new MockCurator(), + new ModelFactoryRegistry(Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry())))), new MockSessionZKClient(app))); } - static void addLocalSession(Tenant tenant, ApplicationPackage app, long sessionId, ApplicationId applicationId) { - LocalSessionRepo localRepo = tenant.getLocalSessionRepo(); - localRepo.addSession(new SessionHandlerTest.MockSession(sessionId, app, applicationId)); - } + static Tenants addApplication(ApplicationId applicationId, long sessionId) throws Exception { + // This method is a good illustration of the spaghetti wiring resulting from no design + // TODO: When this setup looks sane we have refactored sufficiently that there is a design + + TenantName tenantName = applicationId.tenant(); + + Path tenantPath = Tenants.getTenantPath(tenantName); + Path sessionPath = tenantPath.append(Tenant.SESSIONS).append(String.valueOf(sessionId)); + + MockCurator curator = new MockCurator(); + GlobalComponentRegistry globalComponents = new TestComponentRegistry(curator); + + Tenants tenants = new Tenants(globalComponents, Metrics.createTestMetrics()); // Creates the application path element in zk + tenants.writeTenantPath(tenantName); + TenantApplications tenantApplications = ZKTenantApplications.create(curator, + tenantPath.append(Tenant.APPLICATIONS), + new MockReloadHandler(), // TODO: Use the real one + tenantName); + Tenant tenant = TenantBuilder.create(globalComponents, applicationId.tenant(), tenantPath) + .withApplicationRepo(tenantApplications) + .build(); + tenants.addTenant(tenant); + + tenant.getApplicationRepo().createPutApplicationTransaction(applicationId, sessionId).commit(); + ApplicationPackage app = FilesApplicationPackage.fromFile(testApp); - static void addRemoteSession(Tenant tenant, ApplicationPackage app, long sessionId) { - RemoteSessionRepo remoteRepo = tenant.getRemoteSessionRepo(); - remoteRepo.addSession(new RemoteSession(tenant.getName(), sessionId, new TestComponentRegistry(new MockCurator(), new ModelFactoryRegistry(Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry())))), new MockSessionZKClient(app))); + SessionZooKeeperClient sessionClient = new SessionZooKeeperClient(curator, sessionPath); + SessionContext context = new SessionContext(app, + sessionClient, + new File("/serverDb"), + tenant.getApplicationRepo(), + null, + new SuperModelGenerationCounter(curator)); + tenant.getLocalSessionRepo().addSession(new LocalSession(tenantName, sessionId, null, context)); + sessionClient.writeApplicationId(applicationId); // TODO: Instead, use ApplicationRepository to deploy the application + + tenant.getRemoteSessionRepo().addSession(new RemoteSession(tenantName, sessionId, + new TestComponentRegistry(curator, + new ModelFactoryRegistry(Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry())))), + sessionClient)); + return tenants; } private void assertNotAllowed(com.yahoo.jdisc.http.HttpRequest.Method method) throws IOException { - String url = "http://myhost:14000/application/v2/tenant/" + mytenant + "/application/default"; - deleteAndAssertResponse(url, Response.Status.METHOD_NOT_ALLOWED, HttpErrorResponse.errorCodes.METHOD_NOT_ALLOWED, "{\"error-code\":\"METHOD_NOT_ALLOWED\",\"message\":\"Method '" + method + "' is not supported\"}", - method); + String url = "http://myhost:14000/application/v2/tenant/" + mytenantName + "/application/default"; + deleteAndAssertResponse(mockHandler, url, Response.Status.METHOD_NOT_ALLOWED, HttpErrorResponse.errorCodes.METHOD_NOT_ALLOWED, "{\"error-code\":\"METHOD_NOT_ALLOWED\",\"message\":\"Method '" + method + "' is not supported\"}", + method); } - private void deleteAndAssertOKResponse(ApplicationId applicationId) throws IOException { - deleteAndAssertOKResponse(applicationId, true); + private void deleteAndAssertOKResponseMocked(ApplicationId applicationId) throws IOException { + deleteAndAssertOKResponseMocked(applicationId, true); } - private void deleteAndAssertOKResponse(ApplicationId applicationId, boolean fullAppIdInUrl) throws IOException { + private void deleteAndAssertOKResponseMocked(ApplicationId applicationId, boolean fullAppIdInUrl) throws IOException { long sessionId = tenants.tenantsCopy().get(applicationId.tenant()).getApplicationRepo().getSessionIdForApplication(applicationId); - deleteAndAssertResponse(applicationId, Zone.defaultZone(), Response.Status.OK, null, fullAppIdInUrl); + deleteAndAssertResponse(mockHandler, applicationId, Zone.defaultZone(), Response.Status.OK, null, fullAppIdInUrl); assertNull(tenants.tenantsCopy().get(applicationId.tenant()).getLocalSessionRepo().getSession(sessionId)); } - private void deleteAndAssertResponse(ApplicationId applicationId, Zone zone, int expectedStatus, HttpErrorResponse.errorCodes errorCode, boolean fullAppIdInUrl) throws IOException { + private void deleteAndAssertOKResponse(ApplicationHandler handler, Tenant tenant, ApplicationId applicationId) throws IOException { + long sessionId = tenant.getApplicationRepo().getSessionIdForApplication(applicationId); + deleteAndAssertResponse(handler, applicationId, Zone.defaultZone(), Response.Status.OK, null, true); + assertNull(tenant.getLocalSessionRepo().getSession(sessionId)); + } + + private void deleteAndAssertResponse(ApplicationHandler handler, ApplicationId applicationId, Zone zone, int expectedStatus, HttpErrorResponse.errorCodes errorCode, boolean fullAppIdInUrl) throws IOException { String expectedResponse = "{\"message\":\"Application '" + applicationId + "' deleted\"}"; - deleteAndAssertResponse(toUrlPath(applicationId, zone, fullAppIdInUrl), expectedStatus, errorCode, expectedResponse, com.yahoo.jdisc.http.HttpRequest.Method.DELETE); + deleteAndAssertResponse(handler, toUrlPath(applicationId, zone, fullAppIdInUrl), expectedStatus, errorCode, expectedResponse, com.yahoo.jdisc.http.HttpRequest.Method.DELETE); + } + + private void deleteAndAssertResponse(ApplicationHandler handler, String url, int expectedStatus, HttpErrorResponse.errorCodes errorCode, String expectedResponse, com.yahoo.jdisc.http.HttpRequest.Method method) throws IOException { + HttpResponse response = handler.handle(HttpRequest.createTestRequest(url, method)); + if (expectedStatus == 200) { + HandlerTest.assertHttpStatusCodeAndMessage(response, 200, expectedResponse); + } else { + HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(response, expectedStatus, errorCode, expectedResponse); + } } private void assertApplicationGeneration(ApplicationId applicationId, Zone zone, long expectedGeneration, boolean fullAppIdInUrl) throws IOException { @@ -236,19 +329,10 @@ public class ApplicationHandlerTest { } private void assertApplicationGeneration(String url, long expectedGeneration) throws IOException { - HttpResponse response = handler.handle(HttpRequest.createTestRequest(url, com.yahoo.jdisc.http.HttpRequest.Method.GET)); + HttpResponse response = mockHandler.handle(HttpRequest.createTestRequest(url, com.yahoo.jdisc.http.HttpRequest.Method.GET)); HandlerTest.assertHttpStatusCodeAndMessage(response, 200, "{\"generation\":" + expectedGeneration + "}"); } - private void deleteAndAssertResponse(String url, int expectedStatus, HttpErrorResponse.errorCodes errorCode, String expectedResponse, com.yahoo.jdisc.http.HttpRequest.Method method) throws IOException { - HttpResponse response = handler.handle(HttpRequest.createTestRequest(url, method)); - if (expectedStatus == 200) { - HandlerTest.assertHttpStatusCodeAndMessage(response, 200, expectedResponse); - } else { - HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(response, expectedStatus, errorCode, expectedResponse); - } - } - private void assertApplicationExists(TenantName tenantName, ApplicationId applicationId, Zone zone) throws IOException { String expected = applicationId == null ? "[]" : "[\"http://myhost:14000/application/v2/tenant/" + tenantName + "/application/" + applicationId.application().value() + "/environment/" + zone.environment().value() + @@ -262,13 +346,13 @@ public class ApplicationHandlerTest { private void restart(ApplicationId application, Zone zone) throws IOException { String restartUrl = toUrlPath(application, zone, true) + "/restart"; - HttpResponse response = handler.handle(HttpRequest.createTestRequest(restartUrl, com.yahoo.jdisc.http.HttpRequest.Method.POST)); + HttpResponse response = mockHandler.handle(HttpRequest.createTestRequest(restartUrl, com.yahoo.jdisc.http.HttpRequest.Method.POST)); HandlerTest.assertHttpStatusCodeAndMessage(response, 200, ""); } private void converge(ApplicationId application, Zone zone) throws IOException { String restartUrl = toUrlPath(application, zone, true) + "/converge"; - HttpResponse response = handler.handle(HttpRequest.createTestRequest(restartUrl, com.yahoo.jdisc.http.HttpRequest.Method.GET)); + HttpResponse response = mockHandler.handle(HttpRequest.createTestRequest(restartUrl, com.yahoo.jdisc.http.HttpRequest.Method.GET)); HandlerTest.assertHttpStatusCodeAndMessage(response, 200, ""); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java index 894990a5c1b..5ec09f1478f 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java @@ -7,8 +7,11 @@ import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.jdisc.Response; import com.yahoo.vespa.config.server.*; +import com.yahoo.vespa.config.server.host.HostRegistries; +import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.vespa.config.server.http.HandlerTest; import com.yahoo.vespa.config.server.http.HttpErrorResponse; +import com.yahoo.vespa.config.server.tenant.Tenants; import org.junit.Before; import org.junit.Test; @@ -59,14 +62,14 @@ public class HostHandlerTest { assertThat(hostRegistries, is(hostHandler.hostRegistries)); long sessionId = 1; ApplicationId id = ApplicationId.from(mytenant, ApplicationName.defaultName(), InstanceName.defaultName()); - ApplicationHandlerTest.addApplication(tenants.tenantsCopy().get(mytenant), id, sessionId); + ApplicationHandlerTest.addMockApplication(tenants.tenantsCopy().get(mytenant), id, sessionId); assertApplicationForHost(hostname, mytenant, id, Zone.defaultZone()); } @Test public void require_that_handler_gives_error_for_unknown_hostname() throws Exception { long sessionId = 1; - ApplicationHandlerTest.addApplication(tenants.tenantsCopy().get(mytenant), ApplicationId.defaultId(), sessionId); + ApplicationHandlerTest.addMockApplication(tenants.tenantsCopy().get(mytenant), ApplicationId.defaultId(), sessionId); final String hostname = "unknown"; assertErrorForHost(hostname, Response.Status.NOT_FOUND, diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java index b1a330e5f99..39a61e9700f 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.io.StringReader; import java.util.Collections; import java.util.HashSet; -import java.util.concurrent.Executor; import com.yahoo.config.provision.TenantName; import com.yahoo.vespa.config.server.http.HttpErrorResponse; @@ -26,8 +25,8 @@ import com.yahoo.text.StringUtilities; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.ConfigPayload; import com.yahoo.vespa.config.protocol.SlimeConfigResponse; -import com.yahoo.vespa.config.server.Tenants; -import com.yahoo.vespa.config.server.MockRequestHandler; +import com.yahoo.vespa.config.server.tenant.Tenants; +import com.yahoo.vespa.config.server.rpc.MockRequestHandler; import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.config.server.http.HandlerTest; import com.yahoo.vespa.config.server.http.HttpConfigRequest; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java index cad7cbd583c..8c8853ed463 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java @@ -7,8 +7,8 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.logging.AccessLog; import com.yahoo.vespa.config.ConfigKey; -import com.yahoo.vespa.config.server.MockRequestHandler; -import com.yahoo.vespa.config.server.Tenants; +import com.yahoo.vespa.config.server.rpc.MockRequestHandler; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.config.server.http.HandlerTest; import com.yahoo.vespa.config.server.http.HttpErrorResponse; import com.yahoo.vespa.config.server.http.SessionHandlerTest; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java index 2e75d1b02e6..4dd9a17c549 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java @@ -7,9 +7,9 @@ import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.jdisc.http.HttpRequest.Method; import com.yahoo.container.logging.AccessLog; import com.yahoo.jdisc.Response; -import com.yahoo.vespa.config.server.*; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.http.SessionHandlerTest; +import com.yahoo.vespa.config.server.tenant.Tenants; import org.junit.Test; import org.junit.Before; @@ -26,7 +26,7 @@ import static com.yahoo.jdisc.http.HttpRequest.Method.*; * @since 5.1 */ public class ListApplicationsHandlerTest { - private ApplicationRepo applicationRepo, applicationRepo2; + private TenantApplications applicationRepo, applicationRepo2; private ListApplicationsHandler handler; @Before diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java index e4f985b7d9f..f8048cfc253 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java @@ -3,7 +3,6 @@ package com.yahoo.vespa.config.server.http.v2; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.config.server.TestWithTenant; import org.junit.Test; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.jdisc.http.HttpRequest.Method; @@ -21,9 +20,9 @@ public class ListTenantsTest extends TenantTest { @Test public void testListTenants() throws Exception { - tenants.createTenant(a); - tenants.createTenant(b); - tenants.createTenant(c); + tenants.writeTenantPath(a); + tenants.writeTenantPath(b); + tenants.writeTenantPath(c); ListTenantsHandler listTenantsHandler = new ListTenantsHandler(testExecutor(), null, tenants); 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 659a435ca6d..0b0c4ad0629 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 @@ -34,7 +34,7 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import com.yahoo.path.Path; -import com.yahoo.vespa.config.server.application.MemoryApplicationRepo; +import com.yahoo.vespa.config.server.application.MemoryTenantApplications; import com.yahoo.vespa.config.server.http.SessionActiveHandlerTestBase; import com.yahoo.vespa.config.server.http.SessionHandler; import com.yahoo.vespa.config.server.http.SessionCreateHandlerTestBase.MockSessionFactory; @@ -47,7 +47,7 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase { public void setup() throws Exception { tenant = TenantName.from("activatetest"); remoteSessionRepo = new RemoteSessionRepo(); - applicationRepo = new MemoryApplicationRepo(); + applicationRepo = new MemoryTenantApplications(); curator = new MockCurator(); configCurator = ConfigCurator.create(curator); localRepo = new LocalSessionRepo(applicationRepo); @@ -59,7 +59,7 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase { } @Test - public void require_correct_response_on_success() throws Exception { + public void testActivation() throws Exception { activateAndAssertOK(1, 0); } @@ -76,7 +76,7 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase { public void testActivationOfUnpreparedSession() throws Exception { // Needed so we can test that previous active session is still active after a failed activation RemoteSession firstSession = activateAndAssertOK(90l, 0l); - long sessionId = 91l; + long sessionId = 91L; ActivateRequest activateRequest = new ActivateRequest(sessionId, 0l, Session.Status.NEW, "").invoke(); HttpResponse actResponse = activateRequest.getActResponse(); RemoteSession session = activateRequest.getSession(); @@ -84,6 +84,7 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase { assertThat(getRenderedString(actResponse), is("{\"error-code\":\"BAD_REQUEST\",\"message\":\"tenant:"+tenant+" app:default:default Session " + sessionId + " is not prepared\"}")); assertThat(session.getStatus(), is(not(Session.Status.ACTIVATE))); assertThat(firstSession.getStatus(), is(Session.Status.ACTIVATE)); + } @Test @@ -188,7 +189,7 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase { } @Override - public void removed(ApplicationId application) { + public void remove(NestedTransaction transaction, ApplicationId application) { removed = true; lastApplicationId = application; } @@ -209,7 +210,7 @@ public class SessionActiveHandlerTest extends SessionActiveHandlerTestBase { } @Override - public void removed(ApplicationId application) { + public void remove(NestedTransaction transaction, ApplicationId application) { throw new IllegalArgumentException("Cannot remove application"); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java index e31d485f4df..5740701c0eb 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java @@ -6,12 +6,12 @@ import com.yahoo.config.model.application.provider.FilesApplicationPackage; import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.logging.AccessLog; -import com.yahoo.vespa.config.server.*; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.vespa.config.server.application.MemoryApplicationRepo; +import com.yahoo.vespa.config.server.application.MemoryTenantApplications; import com.yahoo.vespa.config.server.http.SessionCreateHandlerTestBase; import com.yahoo.vespa.config.server.http.SessionHandlerTest; import com.yahoo.vespa.config.server.session.*; +import com.yahoo.vespa.config.server.tenant.Tenants; import org.junit.Before; import org.junit.Test; @@ -34,7 +34,7 @@ public class SessionCreateHandlerTest extends SessionCreateHandlerTestBase { @Before public void setupRepo() throws Exception { - applicationRepo = new MemoryApplicationRepo(); + applicationRepo = new MemoryTenantApplications(); localSessionRepo = new LocalSessionRepo(applicationRepo); pathPrefix = "/application/v2/tenant/" + tenant + "/session/"; createdMessage = " for tenant '" + tenant + "' created.\""; 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 3307c016939..de0cfb6246d 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 @@ -17,10 +17,10 @@ import com.yahoo.path.Path; import com.yahoo.slime.JsonDecoder; import com.yahoo.slime.Slime; import com.yahoo.transaction.Transaction; -import com.yahoo.vespa.config.server.ApplicationSet; -import com.yahoo.vespa.config.server.HostRegistry; -import com.yahoo.vespa.config.server.application.ApplicationRepo; -import com.yahoo.vespa.config.server.application.MemoryApplicationRepo; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.host.HostRegistry; +import com.yahoo.vespa.config.server.application.TenantApplications; +import com.yahoo.vespa.config.server.application.MemoryTenantApplications; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.configchange.MockRefeedAction; import com.yahoo.vespa.config.server.configchange.MockRestartAction; @@ -55,7 +55,7 @@ public class SessionPrepareHandlerTest extends SessionPrepareHandlerTestBase { @Before public void setupRepo() throws Exception { - ApplicationRepo applicationRepo = new MemoryApplicationRepo(); + TenantApplications applicationRepo = new MemoryTenantApplications(); curator = new MockCurator(); localRepo = new LocalSessionRepo(applicationRepo); pathPrefix = "/application/v2/tenant/" + tenant + "/session/"; @@ -77,7 +77,7 @@ public class SessionPrepareHandlerTest extends SessionPrepareHandlerTestBase { @Test public void require_that_preparing_with_multiple_tenants_work() throws Exception { - ApplicationRepo applicationRepoDefault = new MemoryApplicationRepo(); + TenantApplications applicationRepoDefault = new MemoryTenantApplications(); LocalSessionRepo localRepoDefault = new LocalSessionRepo(applicationRepoDefault); final TenantName tenantName = TenantName.defaultName(); addTenant(tenantName, localRepoDefault, new RemoteSessionRepo(), new SessionCreateHandlerTestBase.MockSessionFactory()); @@ -193,7 +193,7 @@ public class SessionPrepareHandlerTest extends SessionPrepareHandlerTestBase { builder.createTenant(tenantName).withSessionFactory(sessionFactory) .withLocalSessionRepo(localSessionRepo) .withRemoteSessionRepo(remoteSessionRepo) - .withApplicationRepo(new MemoryApplicationRepo()); + .withApplicationRepo(new MemoryTenantApplications()); return builder; } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java index 106b675c2c7..50fdd671b27 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java @@ -11,7 +11,7 @@ import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.vespa.config.server.*; +import com.yahoo.vespa.config.server.tenant.Tenant; import org.junit.Before; import org.junit.Test; @@ -59,7 +59,7 @@ public class TenantHandlerTest extends TenantTest { @Test public void testGetExisting() throws Exception { - tenants.createTenant(a); + tenants.writeTenantPath(a); TenantGetResponse response = (TenantGetResponse) handler.handleGET(HttpRequest.createTestRequest("http://deploy.example.yahoo.com:80/application/v2/tenant/a", Method.GET)); assertResponseEquals(response, "{\"message\":\"Tenant 'a' exists.\"}"); } @@ -92,7 +92,7 @@ public class TenantHandlerTest extends TenantTest { final int sessionId = 1; ApplicationId app = ApplicationId.from(a, ApplicationName.from("foo"), InstanceName.defaultName()); - ApplicationHandlerTest.addApplication(tenant, app, sessionId); + ApplicationHandlerTest.addMockApplication(tenant, app, sessionId); try { handler.handleDELETE(HttpRequest.createTestRequest("http://deploy.example.yahoo.com:80/application/v2/tenant/" + a, Method.DELETE)); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantTest.java index 930787361af..e6b3a86ebb0 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantTest.java @@ -10,6 +10,7 @@ import java.util.concurrent.Executor; import com.yahoo.vespa.config.server.*; import com.yahoo.vespa.config.server.http.SessionResponse; import com.yahoo.vespa.config.server.monitoring.Metrics; +import com.yahoo.vespa.config.server.tenant.Tenants; import org.junit.After; import org.junit.Before; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TestTenantBuilder.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TestTenantBuilder.java index a128fa6c891..a2b69f96406 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TestTenantBuilder.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TestTenantBuilder.java @@ -6,11 +6,14 @@ import com.google.common.collect.Collections2; import com.yahoo.config.provision.TenantName; import com.yahoo.path.Path; import com.yahoo.vespa.config.server.*; -import com.yahoo.vespa.config.server.application.MemoryApplicationRepo; +import com.yahoo.vespa.config.server.application.MemoryTenantApplications; import com.yahoo.vespa.config.server.http.SessionCreateHandlerTestBase; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.vespa.config.server.session.LocalSessionRepo; import com.yahoo.vespa.config.server.session.RemoteSessionRepo; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; +import com.yahoo.vespa.config.server.tenant.Tenants; import com.yahoo.vespa.curator.mock.MockCurator; import java.util.*; @@ -31,7 +34,7 @@ public class TestTenantBuilder { } public TenantBuilder createTenant(TenantName tenantName) { - MemoryApplicationRepo applicationRepo = new MemoryApplicationRepo(); + MemoryTenantApplications applicationRepo = new MemoryTenantApplications(); TenantBuilder builder = TenantBuilder.create(componentRegistry, tenantName, Path.createRoot().append(tenantName.value())) .withSessionFactory(new SessionCreateHandlerTestBase.MockSessionFactory()) .withLocalSessionRepo(new LocalSessionRepo(applicationRepo)) diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigResponseFactoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/ConfigResponseFactoryTest.java index f127d8716aa..7dace8dd9cb 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigResponseFactoryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/ConfigResponseFactoryTest.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.config.SimpletypesConfig; import com.yahoo.config.codegen.DefParser; @@ -8,6 +8,8 @@ import com.yahoo.text.StringUtilities; import com.yahoo.vespa.config.ConfigPayload; import com.yahoo.vespa.config.protocol.CompressionType; import com.yahoo.vespa.config.protocol.ConfigResponse; +import com.yahoo.vespa.config.server.rpc.LZ4ConfigResponseFactory; +import com.yahoo.vespa.config.server.rpc.UncompressedConfigResponseFactory; import org.junit.Before; import org.junit.Test; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/DelayedConfigResponseTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/DelayedConfigResponseTest.java index 7f9ac50c549..e5ffa4b5e45 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/DelayedConfigResponseTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/DelayedConfigResponseTest.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.config.provision.ApplicationId; @@ -11,6 +11,9 @@ import com.yahoo.vespa.config.protocol.JRTClientConfigRequestV3; import com.yahoo.vespa.config.protocol.JRTServerConfigRequest; import com.yahoo.vespa.config.protocol.JRTServerConfigRequestV3; import com.yahoo.vespa.config.protocol.Trace; +import com.yahoo.vespa.config.server.GetConfigContext; +import com.yahoo.vespa.config.server.rpc.DelayedConfigResponses; +import com.yahoo.vespa.config.server.rpc.MockRpc; import org.junit.Test; import java.util.Collections; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/GetConfigProcessorTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessorTest.java index cd37b4a31c7..409aa5d2288 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/GetConfigProcessorTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessorTest.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.cloud.config.SentinelConfig; import com.yahoo.config.provision.TenantName; @@ -16,6 +16,9 @@ import com.yahoo.vespa.config.protocol.JRTClientConfigRequestV3; import com.yahoo.vespa.config.protocol.JRTServerConfigRequest; import com.yahoo.vespa.config.protocol.JRTServerConfigRequestV3; import com.yahoo.vespa.config.protocol.Trace; +import com.yahoo.vespa.config.server.rpc.GetConfigProcessor; +import com.yahoo.vespa.config.server.rpc.MockRpc; +import com.yahoo.vespa.config.server.tenant.MockTenantProvider; import org.junit.Test; import static org.junit.Assert.assertFalse; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockRequestHandler.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRequestHandler.java index 373545f1a8b..9922cec47c0 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/MockRequestHandler.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRequestHandler.java @@ -1,11 +1,15 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Version; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.GetConfigRequest; import com.yahoo.vespa.config.protocol.ConfigResponse; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.ReloadHandler; +import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.tenant.TenantHandlerProvider; import java.util.*; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockRpc.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java index 70e4b4f6bd0..0478404d9a1 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/MockRpc.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java @@ -1,12 +1,15 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Version; import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.protocol.JRTServerConfigRequest; +import com.yahoo.vespa.config.server.GetConfigContext; +import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.monitoring.Metrics; +import com.yahoo.vespa.config.server.tenant.MockTenantProvider; import java.util.Optional; import java.util.concurrent.CompletionService; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/RpcServerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcServerTest.java index d205bfe05e6..0e0a2cdf8d0 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/RpcServerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcServerTest.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.google.common.base.Joiner; import com.yahoo.cloud.config.LbServicesConfig; @@ -13,6 +13,8 @@ import com.yahoo.jrt.Request; import com.yahoo.vespa.config.*; import com.yahoo.vespa.config.protocol.*; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.ServerCache; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import com.yahoo.vespa.config.util.ConfigUtils; @@ -92,9 +94,9 @@ public class RpcServerTest extends TestWithRpc { } public void testGetConfig() { - tenantProvider.requestHandler.throwException = false; + ((MockRequestHandler)tenantProvider.getRequestHandler()).throwException = false; ConfigKey<?> key = new ConfigKey<>(SimpletypesConfig.class, "brim"); - tenantProvider.requestHandler.responses.put(ApplicationId.defaultId(), createResponse()); + ((MockRequestHandler)tenantProvider.getRequestHandler()).responses.put(ApplicationId.defaultId(), createResponse()); JRTClientConfigRequest req = JRTClientConfigRequestV3.createFromRaw(new RawConfig(key, SimpletypesConfig.CONFIG_DEF_MD5), 120_000, Trace.createDummy(), CompressionType.UNCOMPRESSED, Optional.empty()); assertTrue(req.validateParameters()); performRequest(req.getRequest()); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TestWithRpc.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/TestWithRpc.java index 30143f565e5..f2f2d7c87d4 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TestWithRpc.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/TestWithRpc.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.rpc; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.config.provision.TenantName; @@ -8,7 +8,13 @@ import com.yahoo.jrt.Spec; import com.yahoo.jrt.Supervisor; import com.yahoo.jrt.Transport; import com.yahoo.vespa.config.GenerationCounter; +import com.yahoo.vespa.config.server.host.HostRegistries; +import com.yahoo.vespa.config.server.MemoryGenerationCounter; +import com.yahoo.vespa.config.server.PortRangeAllocator; +import com.yahoo.vespa.config.server.SuperModelController; +import com.yahoo.vespa.config.server.TestConfigDefinitionRepo; import com.yahoo.vespa.config.server.monitoring.Metrics; +import com.yahoo.vespa.config.server.tenant.MockTenantProvider; import org.junit.After; import org.junit.Before; @@ -64,7 +70,7 @@ public class TestWithRpc { protected void createAndStartRpcServer(boolean hostedVespa) { rpcServer = new RpcServer(new ConfigserverConfig(new ConfigserverConfig.Builder().rpcport(port).numthreads(1).maxgetconfigclients(1).hostedVespa(hostedVespa)), new SuperModelController(generationCounter, - new TestConfigDefinitionRepo(), new ConfigserverConfig(new ConfigserverConfig.Builder())), + new TestConfigDefinitionRepo(), new ConfigserverConfig(new ConfigserverConfig.Builder())), Metrics.createTestMetrics(), new HostRegistries()); rpcServer.onTenantCreate(TenantName.from("default"), tenantProvider); t = new Thread(rpcServer); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java index 84fce1c09fe..0971d37c5d6 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java @@ -6,9 +6,10 @@ import com.yahoo.path.Path; import com.yahoo.test.ManualClock; import com.yahoo.vespa.config.server.*; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.config.server.application.MemoryApplicationRepo; +import com.yahoo.vespa.config.server.application.MemoryTenantApplications; import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs; import com.yahoo.io.IOUtils; +import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.vespa.config.server.http.SessionHandlerTest; import com.yahoo.vespa.config.server.zookeeper.SessionCounter; @@ -53,10 +54,10 @@ public class LocalSessionRepoTest extends TestWithCurator { Path.fromString("counter"), Path.fromString("sessions")), Path.createRoot(), - new MemoryApplicationRepo(), + new MemoryTenantApplications(), tenantFileSystemDirs, new HostRegistry<>(), tenantName); - repo = new LocalSessionRepo(tenantFileSystemDirs, loader, new MemoryApplicationRepo(), clock, 5); + repo = new LocalSessionRepo(tenantFileSystemDirs, loader, new MemoryTenantApplications(), clock, 5); } @Test diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java index 4f638d54d46..c793945a738 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java @@ -8,9 +8,11 @@ import com.yahoo.path.Path; import com.yahoo.config.model.application.provider.*; import com.yahoo.slime.Slime; import com.yahoo.vespa.config.server.*; -import com.yahoo.vespa.config.server.application.MemoryApplicationRepo; +import com.yahoo.vespa.config.server.application.MemoryTenantApplications; +import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger; import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs; import com.yahoo.vespa.config.server.deploy.ZooKeeperClient; +import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.mock.MockCurator; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; @@ -162,7 +164,7 @@ public class LocalSessionTest { zkClient.feedZKFileRegistries(Collections.singletonMap(Version.fromIntValues(0, 0, 0), new MockFileRegistry())); File sessionDir = new File(tenantFileSystemDirs.path(), String.valueOf(sessionId)); sessionDir.createNewFile(); - return new LocalSession(tenant, sessionId, preparer, new SessionContext(FilesApplicationPackage.fromFile(testApp), zkc, sessionDir, new MemoryApplicationRepo(), new HostRegistry<>(), superModelGenerationCounter)); + return new LocalSession(tenant, sessionId, preparer, new SessionContext(FilesApplicationPackage.fromFile(testApp), zkc, sessionDir, new MemoryTenantApplications(), new HostRegistry<>(), superModelGenerationCounter)); } private void doPrepare(LocalSession session) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java index 6d8f93f4f8f..68c8bffa823 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java @@ -11,7 +11,9 @@ import com.yahoo.text.Utf8; import com.yahoo.transaction.Transaction; import com.yahoo.vespa.config.server.*; -import com.yahoo.vespa.config.server.application.ApplicationRepo; +import com.yahoo.vespa.config.server.application.TenantApplications; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.curator.Curator; import org.junit.Before; import org.junit.Test; @@ -85,7 +87,7 @@ public class RemoteSessionRepoTest extends TestWithCurator { @Test public void testBadApplicationRepoOnActivate() throws Exception { - ApplicationRepo applicationRepo = new FailingApplicationRepo(); + TenantApplications applicationRepo = new FailingTenantApplications(); curator.framework().create().forPath("/mytenant"); Tenant tenant = TenantBuilder.create(new TestComponentRegistry(curator), TenantName.from("mytenant"), Path.fromString("mytenant")) .withApplicationRepo(applicationRepo) @@ -132,7 +134,8 @@ public class RemoteSessionRepoTest extends TestWithCurator { } while (System.currentTimeMillis() < endTime && !ok); } - private class FailingApplicationRepo implements ApplicationRepo { + private class FailingTenantApplications implements TenantApplications { + @Override public List<ApplicationId> listApplications() { return Collections.singletonList(ApplicationId.defaultId()); @@ -149,8 +152,8 @@ public class RemoteSessionRepoTest extends TestWithCurator { } @Override - public void deleteApplication(ApplicationId applicationId) { - + public Transaction deleteApplication(ApplicationId applicationId) { + return null; } @Override diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java index 2fc65eb77a8..ad192a895b9 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionTest.java @@ -12,7 +12,7 @@ import com.yahoo.config.provision.TenantName; import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.config.provision.Version; import com.yahoo.path.Path; -import com.yahoo.vespa.config.server.ApplicationSet; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.PathProvider; import com.yahoo.vespa.config.server.TestComponentRegistry; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java index 83ed65f03e4..62d911f5273 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java @@ -7,8 +7,11 @@ import com.yahoo.config.model.application.provider.BaseDeployLogger; import com.yahoo.io.IOUtils; import com.yahoo.path.Path; import com.yahoo.vespa.config.server.*; +import com.yahoo.vespa.config.server.http.CompressedApplicationInputStream; +import com.yahoo.vespa.config.server.http.CompressedApplicationInputStreamTest; import com.yahoo.vespa.config.server.http.SessionCreate; +import com.yahoo.vespa.config.server.tenant.TestWithTenant; import org.json.JSONException; import org.json.JSONObject; import org.junit.Before; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java index 308e6aa29d2..61b16a718fa 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java @@ -19,14 +19,17 @@ import com.yahoo.path.Path; import com.yahoo.slime.Slime; import com.yahoo.vespa.config.server.*; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.vespa.config.server.application.MemoryApplicationRepo; +import com.yahoo.vespa.config.server.application.MemoryTenantApplications; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.configchange.MockRestartAction; import com.yahoo.vespa.config.server.configchange.RestartActions; +import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger; +import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.vespa.config.server.http.InvalidApplicationException; import com.yahoo.vespa.config.server.model.TestModelFactory; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; +import com.yahoo.vespa.config.server.tenant.Rotations; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; import org.junit.Before; @@ -197,7 +200,7 @@ public class SessionPreparerTest extends TestWithCurator { } private Set<Rotation> readRotationsFromZK(ApplicationId applicationId) { - return new RotationsCache(curator, tenantPath).readRotationsFromZooKeeper(applicationId); + return new Rotations(curator, tenantPath).readRotationsFromZooKeeper(applicationId); } @Test @@ -219,7 +222,7 @@ public class SessionPreparerTest extends TestWithCurator { final String rotations = "foo.msbe.global.vespa.yahooapis.com"; final ApplicationId applicationId = applicationId("test"); - new RotationsCache(curator, tenantPath).writeRotationsToZooKeeper(applicationId, Collections.singleton(new Rotation(rotations))); + new Rotations(curator, tenantPath).writeRotationsToZooKeeper(applicationId, Collections.singleton(new Rotation(rotations))); final PrepareParams params = new PrepareParams().applicationId(applicationId); final File app = new File("src/test/resources/deploy/app"); preparer.prepare(getContext(getApplicationPackage(app)), getLogger(), params, Optional.empty(), tenantPath); @@ -234,7 +237,7 @@ public class SessionPreparerTest extends TestWithCurator { } private SessionContext getContext(FilesApplicationPackage app) throws IOException { - return new SessionContext(app, new SessionZooKeeperClient(curator, appPath), app.getAppDir(), new MemoryApplicationRepo(), new HostRegistry<>(), new SuperModelGenerationCounter(curator)); + return new SessionContext(app, new SessionZooKeeperClient(curator, appPath), app.getAppDir(), new MemoryTenantApplications(), new HostRegistry<>(), new SuperModelGenerationCounter(curator)); } private FilesApplicationPackage getApplicationPackage(File testFile) throws IOException { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java index de64db1bbc9..5b21130ab80 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java @@ -3,7 +3,7 @@ package com.yahoo.vespa.config.server.session; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.path.Path; -import com.yahoo.vespa.config.server.ApplicationSet; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.curator.mock.MockCurator; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockTenantListener.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/MockTenantListener.java index 1fd92f2acc9..67785bd24e8 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/MockTenantListener.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/MockTenantListener.java @@ -1,7 +1,9 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.config.server.tenant.TenantHandlerProvider; +import com.yahoo.vespa.config.server.tenant.TenantListener; /** * @author lulf diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockTenantProvider.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/MockTenantProvider.java index 4b92c91f581..2e22c442e1b 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/MockTenantProvider.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/MockTenantProvider.java @@ -1,5 +1,10 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; + +import com.yahoo.vespa.config.server.MockReloadHandler; +import com.yahoo.vespa.config.server.rpc.MockRequestHandler; +import com.yahoo.vespa.config.server.ReloadHandler; +import com.yahoo.vespa.config.server.RequestHandler; /** * @author lulf diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TenantRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java index 94e08fdf1b3..f5d67279bbf 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TenantRequestHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.yahoo.config.ConfigInstance; import com.yahoo.config.SimpletypesConfig; @@ -17,6 +17,15 @@ import com.yahoo.vespa.config.GetConfigRequest; import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.protocol.DefContent; import com.yahoo.vespa.config.protocol.VespaVersion; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.host.HostRegistries; +import com.yahoo.vespa.config.server.PathProvider; +import com.yahoo.vespa.config.server.ReloadListener; +import com.yahoo.vespa.config.server.ServerCache; +import com.yahoo.vespa.config.server.TestComponentRegistry; +import com.yahoo.vespa.config.server.TestConfigDefinitionRepo; +import com.yahoo.vespa.config.server.TestWithCurator; +import com.yahoo.vespa.config.server.rpc.UncompressedConfigResponseFactory; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TenantTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantTest.java index c4eb8786917..061407a51d2 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TenantTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantTest.java @@ -1,10 +1,12 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.google.common.testing.EqualsTester; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.config.server.application.MemoryApplicationRepo; +import com.yahoo.vespa.config.server.TestWithCurator; +import com.yahoo.vespa.config.server.application.MemoryTenantApplications; import com.yahoo.vespa.config.server.http.v2.TestTenantBuilder; +import com.yahoo.vespa.config.server.tenant.Tenant; import org.junit.Before; import org.junit.Test; @@ -53,7 +55,7 @@ public class TenantTest extends TestWithCurator { @Test public void close() { - MemoryApplicationRepo repo = (MemoryApplicationRepo) t1.getApplicationRepo(); + MemoryTenantApplications repo = (MemoryTenantApplications) t1.getApplicationRepo(); assertTrue(repo.isOpen()); t1.close(); assertFalse(repo.isOpen()); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TenantsTestCase.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantsTestCase.java index 9f71393115f..603b5798da6 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TenantsTestCase.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantsTestCase.java @@ -1,5 +1,5 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.config.provision.ApplicationId; @@ -7,6 +7,10 @@ import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Version; +import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.ServerCache; +import com.yahoo.vespa.config.server.TestComponentRegistry; +import com.yahoo.vespa.config.server.TestWithCurator; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.vespa.config.server.deploy.MockDeployer; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; @@ -45,13 +49,13 @@ public class TenantsTestCase extends TestWithCurator { @Before public void setupSessions() throws Exception { globalComponentRegistry = new TestComponentRegistry(curator); - listener = globalComponentRegistry.reloadListener; - tenantListener = globalComponentRegistry.tenantListener; + listener = (TenantRequestHandlerTest.MockReloadListener)globalComponentRegistry.getReloadListener(); + tenantListener = (MockTenantListener)globalComponentRegistry.getTenantListener(); tenantListener.tenantsLoaded = false; tenants = new Tenants(globalComponentRegistry, Metrics.createTestMetrics()); assertTrue(tenantListener.tenantsLoaded); - tenants.createTenant(tenant1); - tenants.createTenant(tenant2); + tenants.writeTenantPath(tenant1); + tenants.writeTenantPath(tenant2); } @After @@ -77,7 +81,7 @@ public class TenantsTestCase extends TestWithCurator { @Test public void testTenantListenersNotified() throws Exception { - tenants.createTenant(tenant3); + tenants.writeTenantPath(tenant3); assertThat("tenant3 not the last created tenant. Tenants: " + tenants.tenantsCopy().keySet() + ", /config/v2/tenants: " + readZKChildren("/config/v2/tenants"), tenantListener.tenantCreatedName, is(tenant3)); tenants.deleteTenant(tenant2); assertFalse(tenants.tenantsCopy().containsKey(tenant2)); @@ -89,7 +93,7 @@ public class TenantsTestCase extends TestWithCurator { Map<TenantName, Tenant> tenantsCopy = tenants.tenantsCopy(); assertEquals(tenantsCopy.get(tenant1).getName(), tenant1); assertEquals(tenantsCopy.get(tenant2).getName(), tenant2); - tenants.createTenant(tenant3); + tenants.writeTenantPath(tenant3); tenantsCopy = tenants.tenantsCopy(); assertEquals(tenantsCopy.get(tenant1).getName(), tenant1); assertEquals(tenantsCopy.get(tenant2).getName(), tenant2); @@ -98,7 +102,7 @@ public class TenantsTestCase extends TestWithCurator { @Test public void testPutAdd() throws Exception { - tenants.createTenant(tenant3); + tenants.writeTenantPath(tenant3); assertNotNull(globalComponentRegistry.getCurator().framework().checkExists().forPath(tenants.tenantZkPath(tenant3))); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TestWithTenant.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TestWithTenant.java index 3892bf505b9..2cf12bdfb78 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TestWithTenant.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TestWithTenant.java @@ -1,7 +1,11 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server; +package com.yahoo.vespa.config.server.tenant; +import com.yahoo.vespa.config.server.TestComponentRegistry; +import com.yahoo.vespa.config.server.TestWithCurator; import com.yahoo.vespa.config.server.monitoring.Metrics; +import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.Tenants; import org.junit.Before; import static org.junit.Assert.assertFalse; |