summaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2020-06-05 11:21:20 +0200
committerGitHub <noreply@github.com>2020-06-05 11:21:20 +0200
commit8cb9e85e810b2e1bc7dcd55fcb9c96858c44720f (patch)
treea7974d979ac0803e2ddc08d14273aa2daa8209ca /configserver
parenteabcc5bfe1b6407b9d4d861362cc439485d441d0 (diff)
parent6b111969731bb4d18c2e26e817b0a205e50dc3ea (diff)
Merge pull request #13489 from vespa-engine/musum/configserver-refactoring-6
Config server refactoring, part 6
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelController.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelGenerationCounter.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java10
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java255
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java1
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java7
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java5
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java9
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java6
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/ZKMetricUpdater.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java1
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/DefaultRpcAuthorizerProvider.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java61
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java270
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java5
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java166
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java17
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java9
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java144
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/configchange/ConfigChangeActionsBuilder.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/MockDeployer.java41
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/metrics/ApplicationMetricsRetrieverTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java8
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRepositoryTest.java11
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java373
32 files changed, 585 insertions, 853 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index 9e8010cf8a7..819049c6517 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -223,10 +223,6 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
}
}
- public PrepareResult deploy(CompressedApplicationInputStream in, PrepareParams prepareParams) {
- return deploy(in, prepareParams, false, clock.instant());
- }
-
public PrepareResult deploy(CompressedApplicationInputStream in, PrepareParams prepareParams,
boolean ignoreSessionStaleFailure, Instant now) {
File tempDir = uncheck(() -> Files.createTempDirectory("deploy")).toFile();
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 42c80acd80d..657e113475b 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
@@ -16,7 +16,6 @@ import com.yahoo.vespa.config.protocol.DefContent;
import com.yahoo.vespa.config.server.model.SuperModelConfigProvider;
import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory;
-import java.io.IOException;
import java.io.StringReader;
/**
@@ -74,7 +73,7 @@ public class SuperModelController {
long getGeneration() { return generation; }
- public <CONFIGTYPE extends ConfigInstance> CONFIGTYPE getConfig(Class<CONFIGTYPE> configClass, ApplicationId applicationId, String configId) throws IOException {
+ public <CONFIGTYPE extends ConfigInstance> CONFIGTYPE getConfig(Class<CONFIGTYPE> configClass, ApplicationId applicationId, String configId) {
return model.getConfig(configClass, applicationId, configId);
}
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 6adbcc8dae9..6d5c4a81c92 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,11 +2,9 @@
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 com.yahoo.vespa.curator.recipes.CuratorCounter;
/**
* Distributed global generation counter for the super model.
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 6fcfde80510..aa06c07f8af 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
@@ -3,21 +3,20 @@ package com.yahoo.vespa.config.server;
import com.google.inject.Inject;
import com.yahoo.cloud.config.ConfigserverConfig;
+import com.yahoo.component.Version;
import com.yahoo.config.ConfigInstance;
import com.yahoo.config.FileReference;
import com.yahoo.config.model.api.ConfigDefinitionRepo;
-import com.yahoo.component.Version;
-import java.util.logging.Level;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.vespa.config.ConfigKey;
import com.yahoo.vespa.config.GetConfigRequest;
import com.yahoo.vespa.config.protocol.ConfigResponse;
-import com.yahoo.config.provision.ApplicationId;
import com.yahoo.vespa.config.server.application.ApplicationSet;
import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory;
-import java.io.IOException;
import java.util.Optional;
import java.util.Set;
+import java.util.logging.Level;
/**
* Handles request for supermodel config.
@@ -84,7 +83,7 @@ public class SuperModelRequestHandler implements RequestHandler {
return null;
}
- public <CONFIGTYPE extends ConfigInstance> CONFIGTYPE getConfig(Class<CONFIGTYPE> configClass, ApplicationId applicationId, String configId) throws IOException {
+ public <CONFIGTYPE extends ConfigInstance> CONFIGTYPE getConfig(Class<CONFIGTYPE> configClass, ApplicationId applicationId, String configId) {
return handler.getConfig(configClass, applicationId, configId);
}
@@ -128,4 +127,5 @@ public class SuperModelRequestHandler implements RequestHandler {
superModelManager.markAsComplete();
updateHandler();
}
+
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
index 4f04724a0a8..0b16a41dcba 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
@@ -1,16 +1,26 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.application;
-import com.yahoo.concurrent.StripedExecutor;
+import com.yahoo.component.Version;
+import com.yahoo.config.FileReference;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.TenantName;
-import java.util.logging.Level;
import com.yahoo.path.Path;
import com.yahoo.text.Utf8;
import com.yahoo.transaction.Transaction;
+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.GlobalComponentRegistry;
import com.yahoo.vespa.config.server.NotFoundException;
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.host.HostRegistry;
+import com.yahoo.vespa.config.server.host.HostValidator;
+import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
+import com.yahoo.vespa.config.server.monitoring.Metrics;
+import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.Lock;
@@ -19,15 +29,20 @@ import com.yahoo.vespa.curator.transaction.CuratorTransaction;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
+import java.time.Clock;
import java.time.Duration;
+import java.util.Collection;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
+import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
+import static java.util.stream.Collectors.toSet;
+
/**
* The applications of a tenant, backed by ZooKeeper.
*
@@ -38,7 +53,7 @@ import java.util.stream.Collectors;
* @author Ulf Lilleengen
* @author jonmv
*/
-public class TenantApplications {
+public class TenantApplications implements RequestHandler, ReloadHandler, HostValidator<ApplicationId> {
private static final Logger log = Logger.getLogger(TenantApplications.class.getName());
@@ -46,24 +61,35 @@ public class TenantApplications {
private final Path applicationsPath;
private final Path locksPath;
private final Curator.DirectoryCache directoryCache;
- private final ReloadHandler reloadHandler;
private final Executor zkWatcherExecutor;
+ private final Metrics metrics;
+ private final TenantName tenant;
+ private final List<ReloadListener> reloadListeners;
+ private final ConfigResponseFactory responseFactory;
+ private final HostRegistry<ApplicationId> hostRegistry;
+ private final ApplicationMapper applicationMapper = new ApplicationMapper();
+ private final MetricUpdater tenantMetricUpdater;
+ private final Clock clock = Clock.systemUTC();
- private TenantApplications(Curator curator, ReloadHandler reloadHandler, TenantName tenant,
- ExecutorService zkCacheExecutor, StripedExecutor<TenantName> zkWatcherExecutor) {
- this.curator = curator;
+
+ private TenantApplications(TenantName tenant, GlobalComponentRegistry registry) {
+ this.curator = registry.getCurator();
this.applicationsPath = TenantRepository.getApplicationsPath(tenant);
this.locksPath = TenantRepository.getLocksPath(tenant);
- this.reloadHandler = reloadHandler;
- this.zkWatcherExecutor = command -> zkWatcherExecutor.execute(tenant, command);
- this.directoryCache = curator.createDirectoryCache(applicationsPath.getAbsolute(), false, false, zkCacheExecutor);
+ this.tenant = tenant;
+ this.zkWatcherExecutor = command -> registry.getZkWatcherExecutor().execute(tenant, command);
+ this.directoryCache = curator.createDirectoryCache(applicationsPath.getAbsolute(), false, false, registry.getZkCacheExecutor());
this.directoryCache.start();
this.directoryCache.addListener(this::childEvent);
+ this.metrics = registry.getMetrics();
+ this.reloadListeners = List.of(registry.getReloadListener());
+ this.responseFactory = ConfigResponseFactory.create(registry.getConfigserverConfig());
+ this.tenantMetricUpdater = metrics.getOrCreateMetricUpdater(Metrics.createDimensions(tenant));
+ this.hostRegistry = registry.getHostRegistries().createApplicationHostRegistry(tenant);
}
- public static TenantApplications create(GlobalComponentRegistry registry, ReloadHandler reloadHandler, TenantName tenant) {
- return new TenantApplications(registry.getCurator(), reloadHandler, tenant,
- registry.getZkCacheExecutor(), registry.getZkWatcherExecutor());
+ public static TenantApplications create(GlobalComponentRegistry registry, TenantName tenant) {
+ return new TenantApplications(tenant, registry);
}
/**
@@ -132,7 +158,7 @@ public class TenantApplications {
* Removes all applications not known to this from the config server state.
*/
public void removeUnusedApplications() {
- reloadHandler.removeApplicationsExcept(Set.copyOf(activeApplications()));
+ removeApplicationsExcept(Set.copyOf(activeApplications()));
}
/**
@@ -170,7 +196,7 @@ public class TenantApplications {
}
private void applicationRemoved(ApplicationId applicationId) {
- reloadHandler.removeApplication(applicationId);
+ removeApplication(applicationId);
log.log(Level.INFO, TenantRepository.logPre(applicationId) + "Application removed: " + applicationId);
}
@@ -186,4 +212,201 @@ public class TenantApplications {
return locksPath.append(id.serializedForm());
}
+
+ /**
+ * Gets a config for the given app, or null if not found
+ */
+ @Override
+ public ConfigResponse resolveConfig(ApplicationId appId, GetConfigRequest req, Optional<Version> vespaVersion) {
+ Application application = getApplication(appId, vespaVersion);
+ if (log.isLoggable(Level.FINE)) {
+ log.log(Level.FINE, TenantRepository.logPre(appId) + "Resolving for tenant '" + tenant + "' with handler for application '" + application + "'");
+ }
+ return application.resolveConfig(req, responseFactory);
+ }
+
+ // For testing only
+ long getApplicationGeneration(ApplicationId appId, Optional<Version> vespaVersion) {
+ Application application = getApplication(appId, vespaVersion);
+ return application.getApplicationGeneration();
+ }
+
+ private void notifyReloadListeners(ApplicationSet applicationSet) {
+ for (ReloadListener reloadListener : reloadListeners) {
+ reloadListener.hostsUpdated(tenant, hostRegistry.getAllHosts());
+ reloadListener.configActivated(applicationSet);
+ }
+ }
+
+ /**
+ * Activates the config of the given app. Notifies listeners
+ *
+ * @param applicationSet the {@link ApplicationSet} to be reloaded
+ */
+ @Override
+ public void reloadConfig(ApplicationSet applicationSet) {
+ ApplicationId id = applicationSet.getId();
+ try (Lock lock = lock(id)) {
+ if ( ! exists(id))
+ return; // Application was deleted before activation.
+ if (applicationSet.getApplicationGeneration() != requireActiveSessionOf(id))
+ return; // Application activated a new session before we got here.
+
+ setLiveApp(applicationSet);
+ notifyReloadListeners(applicationSet);
+ }
+ }
+
+ @Override
+ public void removeApplication(ApplicationId applicationId) {
+ try (Lock lock = lock(applicationId)) {
+ if (exists(applicationId))
+ return; // Application was deployed again.
+
+ if (applicationMapper.hasApplication(applicationId, clock.instant())) {
+ applicationMapper.remove(applicationId);
+ hostRegistry.removeHostsForKey(applicationId);
+ reloadListenersOnRemove(applicationId);
+ tenantMetricUpdater.setApplications(applicationMapper.numApplications());
+ metrics.removeMetricUpdater(Metrics.createDimensions(applicationId));
+ }
+ }
+ }
+
+ @Override
+ public void removeApplicationsExcept(Set<ApplicationId> applications) {
+ for (ApplicationId activeApplication : applicationMapper.listApplicationIds()) {
+ if ( ! applications.contains(activeApplication)) {
+ log.log(Level.INFO, "Will remove deleted application " + activeApplication.toShortString());
+ removeApplication(activeApplication);
+ }
+ }
+ }
+
+ private void reloadListenersOnRemove(ApplicationId applicationId) {
+ for (ReloadListener listener : reloadListeners) {
+ listener.hostsUpdated(tenant, hostRegistry.getAllHosts());
+ listener.applicationRemoved(applicationId);
+ }
+ }
+
+ private void setLiveApp(ApplicationSet applicationSet) {
+ ApplicationId id = applicationSet.getId();
+ Collection<String> hostsForApp = applicationSet.getAllHosts();
+ hostRegistry.update(id, hostsForApp);
+ applicationSet.updateHostMetrics();
+ tenantMetricUpdater.setApplications(applicationMapper.numApplications());
+ applicationMapper.register(id, applicationSet);
+ }
+
+ @Override
+ public Set<ConfigKey<?>> listNamedConfigs(ApplicationId appId, Optional<Version> vespaVersion, ConfigKey<?> keyToMatch, boolean recursive) {
+ Application application = getApplication(appId, vespaVersion);
+ return listConfigs(application, keyToMatch, recursive);
+ }
+
+ private Set<ConfigKey<?>> listConfigs(Application application, ConfigKey<?> keyToMatch, boolean recursive) {
+ Set<ConfigKey<?>> ret = new LinkedHashSet<>();
+ for (ConfigKey<?> key : application.allConfigsProduced()) {
+ String configId = key.getConfigId();
+ if (recursive) {
+ key = new ConfigKey<>(key.getName(), configId, key.getNamespace());
+ } else {
+ // Include first part of id as id
+ key = new ConfigKey<>(key.getName(), configId.split("/")[0], key.getNamespace());
+ }
+ if (keyToMatch != null) {
+ String n = key.getName(); // Never null
+ String ns = key.getNamespace(); // Never null
+ if (n.equals(keyToMatch.getName()) &&
+ ns.equals(keyToMatch.getNamespace()) &&
+ configId.startsWith(keyToMatch.getConfigId()) &&
+ !(configId.equals(keyToMatch.getConfigId()))) {
+
+ if (!recursive) {
+ // For non-recursive, include the id segment we were searching for, and first part of the rest
+ key = new ConfigKey<>(key.getName(), appendOneLevelOfId(keyToMatch.getConfigId(), configId), key.getNamespace());
+ }
+ ret.add(key);
+ }
+ } else {
+ ret.add(key);
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public Set<ConfigKey<?>> listConfigs(ApplicationId appId, Optional<Version> vespaVersion, boolean recursive) {
+ Application application = getApplication(appId, vespaVersion);
+ return listConfigs(application, null, recursive);
+ }
+
+ /**
+ * Given baseIdSegment search/ and id search/qrservers/default.0, return search/qrservers
+ * @return id segment with one extra level from the id appended
+ */
+ String appendOneLevelOfId(String baseIdSegment, String id) {
+ if ("".equals(baseIdSegment)) return id.split("/")[0];
+ String theRest = id.substring(baseIdSegment.length());
+ if ("".equals(theRest)) return id;
+ theRest = theRest.replaceFirst("/", "");
+ String theRestFirstSeg = theRest.split("/")[0];
+ return baseIdSegment+"/"+theRestFirstSeg;
+ }
+
+ @Override
+ public Set<ConfigKey<?>> allConfigsProduced(ApplicationId appId, Optional<Version> vespaVersion) {
+ Application application = getApplication(appId, vespaVersion);
+ return application.allConfigsProduced();
+ }
+
+ private Application getApplication(ApplicationId appId, Optional<Version> vespaVersion) {
+ try {
+ return applicationMapper.getForVersion(appId, vespaVersion, clock.instant());
+ } catch (VersionDoesNotExistException ex) {
+ throw new NotFoundException(String.format("%sNo such application (id %s): %s", TenantRepository.logPre(tenant), appId, ex.getMessage()));
+ }
+ }
+
+ @Override
+ public Set<String> allConfigIds(ApplicationId appId, Optional<Version> vespaVersion) {
+ Application application = getApplication(appId, vespaVersion);
+ return application.allConfigIds();
+ }
+
+ @Override
+ public boolean hasApplication(ApplicationId appId, Optional<Version> vespaVersion) {
+ return hasHandler(appId, vespaVersion);
+ }
+
+ private boolean hasHandler(ApplicationId appId, Optional<Version> vespaVersion) {
+ return applicationMapper.hasApplicationForVersion(appId, vespaVersion, clock.instant());
+ }
+
+ @Override
+ public ApplicationId resolveApplicationId(String hostName) {
+ ApplicationId applicationId = hostRegistry.getKeyForHost(hostName);
+ if (applicationId == null) {
+ applicationId = ApplicationId.defaultId();
+ }
+ return applicationId;
+ }
+
+ @Override
+ public Set<FileReference> listFileReferences(ApplicationId applicationId) {
+ return applicationMapper.listApplications(applicationId).stream()
+ .flatMap(app -> app.getModel().fileReferences().stream())
+ .collect(toSet());
+ }
+
+ @Override
+ public void verifyHosts(ApplicationId key, Collection<String> newHosts) {
+ hostRegistry.verifyHosts(key, newHosts);
+ for (ReloadListener reloadListener : reloadListeners) {
+ reloadListener.verifyHostsAreAvailable(tenant, newHosts);
+ }
+ }
+
+
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
index e2cf84d6715..7e83d7013e0 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
@@ -21,7 +21,6 @@ import com.yahoo.vespa.config.server.zookeeper.ZKApplicationPackage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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 ffe3d39b524..2c888df6658 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
@@ -9,13 +9,14 @@ import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.jdisc.Response;
import com.yahoo.jdisc.application.BindingMatch;
-import java.util.logging.Level;
import com.yahoo.vespa.config.server.GlobalComponentRegistry;
import com.yahoo.vespa.config.server.host.HostRegistries;
import com.yahoo.vespa.config.server.host.HostRegistry;
-import com.yahoo.vespa.config.server.http.*;
+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 java.util.concurrent.Executor;
+import java.util.logging.Level;
/**
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 7828ce8963f..6b42ca7fa95 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
@@ -36,7 +36,6 @@ import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.flags.FlagSource;
import java.net.URI;
-import java.time.Instant;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
@@ -88,8 +87,8 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
ApplicationId applicationId,
Optional<DockerImage> wantedDockerImageRepository,
Version wantedNodeVespaVersion,
- Optional<AllocatedHosts> ignored, // Ignored since we have this in the app package for activated models
- Instant now) {
+ Optional<AllocatedHosts> ignored // Ignored since we have this in the app package for activated models
+ ) {
log.log(Level.FINE, String.format("Loading model version %s for session %s application %s",
modelFactory.version(), appGeneration, applicationId));
ModelContext.Properties modelContextProperties = createModelContextProperties(applicationId);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
index 455731d9cb6..245b9db020b 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
@@ -166,8 +166,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
applicationId,
wantedDockerImageRepository,
wantedNodeVespaVersion,
- allocatedHosts.asOptional(),
- now);
+ allocatedHosts.asOptional());
allocatedHosts.set(latestModelVersion.getModel().allocatedHosts()); // Update with additional clusters allocated
allApplicationVersions.add(latestModelVersion);
}
@@ -189,8 +188,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
applicationId,
wantedDockerImageRepository,
wantedNodeVespaVersion,
- allocatedHosts.asOptional(),
- now);
+ allocatedHosts.asOptional());
allocatedHosts.set(modelVersion.getModel().allocatedHosts()); // Update with additional clusters allocated
allApplicationVersions.add(modelVersion);
} catch (RuntimeException e) {
@@ -245,8 +243,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
protected abstract MODELRESULT buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage,
ApplicationId applicationId, Optional<DockerImage> dockerImageRepository,
- Version wantedNodeVespaVersion, Optional<AllocatedHosts> allocatedHosts,
- Instant now);
+ Version wantedNodeVespaVersion, Optional<AllocatedHosts> allocatedHosts);
/**
* Returns a host provisioner returning the previously allocated hosts if available and when on hosted Vespa,
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 e6d275fccdd..2397dba6b5e 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
@@ -32,7 +32,6 @@ import com.yahoo.vespa.config.server.session.PrepareParams;
import java.io.File;
import java.io.IOException;
-import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
@@ -78,13 +77,12 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
}
@Override
- protected PreparedModelResult buildModelVersion(ModelFactory modelFactory,
+ protected PreparedModelResult buildModelVersion(ModelFactory modelFactory,
ApplicationPackage applicationPackage,
ApplicationId applicationId,
Optional<DockerImage> wantedDockerImageRepository,
Version wantedNodeVespaVersion,
- Optional<AllocatedHosts> allocatedHosts,
- Instant now) {
+ Optional<AllocatedHosts> allocatedHosts) {
Version modelVersion = modelFactory.version();
log.log(Level.FINE, "Building model " + modelVersion + " for " + applicationId);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/ZKMetricUpdater.java b/configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/ZKMetricUpdater.java
index 62da6fcffbe..52ca73c68b9 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/ZKMetricUpdater.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/monitoring/ZKMetricUpdater.java
@@ -14,8 +14,6 @@ import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
-import java.util.Timer;
-import java.util.TimerTask;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java
index eb14947f73f..13c21a065ff 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/HostProvisionerProvider.java
@@ -5,10 +5,8 @@ import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.component.ComponentId;
import com.yahoo.component.provider.ComponentRegistry;
import com.yahoo.config.provision.Provisioner;
-import java.util.logging.Level;
import java.util.Optional;
-import java.util.logging.Logger;
/**
* This class is necessary to support both having and not having a host provisioner. We inject
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java
index 307ec5c0c3c..6a681ae143d 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/provision/ProvisionerAdapter.java
@@ -9,7 +9,6 @@ import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.ProvisionLogger;
import com.yahoo.config.provision.Provisioner;
-import com.yahoo.config.provision.NetworkPorts;
import java.util.*;
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java
index 7809000695a..62f7d3ce5d0 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java
@@ -3,10 +3,9 @@ package com.yahoo.vespa.config.server.rpc;
import com.yahoo.cloud.config.SentinelConfig;
import com.yahoo.collections.Pair;
-import com.yahoo.config.provision.TenantName;
import com.yahoo.component.Version;
+import com.yahoo.config.provision.TenantName;
import com.yahoo.jrt.Request;
-import java.util.logging.Level;
import com.yahoo.net.HostName;
import com.yahoo.vespa.config.ConfigPayload;
import com.yahoo.vespa.config.ErrorCode;
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/DefaultRpcAuthorizerProvider.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/DefaultRpcAuthorizerProvider.java
index 5c760f0a25a..8d1d4f58e37 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/DefaultRpcAuthorizerProvider.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/DefaultRpcAuthorizerProvider.java
@@ -8,8 +8,6 @@ import com.yahoo.container.di.componentgraph.Provider;
import com.yahoo.security.tls.TransportSecurityUtils;
import com.yahoo.vespa.config.server.host.HostRegistries;
import com.yahoo.vespa.config.server.rpc.RequestHandlerProvider;
-import com.yahoo.vespa.flags.FlagSource;
-import com.yahoo.vespa.flags.Flags;
/**
* A provider for {@link RpcAuthorizer}. The instance provided is dependent on the configuration of the configserver.
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 9a5a45bc03b..4a2e7cb405b 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
@@ -153,8 +153,6 @@ public class SessionPreparer {
final DeployLogger logger;
final PrepareParams params;
- final Optional<ApplicationSet> currentActiveApplicationSet;
- final Path tenantPath;
final ApplicationId applicationId;
/** The repository part of docker image to be used for this deployment */
@@ -187,8 +185,6 @@ public class SessionPreparer {
SessionZooKeeperClient sessionZooKeeperClient) {
this.logger = logger;
this.params = params;
- this.currentActiveApplicationSet = currentActiveApplicationSet;
- this.tenantPath = tenantPath;
this.applicationPackage = preprocessedApplicationPackage;
this.sessionZooKeeperClient = sessionZooKeeperClient;
this.applicationId = params.getApplicationId();
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java
index 43b25826507..e2776dc382e 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java
@@ -12,9 +12,7 @@ import com.yahoo.vespa.config.server.GlobalComponentRegistry;
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.host.HostValidator;
import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
-import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory;
import com.yahoo.vespa.config.server.session.LocalSessionRepo;
import com.yahoo.vespa.config.server.session.RemoteSessionRepo;
import com.yahoo.vespa.config.server.session.SessionFactory;
@@ -75,7 +73,7 @@ public class TenantRepository {
private static final Logger log = Logger.getLogger(TenantRepository.class.getName());
private final Map<TenantName, Tenant> tenants = Collections.synchronizedMap(new LinkedHashMap<>());
- private final GlobalComponentRegistry globalComponentRegistry;
+ private final GlobalComponentRegistry componentRegistry;
private final List<TenantListener> tenantListeners = Collections.synchronizedList(new ArrayList<>());
private final Curator curator;
@@ -90,30 +88,30 @@ public class TenantRepository {
/**
* Creates a new tenant repository
*
- * @param globalComponentRegistry a {@link com.yahoo.vespa.config.server.GlobalComponentRegistry}
+ * @param componentRegistry a {@link com.yahoo.vespa.config.server.GlobalComponentRegistry}
*/
@Inject
- public TenantRepository(GlobalComponentRegistry globalComponentRegistry) {
- this(globalComponentRegistry, true);
+ public TenantRepository(GlobalComponentRegistry componentRegistry) {
+ this(componentRegistry, true);
}
/**
* Creates a new tenant repository
*
- * @param globalComponentRegistry a {@link com.yahoo.vespa.config.server.GlobalComponentRegistry}
+ * @param componentRegistry a {@link com.yahoo.vespa.config.server.GlobalComponentRegistry}
* @param useZooKeeperWatchForTenantChanges set to false for tests where you want to control adding and deleting
* tenants yourself
*/
- public TenantRepository(GlobalComponentRegistry globalComponentRegistry, boolean useZooKeeperWatchForTenantChanges) {
- this.globalComponentRegistry = globalComponentRegistry;
- ConfigserverConfig configserverConfig = globalComponentRegistry.getConfigserverConfig();
+ public TenantRepository(GlobalComponentRegistry componentRegistry, boolean useZooKeeperWatchForTenantChanges) {
+ this.componentRegistry = componentRegistry;
+ ConfigserverConfig configserverConfig = componentRegistry.getConfigserverConfig();
this.bootstrapExecutor = Executors.newFixedThreadPool(configserverConfig.numParallelTenantLoaders());
this.throwExceptionIfBootstrappingFails = configserverConfig.throwIfBootstrappingTenantRepoFails();
- this.curator = globalComponentRegistry.getCurator();
- metricUpdater = globalComponentRegistry.getMetrics().getOrCreateMetricUpdater(Collections.emptyMap());
- this.tenantListeners.add(globalComponentRegistry.getTenantListener());
- this.zkCacheExecutor = globalComponentRegistry.getZkCacheExecutor();
- this.zkWatcherExecutor = globalComponentRegistry.getZkWatcherExecutor();
+ this.curator = componentRegistry.getCurator();
+ metricUpdater = componentRegistry.getMetrics().getOrCreateMetricUpdater(Collections.emptyMap());
+ this.tenantListeners.add(componentRegistry.getTenantListener());
+ this.zkCacheExecutor = componentRegistry.getZkCacheExecutor();
+ this.zkWatcherExecutor = componentRegistry.getZkWatcherExecutor();
curator.framework().getConnectionStateListenable().addListener(this::stateChanged);
curator.create(tenantsPath);
@@ -210,34 +208,21 @@ public class TenantRepository {
private void createTenant(TenantName tenantName, RequestHandler requestHandler, ReloadHandler reloadHandler) {
if (tenants.containsKey(tenantName)) return;
- TenantRequestHandler tenantRequestHandler = null;
- if (requestHandler == null) {
- tenantRequestHandler = new TenantRequestHandler(globalComponentRegistry.getMetrics(),
- tenantName,
- List.of(globalComponentRegistry.getReloadListener()),
- ConfigResponseFactory.create(globalComponentRegistry.getConfigserverConfig()),
- globalComponentRegistry);
- requestHandler = tenantRequestHandler;
- }
-
- if (reloadHandler == null && tenantRequestHandler != null)
- reloadHandler = tenantRequestHandler;
-
- HostValidator<ApplicationId> hostValidator = tenantRequestHandler;
- TenantApplications applicationRepo = TenantApplications.create(globalComponentRegistry,
- reloadHandler,
- tenantName);
-
- SessionFactory sessionFactory = new SessionFactory(globalComponentRegistry, applicationRepo, hostValidator, tenantName);
- LocalSessionRepo localSessionRepo = new LocalSessionRepo(tenantName, globalComponentRegistry, sessionFactory);
- RemoteSessionRepo remoteSessionRepo = new RemoteSessionRepo(globalComponentRegistry,
+ TenantApplications applicationRepo = TenantApplications.create(componentRegistry, tenantName);
+ if (requestHandler == null)
+ requestHandler = applicationRepo;
+ if (reloadHandler == null)
+ reloadHandler = applicationRepo;
+ SessionFactory sessionFactory = new SessionFactory(componentRegistry, applicationRepo, applicationRepo, tenantName);
+ LocalSessionRepo localSessionRepo = new LocalSessionRepo(tenantName, componentRegistry, sessionFactory);
+ RemoteSessionRepo remoteSessionRepo = new RemoteSessionRepo(componentRegistry,
sessionFactory,
reloadHandler,
tenantName,
applicationRepo);
log.log(Level.INFO, "Creating tenant '" + tenantName + "'");
- Tenant tenant = new Tenant(tenantName, sessionFactory, localSessionRepo, remoteSessionRepo, requestHandler,
- reloadHandler, applicationRepo, globalComponentRegistry.getCurator());
+ Tenant tenant = new Tenant(tenantName, sessionFactory, localSessionRepo, remoteSessionRepo, requestHandler,
+ reloadHandler, applicationRepo, componentRegistry.getCurator());
notifyNewTenant(tenant);
tenants.putIfAbsent(tenantName, tenant);
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java
deleted file mode 100644
index 25d6f194fdc..00000000000
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.yahoo.component.Version;
-import com.yahoo.config.FileReference;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.TenantName;
-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.GlobalComponentRegistry;
-import com.yahoo.vespa.config.server.NotFoundException;
-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.Application;
-import com.yahoo.vespa.config.server.application.ApplicationMapper;
-import com.yahoo.vespa.config.server.application.ApplicationSet;
-import com.yahoo.vespa.config.server.application.TenantApplications;
-import com.yahoo.vespa.config.server.application.VersionDoesNotExistException;
-import com.yahoo.vespa.config.server.host.HostRegistry;
-import com.yahoo.vespa.config.server.host.HostValidator;
-import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
-import com.yahoo.vespa.config.server.monitoring.Metrics;
-import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory;
-import com.yahoo.vespa.curator.Lock;
-
-import java.time.Clock;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.logging.Level;
-
-import static java.util.stream.Collectors.toSet;
-
-/**
- * A per tenant request handler, for handling reload (activate application) and getConfig requests for
- * a set of applications belonging to a tenant.
- *
- * @author Harald Musum
- */
-public class TenantRequestHandler implements RequestHandler, ReloadHandler, HostValidator<ApplicationId> {
-
- private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(TenantRequestHandler.class.getName());
-
- private final Metrics metrics;
- private final TenantName tenant;
- private final List<ReloadListener> reloadListeners;
- private final ConfigResponseFactory responseFactory;
- private final HostRegistry<ApplicationId> hostRegistry;
- private final ApplicationMapper applicationMapper = new ApplicationMapper();
- private final MetricUpdater tenantMetricUpdater;
- private final Clock clock = Clock.systemUTC();
- private final TenantApplications applications;
-
- public TenantRequestHandler(Metrics metrics,
- TenantName tenant,
- List<ReloadListener> reloadListeners,
- ConfigResponseFactory responseFactory,
- GlobalComponentRegistry registry) { // TODO jvenstad: Merge this class with TenantApplications, and straighten this out.
- this.metrics = metrics;
- this.tenant = tenant;
- this.reloadListeners = List.copyOf(reloadListeners);
- this.responseFactory = responseFactory;
- this.tenantMetricUpdater = metrics.getOrCreateMetricUpdater(Metrics.createDimensions(tenant));
- this.hostRegistry = registry.getHostRegistries().createApplicationHostRegistry(tenant);
- this.applications = TenantApplications.create(registry, this, tenant);
-
- }
-
- /**
- * Gets a config for the given app, or null if not found
- */
- @Override
- public ConfigResponse resolveConfig(ApplicationId appId, GetConfigRequest req, Optional<Version> vespaVersion) {
- Application application = getApplication(appId, vespaVersion);
- if (log.isLoggable(Level.FINE)) {
- log.log(Level.FINE, TenantRepository.logPre(appId) + "Resolving for tenant '" + tenant + "' with handler for application '" + application + "'");
- }
- return application.resolveConfig(req, responseFactory);
- }
-
- // For testing only
- long getApplicationGeneration(ApplicationId appId, Optional<Version> vespaVersion) {
- Application application = getApplication(appId, vespaVersion);
- return application.getApplicationGeneration();
- }
-
- private void notifyReloadListeners(ApplicationSet applicationSet) {
- for (ReloadListener reloadListener : reloadListeners) {
- reloadListener.hostsUpdated(tenant, hostRegistry.getAllHosts());
- reloadListener.configActivated(applicationSet);
- }
- }
-
- /**
- * Activates the config of the given app. Notifies listeners
- *
- * @param applicationSet the {@link ApplicationSet} to be reloaded
- */
- @Override
- public void reloadConfig(ApplicationSet applicationSet) {
- ApplicationId id = applicationSet.getId();
- try (Lock lock = applications.lock(id)) {
- if ( ! applications.exists(id))
- return; // Application was deleted before activation.
- if (applicationSet.getApplicationGeneration() != applications.requireActiveSessionOf(id))
- return; // Application activated a new session before we got here.
-
- setLiveApp(applicationSet);
- notifyReloadListeners(applicationSet);
- }
- }
-
- @Override
- public void removeApplication(ApplicationId applicationId) {
- try (Lock lock = applications.lock(applicationId)) {
- if (applications.exists(applicationId))
- return; // Application was deployed again.
-
- if (applicationMapper.hasApplication(applicationId, clock.instant())) {
- applicationMapper.remove(applicationId);
- hostRegistry.removeHostsForKey(applicationId);
- reloadListenersOnRemove(applicationId);
- tenantMetricUpdater.setApplications(applicationMapper.numApplications());
- metrics.removeMetricUpdater(Metrics.createDimensions(applicationId));
- }
- }
- }
-
- @Override
- public void removeApplicationsExcept(Set<ApplicationId> applications) {
- for (ApplicationId activeApplication : applicationMapper.listApplicationIds()) {
- if ( ! applications.contains(activeApplication)) {
- log.log(Level.INFO, "Will remove deleted application " + activeApplication.toShortString());
- removeApplication(activeApplication);
- }
- }
- }
-
- private void reloadListenersOnRemove(ApplicationId applicationId) {
- for (ReloadListener listener : reloadListeners) {
- listener.hostsUpdated(tenant, hostRegistry.getAllHosts());
- listener.applicationRemoved(applicationId);
- }
- }
-
- private void setLiveApp(ApplicationSet applicationSet) {
- ApplicationId id = applicationSet.getId();
- Collection<String> hostsForApp = applicationSet.getAllHosts();
- hostRegistry.update(id, hostsForApp);
- applicationSet.updateHostMetrics();
- tenantMetricUpdater.setApplications(applicationMapper.numApplications());
- applicationMapper.register(id, applicationSet);
- }
-
- @Override
- public Set<ConfigKey<?>> listNamedConfigs(ApplicationId appId, Optional<Version> vespaVersion, ConfigKey<?> keyToMatch, boolean recursive) {
- Application application = getApplication(appId, vespaVersion);
- return listConfigs(application, keyToMatch, recursive);
- }
-
- private Set<ConfigKey<?>> listConfigs(Application application, ConfigKey<?> keyToMatch, boolean recursive) {
- Set<ConfigKey<?>> ret = new LinkedHashSet<>();
- for (ConfigKey<?> key : application.allConfigsProduced()) {
- String configId = key.getConfigId();
- if (recursive) {
- key = new ConfigKey<>(key.getName(), configId, key.getNamespace());
- } else {
- // Include first part of id as id
- key = new ConfigKey<>(key.getName(), configId.split("/")[0], key.getNamespace());
- }
- if (keyToMatch != null) {
- String n = key.getName(); // Never null
- String ns = key.getNamespace(); // Never null
- if (n.equals(keyToMatch.getName()) &&
- ns.equals(keyToMatch.getNamespace()) &&
- configId.startsWith(keyToMatch.getConfigId()) &&
- !(configId.equals(keyToMatch.getConfigId()))) {
-
- if (!recursive) {
- // For non-recursive, include the id segment we were searching for, and first part of the rest
- key = new ConfigKey<>(key.getName(), appendOneLevelOfId(keyToMatch.getConfigId(), configId), key.getNamespace());
- }
- ret.add(key);
- }
- } else {
- ret.add(key);
- }
- }
- return ret;
- }
-
- @Override
- public Set<ConfigKey<?>> listConfigs(ApplicationId appId, Optional<Version> vespaVersion, boolean recursive) {
- Application application = getApplication(appId, vespaVersion);
- return listConfigs(application, null, recursive);
- }
-
- /**
- * Given baseIdSegment search/ and id search/qrservers/default.0, return search/qrservers
- * @return id segment with one extra level from the id appended
- */
- String appendOneLevelOfId(String baseIdSegment, String id) {
- if ("".equals(baseIdSegment)) return id.split("/")[0];
- String theRest = id.substring(baseIdSegment.length());
- if ("".equals(theRest)) return id;
- theRest = theRest.replaceFirst("/", "");
- String theRestFirstSeg = theRest.split("/")[0];
- return baseIdSegment+"/"+theRestFirstSeg;
- }
-
- @Override
- public Set<ConfigKey<?>> allConfigsProduced(ApplicationId appId, Optional<Version> vespaVersion) {
- Application application = getApplication(appId, vespaVersion);
- return application.allConfigsProduced();
- }
-
- private Application getApplication(ApplicationId appId, Optional<Version> vespaVersion) {
- try {
- return applicationMapper.getForVersion(appId, vespaVersion, clock.instant());
- } catch (VersionDoesNotExistException ex) {
- throw new NotFoundException(String.format("%sNo such application (id %s): %s", TenantRepository.logPre(tenant), appId, ex.getMessage()));
- }
- }
-
- @Override
- public Set<String> allConfigIds(ApplicationId appId, Optional<Version> vespaVersion) {
- Application application = getApplication(appId, vespaVersion);
- return application.allConfigIds();
- }
-
- @Override
- public boolean hasApplication(ApplicationId appId, Optional<Version> vespaVersion) {
- return hasHandler(appId, vespaVersion);
- }
-
- private boolean hasHandler(ApplicationId appId, Optional<Version> vespaVersion) {
- return applicationMapper.hasApplicationForVersion(appId, vespaVersion, clock.instant());
- }
-
- @Override
- public ApplicationId resolveApplicationId(String hostName) {
- ApplicationId applicationId = hostRegistry.getKeyForHost(hostName);
- if (applicationId == null) {
- applicationId = ApplicationId.defaultId();
- }
- return applicationId;
- }
-
- @Override
- public Set<FileReference> listFileReferences(ApplicationId applicationId) {
- return applicationMapper.listApplications(applicationId).stream()
- .flatMap(app -> app.getModel().fileReferences().stream())
- .collect(toSet());
- }
-
- @Override
- public void verifyHosts(ApplicationId key, Collection<String> newHosts) {
- hostRegistry.verifyHosts(key, newHosts);
- for (ReloadListener reloadListener : reloadListeners) {
- reloadListener.verifyHostsAreAvailable(tenant, newHosts);
- }
- }
-
- TenantApplications applications() { return applications; }
-
-}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java
index f3f9c914be8..35e8b0917cf 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java
@@ -111,11 +111,6 @@ public class ConfigCurator {
return (data == null) ? null : Utf8.toString(data);
}
- /** Returns the data at a path and node. Replaces / by # in node names. Returns null if the path doesn't exist. */
- public byte[] getBytes(String path, String node) {
- return getBytes(createFullPath(path, node));
- }
-
/**
* Returns the data at a path, or null if the path does not exist.
*
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
index d44be294713..3e5b539a5bf 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
@@ -2,7 +2,11 @@
package com.yahoo.vespa.config.server;
import com.yahoo.cloud.config.ConfigserverConfig;
+import com.yahoo.component.Version;
+import com.yahoo.config.ConfigInstance;
+import com.yahoo.config.SimpletypesConfig;
import com.yahoo.config.application.api.ApplicationMetaData;
+import com.yahoo.config.model.NullConfigModelRegistry;
import com.yahoo.config.model.api.ApplicationRoles;
import com.yahoo.config.model.application.provider.BaseDeployLogger;
import com.yahoo.config.provision.AllocatedHosts;
@@ -20,7 +24,14 @@ import com.yahoo.io.IOUtils;
import com.yahoo.jdisc.Metric;
import com.yahoo.test.ManualClock;
import com.yahoo.text.Utf8;
+import com.yahoo.vespa.config.ConfigKey;
+import com.yahoo.vespa.config.ConfigPayload;
+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.OrchestratorMock;
+import com.yahoo.vespa.config.server.application.TenantApplications;
import com.yahoo.vespa.config.server.deploy.DeployTester;
import com.yahoo.vespa.config.server.http.InternalServerException;
import com.yahoo.vespa.config.server.http.SessionHandlerTest;
@@ -36,6 +47,9 @@ import com.yahoo.vespa.config.server.tenant.Tenant;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
+import com.yahoo.vespa.model.VespaModelFactory;
+import org.hamcrest.core.Is;
+import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -76,6 +90,8 @@ public class ApplicationRepositoryTest {
private final static File testAppJdiscOnly = new File("src/test/apps/app-jdisc-only");
private final static File testAppJdiscOnlyRestart = new File("src/test/apps/app-jdisc-only-restart");
private final static File testAppLogServerWithContainer = new File("src/test/apps/app-logserver-with-container");
+ private final static File app1 = new File("src/test/apps/cs1");
+ private final static File app2 = new File("src/test/apps/cs2");
private final static TenantName tenant1 = TenantName.from("test1");
private final static TenantName tenant2 = TenantName.from("test2");
@@ -94,12 +110,21 @@ public class ApplicationRepositoryTest {
@Rule
public ExpectedException exceptionRule = ExpectedException.none();
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
@Before
- public void setup() {
+ public void setup() throws IOException {
Curator curator = new MockCurator();
- tenantRepository = new TenantRepository(new TestComponentRegistry.Builder()
- .curator(curator)
- .build());
+ TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder()
+ .curator(curator)
+ .configServerConfig(new ConfigserverConfig.Builder()
+ .payloadCompressionType(ConfigserverConfig.PayloadCompressionType.Enum.UNCOMPRESSED)
+ .configServerDBDir(tempFolder.newFolder("configserverdb").getAbsolutePath())
+ .configDefinitionsDir(tempFolder.newFolder("configdefinitions").getAbsolutePath())
+ .build())
+ .build();
+ tenantRepository = new TenantRepository(componentRegistry, false);
tenantRepository.addTenant(TenantRepository.HOSTED_VESPA_TENANT);
tenantRepository.addTenant(tenant1);
tenantRepository.addTenant(tenant2);
@@ -529,6 +554,93 @@ public class ApplicationRepositoryTest {
assertEquals(Session.Status.DEACTIVATE, firstSession.getStatus());
}
+ @Test
+ public void testResolveForAppId() {
+ Version vespaVersion = new VespaModelFactory(new NullConfigModelRegistry()).version();
+ applicationRepository.deploy(app1, new PrepareParams.Builder()
+ .applicationId(applicationId())
+ .vespaVersion(vespaVersion)
+ .build());
+
+ // TODO: Need to reload config before resolving works
+ RequestHandler requestHandler = reloadConfig(applicationId());
+ SimpletypesConfig config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion);
+ assertEquals(1337 , config.intval());
+ }
+
+ @Test
+ public void testResolveConfigForMultipleApps() {
+ Version vespaVersion = new VespaModelFactory(new NullConfigModelRegistry()).version();
+ applicationRepository.deploy(app1, new PrepareParams.Builder()
+ .applicationId(applicationId())
+ .vespaVersion(vespaVersion)
+ .build());
+
+ ApplicationId appId2 = new ApplicationId.Builder()
+ .tenant(tenant1)
+ .applicationName("myapp2")
+ .instanceName("default")
+ .build();
+ applicationRepository.deploy(app2, new PrepareParams.Builder()
+ .applicationId(appId2)
+ .vespaVersion(vespaVersion)
+ .build());
+
+ // TODO: Need to reload config before resolving works
+ RequestHandler requestHandler = reloadConfig(applicationId());
+ SimpletypesConfig config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion);
+ assertEquals(1337, config.intval());
+
+ // TODO: Need to reload config before resolving works
+ RequestHandler requestHandler2 = reloadConfig(appId2);
+ SimpletypesConfig config2 = resolve(SimpletypesConfig.class, requestHandler2, appId2, vespaVersion);
+ assertEquals(1330, config2.intval());
+
+ assertTrue(requestHandler.hasApplication(applicationId(), Optional.of(vespaVersion)));
+ assertThat(requestHandler.resolveApplicationId("doesnotexist"), Is.is(ApplicationId.defaultId()));
+ assertThat(requestHandler.resolveApplicationId("mytesthost"), Is.is(new ApplicationId.Builder()
+ .tenant(tenant1)
+ .applicationName("testapp").build())); // Host set in application package.
+ }
+
+ @Test
+ public void testResolveMultipleVersions() {
+ Version vespaVersion = new VespaModelFactory(new NullConfigModelRegistry()).version();
+ applicationRepository.deploy(app1, new PrepareParams.Builder()
+ .applicationId(applicationId())
+ .vespaVersion(vespaVersion)
+ .build());
+
+ // TODO: Need to reload config before resolving works
+ RequestHandler requestHandler = reloadConfig(applicationId());
+ SimpletypesConfig config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion);
+ assertEquals(1337, config.intval());
+
+ // TODO: Revisit this test, I cannot see that we create a model for version 3.2.1
+ config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), new Version(3, 2, 1));
+ assertThat(config.intval(), Is.is(1337));
+ }
+
+ @Test
+ public void testResolveForDeletedApp() {
+ Version vespaVersion = new VespaModelFactory(new NullConfigModelRegistry()).version();
+ applicationRepository.deploy(app1, new PrepareParams.Builder()
+ .applicationId(applicationId())
+ .vespaVersion(vespaVersion)
+ .build());
+
+ // TODO: Need to reload config before resolving works
+ RequestHandler requestHandler = reloadConfig(applicationId());
+ SimpletypesConfig config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion);
+ assertEquals(1337 , config.intval());
+
+ applicationRepository.delete(applicationId());
+
+ exceptionRule.expect(com.yahoo.vespa.config.server.NotFoundException.class);
+ exceptionRule.expectMessage(containsString("No such application id: test1.testapp"));
+ resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion);
+ }
+
private ApplicationRepository createApplicationRepository() {
return new ApplicationRepository(tenantRepository,
provisioner,
@@ -569,7 +681,6 @@ public class ApplicationRepositoryTest {
return applicationRepository.getMetadataFromLocalSession(tenant, sessionId);
}
-
/** Stores all added or set values for each metric and context. */
static class MockMetric implements Metric {
@@ -591,7 +702,6 @@ public class ApplicationRepositoryTest {
return new Context(properties);
}
-
private static class Context implements Metric.Context {
private final Map<String, ?> point;
@@ -604,4 +714,48 @@ public class ApplicationRepositoryTest {
}
+ private <T extends ConfigInstance> T resolve(Class<T> clazz,
+ RequestHandler applications,
+ ApplicationId appId,
+ Version vespaVersion) {
+ String configId = "";
+ ConfigResponse response = getConfigResponse(clazz, applications, appId, vespaVersion, configId);
+ return ConfigPayload.fromUtf8Array(response.getPayload()).toInstance(clazz, configId);
+ }
+
+ private <T extends ConfigInstance> ConfigResponse getConfigResponse(Class<T> clazz,
+ RequestHandler applications,
+ ApplicationId appId,
+ Version vespaVersion,
+ String configId) {
+ return applications.resolveConfig(appId, new GetConfigRequest() {
+ @Override
+ public ConfigKey<T> getConfigKey() {
+ return new ConfigKey<>(clazz, configId);
+ }
+
+ @Override
+ public DefContent getDefContent() {
+ return DefContent.fromClass(clazz);
+ }
+
+ @Override
+ public Optional<VespaVersion> getVespaVersion() {
+ return Optional.of(VespaVersion.fromString(vespaVersion.toFullString()));
+ }
+
+ @Override
+ public boolean noCache() {
+ return false;
+ }
+ }, Optional.empty());
+ }
+
+ @NotNull
+ private RequestHandler reloadConfig(ApplicationId applicationId) {
+ RequestHandler requestHandler = tenantRepository.getTenant(applicationId.tenant()).getRequestHandler();
+ ((TenantApplications) requestHandler).reloadConfig(applicationRepository.getActiveSession(applicationId).ensureApplicationLoaded());
+ return requestHandler;
+ }
+
}
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 4346d83e85e..f91205af44d 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
@@ -2,19 +2,16 @@
package com.yahoo.vespa.config.server;
import com.yahoo.cloud.config.ConfigserverConfig;
-import com.yahoo.config.model.application.provider.FilesApplicationPackage;
-import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.component.Version;
+import com.yahoo.config.model.application.provider.FilesApplicationPackage;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Zone;
-import com.yahoo.config.provisioning.FlavorsConfig;
import com.yahoo.vespa.config.server.application.Application;
-import com.yahoo.config.provision.ApplicationId;
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.flags.InMemoryFlagSource;
import com.yahoo.vespa.model.VespaModel;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -28,7 +25,11 @@ import java.util.Arrays;
import java.util.Optional;
import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
/**
* @author Ulf Lilleengen
@@ -129,10 +130,6 @@ public class SuperModelRequestHandlerTest {
}
- public static NodeFlavors emptyNodeFlavors() {
- return new NodeFlavors(new FlavorsConfig(new FlavorsConfig.Builder()));
- }
-
private ApplicationId applicationId(String tenantName, String applicationName) {
return ApplicationId.from(tenantName, applicationName, "default");
}
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 b3dca7c73f3..ec5648757f1 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
@@ -11,6 +11,7 @@ import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
import com.yahoo.container.jdisc.secretstore.SecretStore;
import com.yahoo.vespa.config.server.application.PermanentApplicationPackage;
+import com.yahoo.vespa.config.server.application.TenantApplicationsTest;
import com.yahoo.vespa.config.server.host.HostRegistries;
import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
import com.yahoo.vespa.config.server.monitoring.Metrics;
@@ -20,7 +21,6 @@ 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.config.server.zookeeper.ConfigCurator;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
@@ -106,7 +106,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
.configDefinitionsDir(uncheck(() -> Files.createTempDirectory("configdefinitions")).toString())
.sessionLifetime(5));
private ConfigDefinitionRepo defRepo = new StaticConfigDefinitionRepo();
- private TenantRequestHandlerTest.MockReloadListener reloadListener = new TenantRequestHandlerTest.MockReloadListener();
+ private ReloadListener reloadListener = new TenantApplicationsTest.MockReloadListener();
private MockTenantListener tenantListener = new MockTenantListener();
private Optional<PermanentApplicationPackage> permanentApplicationPackage = Optional.empty();
private HostRegistries hostRegistries = new HostRegistries();
@@ -156,6 +156,11 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
return this;
}
+ public Builder reloadListener(ReloadListener reloadListener) {
+ this.reloadListener = reloadListener;
+ return this;
+ }
+
public TestComponentRegistry build() {
final PermanentApplicationPackage permApp = this.permanentApplicationPackage
.orElse(new PermanentApplicationPackage(configserverConfig));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java
index 4cccafef266..e64921e3ea0 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java
@@ -59,7 +59,7 @@ public class HttpProxyTest {
public void testFetchException() {
when(fetcher.get(any(), any())).thenThrow(new RequestTimeoutException("timed out"));
- HttpResponse actualResponse = proxy.get(applicationMock, hostname, CLUSTERCONTROLLER_CONTAINER.serviceName,
- "clustercontroller-status/v1/clusterName");
+ proxy.get(applicationMock, hostname, CLUSTERCONTROLLER_CONTAINER.serviceName,
+ "clustercontroller-status/v1/clusterName");
}
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
index 33932a678b7..969040174dd 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
@@ -1,23 +1,49 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.application;
+import com.yahoo.cloud.config.ConfigserverConfig;
+import com.yahoo.component.Version;
+import com.yahoo.config.model.NullConfigModelRegistry;
+import com.yahoo.config.model.application.provider.FilesApplicationPackage;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.TenantName;
import com.yahoo.text.Utf8;
-import com.yahoo.vespa.config.server.MockReloadHandler;
-
+import com.yahoo.vespa.config.ConfigKey;
+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.model.TestModelFactory;
+import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
+import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
+import com.yahoo.vespa.model.VespaModel;
+import com.yahoo.vespa.model.VespaModelFactory;
import org.apache.curator.framework.CuratorFramework;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-
+import org.junit.rules.TemporaryFolder;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
/**
* @author Ulf Lilleengen
@@ -25,14 +51,34 @@ import static org.junit.Assert.*;
public class TenantApplicationsTest {
private static final TenantName tenantName = TenantName.from("tenant");
+ private static final Version vespaVersion = new VespaModelFactory(new NullConfigModelRegistry()).version();
- private Curator curator;
+ private MockReloadListener listener = new MockReloadListener();
private CuratorFramework curatorFramework;
+ private TestComponentRegistry componentRegistry;
+ private TenantApplications applications;
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
@Before
- public void setup() {
- curator = new MockCurator();
+ public void setup() throws IOException {
+ Curator curator = new MockCurator();
curatorFramework = curator.framework();
+ componentRegistry = new TestComponentRegistry.Builder()
+ .curator(curator)
+ .configServerConfig(new ConfigserverConfig.Builder()
+ .payloadCompressionType(ConfigserverConfig.PayloadCompressionType.Enum.UNCOMPRESSED)
+ .configServerDBDir(tempFolder.newFolder("configserverdb").getAbsolutePath())
+ .configDefinitionsDir(tempFolder.newFolder("configdefinitions").getAbsolutePath())
+ .build())
+ .modelFactoryRegistry(createRegistry())
+ .reloadListener(listener)
+ .build();
+ TenantRepository tenantRepository = new TenantRepository(componentRegistry, false);
+ tenantRepository.addTenant(TenantRepository.HOSTED_VESPA_TENANT);
+ tenantRepository.addTenant(tenantName);
+ applications = TenantApplications.create(componentRegistry, tenantName);
}
@Test
@@ -94,29 +140,71 @@ public class TenantApplicationsTest {
assertThat(repo.activeApplications().size(), is(0));
}
- @Test
- public void require_that_reload_handler_is_called_when_apps_are_removed() throws Exception {
- ApplicationId foo = createApplicationId("foo");
- writeApplicationData(foo, 3L);
- writeApplicationData(createApplicationId("bar"), 4L);
- MockReloadHandler reloadHandler = new MockReloadHandler();
- TenantApplications repo = createZKAppRepo(reloadHandler);
- assertNull(reloadHandler.lastRemoved);
- repo.createDeleteTransaction(foo).commit();
- long endTime = System.currentTimeMillis() + 60_000;
- while (System.currentTimeMillis() < endTime && reloadHandler.lastRemoved == null) {
- Thread.sleep(100);
+ public static class MockReloadListener implements ReloadListener {
+ public AtomicInteger reloaded = new AtomicInteger(0);
+ AtomicInteger removed = new AtomicInteger(0);
+ Map<String, Collection<String>> tenantHosts = new LinkedHashMap<>();
+
+ @Override
+ public void configActivated(ApplicationSet application) {
+ reloaded.incrementAndGet();
+ }
+
+ @Override
+ public void hostsUpdated(TenantName tenant, Collection<String> newHosts) {
+ tenantHosts.put(tenant.value(), newHosts);
+ }
+
+ @Override
+ public void verifyHostsAreAvailable(TenantName tenant, Collection<String> newHosts) {
+ }
+
+ @Override
+ public void applicationRemoved(ApplicationId applicationId) {
+ removed.incrementAndGet();
}
- assertNotNull(reloadHandler.lastRemoved);
- assertThat(reloadHandler.lastRemoved.serializedForm(), is(foo.serializedForm()));
}
- private TenantApplications createZKAppRepo() {
- return createZKAppRepo(new MockReloadHandler());
+ private void assertdefaultAppNotFound() {
+ assertFalse(applications.hasApplication(ApplicationId.defaultId(), Optional.of(vespaVersion)));
+ }
+
+ @Test
+ public void testListConfigs() throws IOException, SAXException {
+ assertdefaultAppNotFound();
+
+ VespaModel model = new VespaModel(FilesApplicationPackage.fromFile(new File("src/test/apps/app")));
+ applications.createApplication(ApplicationId.defaultId());
+ applications.createPutTransaction(ApplicationId.defaultId(), 1).commit();
+ applications.reloadConfig(ApplicationSet.fromSingle(new Application(model,
+ new ServerCache(),
+ 1,
+ false,
+ vespaVersion,
+ MetricUpdater.createTestUpdater(),
+ ApplicationId.defaultId())));
+ Set<ConfigKey<?>> configNames = applications.listConfigs(ApplicationId.defaultId(), Optional.of(vespaVersion), false);
+ assertTrue(configNames.contains(new ConfigKey<>("sentinel", "hosts", "cloud.config")));
+
+ configNames = applications.listConfigs(ApplicationId.defaultId(), Optional.of(vespaVersion), true);
+ assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "container", "document.config")));
+ assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "", "document.config")));
+ assertTrue(configNames.contains(new ConfigKey<>("documenttypes", "", "document")));
+ assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "container", "document.config")));
+ assertTrue(configNames.contains(new ConfigKey<>("health-monitor", "container", "container.jdisc.config")));
+ assertTrue(configNames.contains(new ConfigKey<>("specific", "container", "project")));
}
- private TenantApplications createZKAppRepo(MockReloadHandler reloadHandler) {
- return TenantApplications.create(new TestComponentRegistry.Builder().curator(curator).build(), reloadHandler, tenantName);
+ @Test
+ public void testAppendIdsInNonRecursiveListing() {
+ assertEquals(applications.appendOneLevelOfId("search/music", "search/music/qrservers/default/qr.0"), "search/music/qrservers");
+ assertEquals(applications.appendOneLevelOfId("search", "search/music/qrservers/default/qr.0"), "search/music");
+ assertEquals(applications.appendOneLevelOfId("search/music/qrservers/default/qr.0", "search/music/qrservers/default/qr.0"), "search/music/qrservers/default/qr.0");
+ assertEquals(applications.appendOneLevelOfId("", "search/music/qrservers/default/qr.0"), "search");
+ }
+
+ private TenantApplications createZKAppRepo() {
+ return TenantApplications.create(componentRegistry, tenantName);
}
private static ApplicationId createApplicationId(String name) {
@@ -134,4 +222,10 @@ public class TenantApplicationsTest {
.forPath(TenantRepository.getApplicationsPath(tenantName).append(applicationId).getAbsolute(),
Utf8.toAsciiBytes(sessionId));
}
+
+ private ModelFactoryRegistry createRegistry() {
+ return new ModelFactoryRegistry(Arrays.asList(new TestModelFactory(vespaVersion),
+ new TestModelFactory(new Version(3, 2, 1))));
+ }
+
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/configchange/ConfigChangeActionsBuilder.java b/configserver/src/test/java/com/yahoo/vespa/config/server/configchange/ConfigChangeActionsBuilder.java
index 2566b1029a8..e2c3369d49e 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/configchange/ConfigChangeActionsBuilder.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/configchange/ConfigChangeActionsBuilder.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.configchange;
import com.google.common.collect.ImmutableMap;
@@ -6,7 +6,6 @@ import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.config.model.api.ServiceInfo;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/MockDeployer.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/MockDeployer.java
deleted file mode 100644
index 967e2321b95..00000000000
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/MockDeployer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.config.server.deploy;
-
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.Deployment;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.util.Optional;
-
-/**
- * @author Ulf Lilleengen
- */
-public class MockDeployer implements com.yahoo.config.provision.Deployer {
-
- @Override
- public Optional<Deployment> deployFromLocalActive(ApplicationId application) {
- return deployFromLocalActive(application, Duration.ofSeconds(60));
- }
-
- @Override
- public Optional<Deployment> deployFromLocalActive(ApplicationId application, boolean bootstrap) {
- return Optional.empty();
- }
-
- @Override
- public Optional<Deployment> deployFromLocalActive(ApplicationId application, Duration timeout) {
- return Optional.empty();
- }
-
- @Override
- public Optional<Deployment> deployFromLocalActive(ApplicationId application, Duration timeout, boolean bootstrap) {
- return Optional.empty();
- }
-
- @Override
- public Optional<Instant> lastDeployTime(ApplicationId application) {
- return Optional.empty();
- }
-
-}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/ApplicationMetricsRetrieverTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/ApplicationMetricsRetrieverTest.java
index 492767728e5..49de9b41ca1 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/ApplicationMetricsRetrieverTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/ApplicationMetricsRetrieverTest.java
@@ -1,7 +1,6 @@
// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.metrics;
-import com.yahoo.component.Version;
import com.yahoo.config.FileReference;
import com.yahoo.config.model.api.FileDistribution;
import com.yahoo.config.model.api.HostInfo;
@@ -23,7 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
/**
* @author olaa
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java
index 07f6e9cf222..d923f4c1856 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java
@@ -55,14 +55,6 @@ public class MockRpc extends RpcServer {
this(port, true, tempDir);
}
- /** Reset fields used to assert on the calls made to this */
- public void resetChecks() {
- forced = false;
- tryResolveConfig = false;
- tryRespond = false;
- latestRequest = null;
- }
-
private static ConfigserverConfig createConfig(int port) {
ConfigserverConfig.Builder b = new ConfigserverConfig.Builder();
b.rpcport(port);
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 2c119a119b6..a758698d3b5 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
@@ -59,7 +59,7 @@ public class LocalSessionRepoTest {
.build())
.build();
SessionFactory sessionFactory = new SessionFactory(globalComponentRegistry,
- TenantApplications.create(globalComponentRegistry, new MockReloadHandler(), tenantName),
+ TenantApplications.create(globalComponentRegistry, tenantName),
new HostRegistry<>(),
tenantName);
repo = new LocalSessionRepo(tenantName, globalComponentRegistry, sessionFactory);
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 ce3b119d852..b072f20414f 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
@@ -12,7 +12,6 @@ import com.yahoo.config.provision.TenantName;
import com.yahoo.path.Path;
import com.yahoo.slime.Slime;
import com.yahoo.transaction.NestedTransaction;
-import com.yahoo.vespa.config.server.MockReloadHandler;
import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.application.TenantApplications;
import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger;
@@ -138,7 +137,7 @@ public class LocalSessionTest {
File sessionDir = new File(tenantFileSystemDirs.sessionsPath(), String.valueOf(sessionId));
sessionDir.createNewFile();
TenantApplications applications = TenantApplications.create(
- new TestComponentRegistry.Builder().curator(curator).build(), new MockReloadHandler(), tenant);
+ new TestComponentRegistry.Builder().curator(curator).build(), tenant);
applications.createApplication(zkc.readApplicationId());
return new LocalSession(tenant, sessionId, preparer, FilesApplicationPackage.fromFile(testApp),
zkc, sessionDir, applications, new HostRegistry<>());
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRepositoryTest.java
index c3237c9fabb..51b0a36d8f4 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRepositoryTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRepositoryTest.java
@@ -2,21 +2,20 @@
package com.yahoo.vespa.config.server.tenant;
import com.yahoo.cloud.config.ConfigserverConfig;
+import com.yahoo.component.Version;
import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
-import com.yahoo.component.Version;
import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.config.server.GlobalComponentRegistry;
-import com.yahoo.vespa.config.server.ReloadHandler;
-import com.yahoo.vespa.config.server.RequestHandler;
-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.application.Application;
+import com.yahoo.vespa.config.server.application.ApplicationSet;
+import com.yahoo.vespa.config.server.application.TenantApplicationsTest;
import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
@@ -47,7 +46,7 @@ public class TenantRepositoryTest {
private TenantRepository tenantRepository;
private TestComponentRegistry globalComponentRegistry;
- private TenantRequestHandlerTest.MockReloadListener listener;
+ private TenantApplicationsTest.MockReloadListener listener;
private MockTenantListener tenantListener;
private Curator curator;
@@ -61,7 +60,7 @@ public class TenantRepositoryTest {
public void setupSessions() {
curator = new MockCurator();
globalComponentRegistry = new TestComponentRegistry.Builder().curator(curator).build();
- listener = (TenantRequestHandlerTest.MockReloadListener)globalComponentRegistry.getReloadListener();
+ listener = (TenantApplicationsTest.MockReloadListener)globalComponentRegistry.getReloadListener();
tenantListener = (MockTenantListener)globalComponentRegistry.getTenantListener();
assertFalse(tenantListener.tenantsLoaded);
tenantRepository = new TenantRepository(globalComponentRegistry);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
deleted file mode 100644
index fa9efec1255..00000000000
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.yahoo.component.Version;
-import com.yahoo.config.ConfigInstance;
-import com.yahoo.config.SimpletypesConfig;
-import com.yahoo.config.application.api.ApplicationPackage;
-import com.yahoo.config.model.NullConfigModelRegistry;
-import com.yahoo.config.model.application.provider.BaseDeployLogger;
-import com.yahoo.config.model.application.provider.DeployData;
-import com.yahoo.config.model.application.provider.FilesApplicationPackage;
-import com.yahoo.config.model.application.provider.MockFileRegistry;
-import com.yahoo.config.provision.AllocatedHosts;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ApplicationName;
-import com.yahoo.config.provision.TenantName;
-import com.yahoo.io.IOUtils;
-import com.yahoo.vespa.config.ConfigKey;
-import com.yahoo.vespa.config.ConfigPayload;
-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.ReloadListener;
-import com.yahoo.vespa.config.server.ServerCache;
-import com.yahoo.vespa.config.server.TestComponentRegistry;
-import com.yahoo.vespa.config.server.application.Application;
-import com.yahoo.vespa.config.server.application.ApplicationSet;
-import com.yahoo.vespa.config.server.deploy.ZooKeeperDeployer;
-import com.yahoo.vespa.config.server.model.TestModelFactory;
-import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
-import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
-import com.yahoo.vespa.config.server.monitoring.Metrics;
-import com.yahoo.vespa.config.server.rpc.UncompressedConfigResponseFactory;
-import com.yahoo.vespa.config.server.session.RemoteSession;
-import com.yahoo.vespa.config.server.session.SessionZooKeeperClient;
-import com.yahoo.vespa.curator.Curator;
-import com.yahoo.vespa.curator.mock.MockCurator;
-import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.VespaModelFactory;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.xml.sax.SAXException;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Ulf Lilleengen
- */
-public class TenantRequestHandlerTest {
-
- private static final Version vespaVersion = new VespaModelFactory(new NullConfigModelRegistry()).version();
- private TenantRequestHandler server;
- private MockReloadListener listener = new MockReloadListener();
- private File app1 = new File("src/test/apps/cs1");
- private File app2 = new File("src/test/apps/cs2");
- private TenantName tenant = TenantName.from("mytenant");
- private TestComponentRegistry componentRegistry;
- private Curator curator;
-
- @Rule
- public TemporaryFolder tempFolder = new TemporaryFolder();
-
- private ApplicationId defaultApp() {
- return new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(tenant).build();
- }
-
- @Before
- public void setUp() throws IOException {
- curator = new MockCurator();
-
- feedApp(app1, 1, defaultApp(), false);
- Metrics sh = Metrics.createTestMetrics();
- List<ReloadListener> listeners = new ArrayList<>();
- listeners.add(listener);
- componentRegistry = new TestComponentRegistry.Builder()
- .curator(curator)
- .modelFactoryRegistry(createRegistry())
- .build();
- server = new TenantRequestHandler(sh, tenant, listeners, new UncompressedConfigResponseFactory(), componentRegistry);
- }
-
- private void feedApp(File appDir, long sessionId, ApplicationId appId, boolean internalRedeploy) throws IOException {
- SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, TenantRepository.getSessionsPath(tenant).append(String.valueOf(sessionId)));
- zkc.writeApplicationId(appId);
- File app = tempFolder.newFolder();
- IOUtils.copyDirectory(appDir, app);
- ZooKeeperDeployer deployer = zkc.createDeployer(new BaseDeployLogger());
- DeployData deployData = new DeployData("user",
- appDir.toString(),
- appId,
- 0L,
- internalRedeploy,
- 0L,
- 0L);
- ApplicationPackage appPackage = FilesApplicationPackage.fromFileWithDeployData(appDir, deployData);
- deployer.deploy(appPackage,
- Collections.singletonMap(vespaVersion, new MockFileRegistry()),
- AllocatedHosts.withHosts(Collections.emptySet()));
- }
-
- private ApplicationSet reloadConfig(long sessionId) {
- return reloadConfig(sessionId, "default");
- }
-
- private ApplicationSet reloadConfig(long sessionId, String application) {
- SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, TenantRepository.getSessionsPath(tenant).append(String.valueOf(sessionId)));
- zkc.writeApplicationId(new ApplicationId.Builder().tenant(tenant).applicationName(application).build());
- RemoteSession session = new RemoteSession(tenant, sessionId, componentRegistry, zkc);
- return session.ensureApplicationLoaded();
- }
-
- private ModelFactoryRegistry createRegistry() {
- return new ModelFactoryRegistry(Arrays.asList(new TestModelFactory(vespaVersion),
- new TestModelFactory(new Version(3, 2, 1))));
- }
-
- private <T extends ConfigInstance> T resolve(Class<T> clazz,
- TenantRequestHandler tenantRequestHandler,
- ApplicationId appId,
- Version vespaVersion,
- String configId) {
- ConfigResponse response = getConfigResponse(clazz, tenantRequestHandler, appId, vespaVersion, configId);
- return ConfigPayload.fromUtf8Array(response.getPayload()).toInstance(clazz, configId);
- }
-
- private <T extends ConfigInstance> ConfigResponse getConfigResponse(Class<T> clazz,
- TenantRequestHandler tenantRequestHandler,
- ApplicationId appId,
- Version vespaVersion,
- String configId) {
- return tenantRequestHandler.resolveConfig(appId, new GetConfigRequest() {
- @Override
- public ConfigKey<T> getConfigKey() {
- return new ConfigKey<>(clazz, configId);
- }
-
- @Override
- public DefContent getDefContent() {
- return DefContent.fromClass(clazz);
- }
-
- @Override
- public Optional<VespaVersion> getVespaVersion() {
- return Optional.of(VespaVersion.fromString(vespaVersion.toFullString()));
- }
-
- @Override
- public boolean noCache() {
- return false;
- }
- }, Optional.empty());
- }
-
- @Test
- public void testReloadConfig() throws IOException {
- ApplicationId applicationId = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(tenant).build();
-
- server.applications().createApplication(applicationId);
- server.applications().createPutTransaction(applicationId, 1).commit();
- server.reloadConfig(reloadConfig(1));
- assertThat(listener.reloaded.get(), is(1));
- // Using only payload list for this simple test
- SimpletypesConfig config = resolve(SimpletypesConfig.class, server, defaultApp(), vespaVersion, "");
- assertThat(config.intval(), is(1337));
- assertThat(server.getApplicationGeneration(applicationId, Optional.of(vespaVersion)), is(1L));
-
- server.reloadConfig(reloadConfig(1L));
- ConfigResponse configResponse = getConfigResponse(SimpletypesConfig.class, server, defaultApp(), vespaVersion, "");
- assertFalse(configResponse.isInternalRedeploy());
- config = resolve(SimpletypesConfig.class, server, defaultApp(), vespaVersion, "");
- assertThat(config.intval(), is(1337));
- assertThat(listener.reloaded.get(), is(2));
- assertThat(server.getApplicationGeneration(applicationId, Optional.of(vespaVersion)), is(1L));
- assertThat(listener.tenantHosts.size(), is(1));
- assertThat(server.resolveApplicationId("mytesthost"), is(applicationId));
-
- listener.reloaded.set(0);
- feedApp(app2, 2, defaultApp(), true);
- server.applications().createPutTransaction(applicationId, 2).commit();
- server.reloadConfig(reloadConfig(2L));
- configResponse = getConfigResponse(SimpletypesConfig.class, server, defaultApp(), vespaVersion, "");
- assertTrue(configResponse.isInternalRedeploy());
- config = resolve(SimpletypesConfig.class, server, defaultApp(), vespaVersion,"");
- assertThat(config.intval(), is(1330));
- assertThat(listener.reloaded.get(), is(1));
- assertThat(server.getApplicationGeneration(applicationId, Optional.of(vespaVersion)), is(2L));
- }
-
- @Test
- public void testRemoveApplication() {
- ApplicationId appId = ApplicationId.from(tenant.value(), "default", "default");
- server.reloadConfig(reloadConfig(1));
- assertThat(listener.reloaded.get(), is(0));
-
- server.applications().createApplication(appId);
- server.applications().createPutTransaction(appId, 1).commit();
- server.reloadConfig(reloadConfig(1));
- assertThat(listener.reloaded.get(), is(1));
-
- assertThat(listener.removed.get(), is(0));
-
- server.removeApplication(appId);
- assertThat(listener.removed.get(), is(0));
-
- server.applications().createDeleteTransaction(appId).commit();
- server.removeApplication(appId);
- assertThat(listener.removed.get(), is(1));
- }
-
- @Test
- public void testResolveForAppId() {
- long id = 1L;
- ApplicationId appId = new ApplicationId.Builder()
- .tenant(tenant)
- .applicationName("myapp").instanceName("myinst").build();
- server.applications().createApplication(appId);
- server.applications().createPutTransaction(appId, 1).commit();
- SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, TenantRepository.getSessionsPath(tenant).append(String.valueOf(id)));
- zkc.writeApplicationId(appId);
- RemoteSession session = new RemoteSession(appId.tenant(), id, componentRegistry, zkc);
- server.reloadConfig(session.ensureApplicationLoaded());
- SimpletypesConfig config = resolve(SimpletypesConfig.class, server, appId, vespaVersion, "");
- assertThat(config.intval(), is(1337));
- }
-
- @Test
- public void testResolveMultipleApps() throws IOException {
- ApplicationId appId1 = new ApplicationId.Builder()
- .tenant(tenant)
- .applicationName("myapp1").instanceName("myinst1").build();
- ApplicationId appId2 = new ApplicationId.Builder()
- .tenant(tenant)
- .applicationName("myapp2").instanceName("myinst2").build();
- feedAndReloadApp(app1, 1, appId1);
- SimpletypesConfig config = resolve(SimpletypesConfig.class, server, appId1, vespaVersion, "");
- assertThat(config.intval(), is(1337));
-
- feedAndReloadApp(app2, 2, appId2);
- config = resolve(SimpletypesConfig.class, server, appId2, vespaVersion, "");
- assertThat(config.intval(), is(1330));
- }
-
- @Test
- public void testResolveMultipleVersions() throws IOException {
- ApplicationId appId = new ApplicationId.Builder()
- .tenant(tenant)
- .applicationName("myapp1").instanceName("myinst1").build();
- feedAndReloadApp(app1, 1, appId);
- SimpletypesConfig config = resolve(SimpletypesConfig.class, server, appId, vespaVersion, "");
- assertThat(config.intval(), is(1337));
- config = resolve(SimpletypesConfig.class, server, appId, new Version(3, 2, 1), "");
- assertThat(config.intval(), is(1337));
- }
-
- private void feedAndReloadApp(File appDir, long sessionId, ApplicationId appId) throws IOException {
- server.applications().createApplication(appId);
- server.applications().createPutTransaction(appId, sessionId).commit();
- feedApp(appDir, sessionId, appId, false);
- SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, TenantRepository.getSessionsPath(tenant).append(String.valueOf(sessionId)));
- zkc.writeApplicationId(appId);
- RemoteSession session = new RemoteSession(tenant, sessionId, componentRegistry, zkc);
- server.reloadConfig(session.ensureApplicationLoaded());
- }
-
- public static class MockReloadListener implements ReloadListener {
- AtomicInteger reloaded = new AtomicInteger(0);
- AtomicInteger removed = new AtomicInteger(0);
- Map<String, Collection<String>> tenantHosts = new LinkedHashMap<>();
-
- @Override
- public void configActivated(ApplicationSet application) {
- reloaded.incrementAndGet();
- }
-
- @Override
- public void hostsUpdated(TenantName tenant, Collection<String> newHosts) {
- tenantHosts.put(tenant.value(), newHosts);
- }
-
- @Override
- public void verifyHostsAreAvailable(TenantName tenant, Collection<String> newHosts) {
- }
-
- @Override
- public void applicationRemoved(ApplicationId applicationId) {
- removed.incrementAndGet();
- }
- }
-
- @Test
- public void testHasApplication() {
- assertdefaultAppNotFound();
- ApplicationId appId = ApplicationId.from(tenant.value(), "default", "default");
- server.applications().createApplication(appId);
- server.applications().createPutTransaction(appId, 1).commit();
- server.reloadConfig(reloadConfig(1));
- assertTrue(server.hasApplication(appId, Optional.of(vespaVersion)));
- }
-
- private void assertdefaultAppNotFound() {
- assertFalse(server.hasApplication(ApplicationId.defaultId(), Optional.of(vespaVersion)));
- }
-
- @Test
- public void testMultipleApplicationsReload() {
- ApplicationId appId = ApplicationId.from(tenant.value(), "foo", "default");
- assertdefaultAppNotFound();
- server.applications().createApplication(appId);
- server.applications().createPutTransaction(appId, 1).commit();
- server.reloadConfig(reloadConfig(1, "foo"));
- assertdefaultAppNotFound();
- assertTrue(server.hasApplication(appId,
- Optional.of(vespaVersion)));
- assertThat(server.resolveApplicationId("doesnotexist"), is(ApplicationId.defaultId()));
- assertThat(server.resolveApplicationId("mytesthost"), is(new ApplicationId.Builder()
- .tenant(tenant)
- .applicationName("foo").build())); // Host set in application package.
- }
-
- @Test
- public void testListConfigs() throws IOException, SAXException {
- assertdefaultAppNotFound();
-
- VespaModel model = new VespaModel(FilesApplicationPackage.fromFile(new File("src/test/apps/app")));
- server.applications().createApplication(ApplicationId.defaultId());
- server.applications().createPutTransaction(ApplicationId.defaultId(), 1).commit();
- server.reloadConfig(ApplicationSet.fromSingle(new Application(model,
- new ServerCache(),
- 1,
- false,
- vespaVersion,
- MetricUpdater.createTestUpdater(),
- ApplicationId.defaultId())));
- Set<ConfigKey<?>> configNames = server.listConfigs(ApplicationId.defaultId(), Optional.of(vespaVersion), false);
- assertTrue(configNames.contains(new ConfigKey<>("sentinel", "hosts", "cloud.config")));
-
- configNames = server.listConfigs(ApplicationId.defaultId(), Optional.of(vespaVersion), true);
- assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "container", "document.config")));
- assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "", "document.config")));
- assertTrue(configNames.contains(new ConfigKey<>("documenttypes", "", "document")));
- assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "container", "document.config")));
- assertTrue(configNames.contains(new ConfigKey<>("health-monitor", "container", "container.jdisc.config")));
- assertTrue(configNames.contains(new ConfigKey<>("specific", "container", "project")));
- }
-
- @Test
- public void testAppendIdsInNonRecursiveListing() {
- assertEquals(server.appendOneLevelOfId("search/music", "search/music/qrservers/default/qr.0"), "search/music/qrservers");
- assertEquals(server.appendOneLevelOfId("search", "search/music/qrservers/default/qr.0"), "search/music");
- assertEquals(server.appendOneLevelOfId("search/music/qrservers/default/qr.0", "search/music/qrservers/default/qr.0"), "search/music/qrservers/default/qr.0");
- assertEquals(server.appendOneLevelOfId("", "search/music/qrservers/default/qr.0"), "search");
- }
-}