aboutsummaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java103
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java6
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java13
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java16
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java27
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java28
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java17
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java35
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantMetaData.java65
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java13
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java91
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java10
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java5
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java14
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java5
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java7
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java35
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java8
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java79
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionRepositoryTest.java12
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java90
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRepositoryTest.java9
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java4
30 files changed, 504 insertions, 206 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 eb268546580..bf2fdbf03ef 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
@@ -25,6 +25,7 @@ import com.yahoo.io.IOUtils;
import com.yahoo.jdisc.Metric;
import com.yahoo.path.Path;
import com.yahoo.slime.Slime;
+import com.yahoo.text.Utf8;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.transaction.Transaction;
import com.yahoo.vespa.config.server.application.Application;
@@ -60,9 +61,17 @@ import com.yahoo.vespa.config.server.tenant.ApplicationRolesStore;
import com.yahoo.vespa.config.server.tenant.ContainerEndpointsCache;
import com.yahoo.vespa.config.server.tenant.EndpointCertificateMetadataStore;
import com.yahoo.vespa.config.server.tenant.Tenant;
+import com.yahoo.vespa.config.server.tenant.TenantMetaData;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.Lock;
+import com.yahoo.vespa.curator.transaction.CuratorOperations;
+import com.yahoo.vespa.curator.transaction.CuratorTransaction;
+import com.yahoo.vespa.defaults.Defaults;
+import com.yahoo.vespa.flags.BooleanFlag;
+import com.yahoo.vespa.flags.FlagSource;
+import com.yahoo.vespa.flags.Flags;
+import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.orchestrator.Orchestrator;
import java.io.File;
@@ -90,9 +99,10 @@ import java.util.stream.Collectors;
import static com.yahoo.config.model.api.container.ContainerServiceType.CLUSTERCONTROLLER_CONTAINER;
import static com.yahoo.config.model.api.container.ContainerServiceType.CONTAINER;
import static com.yahoo.config.model.api.container.ContainerServiceType.LOGSERVER_CONTAINER;
-import static com.yahoo.vespa.curator.Curator.CompletionWaiter;
+import static com.yahoo.vespa.config.server.filedistribution.FileDistributionUtil.fileReferenceExistsOnDisk;
import static com.yahoo.vespa.config.server.filedistribution.FileDistributionUtil.getFileReferencesOnDisk;
import static com.yahoo.vespa.config.server.tenant.TenantRepository.HOSTED_VESPA_TENANT;
+import static com.yahoo.vespa.curator.Curator.CompletionWaiter;
import static com.yahoo.yolean.Exceptions.uncheck;
import static java.nio.file.Files.readAttributes;
@@ -120,6 +130,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
private final LogRetriever logRetriever;
private final TesterClient testerClient;
private final Metric metric;
+ private final BooleanFlag useTenantMetaData;
@Inject
public ApplicationRepository(TenantRepository tenantRepository,
@@ -130,7 +141,8 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
ConfigserverConfig configserverConfig,
Orchestrator orchestrator,
TesterClient testerClient,
- Metric metric) {
+ Metric metric,
+ FlagSource flagSource) {
this(tenantRepository,
hostProvisionerProvider.getHostProvisioner(),
infraDeployerProvider.getInfraDeployer(),
@@ -142,7 +154,8 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
new FileDistributionStatus(),
Clock.systemUTC(),
testerClient,
- metric);
+ metric,
+ flagSource);
}
// For testing
@@ -157,7 +170,8 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
new LogRetriever(),
clock,
new TesterClient(),
- new NullMetric());
+ new NullMetric(),
+ new InMemoryFlagSource());
}
// For testing
@@ -168,7 +182,8 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
LogRetriever logRetriever,
Clock clock,
TesterClient testerClient,
- Metric metric) {
+ Metric metric,
+ FlagSource flagSource) {
this(tenantRepository,
Optional.of(hostProvisioner),
Optional.empty(),
@@ -180,7 +195,8 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
new FileDistributionStatus(),
clock,
testerClient,
- metric);
+ metric,
+ flagSource);
}
private ApplicationRepository(TenantRepository tenantRepository,
@@ -194,7 +210,8 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
FileDistributionStatus fileDistributionStatus,
Clock clock,
TesterClient testerClient,
- Metric metric) {
+ Metric metric,
+ FlagSource flagSource) {
this.tenantRepository = tenantRepository;
this.hostProvisioner = hostProvisioner;
this.infraDeployer = infraDeployer;
@@ -207,6 +224,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
this.clock = clock;
this.testerClient = testerClient;
this.metric = metric;
+ this.useTenantMetaData = Flags.USE_TENANT_META_DATA.bindTo(flagSource);
}
public Metric metric() {
@@ -252,7 +270,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
boolean ignoreSessionStaleFailure, Instant now) {
ApplicationId applicationId = prepareParams.getApplicationId();
long sessionId = createSession(applicationId, prepareParams.getTimeoutBudget(), applicationPackage);
- Tenant tenant = tenantRepository.getTenant(applicationId.tenant());
+ Tenant tenant = getTenant(applicationId);
PrepareResult result = prepare(tenant, sessionId, prepareParams, now);
activate(tenant, sessionId, prepareParams.getTimeoutBudget(), ignoreSessionStaleFailure);
return result;
@@ -346,16 +364,36 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
}
public Transaction deactivateCurrentActivateNew(Session active, LocalSession prepared, boolean ignoreStaleSessionFailure) {
- SessionRepository sessionRepository = tenantRepository.getTenant(prepared.getTenantName()).getSessionRepository();
- Transaction transaction = sessionRepository.createActivateTransaction(prepared);
+ Tenant tenant = tenantRepository.getTenant(prepared.getTenantName());
+ Transaction transaction = tenant.getSessionRepository().createActivateTransaction(prepared);
if (active != null) {
checkIfActiveHasChanged(prepared, active, ignoreStaleSessionFailure);
checkIfActiveIsNewerThanSessionToBeActivated(prepared.getSessionId(), active.getSessionId());
transaction.add(active.createDeactivateTransaction().operations());
}
+
+ if (useTenantMetaData.value())
+ transaction.add(writeTenantMetaData(tenant).operations());
+
return transaction;
}
+ private String createMetaData(Tenant tenant) {
+ return new TenantMetaData(tenant.getSessionRepository().clock().instant()).asJsonString();
+ }
+
+ TenantMetaData getTenantMetaData(Tenant tenant) {
+ Optional<byte[]> data = tenantRepository.getCurator().getData(TenantRepository.getTenantPath(tenant.getName()));
+ return data.map(bytes -> TenantMetaData.fromJsonString(Utf8.toString(bytes))).orElse(new TenantMetaData(tenant.getCreatedTime()));
+ }
+
+ private Transaction writeTenantMetaData(Tenant tenant) {
+ String jsonString = createMetaData(tenant);
+ return new CuratorTransaction(tenantRepository.getCurator())
+ .add(CuratorOperations.setData(TenantRepository.getTenantPath(tenant.getName()).getAbsolute(),
+ Utf8.toBytes(jsonString)));
+ }
+
static void checkIfActiveHasChanged(LocalSession session, Session currentActiveSession, boolean ignoreStaleSessionFailure) {
long activeSessionAtCreate = session.getActiveSessionAtCreate();
log.log(Level.FINE, currentActiveSession.logPre() + "active session id at create time=" + activeSessionAtCreate);
@@ -379,10 +417,6 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
}
}
- private static boolean isValidSession(Session session) {
- return session != null;
- }
-
// As of now, config generation is based on session id, and config generation must be a monotonically
// increasing number
static void checkIfActiveIsNewerThanSessionToBeActivated(long sessionId, long currentActiveSessionId) {
@@ -412,7 +446,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
* @throws RuntimeException if the delete transaction fails. This method is exception safe.
*/
public boolean delete(ApplicationId applicationId, Duration waitTime) {
- Tenant tenant = tenantRepository.getTenant(applicationId.tenant());
+ Tenant tenant = getTenant(applicationId);
if (tenant == null) return false;
TenantApplications tenantApplications = tenant.getApplicationRepo();
@@ -554,6 +588,9 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
long sessionId = getSessionIdForApplication(tenant, applicationId);
RemoteSession session = getRemoteSession(tenant, sessionId);
return session.ensureApplicationLoaded().getForVersionOrLatest(version, clock.instant());
+ } catch (NotFoundException e) {
+ log.log(Level.WARNING, "Failed getting application for '" + applicationId + "': " + e.getMessage());
+ throw e;
} catch (Exception e) {
log.log(Level.WARNING, "Failed getting application for '" + applicationId + "'", e);
throw e;
@@ -586,7 +623,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
}
private boolean localSessionHasBeenDeleted(ApplicationId applicationId, long sessionId, Duration waitTime) {
- SessionRepository sessionRepository = tenantRepository.getTenant(applicationId.tenant()).getSessionRepository();
+ SessionRepository sessionRepository = getTenant(applicationId).getSessionRepository();
Instant end = Instant.now().plus(waitTime);
do {
if (sessionRepository.getRemoteSession(sessionId) == null) return true;
@@ -596,6 +633,26 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
return false;
}
+ public Optional<String> getApplicationPackageReference(ApplicationId applicationId) {
+ Optional<String> applicationPackage = Optional.empty();
+ RemoteSession session = getActiveSession(applicationId);
+ if (session != null) {
+ FileReference applicationPackageReference = session.getApplicationPackageReference();
+ File downloadDirectory = new File(Defaults.getDefaults().underVespaHome(configserverConfig().fileReferencesDir()));
+ if (applicationPackageReference != null && ! fileReferenceExistsOnDisk(downloadDirectory, applicationPackageReference))
+ applicationPackage = Optional.of(applicationPackageReference.value());
+ }
+ return applicationPackage;
+ }
+
+ public List<Version> getAllVersions(ApplicationId applicationId) {
+ Optional<ApplicationSet> applicationSet = getCurrentActiveApplicationSet(getTenant(applicationId), applicationId);
+ if (applicationSet.isEmpty())
+ return List.of();
+ else
+ return applicationSet.get().getAllVersions(applicationId);
+ }
+
// ---------------- Convergence ----------------------------------------------------------------
public HttpResponse checkServiceForConfigConvergence(ApplicationId applicationId, String hostAndPort, URI uri,
@@ -671,11 +728,11 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
* @return the active session, or null if there is no active session for the given application id.
*/
public RemoteSession getActiveSession(ApplicationId applicationId) {
- return getActiveSession(tenantRepository.getTenant(applicationId.tenant()), applicationId);
+ return getActiveSession(getTenant(applicationId), applicationId);
}
public long getSessionIdForApplication(ApplicationId applicationId) {
- Tenant tenant = tenantRepository.getTenant(applicationId.tenant());
+ Tenant tenant = getTenant(applicationId);
if (tenant == null) throw new NotFoundException("Tenant '" + applicationId.tenant() + "' not found");
return getSessionIdForApplication(tenant, applicationId);
}
@@ -704,7 +761,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
DeployLogger logger,
boolean internalRedeploy,
TimeoutBudget timeoutBudget) {
- Tenant tenant = tenantRepository.getTenant(applicationId.tenant());
+ Tenant tenant = getTenant(applicationId);
SessionRepository sessionRepository = tenant.getSessionRepository();
RemoteSession fromSession = getExistingSession(tenant, applicationId);
LocalSession session = sessionRepository.createSessionFromExisting(fromSession, logger, internalRedeploy, timeoutBudget);
@@ -724,7 +781,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
}
public long createSession(ApplicationId applicationId, TimeoutBudget timeoutBudget, File applicationDirectory) {
- Tenant tenant = tenantRepository.getTenant(applicationId.tenant());
+ Tenant tenant = getTenant(applicationId);
tenant.getApplicationRepo().createApplication(applicationId);
Optional<Long> activeSessionId = tenant.getApplicationRepo().activeSessionOf(applicationId);
LocalSession session = tenant.getSessionRepository().createSession(applicationDirectory,
@@ -742,9 +799,9 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
Set<ApplicationId> applicationIds = new HashSet<>();
sessionsPerTenant.values()
.forEach(sessionList -> sessionList.stream()
- .map(Session::getApplicationId)
- .filter(Objects::nonNull)
- .forEach(applicationIds::add));
+ .map(Session::getOptionalApplicationId)
+ .filter(Optional::isPresent)
+ .forEach(appId -> applicationIds.add(appId.get())));
Map<ApplicationId, Long> activeSessions = new HashMap<>();
applicationIds.forEach(applicationId -> {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java
index 0aab83d5a6a..cbea6d99dd2 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java
@@ -105,7 +105,11 @@ public class ConfigServerBootstrap extends AbstractComponent implements Runnable
initializing(vipStatusMode);
// Run maintainers that cleans up zookeeper and disk usage before bootstrapping
- configServerMaintenance.ifPresent(ConfigServerMaintenance::runBeforeBootstrap);
+ try {
+ configServerMaintenance.ifPresent(ConfigServerMaintenance::runBeforeBootstrap);
+ } catch (Exception e) {
+ log.log(Level.INFO, "Running maintainers before bootstrap failed, continuing with bootstrap", e);
+ }
switch (mode) {
case BOOTSTRAP_IN_SEPARATE_THREAD:
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java
index 5ce9ebca69d..c0158b55422 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationMapper.java
@@ -57,7 +57,7 @@ public final class ApplicationMapper {
/** Returns whether this registry has an application for the given application id */
public boolean hasApplication(ApplicationId applicationId, Instant now) {
- return hasApplicationForVersion(applicationId, Optional.<Version>empty(), now);
+ return hasApplicationForVersion(applicationId, Optional.empty(), now);
}
/** Returns whether this registry has an application for the given application id and vespa version */
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 d87a37829de..ee9b8a60305 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
@@ -119,6 +119,16 @@ public class TenantApplications implements RequestHandler, HostValidator<Applica
return curator.getChildren(applicationsPath).stream()
.sorted()
.map(ApplicationId::fromSerializedForm)
+ .filter(applicationId -> {
+ if ( ! applicationId.tenant().equals(tenant)) {
+ log.log(Level.WARNING, "There is an application ('" + applicationId + "') with wrong tenant (should be '" +
+ tenant + "') in " + applicationsPath + ", deleting it");
+ curator.delete(applicationsPath.append(applicationId.serializedForm()));
+ return false;
+ } else {
+ return true;
+ }
+ })
.filter(id -> activeSessionOf(id).isPresent())
.collect(Collectors.toUnmodifiableList());
}
@@ -153,6 +163,8 @@ public class TenantApplications implements RequestHandler, HostValidator<Applica
* Creates a node for the given application, marking its existence.
*/
public void createApplication(ApplicationId id) {
+ if (! id.tenant().equals(tenant))
+ throw new IllegalArgumentException("Cannot write application id '" + id + "' for tenant '" + tenant + "'");
try (Lock lock = lock(id)) {
curator.create(applicationPath(id));
}
@@ -420,4 +432,5 @@ public class TenantApplications implements RequestHandler, HostValidator<Applica
}
public TenantFileSystemDirs getTenantFileSystemDirs() { return tenantFileSystemDirs; }
+
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
index 8c2e6027691..11ce659625d 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
@@ -108,17 +108,18 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
@Override
public void prepare() {
if (prepared) return;
- try (ActionTimer timer = applicationRepository.timerFor(session.getApplicationId(), "deployment.prepareMillis")) {
+ ApplicationId applicationId = session.getApplicationId();
+ try (ActionTimer timer = applicationRepository.timerFor(applicationId, "deployment.prepareMillis")) {
TimeoutBudget timeoutBudget = new TimeoutBudget(clock, timeout);
- PrepareParams.Builder params = new PrepareParams.Builder().applicationId(session.getApplicationId())
+ PrepareParams.Builder params = new PrepareParams.Builder().applicationId(applicationId)
.timeoutBudget(timeoutBudget)
.ignoreValidationErrors(!validate)
.vespaVersion(version.toString())
.isBootstrap(isBootstrap);
dockerImageRepository.ifPresent(params::dockerImageRepository);
athenzDomain.ifPresent(params::athenzDomain);
- Optional<ApplicationSet> activeApplicationSet = applicationRepository.getCurrentActiveApplicationSet(tenant, session.getApplicationId());
+ Optional<ApplicationSet> activeApplicationSet = applicationRepository.getCurrentActiveApplicationSet(tenant, applicationId);
tenant.getSessionRepository().prepareLocalSession(session, logger, params.build(), activeApplicationSet,
tenant.getPath(), clock.instant());
this.prepared = true;
@@ -131,11 +132,10 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
if ( ! prepared)
prepare();
- try (ActionTimer timer = applicationRepository.timerFor(session.getApplicationId(), "deployment.activateMillis")) {
+ validateSessionStatus(session);
+ ApplicationId applicationId = session.getApplicationId();
+ try (ActionTimer timer = applicationRepository.timerFor(applicationId, "deployment.activateMillis")) {
TimeoutBudget timeoutBudget = new TimeoutBudget(clock, timeout);
- validateSessionStatus(session);
- ApplicationId applicationId = session.getApplicationId();
-
if ( ! timeoutBudget.hasTimeLeft()) throw new RuntimeException("Timeout exceeded when trying to activate '" + applicationId + "'");
RemoteSession previousActiveSession;
@@ -148,7 +148,7 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
throw e;
}
catch (Exception e) {
- throw new InternalServerException("Error activating application", e);
+ throw new InternalServerException("Error when activating '" + applicationId + "'", e);
}
waiter.awaitCompletion(timeoutBudget.timeLeft());
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java
index 8426d6b56cf..0a805cc6b21 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java
@@ -3,7 +3,6 @@ package com.yahoo.vespa.config.server.http.v2;
import com.google.inject.Inject;
import com.yahoo.component.Version;
-import com.yahoo.config.FileReference;
import com.yahoo.config.application.api.ApplicationFile;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
@@ -18,18 +17,13 @@ import com.yahoo.jdisc.application.BindingMatch;
import com.yahoo.jdisc.application.UriPattern;
import com.yahoo.slime.Cursor;
import com.yahoo.vespa.config.server.ApplicationRepository;
-import com.yahoo.vespa.config.server.application.ApplicationSet;
import com.yahoo.vespa.config.server.http.ContentHandler;
import com.yahoo.vespa.config.server.http.ContentRequest;
import com.yahoo.vespa.config.server.http.HttpErrorResponse;
import com.yahoo.vespa.config.server.http.HttpHandler;
import com.yahoo.vespa.config.server.http.JSONResponse;
import com.yahoo.vespa.config.server.http.NotFoundException;
-import com.yahoo.vespa.config.server.session.RemoteSession;
-import com.yahoo.vespa.config.server.tenant.Tenant;
-import com.yahoo.vespa.defaults.Defaults;
-import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
@@ -38,8 +32,6 @@ import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static com.yahoo.vespa.config.server.filedistribution.FileDistributionUtil.fileReferenceExistsOnDisk;
-
/**
* Operations on applications (delete, wait for config convergence, restart, application content etc.)
*
@@ -169,21 +161,10 @@ public class ApplicationHandler extends HttpHandler {
}
GetApplicationResponse getApplicationResponse(ApplicationId applicationId) {
- Tenant tenant = applicationRepository.getTenant(applicationId);
- Optional<ApplicationSet> applicationSet = applicationRepository.getCurrentActiveApplicationSet(tenant, applicationId);
- String applicationPackage = "";
- RemoteSession session = applicationRepository.getActiveSession(applicationId);
- if (session != null) {
- FileReference applicationPackageReference = session.getApplicationPackageReference();
- File downloadDirectory = new File(Defaults.getDefaults().underVespaHome(applicationRepository.configserverConfig().fileReferencesDir()));
- if (applicationPackageReference != null && ! fileReferenceExistsOnDisk(downloadDirectory, applicationPackageReference))
- applicationPackage = applicationPackageReference.value();
- }
-
return new GetApplicationResponse(Response.Status.OK,
applicationRepository.getApplicationGeneration(applicationId),
- applicationSet.get().getAllVersions(applicationId),
- applicationPackage);
+ applicationRepository.getAllVersions(applicationId),
+ applicationRepository.getApplicationPackageReference(applicationId));
}
@Override
@@ -346,10 +327,10 @@ public class ApplicationHandler extends HttpHandler {
}
private static class GetApplicationResponse extends JSONResponse {
- GetApplicationResponse(int status, long generation, List<Version> modelVersions, String applicationPackageReference) {
+ GetApplicationResponse(int status, long generation, List<Version> modelVersions, Optional<String> applicationPackageReference) {
super(status);
object.setLong("generation", generation);
- object.setString("applicationPackageFileReference", applicationPackageReference);
+ object.setString("applicationPackageFileReference", applicationPackageReference.orElse(""));
Cursor modelVersionArray = object.setArray("modelVersions");
modelVersions.forEach(version -> modelVersionArray.addString(version.toFullString()));
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java
index 124902c988a..4e75234620f 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java
@@ -45,7 +45,7 @@ public class SessionActiveHandler extends SessionHandler {
Utils.checkThatTenantExists(tenantRepository, tenantName);
Tenant tenant = tenantRepository.getTenant(tenantName);
TimeoutBudget timeoutBudget = getTimeoutBudget(request, DEFAULT_ACTIVATE_TIMEOUT);
- final Long sessionId = getSessionIdV2(request);
+ long sessionId = getSessionIdV2(request);
ApplicationId applicationId = applicationRepository.activate(tenant, sessionId, timeoutBudget,
shouldIgnoreSessionStaleFailure(request));
ApplicationMetaData metaData = applicationRepository.getMetadataFromLocalSession(tenant, sessionId);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java
index e9687000b3c..e41d5264c08 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java
@@ -89,7 +89,7 @@ public class ApplicationPackageMaintainer extends ConfigServerMaintainer {
}
private void createLocalSessionIfMissing(ApplicationId applicationId, long sessionId) {
- Tenant tenant = applicationRepository.tenantRepository().getTenant(applicationId.tenant());
+ Tenant tenant = applicationRepository.getTenant(applicationId);
SessionRepository sessionRepository = tenant.getSessionRepository();
if (sessionRepository.getLocalSession(sessionId) == null)
sessionRepository.createLocalSessionUsingDistributedApplicationPackage(sessionId);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
index 013daa86767..36cac87a326 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
@@ -60,7 +60,7 @@ public class RemoteSession extends Session {
// Read hosts allocated on the config server instance which created this
Optional<AllocatedHosts> allocatedHosts = applicationPackage.getAllocatedHosts();
- return ApplicationSet.fromList(applicationLoader.buildModels(sessionZooKeeperClient.readApplicationId(),
+ return ApplicationSet.fromList(applicationLoader.buildModels(getApplicationId(),
sessionZooKeeperClient.readDockerImageRepository(),
sessionZooKeeperClient.readVespaVersion(),
applicationPackage,
@@ -101,7 +101,7 @@ public class RemoteSession extends Session {
KeeperException.NodeExistsException.class);
Class<? extends Throwable> exceptionClass = e.getCause().getClass();
if (acceptedExceptions.contains(exceptionClass))
- log.log(Level.INFO, "Not able to notify completion for session " + getSessionId() +
+ log.log(Level.FINE, "Not able to notify completion for session " + getSessionId() +
" (" + completionWaiter + ")," +
" node " + (exceptionClass.equals(KeeperException.NoNodeException.class)
? "has been deleted"
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java
index 0fc85b5e51a..b3e35e955de 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java
@@ -34,21 +34,22 @@ public abstract class Session implements Comparable<Session> {
protected final Optional<ApplicationPackage> applicationPackage;
protected Session(TenantName tenant, long sessionId, SessionZooKeeperClient sessionZooKeeperClient) {
- this.tenant = tenant;
- this.sessionId = sessionId;
- this.sessionZooKeeperClient = sessionZooKeeperClient;
- this.applicationPackage = Optional.empty();
+ this(tenant, sessionId, sessionZooKeeperClient, Optional.empty());
}
protected Session(TenantName tenant, long sessionId, SessionZooKeeperClient sessionZooKeeperClient,
ApplicationPackage applicationPackage) {
+ this(tenant, sessionId, sessionZooKeeperClient, Optional.of(applicationPackage));
+ }
+
+ private Session(TenantName tenant, long sessionId, SessionZooKeeperClient sessionZooKeeperClient,
+ Optional<ApplicationPackage> applicationPackage) {
this.tenant = tenant;
this.sessionId = sessionId;
this.sessionZooKeeperClient = sessionZooKeeperClient;
- this.applicationPackage = Optional.of(applicationPackage);
+ this.applicationPackage = applicationPackage;
}
-
public final long getSessionId() {
return sessionId;
}
@@ -133,7 +134,20 @@ public abstract class Session implements Comparable<Session> {
sessionZooKeeperClient.writeAthenzDomain(athenzDomain);
}
- public ApplicationId getApplicationId() { return sessionZooKeeperClient.readApplicationId(); }
+ /** Returns application id read from ZooKeeper. Will throw RuntimeException if not found */
+ public ApplicationId getApplicationId() {
+ return sessionZooKeeperClient.readApplicationId()
+ .orElseThrow(() -> new RuntimeException("Unable to read application id for session " + sessionId));
+ }
+
+ /** Returns application id read from ZooKeeper. Will return Optional.empty() if not found */
+ public Optional<ApplicationId> getOptionalApplicationId() {
+ try {
+ return Optional.of(getApplicationId());
+ } catch (RuntimeException e) {
+ return Optional.empty();
+ }
+ }
public FileReference getApplicationPackageReference() {return sessionZooKeeperClient.readApplicationPackageReference(); }
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
index 03769d0a537..2e6180aeb81 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
@@ -9,7 +9,6 @@ import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.model.application.provider.DeployData;
import com.yahoo.config.model.application.provider.FilesApplicationPackage;
import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.TenantName;
import com.yahoo.io.IOUtils;
import com.yahoo.path.Path;
@@ -183,8 +182,9 @@ public class SessionRepository {
deleteLocalSession(candidate);
} else if (createTime.plus(Duration.ofDays(1)).isBefore(clock.instant())) {
// Sessions with state ACTIVATE, but which are not actually active
- ApplicationId applicationId = candidate.getApplicationId();
- Long activeSession = activeSessions.get(applicationId);
+ Optional<ApplicationId> applicationId = candidate.getOptionalApplicationId();
+ if (applicationId.isEmpty()) continue;
+ Long activeSession = activeSessions.get(applicationId.get());
if (activeSession == null || activeSession != candidate.getSessionId()) {
deleteLocalSession(candidate);
log.log(Level.INFO, "Deleted inactive session " + candidate.getSessionId() + " created " +
@@ -624,7 +624,8 @@ public class SessionRepository {
log.log(Level.INFO, "File reference for session id " + sessionId + ": " + fileReference + " not found in " + fileDirectory);
return Optional.empty();
}
- ApplicationId applicationId = sessionZKClient.readApplicationId();
+ ApplicationId applicationId = sessionZKClient.readApplicationId()
+ .orElseThrow(() -> new RuntimeException("Could not find application id for session " + sessionId));
log.log(Level.INFO, "Creating local session for tenant '" + tenantName + "' with session id " + sessionId);
LocalSession localSession = createLocalSession(sessionDir, applicationId, sessionId);
addLocalSession(localSession);
@@ -654,9 +655,7 @@ public class SessionRepository {
private SessionZooKeeperClient createSessionZooKeeperClient(long sessionId) {
String serverId = componentRegistry.getConfigserverConfig().serverId();
- Optional<NodeFlavors> nodeFlavors = componentRegistry.getZone().nodeFlavors();
- Path sessionPath = getSessionPath(sessionId);
- return new SessionZooKeeperClient(curator, componentRegistry.getConfigCurator(), sessionPath, serverId, nodeFlavors);
+ return new SessionZooKeeperClient(curator, componentRegistry.getConfigCurator(), tenantName, sessionId, serverId);
}
private File getAndValidateExistingSessionAppDir(long sessionId) {
@@ -693,13 +692,15 @@ public class SessionRepository {
return curator.lock(lockPath(sessionId), Duration.ofMinutes(1)); // These locks shouldn't be held for very long.
}
+ public Clock clock() { return clock; }
+
private Path lockPath(long sessionId) {
return locksPath.append(String.valueOf(sessionId));
}
public Transaction createActivateTransaction(Session session) {
Transaction transaction = createSetStatusTransaction(session, Session.Status.ACTIVATE);
- transaction.add(applicationRepo.createPutTransaction(session.sessionZooKeeperClient.readApplicationId(), session.getSessionId()).operations());
+ transaction.add(applicationRepo.createPutTransaction(session.getApplicationId(), session.getSessionId()).operations());
return transaction;
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
index 27440b3765b..d28a322a05a 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
@@ -11,13 +11,14 @@ import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.DockerImage;
-import com.yahoo.config.provision.NodeFlavors;
+import com.yahoo.config.provision.TenantName;
import com.yahoo.path.Path;
import com.yahoo.text.Utf8;
import com.yahoo.transaction.Transaction;
import com.yahoo.vespa.config.server.UserConfigDefinitionRepo;
import com.yahoo.vespa.config.server.deploy.ZooKeeperClient;
import com.yahoo.vespa.config.server.deploy.ZooKeeperDeployer;
+import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
import com.yahoo.vespa.config.server.zookeeper.ZKApplicationPackage;
import com.yahoo.vespa.curator.Curator;
@@ -48,27 +49,21 @@ public class SessionZooKeeperClient {
private static final String ATHENZ_DOMAIN = "athenzDomain";
private final Curator curator;
private final ConfigCurator configCurator;
+ private final TenantName tenantName;
private final Path sessionPath;
private final Path sessionStatusPath;
private final String serverId; // hostname
- private final Optional<NodeFlavors> nodeFlavors;
-
- // Only for testing
- // TODO: Remove, use the constructor below
- public SessionZooKeeperClient(Curator curator, Path sessionPath) {
- this(curator, ConfigCurator.create(curator), sessionPath, "1", Optional.empty());
- }
public SessionZooKeeperClient(Curator curator,
ConfigCurator configCurator,
- Path sessionPath,
- String serverId,
- Optional<NodeFlavors> nodeFlavors) {
+ TenantName tenantName,
+ long sessionId,
+ String serverId) {
this.curator = curator;
this.configCurator = configCurator;
- this.sessionPath = sessionPath;
+ this.tenantName = tenantName;
+ this.sessionPath = getSessionPath(tenantName, sessionId);
this.serverId = serverId;
- this.nodeFlavors = nodeFlavors;
this.sessionStatusPath = sessionPath.append(ConfigCurator.SESSIONSTATE_ZK_SUBPATH);
}
@@ -135,7 +130,7 @@ public class SessionZooKeeperClient {
}
public ApplicationPackage loadApplicationPackage() {
- return new ZKApplicationPackage(configCurator, sessionPath, nodeFlavors);
+ return new ZKApplicationPackage(configCurator, sessionPath);
}
public ConfigDefinitionRepo getUserConfigDefinitions() {
@@ -147,12 +142,16 @@ public class SessionZooKeeperClient {
}
public void writeApplicationId(ApplicationId id) {
+ if ( ! id.tenant().equals(tenantName))
+ throw new IllegalArgumentException("Cannot write application id '" + id + "' for tenant '" + tenantName + "'");
configCurator.putData(applicationIdPath(), id.serializedForm());
}
- public ApplicationId readApplicationId() {
+ public Optional<ApplicationId> readApplicationId() {
String idString = configCurator.getData(applicationIdPath());
- return idString == null ? null : ApplicationId.fromSerializedForm(idString);
+ return (idString == null)
+ ? Optional.empty()
+ : Optional.of(ApplicationId.fromSerializedForm(idString));
}
void writeApplicationPackageReference(FileReference applicationPackageReference) {
@@ -255,4 +254,8 @@ public class SessionZooKeeperClient {
transaction.commit();
}
+ private static Path getSessionPath(TenantName tenantName, long sessionId) {
+ return TenantRepository.getSessionsPath(tenantName).append(String.valueOf(sessionId));
+ }
+
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantMetaData.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantMetaData.java
new file mode 100644
index 00000000000..47a3dcc8ee0
--- /dev/null
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantMetaData.java
@@ -0,0 +1,65 @@
+// 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.tenant;
+
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.Inspector;
+import com.yahoo.slime.JsonDecoder;
+import com.yahoo.slime.JsonFormat;
+import com.yahoo.slime.Slime;
+import com.yahoo.text.Utf8;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+
+/**
+ * Metadata for a tenant. At the moment only stores last deploy time, to be used by TenantsMaintainer
+ * to GC unused tenants
+ *
+ * @author hmusum
+ */
+public class TenantMetaData {
+
+ private final Instant lastDeployTimestamp;
+
+ public TenantMetaData(Instant instant) {
+ this.lastDeployTimestamp = instant;
+ }
+
+ public Instant lastDeployTimestamp() {
+ return lastDeployTimestamp;
+ }
+
+ public String asJsonString() {
+ Slime slime = getSlime();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ new JsonFormat(false).encode(baos, slime);
+ return baos.toString(StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to encode metadata", e);
+ }
+ }
+
+ public static TenantMetaData fromJsonString(String jsonString) {
+ try {
+ Slime data = new Slime();
+ new JsonDecoder().decode(data, Utf8.toBytes(jsonString));
+ Inspector root = data.get();
+ Inspector lastDeployTimestamp = root.field("lastDeployTimestamp");
+
+ return new TenantMetaData(Instant.ofEpochMilli(lastDeployTimestamp.asLong()));
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Error parsing json metadata", e);
+ }
+ }
+
+ private Slime getSlime() {
+ Slime slime = new Slime();
+ Cursor meta = slime.setObject();
+ meta.setLong("lastDeployTimestamp", lastDeployTimestamp.toEpochMilli());
+ return slime;
+ }
+
+}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java
index 11cec9efd95..665f37759b4 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java
@@ -13,7 +13,6 @@ import com.yahoo.config.codegen.DefParser;
import com.yahoo.config.model.application.provider.PreGeneratedFileRegistry;
import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.serialization.AllocatedHostsSerializer;
import com.yahoo.io.IOUtils;
import com.yahoo.io.reader.NamedReader;
@@ -52,17 +51,17 @@ public class ZKApplicationPackage implements ApplicationPackage {
public static final String allocatedHostsNode = "allocatedHosts";
private final ApplicationMetaData metaData;
- public ZKApplicationPackage(ConfigCurator zk, Path sessionPath, Optional<NodeFlavors> nodeFlavors) {
+ public ZKApplicationPackage(ConfigCurator zk, Path sessionPath) {
verifyAppPath(zk, sessionPath);
zkApplication = new ZKApplication(zk, sessionPath);
metaData = readMetaDataFromLiveApp(zkApplication);
importFileRegistries();
- allocatedHosts = importAllocatedHosts(nodeFlavors);
+ allocatedHosts = importAllocatedHosts();
}
- private Optional<AllocatedHosts> importAllocatedHosts(Optional<NodeFlavors> nodeFlavors) {
+ private Optional<AllocatedHosts> importAllocatedHosts() {
if ( ! zkApplication.exists(ZKApplicationPackage.allocatedHostsNode)) return Optional.empty();
- return Optional.of(readAllocatedHosts(nodeFlavors));
+ return Optional.of(readAllocatedHosts());
}
/**
@@ -70,9 +69,9 @@ public class ZKApplicationPackage implements ApplicationPackage {
*
* @return the allocated hosts at this node or empty if there is no data at this path
*/
- private AllocatedHosts readAllocatedHosts(Optional<NodeFlavors> nodeFlavors) {
+ private AllocatedHosts readAllocatedHosts() {
try {
- return AllocatedHostsSerializer.fromJson(zkApplication.getBytes(ZKApplicationPackage.allocatedHostsNode), nodeFlavors);
+ return AllocatedHostsSerializer.fromJson(zkApplication.getBytes(ZKApplicationPackage.allocatedHostsNode));
} catch (Exception e) {
throw new RuntimeException("Unable to read allocated hosts", e);
}
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 e42fb78f595..239f103332c 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
@@ -9,6 +9,7 @@ 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.model.application.provider.FilesApplicationPackage;
import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
@@ -41,11 +42,13 @@ import com.yahoo.vespa.config.server.session.PrepareParams;
import com.yahoo.vespa.config.server.session.RemoteSession;
import com.yahoo.vespa.config.server.session.Session;
import com.yahoo.vespa.config.server.session.SessionRepository;
+import com.yahoo.vespa.config.server.session.SessionZooKeeperClient;
import com.yahoo.vespa.config.server.session.SilentDeployLogger;
import com.yahoo.vespa.config.server.tenant.ApplicationRolesStore;
import com.yahoo.vespa.config.server.tenant.Tenant;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
+import com.yahoo.vespa.config.util.ConfigUtils;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.flags.FlagSource;
@@ -61,6 +64,7 @@ import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
@@ -105,6 +109,7 @@ public class ApplicationRepositoryTest {
private SessionHandlerTest.MockProvisioner provisioner;
private OrchestratorMock orchestrator;
private TimeoutBudget timeoutBudget;
+ private Curator curator;
private ConfigCurator configCurator;
@Rule
@@ -119,7 +124,7 @@ public class ApplicationRepositoryTest {
}
public void setup(FlagSource flagSource) throws IOException {
- Curator curator = new MockCurator();
+ curator = new MockCurator();
configCurator = ConfigCurator.create(curator);
ConfigserverConfig configserverConfig = new ConfigserverConfig.Builder()
.payloadCompressionType(ConfigserverConfig.PayloadCompressionType.Enum.UNCOMPRESSED)
@@ -147,7 +152,8 @@ public class ApplicationRepositoryTest {
new MockLogRetriever(),
clock,
new MockTesterClient(),
- new NullMetric());
+ new NullMetric(),
+ flagSource);
timeoutBudget = new TimeoutBudget(clock, Duration.ofSeconds(60));
}
@@ -157,11 +163,33 @@ public class ApplicationRepositoryTest {
assertTrue(result.configChangeActions().getRefeedActions().isEmpty());
assertTrue(result.configChangeActions().getRestartActions().isEmpty());
- TenantName tenantName = applicationId().tenant();
- Tenant tenant = tenantRepository.getTenant(tenantName);
+ Tenant tenant = applicationRepository.getTenant(applicationId());
LocalSession session = tenant.getSessionRepository().getLocalSession(tenant.getApplicationRepo()
.requireActiveSessionOf(applicationId()));
session.getAllocatedHosts();
+
+ assertEquals(Instant.EPOCH, applicationRepository.getTenantMetaData(tenant).lastDeployTimestamp());
+ }
+
+ @Test
+ public void prepareAndActivateWithTenantMetaData() throws IOException {
+ FlagSource flagSource = new InMemoryFlagSource().withBooleanFlag(Flags.USE_TENANT_META_DATA.id(), true);
+ setup(flagSource);
+
+ Duration duration = Duration.ofHours(1);
+ clock.advance(duration);
+ Instant deployTime = clock.instant();
+ PrepareResult result = prepareAndActivate(testApp);
+ assertTrue(result.configChangeActions().getRefeedActions().isEmpty());
+ assertTrue(result.configChangeActions().getRestartActions().isEmpty());
+
+ Tenant tenant = applicationRepository.getTenant(applicationId());
+ LocalSession session = tenant.getSessionRepository().getLocalSession(tenant.getApplicationRepo()
+ .requireActiveSessionOf(applicationId()));
+ session.getAllocatedHosts();
+
+ assertEquals(deployTime.toEpochMilli(),
+ applicationRepository.getTenantMetaData(tenant).lastDeployTimestamp().toEpochMilli());
}
@Test
@@ -189,8 +217,7 @@ public class ApplicationRepositoryTest {
long secondSessionId = result2.sessionId();
assertNotEquals(firstSessionId, secondSessionId);
- TenantName tenantName = applicationId().tenant();
- Tenant tenant = tenantRepository.getTenant(tenantName);
+ Tenant tenant = applicationRepository.getTenant(applicationId());
LocalSession session = tenant.getSessionRepository().getLocalSession(
tenant.getApplicationRepo().requireActiveSessionOf(applicationId()));
assertEquals(firstSessionId, session.getMetaData().getPreviousActiveGeneration());
@@ -273,8 +300,7 @@ public class ApplicationRepositoryTest {
@Test
public void delete() {
- TenantName tenantName = applicationId().tenant();
- Tenant tenant = tenantRepository.getTenant(tenantName);
+ Tenant tenant = applicationRepository.getTenant(applicationId());
SessionRepository sessionRepository = tenant.getSessionRepository();
{
PrepareResult result = deployApp(testApp);
@@ -347,9 +373,10 @@ public class ApplicationRepositoryTest {
@Test
public void testDeletingInactiveSessions() throws IOException {
+ File serverdb = temporaryFolder.newFolder("serverdb");
ConfigserverConfig configserverConfig =
new ConfigserverConfig(new ConfigserverConfig.Builder()
- .configServerDBDir(temporaryFolder.newFolder("serverdb").getAbsolutePath())
+ .configServerDBDir(serverdb.getAbsolutePath())
.configDefinitionsDir(temporaryFolder.newFolder("configdefinitions").getAbsolutePath())
.sessionLifetime(60));
DeployTester tester = new DeployTester(configserverConfig, clock);
@@ -387,6 +414,8 @@ public class ApplicationRepositoryTest {
// There should be no expired remote sessions in the common case
assertEquals(0, tester.applicationRepository().deleteExpiredRemoteSessions(clock, Duration.ofSeconds(0)));
+ assertEquals(1, sessionRepository.getLocalSessions().size());
+
// Deploy, but do not activate
Optional<com.yahoo.config.provision.Deployment> deployment4 = tester.redeployFromLocalActive();
assertTrue(deployment4.isPresent());
@@ -396,6 +425,25 @@ public class ApplicationRepositoryTest {
sessionRepository.deleteLocalSession(localSession);
assertEquals(1, sessionRepository.getLocalSessions().size());
+ // Create a local session without any data in zookeeper (corner case seen in production occasionally)
+ // and check that expiring local sessions still work
+ int sessionId = 6;
+ Files.createDirectory(new TenantFileSystemDirs(serverdb, tenant1).getUserApplicationDir(sessionId).toPath());
+ LocalSession localSession2 = new LocalSession(tenant1,
+ sessionId,
+ FilesApplicationPackage.fromFile(testApp),
+ new SessionZooKeeperClient(curator,
+ configCurator,
+ tenant1,
+ sessionId,
+ ConfigUtils.getCanonicalHostName()));
+ sessionRepository.addLocalSession(localSession2);
+ assertEquals(2, sessionRepository.getLocalSessions().size());
+
+ // Check that trying to expire local session when there exists a local session with no zookeeper data works
+ tester.applicationRepository().deleteExpiredLocalSessions();
+ assertEquals(1, sessionRepository.getLocalSessions().size());
+
// Check that trying to expire when there are no active sessions works
tester.applicationRepository().deleteExpiredLocalSessions();
}
@@ -410,7 +458,8 @@ public class ApplicationRepositoryTest {
new MockLogRetriever(),
new ManualClock(),
new MockTesterClient(),
- actual);
+ actual,
+ new InMemoryFlagSource());
deployApp(testAppLogServerWithContainer);
Map<String, ?> context = Map.of("applicationId", "test1.testapp.default",
"tenantName", "test1",
@@ -424,7 +473,7 @@ public class ApplicationRepositoryTest {
@Test
public void deletesApplicationRoles() {
- var tenant = tenantRepository.getTenant(tenant1);
+ var tenant = applicationRepository.getTenant(applicationId());
var applicationId = applicationId(tenant1);
var prepareParams = new PrepareParams.Builder().applicationId(applicationId)
.applicationRoles(ApplicationRoles.fromString("hostRole","containerRole")).build();
@@ -447,8 +496,7 @@ public class ApplicationRepositoryTest {
public void require_that_provision_info_can_be_read() {
prepareAndActivate(testAppJdiscOnly);
- TenantName tenantName = applicationId().tenant();
- Tenant tenant = tenantRepository.getTenant(tenantName);
+ Tenant tenant = applicationRepository.getTenant(applicationId());
LocalSession session = tenant.getSessionRepository().getLocalSession(tenant.getApplicationRepo().requireActiveSessionOf(applicationId()));
List<NetworkPorts.Allocation> list = new ArrayList<>();
@@ -494,7 +542,7 @@ public class ApplicationRepositoryTest {
long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, testAppJdiscOnly);
exceptionRule.expect(IllegalStateException.class);
exceptionRule.expectMessage(containsString("tenant:test1 Session 3 is not prepared"));
- applicationRepository.activate(tenantRepository.getTenant(tenant1), sessionId, timeoutBudget, false);
+ applicationRepository.activate(applicationRepository.getTenant(applicationId()), sessionId, timeoutBudget, false);
RemoteSession activeSession = applicationRepository.getActiveSession(applicationId());
assertEquals(firstSession, activeSession.getSessionId());
@@ -508,10 +556,10 @@ public class ApplicationRepositoryTest {
long firstSession = result.sessionId();
long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, testAppJdiscOnly);
- applicationRepository.prepare(tenantRepository.getTenant(tenant1), sessionId, prepareParams(), clock.instant());
+ applicationRepository.prepare(applicationRepository.getTenant(applicationId()), sessionId, prepareParams(), clock.instant());
exceptionRule.expect(RuntimeException.class);
exceptionRule.expectMessage(containsString("Timeout exceeded when trying to activate 'test1.testapp'"));
- applicationRepository.activate(tenantRepository.getTenant(tenant1), sessionId, new TimeoutBudget(clock, Duration.ofSeconds(0)), false);
+ applicationRepository.activate(applicationRepository.getTenant(applicationId()), sessionId, new TimeoutBudget(clock, Duration.ofSeconds(0)), false);
RemoteSession activeSession = applicationRepository.getActiveSession(applicationId());
assertEquals(firstSession, activeSession.getSessionId());
@@ -533,10 +581,10 @@ public class ApplicationRepositoryTest {
PrepareResult result2 = deployApp(testAppJdiscOnly);
result2.sessionId();
- applicationRepository.prepare(tenantRepository.getTenant(tenant1), sessionId2, prepareParams(), clock.instant());
+ applicationRepository.prepare(applicationRepository.getTenant(applicationId()), sessionId2, prepareParams(), clock.instant());
exceptionRule.expect(ActivationConflictException.class);
exceptionRule.expectMessage(containsString("tenant:test1 app:testapp:default Cannot activate session 3 because the currently active session (4) has changed since session 3 was created (was 2 at creation time)"));
- applicationRepository.activate(tenantRepository.getTenant(tenant1), sessionId2, timeoutBudget, false);
+ applicationRepository.activate(applicationRepository.getTenant(applicationId()), sessionId2, timeoutBudget, false);
}
@Test
@@ -546,11 +594,11 @@ public class ApplicationRepositoryTest {
exceptionRule.expect(IllegalStateException.class);
exceptionRule.expectMessage(containsString("Session is active: 2"));
- applicationRepository.prepare(tenantRepository.getTenant(tenant1), sessionId, prepareParams(), clock.instant());
+ applicationRepository.prepare(applicationRepository.getTenant(applicationId()), sessionId, prepareParams(), clock.instant());
exceptionRule.expect(IllegalStateException.class);
exceptionRule.expectMessage(containsString("tenant:test1 app:testapp:default Session 2 is already active"));
- applicationRepository.activate(tenantRepository.getTenant(tenant1), sessionId, timeoutBudget, false);
+ applicationRepository.activate(applicationRepository.getTenant(applicationId()), sessionId, timeoutBudget, false);
}
@Test
@@ -661,7 +709,8 @@ public class ApplicationRepositoryTest {
new MockLogRetriever(),
clock,
new MockTesterClient(),
- new NullMetric());
+ new NullMetric(),
+ new InMemoryFlagSource());
}
private PrepareResult prepareAndActivate(File application) {
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 05f7aade168..cde115eec40 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
@@ -171,19 +171,21 @@ public class TenantApplicationsTest {
@Test
public void testListConfigs() throws IOException, SAXException {
+ applications = TenantApplications.create(componentRegistry, TenantName.defaultName());
assertdefaultAppNotFound();
VespaModel model = new VespaModel(FilesApplicationPackage.fromFile(new File("src/test/apps/app")));
- applications.createApplication(ApplicationId.defaultId());
- applications.createPutTransaction(ApplicationId.defaultId(), 1).commit();
+ ApplicationId applicationId = ApplicationId.defaultId();
+ applications.createApplication(applicationId);
+ applications.createPutTransaction(applicationId, 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);
+ applicationId)));
+ Set<ConfigKey<?>> configNames = applications.listConfigs(applicationId, Optional.of(vespaVersion), false);
assertTrue(configNames.contains(new ConfigKey<>("sentinel", "hosts", "cloud.config")));
configNames = applications.listConfigs(ApplicationId.defaultId(), Optional.of(vespaVersion), true);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
index a574d8f3b60..2b7c1c3a6dc 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
@@ -43,6 +43,7 @@ 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.flags.InMemoryFlagSource;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.VespaModelFactory;
@@ -133,7 +134,8 @@ public class DeployTester {
new LogRetriever(),
clock,
new MockTesterClient(),
- new NullMetric());
+ new NullMetric(),
+ new InMemoryFlagSource());
}
public Tenant tenant() {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
index dfc5649433a..deff0aba376 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
@@ -165,7 +165,7 @@ public class ZooKeeperClientTest {
Path hostsPath = app.append(ZKApplicationPackage.allocatedHostsNode);
assertTrue(zk.exists(hostsPath.getAbsolute()));
- AllocatedHosts deserialized = fromJson(zk.getBytes(hostsPath.getAbsolute()), Optional.empty());
+ AllocatedHosts deserialized = fromJson(zk.getBytes(hostsPath.getAbsolute()));
assertEquals(hosts, deserialized.getHosts());
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java
index 8bf5215a696..0db6aea312d 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java
@@ -45,13 +45,12 @@ public class ApplicationContentHandlerTest extends ContentHandlerTestBase {
private final ApplicationId appId1 = new ApplicationId.Builder().tenant(tenantName1).applicationName("foo").instanceName("quux").build();
private final ApplicationId appId2 = new ApplicationId.Builder().tenant(tenantName2).applicationName("foo").instanceName("quux").build();
- private TenantRepository tenantRepository;
private ApplicationRepository applicationRepository;
private ApplicationHandler handler;
@Before
public void setupHandler() {
- tenantRepository = new TenantRepository(componentRegistry, false);
+ TenantRepository tenantRepository = new TenantRepository(componentRegistry, false);
tenantRepository.addTenant(tenantName1);
tenantRepository.addTenant(tenantName2);
@@ -106,7 +105,7 @@ public class ApplicationContentHandlerTest extends ContentHandlerTestBase {
@Test
public void require_that_get_does_not_set_write_flag() throws IOException {
- Tenant tenant1 = tenantRepository.getTenant(tenantName1);
+ Tenant tenant1 = applicationRepository.getTenant(appId1);
LocalSession session = applicationRepository.getActiveLocalSession(tenant1, appId1);
assertContent("/test.txt", "foo\n");
assertThat(session.getStatus(), is(Session.Status.ACTIVATE));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
index 1a558f89284..9f8eb95a348 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
@@ -32,6 +32,7 @@ import com.yahoo.vespa.config.server.provision.HostProvisionerProvider;
import com.yahoo.vespa.config.server.session.PrepareParams;
import com.yahoo.vespa.config.server.tenant.Tenant;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
+import com.yahoo.vespa.flags.InMemoryFlagSource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -98,7 +99,8 @@ public class ApplicationHandlerTest {
logRetriever,
Clock.systemUTC(),
testerClient,
- metric);
+ metric,
+ new InMemoryFlagSource());
}
@After
@@ -113,7 +115,7 @@ public class ApplicationHandlerTest {
{
applicationRepository.deploy(testApp, prepareParams(applicationId));
- Tenant mytenant = tenantRepository.getTenant(applicationId.tenant());
+ Tenant mytenant = applicationRepository.getTenant(applicationId);
deleteAndAssertOKResponse(mytenant, applicationId);
}
@@ -207,7 +209,8 @@ public class ApplicationHandlerTest {
configserverConfig,
orchestrator,
testerClient,
- metric);
+ metric,
+ new InMemoryFlagSource());
ApplicationHandler mockHandler = createApplicationHandler(applicationRepository);
when(mockHttpProxy.get(any(), eq(host), eq(CLUSTERCONTROLLER_CONTAINER.serviceName),eq("clustercontroller-status/v1/clusterName1")))
.thenReturn(new StaticResponse(200, "text/html", "<html>...</html>"));
@@ -301,9 +304,10 @@ public class ApplicationHandlerTest {
}
private void deleteAndAssertOKResponseMocked(ApplicationId applicationId, boolean fullAppIdInUrl) throws IOException {
- long sessionId = tenantRepository.getTenant(applicationId.tenant()).getApplicationRepo().requireActiveSessionOf(applicationId);
+ Tenant tenant = applicationRepository.getTenant(applicationId);
+ long sessionId = tenant.getApplicationRepo().requireActiveSessionOf(applicationId);
deleteAndAssertResponse(applicationId, Zone.defaultZone(), Response.Status.OK, null, fullAppIdInUrl);
- assertNull(tenantRepository.getTenant(applicationId.tenant()).getSessionRepository().getLocalSession(sessionId));
+ assertNull(tenant.getSessionRepository().getLocalSession(sessionId));
}
private void deleteAndAssertOKResponse(Tenant tenant, ApplicationId applicationId) throws IOException {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java
index 364e7372e20..5bf5e1f2229 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java
@@ -39,7 +39,6 @@ public class HostHandlerTest {
private HostHandler handler;
private final static TenantName mytenant = TenantName.from("mytenant");
private final static Zone zone = Zone.defaultZone();
- private TenantRepository tenantRepository;
private ApplicationRepository applicationRepository;
@Before
@@ -47,7 +46,7 @@ public class HostHandlerTest {
TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder()
.zone(zone)
.build();
- tenantRepository = new TenantRepository(componentRegistry);
+ TenantRepository tenantRepository = new TenantRepository(componentRegistry);
tenantRepository.addTenant(mytenant);
applicationRepository = new ApplicationRepository(tenantRepository,
new SessionHandlerTest.MockProvisioner(),
@@ -60,7 +59,7 @@ public class HostHandlerTest {
public void require_correct_tenant_and_application_for_hostname() throws Exception {
ApplicationId applicationId = applicationId();
applicationRepository.deploy(testApp, new PrepareParams.Builder().applicationId(applicationId).build());
- Tenant tenant = tenantRepository.getTenant(mytenant);
+ Tenant tenant = applicationRepository.getTenant(applicationId);
String hostname = applicationRepository.getCurrentActiveApplicationSet(tenant, applicationId).get().getAllHosts().iterator().next();
assertApplicationForHost(hostname, applicationId);
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
index 53422df3fad..e48752afaf6 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java
@@ -58,7 +58,6 @@ public class SessionActiveHandlerTest {
private SessionHandlerTest.MockProvisioner hostProvisioner;
private TestComponentRegistry componentRegistry;
- private TenantRepository tenantRepository;
private ApplicationRepository applicationRepository;
private SessionActiveHandler handler;
@@ -73,10 +72,10 @@ public class SessionActiveHandlerTest {
.curator(new MockCurator())
.modelFactoryRegistry(new ModelFactoryRegistry(List.of((modelFactory))))
.build();
- tenantRepository = new TenantRepository(componentRegistry, false);
+ TenantRepository tenantRepository = new TenantRepository(componentRegistry, false);
+ tenantRepository.addTenant(tenantName);
applicationRepository = new ApplicationRepository(tenantRepository, hostProvisioner,
new OrchestratorMock(), componentRegistry.getClock());
- tenantRepository.addTenant(tenantName);
handler = createHandler();
}
@@ -124,7 +123,7 @@ public class SessionActiveHandlerTest {
ApplicationMetaData getMetaData() { return metaData; }
void invoke() {
- Tenant tenant = tenantRepository.getTenant(tenantName);
+ Tenant tenant = applicationRepository.getTenant(applicationId());
long sessionId = applicationRepository.createSession(applicationId(),
new TimeoutBudget(componentRegistry.getClock(), Duration.ofSeconds(10)),
testApp);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java
index 3ab56d3869a..cda62361256 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java
@@ -54,7 +54,7 @@ public class SessionContentHandlerTest extends ContentHandlerTestBase {
new OrchestratorMock(),
Clock.systemUTC());
applicationRepository.deploy(testApp, new PrepareParams.Builder().applicationId(applicationId()).build());
- Tenant tenant = tenantRepository.getTenant(tenantName);
+ Tenant tenant = applicationRepository.getTenant(applicationId());
sessionId = applicationRepository.getActiveLocalSession(tenant, applicationId()).getSessionId();
handler = createHandler();
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 cf01c9b6713..fb268492dd7 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
@@ -69,17 +69,17 @@ public class LocalSessionTest {
@Test
public void require_that_session_is_initialized() throws Exception {
- LocalSession session = createSession(TenantName.defaultName(), 2);
+ LocalSession session = createSession(applicationId(), 2);
assertThat(session.getSessionId(), is(2L));
- session = createSession(TenantName.defaultName(), Long.MAX_VALUE);
+ session = createSession(applicationId(), Long.MAX_VALUE);
assertThat(session.getSessionId(), is(Long.MAX_VALUE));
assertThat(session.getActiveSessionAtCreate(), is(0L));
}
@Test
public void require_that_marking_session_modified_changes_status_to_new() throws Exception {
- LocalSession session = createSession(TenantName.defaultName(), 3);
- doPrepare(session);
+ LocalSession session = createSession(applicationId(), 3);
+ doPrepare(session, applicationId());
assertThat(session.getStatus(), is(Session.Status.PREPARE));
session.getApplicationFile(Path.createRoot(), Session.Mode.READ);
assertThat(session.getStatus(), is(Session.Status.PREPARE));
@@ -89,7 +89,7 @@ public class LocalSessionTest {
@Test
public void require_that_application_file_can_be_fetched() throws Exception {
- LocalSession session = createSession(TenantName.defaultName(), 3);
+ LocalSession session = createSession(applicationId(), 3);
ApplicationFile f1 = session.getApplicationFile(Path.fromString("services.xml"), Session.Mode.READ);
ApplicationFile f2 = session.getApplicationFile(Path.fromString("services2.xml"), Session.Mode.READ);
assertTrue(f1.exists());
@@ -98,36 +98,37 @@ public class LocalSessionTest {
@Test(expected = IllegalStateException.class)
public void require_that_no_provision_info_throws_exception() throws Exception {
- createSession(TenantName.defaultName(), 3).getAllocatedHosts();
+ createSession(applicationId(), 3).getAllocatedHosts();
}
- private LocalSession createSession(TenantName tenant, long sessionId) throws Exception {
- return createSession(tenant, sessionId, Optional.empty());
+ private LocalSession createSession(ApplicationId applicationId, long sessionId) throws Exception {
+ return createSession(applicationId, sessionId, Optional.empty());
}
- private LocalSession createSession(TenantName tenant, long sessionId,
+ private LocalSession createSession(ApplicationId applicationId, long sessionId,
Optional<AllocatedHosts> allocatedHosts) throws Exception {
- SessionZooKeeperClient zkc = new MockSessionZKClient(curator, tenant, sessionId, allocatedHosts);
+ TenantName tenantName = applicationId.tenant();
+ SessionZooKeeperClient zkc = new MockSessionZKClient(curator, tenantName, sessionId, allocatedHosts);
zkc.createWriteStatusTransaction(Session.Status.NEW).commit();
ZooKeeperClient zkClient = new ZooKeeperClient(configCurator, new BaseDeployLogger(),
- TenantRepository.getSessionsPath(tenant).append(String.valueOf(sessionId)));
+ TenantRepository.getSessionsPath(tenantName).append(String.valueOf(sessionId)));
if (allocatedHosts.isPresent()) {
zkClient.write(allocatedHosts.get());
}
zkClient.write(Collections.singletonMap(new Version(0, 0, 0), new MockFileRegistry()));
TenantApplications applications = tenantRepository.getTenant(tenantName).getApplicationRepo();
- applications.createApplication(applicationId());
- LocalSession session = new LocalSession(tenant, sessionId, FilesApplicationPackage.fromFile(testApp), zkc);
- session.setApplicationId(applicationId());
+ applications.createApplication(applicationId);
+ LocalSession session = new LocalSession(tenantName, sessionId, FilesApplicationPackage.fromFile(testApp), zkc);
+ session.setApplicationId(applicationId);
return session;
}
- private void doPrepare(LocalSession session) {
- doPrepare(session, new PrepareParams.Builder().applicationId(applicationId()).build());
+ private void doPrepare(LocalSession session, ApplicationId applicationId) {
+ doPrepare(session, new PrepareParams.Builder().applicationId(applicationId).build());
}
private void doPrepare(LocalSession session, PrepareParams params) {
- SessionRepository sessionRepository = tenantRepository.getTenant(tenantName).getSessionRepository();
+ SessionRepository sessionRepository = tenantRepository.getTenant(params.getApplicationId().tenant()).getSessionRepository();
sessionRepository.prepareLocalSession(session, getLogger(), params, Optional.empty(), tenantPath, Instant.now());
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java
index 692510b8b6d..0451ef84e09 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/MockSessionZKClient.java
@@ -6,6 +6,8 @@ import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.TenantName;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
+import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
+import com.yahoo.vespa.config.util.ConfigUtils;
import com.yahoo.vespa.curator.Curator;
import java.util.Optional;
@@ -30,7 +32,11 @@ public class MockSessionZKClient extends SessionZooKeeperClient {
}
MockSessionZKClient(Curator curator, TenantName tenantName, long sessionId, ApplicationPackage application) {
- super(curator, TenantRepository.getSessionsPath(tenantName).append(String.valueOf(sessionId)));
+ super(curator,
+ ConfigCurator.create(curator),
+ tenantName,
+ sessionId,
+ ConfigUtils.getCanonicalHostName());
this.app = application;
curator.create(TenantRepository.getSessionsPath(tenantName).append(String.valueOf(sessionId)));
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
index e53f9270983..b181ad3e8d6 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
@@ -42,13 +42,16 @@ import com.yahoo.vespa.config.server.provision.HostProvisionerProvider;
import com.yahoo.vespa.config.server.tenant.ContainerEndpointsCache;
import com.yahoo.vespa.config.server.tenant.EndpointCertificateMetadataStore;
import com.yahoo.vespa.config.server.tenant.EndpointCertificateRetriever;
+import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
+import com.yahoo.vespa.config.util.ConfigUtils;
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.flags.InMemoryFlagSource;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import javax.security.auth.x500.X500Principal;
@@ -80,7 +83,6 @@ import static org.junit.Assert.assertTrue;
public class SessionPreparerTest {
private static final Path tenantPath = Path.createRoot();
- private static final Path sessionsPath = tenantPath.append("sessions").append("testapp");
private static final File testApp = new File("src/test/apps/app");
private static final File invalidTestApp = new File("src/test/apps/illegalApp");
private static final Version version123 = new Version(1, 2, 3);
@@ -98,6 +100,9 @@ public class SessionPreparerTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
@Before
public void setUp() throws IOException {
curator = new MockCurator();
@@ -145,25 +150,44 @@ public class SessionPreparerTest {
@Test
public void require_that_application_validation_exception_is_ignored_if_forced() throws IOException {
- prepare(invalidTestApp, new PrepareParams.Builder().applicationId(applicationId()).ignoreValidationErrors(true).timeoutBudget(TimeoutBudgetTest.day()).build());
+ prepare(invalidTestApp,
+ new PrepareParams.Builder()
+ .applicationId(applicationId())
+ .ignoreValidationErrors(true)
+ .timeoutBudget(TimeoutBudgetTest.day())
+ .build(),
+ 1);
}
@Test
public void require_that_zookeeper_is_not_written_to_if_dryrun() throws IOException {
- prepare(testApp, new PrepareParams.Builder().applicationId(applicationId()).dryRun(true).timeoutBudget(TimeoutBudgetTest.day()).build());
- assertFalse(configCurator.exists(sessionsPath.append(ConfigCurator.USERAPP_ZK_SUBPATH).append("services.xml").getAbsolute()));
+ long sessionId = 1;
+ prepare(testApp,
+ new PrepareParams.Builder()
+ .applicationId(applicationId())
+ .dryRun(true)
+ .timeoutBudget(TimeoutBudgetTest.day())
+ .build(),
+ 1);
+ Path sessionPath = sessionPath(sessionId);
+ assertFalse(configCurator.exists(sessionPath.append(ConfigCurator.USERAPP_ZK_SUBPATH).append("services.xml").getAbsolute()));
}
@Test
public void require_that_filedistribution_is_ignored_on_dryrun() throws IOException {
- PrepareResult result = prepare(testApp, new PrepareParams.Builder().applicationId(applicationId()).dryRun(true).build());
+ PrepareResult result = prepare(testApp,
+ new PrepareParams.Builder()
+ .applicationId(applicationId())
+ .dryRun(true)
+ .build(),
+ 1);
assertTrue(result.getFileRegistries().get(version321).export().isEmpty());
}
@Test
public void require_that_application_is_prepared() throws Exception {
prepare(testApp);
- assertTrue(configCurator.exists(sessionsPath.append(ConfigCurator.USERAPP_ZK_SUBPATH).append("services.xml").getAbsolute()));
+ assertTrue(configCurator.exists(sessionPath(1).append(ConfigCurator.USERAPP_ZK_SUBPATH).append("services.xml").getAbsolute()));
}
@Test(expected = InvalidApplicationException.class)
@@ -172,7 +196,7 @@ public class SessionPreparerTest {
HostRegistry<ApplicationId> hostValidator = new HostRegistry<>();
hostValidator.update(applicationId("foo"), Collections.singletonList("mytesthost"));
preparer.prepare(hostValidator, new BaseDeployLogger(), new PrepareParams.Builder().applicationId(applicationId("default")).build(),
- Optional.empty(), tenantPath, Instant.now(), app.getAppDir(), app, new SessionZooKeeperClient(curator, sessionsPath));
+ Optional.empty(), tenantPath, Instant.now(), app.getAppDir(), app, createSessionZooKeeperClient());
}
@Test
@@ -187,28 +211,37 @@ public class SessionPreparerTest {
hostValidator.update(applicationId, Collections.singletonList("mytesthost"));
preparer.prepare(hostValidator, logger, new PrepareParams.Builder().applicationId(applicationId).build(),
Optional.empty(), tenantPath, Instant.now(), app.getAppDir(), app,
- new SessionZooKeeperClient(curator, sessionsPath));
+ createSessionZooKeeperClient());
assertEquals(logged.toString(), "");
}
@Test
public void require_that_application_id_is_written_in_prepare() throws IOException {
+ PrepareParams params = new PrepareParams.Builder().applicationId(applicationId()).build();
+ int sessionId = 1;
+ prepare(testApp, params);
+ assertThat(createSessionZooKeeperClient(sessionId).readApplicationId().get(), is(applicationId()));
+ }
+
+ @Test
+ public void require_that_writing_wrong_application_id_fails() throws IOException {
TenantName tenant = TenantName.from("tenant");
ApplicationId origId = new ApplicationId.Builder()
- .tenant(tenant)
- .applicationName("foo").instanceName("quux").build();
+ .tenant(tenant)
+ .applicationName("foo")
+ .instanceName("quux")
+ .build();
PrepareParams params = new PrepareParams.Builder().applicationId(origId).build();
+ expectedException.expect(RuntimeException.class);
+ expectedException.expectMessage("Error preparing session");
prepare(testApp, params);
- SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, sessionsPath);
- assertTrue(configCurator.exists(sessionsPath.append(SessionZooKeeperClient.APPLICATION_ID_PATH).getAbsolute()));
- assertThat(zkc.readApplicationId(), is(origId));
}
@Test
public void require_that_file_reference_of_application_package_is_written_to_zk() throws Exception {
flagSource.withBooleanFlag(Flags.CONFIGSERVER_DISTRIBUTE_APPLICATION_PACKAGE.id(), true);
prepare(testApp);
- assertTrue(configCurator.exists(sessionsPath.append(APPLICATION_PACKAGE_REFERENCE_PATH).getAbsolute()));
+ assertTrue(configCurator.exists(sessionPath(1).append(APPLICATION_PACKAGE_REFERENCE_PATH).getAbsolute()));
}
@Test
@@ -333,10 +366,14 @@ public class SessionPreparerTest {
}
private PrepareResult prepare(File app, PrepareParams params) throws IOException {
+ return prepare(app, params, 1);
+ }
+
+ private PrepareResult prepare(File app, PrepareParams params, long sessionId) throws IOException {
FilesApplicationPackage applicationPackage = getApplicationPackage(app);
return preparer.prepare(new HostRegistry<>(), getLogger(), params,
Optional.empty(), tenantPath, Instant.now(), applicationPackage.getAppDir(),
- applicationPackage, new SessionZooKeeperClient(curator, sessionsPath));
+ applicationPackage, createSessionZooKeeperClient(sessionId));
}
private FilesApplicationPackage getApplicationPackage(File testFile) throws IOException {
@@ -360,6 +397,18 @@ public class SessionPreparerTest {
ApplicationName.from(applicationName), InstanceName.defaultName());
}
+ private SessionZooKeeperClient createSessionZooKeeperClient() {
+ return createSessionZooKeeperClient(1);
+ }
+
+ private SessionZooKeeperClient createSessionZooKeeperClient(long sessionId) {
+ return new SessionZooKeeperClient(curator, configCurator, applicationId().tenant(), sessionId, ConfigUtils.getCanonicalHostName());
+ }
+
+ private Path sessionPath(long sessionId) {
+ return TenantRepository.getSessionsPath(applicationId().tenant()).append(String.valueOf(sessionId));
+ }
+
private static class FailWithTransientExceptionProvisioner implements Provisioner {
@Override
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionRepositoryTest.java
index 13a27e570c2..fb7b5280b1e 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionRepositoryTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionRepositoryTest.java
@@ -11,6 +11,8 @@ import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.application.OrchestratorMock;
import com.yahoo.vespa.config.server.http.SessionHandlerTest;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
+import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
+import com.yahoo.vespa.config.util.ConfigUtils;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.flags.FlagSource;
@@ -149,11 +151,11 @@ public class SessionRepositoryTest {
}
private void createSession(long sessionId, boolean wait) {
- createSession(sessionId, wait, sessionRepository);
- }
-
- private void createSession(long sessionId, boolean wait, SessionRepository sessionRepository) {
- SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, sessionRepository.getSessionPath(sessionId));
+ SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator,
+ ConfigCurator.create(curator),
+ tenantName,
+ sessionId,
+ ConfigUtils.getCanonicalHostName());
zkc.createNewSession(Instant.now());
if (wait) {
Curator.CompletionWaiter waiter = zkc.getUploadWaiter();
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java
index 1d7df7acfd0..de55a6677ff 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java
@@ -3,13 +3,18 @@ package com.yahoo.vespa.config.server.session;
import com.yahoo.config.FileReference;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.TenantName;
import com.yahoo.path.Path;
import com.yahoo.text.Utf8;
+import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
+import com.yahoo.vespa.config.util.ConfigUtils;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import java.time.Instant;
@@ -22,18 +27,24 @@ import static org.junit.Assert.assertTrue;
*/
public class SessionZooKeeperClientTest {
+ private static final TenantName tenantName = TenantName.defaultName();
+
private Curator curator;
private ConfigCurator configCurator;
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
@Before
public void setup() {
curator = new MockCurator();
configCurator = ConfigCurator.create(curator);
+ curator.create(sessionsPath());
}
@Test
public void require_that_status_can_be_updated() {
- SessionZooKeeperClient zkc = createSessionZKClient("1");
+ SessionZooKeeperClient zkc = createSessionZKClient(1);
zkc.writeStatus(Session.Status.NEW);
assertThat(zkc.readStatus(), is(Session.Status.NEW));
@@ -49,45 +60,68 @@ public class SessionZooKeeperClientTest {
@Test
public void require_that_status_is_written_to_zk() {
- SessionZooKeeperClient zkc = createSessionZKClient("2");
+ int sessionId = 2;
+ SessionZooKeeperClient zkc = createSessionZKClient(sessionId);
zkc.writeStatus(Session.Status.NEW);
- String path = "/2" + ConfigCurator.SESSIONSTATE_ZK_SUBPATH;
+ String path = sessionPath(sessionId).append(ConfigCurator.SESSIONSTATE_ZK_SUBPATH).getAbsolute();
assertTrue(configCurator.exists(path));
assertThat(configCurator.getData(path), is("NEW"));
}
@Test
public void require_that_status_is_read_from_zk() {
- SessionZooKeeperClient zkc = createSessionZKClient("3");
- curator.set(Path.fromString("3").append(ConfigCurator.SESSIONSTATE_ZK_SUBPATH), Utf8.toBytes("PREPARE"));
+ int sessionId = 3;
+ SessionZooKeeperClient zkc = createSessionZKClient(sessionId);
+ curator.set(sessionPath(sessionId).append(ConfigCurator.SESSIONSTATE_ZK_SUBPATH), Utf8.toBytes("PREPARE"));
assertThat(zkc.readStatus(), is(Session.Status.PREPARE));
}
@Test
public void require_that_application_id_is_written_to_zk() {
ApplicationId id = new ApplicationId.Builder()
- .tenant("tenant")
- .applicationName("foo").instanceName("bim").build();
- SessionZooKeeperClient zkc = createSessionZKClient("3");
+ .tenant(tenantName)
+ .applicationName("foo")
+ .instanceName("bim")
+ .build();
+ int sessionId = 3;
+ SessionZooKeeperClient zkc = createSessionZKClient(sessionId);
zkc.writeApplicationId(id);
- String path = "/3/" + SessionZooKeeperClient.APPLICATION_ID_PATH;
+ String path = sessionPath(sessionId).append(SessionZooKeeperClient.APPLICATION_ID_PATH).getAbsolute();
assertTrue(configCurator.exists(path));
- assertThat(configCurator.getData(path), is("tenant:foo:bim"));
+ assertThat(configCurator.getData(path), is(id.serializedForm()));
+ }
+
+ @Test
+ public void require_that_wrong_application_gives_exception() {
+ ApplicationId id = new ApplicationId.Builder()
+ .tenant("someOtherTenant")
+ .applicationName("foo")
+ .instanceName("bim")
+ .build();
+ int sessionId = 3;
+ SessionZooKeeperClient zkc = createSessionZKClient(sessionId);
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Cannot write application id 'someOtherTenant.foo.bim' for tenant 'default'");
+ zkc.writeApplicationId(id);
}
@Test
public void require_that_application_id_is_read_from_zk() {
ApplicationId id = new ApplicationId.Builder()
- .tenant("tenant")
- .applicationName("bar").instanceName("quux").build();
+ .tenant("tenant")
+ .applicationName("bar")
+ .instanceName("quux")
+ .build();
String idNoVersion = id.serializedForm();
- assertApplicationIdParse("3", idNoVersion, idNoVersion);
+ assertApplicationIdParse(3, idNoVersion, idNoVersion);
}
@Test
public void require_that_create_time_can_be_written_and_read() {
- SessionZooKeeperClient zkc = createSessionZKClient("3");
- curator.delete(Path.fromString("3"));
+ int sessionId = 3;
+ SessionZooKeeperClient zkc = createSessionZKClient(sessionId);
+ curator.delete(sessionPath(sessionId));
assertThat(zkc.readCreateTime(), is(Instant.EPOCH));
Instant now = Instant.now();
zkc.createNewSession(now);
@@ -98,23 +132,35 @@ public class SessionZooKeeperClientTest {
@Test
public void require_that_application_package_file_reference_can_be_written_and_read() {
final FileReference testRef = new FileReference("test-ref");
- SessionZooKeeperClient zkc = createSessionZKClient("3");
+ SessionZooKeeperClient zkc = createSessionZKClient(3);
zkc.writeApplicationPackageReference(testRef);
assertThat(zkc.readApplicationPackageReference(), is(testRef));
}
- private void assertApplicationIdParse(String sessionId, String idString, String expectedIdString) {
+ private void assertApplicationIdParse(long sessionId, String idString, String expectedIdString) {
SessionZooKeeperClient zkc = createSessionZKClient(sessionId);
- String path = "/" + sessionId + "/" + SessionZooKeeperClient.APPLICATION_ID_PATH;
+ String path = sessionPath(sessionId).append(SessionZooKeeperClient.APPLICATION_ID_PATH).getAbsolute();
configCurator.putData(path, idString);
- ApplicationId zkId = zkc.readApplicationId();
- assertThat(zkId.serializedForm(), is(expectedIdString));
+ ApplicationId applicationId = zkc.readApplicationId().get();
+ assertThat(applicationId.serializedForm(), is(expectedIdString));
}
- private SessionZooKeeperClient createSessionZKClient(String sessionId) {
- SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, Path.fromString(sessionId));
+ private SessionZooKeeperClient createSessionZKClient(long sessionId) {
+ SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator,
+ ConfigCurator.create(curator),
+ tenantName,
+ sessionId,
+ ConfigUtils.getCanonicalHostName());
zkc.createNewSession(Instant.now());
return zkc;
}
+ private static Path sessionsPath() {
+ return TenantRepository.getSessionsPath(tenantName);
+ }
+
+ private static Path sessionPath(long sessionId) {
+ return sessionsPath().append(String.valueOf(sessionId));
+ }
+
}
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 f372b21b065..a31b06bbebb 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
@@ -5,7 +5,9 @@ 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.ApplicationName;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
@@ -84,8 +86,9 @@ public class TenantRepositoryTest {
@Test
public void testListenersAdded() throws IOException, SAXException {
TenantApplications applicationRepo = tenantRepository.getTenant(tenant1).getApplicationRepo();
- applicationRepo.createApplication(ApplicationId.defaultId());
- applicationRepo.createPutTransaction(ApplicationId.defaultId(), 4).commit();
+ ApplicationId id = ApplicationId.from(tenant1, ApplicationName.defaultName(), InstanceName.defaultName());
+ applicationRepo.createApplication(id);
+ applicationRepo.createPutTransaction(id, 4).commit();
applicationRepo.reloadConfig(ApplicationSet.fromSingle(
new Application(new VespaModel(MockApplicationPackage.createEmpty()),
new ServerCache(),
@@ -93,7 +96,7 @@ public class TenantRepositoryTest {
false,
new Version(1, 2, 3),
MetricUpdater.createTestUpdater(),
- ApplicationId.defaultId())));
+ id)));
assertEquals(1, listener.reloaded.get());
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
index 4b4605cce7d..32d5d84f323 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
@@ -48,7 +48,7 @@ public class ZKApplicationPackageTest {
Collections.singleton(new HostSpec("foo.yahoo.com",
TEST_FLAVOR.get().resources(),
TEST_FLAVOR.get().resources(),
- NodeResources.unspecified(),
+ TEST_FLAVOR.get().resources(),
ClusterMembership.from("container/test/0/0", Version.fromString("6.73.1"),
Optional.of(DockerImage.fromString("docker.foo.com:4443/vespa/bar"))),
Optional.of(Version.fromString("6.0.1")), Optional.empty(),
@@ -67,7 +67,7 @@ public class ZKApplicationPackageTest {
@Test
public void testBasicZKFeed() throws IOException {
feed(configCurator, new File(APP));
- ZKApplicationPackage zkApp = new ZKApplicationPackage(configCurator, Path.fromString("/0"), Optional.of(new MockNodeFlavors()));
+ ZKApplicationPackage zkApp = new ZKApplicationPackage(configCurator, Path.fromString("/0"));
assertTrue(Pattern.compile(".*<slobroks>.*",Pattern.MULTILINE+Pattern.DOTALL).matcher(IOUtils.readAll(zkApp.getServices())).matches());
assertTrue(Pattern.compile(".*<alias>.*",Pattern.MULTILINE+Pattern.DOTALL).matcher(IOUtils.readAll(zkApp.getHosts())).matches());
assertTrue(Pattern.compile(".*<slobroks>.*",Pattern.MULTILINE+Pattern.DOTALL).matcher(IOUtils.readAll(zkApp.getFile(Path.fromString("services.xml")).createReader())).matches());