diff options
author | Harald Musum <musum@verizonmedia.com> | 2020-06-02 20:26:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-02 20:26:08 +0200 |
commit | 8931d080cd774c51edcb69002f3d0457407cdf01 (patch) | |
tree | 11fd26803768c4300176a4b1c4f97486cdbd9388 /configserver | |
parent | 1b786c3929724340713aeb7dd09cb061232fe3dc (diff) |
Revert "Config server refactoring, part 4"
Diffstat (limited to 'configserver')
22 files changed, 522 insertions, 247 deletions
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 d90a79795cf..b7555ee3bfb 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 @@ -185,7 +185,7 @@ public class Deployment implements com.yahoo.config.provision.Deployment { } } - private static Transaction deactivateCurrentActivateNew(Session active, LocalSession prepared, boolean ignoreStaleSessionFailure) { + private static Transaction deactivateCurrentActivateNew(RemoteSession active, LocalSession prepared, boolean ignoreStaleSessionFailure) { Transaction transaction = prepared.createActivateTransaction(); if (isValidSession(active)) { checkIfActiveHasChanged(prepared, active, ignoreStaleSessionFailure); @@ -195,11 +195,11 @@ public class Deployment implements com.yahoo.config.provision.Deployment { return transaction; } - private static boolean isValidSession(Session session) { + private static boolean isValidSession(RemoteSession session) { return session != null; } - private static void checkIfActiveHasChanged(LocalSession session, Session currentActiveSession, boolean ignoreStaleSessionFailure) { + private static void checkIfActiveHasChanged(LocalSession session, RemoteSession currentActiveSession, boolean ignoreStaleSessionFailure) { long activeSessionAtCreate = session.getActiveSessionAtCreate(); log.log(Level.FINE, currentActiveSession.logPre() + "active session id at create time=" + activeSessionAtCreate); if (activeSessionAtCreate == 0) return; // No active session at create diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java index 831f4ba3679..e61c884cbf6 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java @@ -24,7 +24,6 @@ import com.yahoo.vespa.curator.Curator; import java.io.File; import java.time.Instant; import java.util.Optional; -import java.util.logging.Level; /** * A LocalSession is a session that has been created locally on this configserver. A local session can be edited and @@ -68,7 +67,6 @@ public class LocalSession extends Session implements Comparable<LocalSession> { Path tenantPath, Instant now) { applicationRepo.createApplication(params.getApplicationId()); // TODO jvenstad: This is wrong, but it has to be done now, since preparation can change the application ID of a session :( - logger.log(Level.FINE, "Created application " + params.getApplicationId()); Curator.CompletionWaiter waiter = zooKeeperClient.createPrepareWaiter(); ConfigChangeActions actions = sessionPreparer.prepare(hostValidator, logger, params, currentActiveApplicationSet, tenantPath, now, 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 d0082d34114..a1d767b0d1c 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 @@ -140,8 +140,22 @@ public class RemoteSession extends Session { return zooKeeperClient.getAllocatedHosts(); } + // Note: Assumes monotonically increasing session ids + public boolean isNewerThan(long sessionId) { + return getSessionId() > sessionId; + } + + public Transaction createDeactivateTransaction() { + return createSetStatusTransaction(Status.DEACTIVATE); + } + + private Transaction createSetStatusTransaction(Status status) { + return zooKeeperClient.createWriteStatusTransaction(status); + } + public ApplicationMetaData getMetaData() { return zooKeeperClient.loadApplicationPackage().getMetaData(); } + } 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 7803bd05e0a..a57bfeda12e 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 @@ -8,7 +8,6 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.AthenzDomain; import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.TenantName; -import com.yahoo.transaction.Transaction; import com.yahoo.vespa.config.server.tenant.TenantRepository; import java.time.Instant; @@ -117,15 +116,4 @@ public abstract class Session { return zooKeeperClient.getAllocatedHosts(); } - public Transaction createDeactivateTransaction() { - return createSetStatusTransaction(Status.DEACTIVATE); - } - - private Transaction createSetStatusTransaction(Status status) { - return zooKeeperClient.createWriteStatusTransaction(status); - } - - // Note: Assumes monotonically increasing session ids - public boolean isNewerThan(long sessionId) { return getSessionId() > sessionId; } - } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java index f0aab8b2312..bbd3ae55f10 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java @@ -38,6 +38,7 @@ public class Tenant implements TenantHandlerProvider { private final Curator curator; Tenant(TenantName name, + Path path, SessionFactory sessionFactory, LocalSessionRepo localSessionRepo, RemoteSessionRepo remoteSessionRepo, @@ -46,7 +47,7 @@ public class Tenant implements TenantHandlerProvider { TenantApplications applicationRepo, Curator curator) { this.name = name; - this.path = TenantRepository.getTenantPath(name); + this.path = path; this.requestHandler = requestHandler; this.reloadHandler = reloadHandler; this.remoteSessionRepo = remoteSessionRepo; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java new file mode 100644 index 00000000000..108892803c1 --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantBuilder.java @@ -0,0 +1,141 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.tenant; + +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory; +import com.yahoo.vespa.config.server.GlobalComponentRegistry; +import com.yahoo.vespa.config.server.host.HostValidator; +import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.application.TenantApplications; +import com.yahoo.vespa.config.server.session.*; + +import java.util.Collections; + +/** + * Builder for helping out with tenant creation. Each of a tenants dependencies may be overridden for testing. + * + * @author Ulf Lilleengen + */ +public class TenantBuilder { + + private final GlobalComponentRegistry componentRegistry; + private final TenantName tenant; + private RemoteSessionRepo remoteSessionRepo; + private LocalSessionRepo localSessionRepo; + private SessionFactory sessionFactory; + private LocalSessionLoader localSessionLoader; + private TenantApplications applicationRepo; + private TenantRequestHandler reloadHandler; + private RequestHandler requestHandler; + private RemoteSessionFactory remoteSessionFactory; + private HostValidator<ApplicationId> hostValidator; + + private TenantBuilder(GlobalComponentRegistry componentRegistry, TenantName tenant) { + this.componentRegistry = componentRegistry; + this.tenant = tenant; + } + + public static TenantBuilder create(GlobalComponentRegistry componentRegistry, TenantName tenant) { + return new TenantBuilder(componentRegistry, tenant); + } + + public TenantBuilder withSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + return this; + } + + public TenantBuilder withLocalSessionRepo(LocalSessionRepo localSessionRepo) { + this.localSessionRepo = localSessionRepo; + return this; + } + + public TenantBuilder withApplicationRepo(TenantApplications applicationRepo) { + this.applicationRepo = applicationRepo; + return this; + } + + public TenantBuilder withRequestHandler(RequestHandler requestHandler) { + this.requestHandler = requestHandler; + return this; + } + + /** + * Create a real tenant from the properties given by this builder. + * + * @return a new {@link Tenant} instance. + */ + public Tenant build() { + createTenantRequestHandler(); + createApplicationRepo(); + createRemoteSessionFactory(); + createRemoteSessionRepo(); + createSessionFactory(); + createLocalSessionRepo(); + return new Tenant(tenant, + TenantRepository.getTenantPath(tenant), + sessionFactory, + localSessionRepo, + remoteSessionRepo, + requestHandler, + reloadHandler, + applicationRepo, + componentRegistry.getCurator()); + } + + private void createLocalSessionRepo() { + if (localSessionRepo == null) { + localSessionRepo = new LocalSessionRepo(tenant, componentRegistry, localSessionLoader); + } + } + + private void createSessionFactory() { + if (sessionFactory == null || localSessionLoader == null) { + SessionFactoryImpl impl = new SessionFactoryImpl(componentRegistry, applicationRepo, hostValidator, tenant); + if (sessionFactory == null) { + sessionFactory = impl; + } + if (localSessionLoader == null) { + localSessionLoader = impl; + } + } + } + + private void createApplicationRepo() { + if (applicationRepo == null) { + applicationRepo = reloadHandler.applications(); + } + } + + private void createTenantRequestHandler() { + if (requestHandler == null || reloadHandler == null) { + TenantRequestHandler impl = new TenantRequestHandler(componentRegistry.getMetrics(), + tenant, + Collections.singletonList(componentRegistry.getReloadListener()), + ConfigResponseFactory.create(componentRegistry.getConfigserverConfig()), + componentRegistry); + this.hostValidator = impl; + if (requestHandler == null) { + requestHandler = impl; + } + reloadHandler = impl; + } + } + + private void createRemoteSessionFactory() { + if (remoteSessionFactory == null) { + remoteSessionFactory = new RemoteSessionFactory(componentRegistry, tenant); + } + } + + private void createRemoteSessionRepo() { + remoteSessionRepo = new RemoteSessionRepo(componentRegistry, + remoteSessionFactory, + reloadHandler, + tenant, + applicationRepo); + + } + + public TenantName getTenantName() { return tenant; } +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java index 3c4ed16d669..0ae5ca86215 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java @@ -7,19 +7,10 @@ import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.concurrent.StripedExecutor; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; +import java.util.logging.Level; import com.yahoo.path.Path; import com.yahoo.vespa.config.server.GlobalComponentRegistry; -import com.yahoo.vespa.config.server.ReloadHandler; -import com.yahoo.vespa.config.server.RequestHandler; -import com.yahoo.vespa.config.server.application.TenantApplications; -import com.yahoo.vespa.config.server.host.HostValidator; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; -import com.yahoo.vespa.config.server.rpc.ConfigResponseFactory; -import com.yahoo.vespa.config.server.session.LocalSessionRepo; -import com.yahoo.vespa.config.server.session.RemoteSessionFactory; -import com.yahoo.vespa.config.server.session.RemoteSessionRepo; -import com.yahoo.vespa.config.server.session.SessionFactory; -import com.yahoo.vespa.config.server.session.SessionFactoryImpl; import com.yahoo.vespa.curator.Curator; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; @@ -44,7 +35,6 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -147,13 +137,12 @@ public class TenantRepository { } public synchronized void addTenant(TenantName tenantName) { - addTenant(tenantName, null, null); + addTenant(TenantBuilder.create(globalComponentRegistry, tenantName)); } - public synchronized void addTenant(TenantName tenantName, RequestHandler requestHandler, - ReloadHandler reloadHandler) { - writeTenantPath(tenantName); - createTenant(tenantName, requestHandler, reloadHandler); + public synchronized void addTenant(TenantBuilder builder) { + writeTenantPath(builder.getTenantName()); + createTenant(builder); } private static Set<TenantName> readTenantsFromZooKeeper(Curator curator) { @@ -204,41 +193,17 @@ public class TenantRepository { } } - protected void createTenant(TenantName tenantName) { - createTenant(tenantName, null, null); + private void createTenant(TenantName tenantName) { + createTenant(TenantBuilder.create(globalComponentRegistry, tenantName)); } // Creates tenant and all its dependencies. This also includes loading active applications - private void createTenant(TenantName tenantName, RequestHandler requestHandler, ReloadHandler reloadHandler) { + protected void createTenant(TenantBuilder builder) { + TenantName tenantName = builder.getTenantName(); if (tenants.containsKey(tenantName)) return; - TenantRequestHandler tenantRequestHandler = null; - if (requestHandler == null) { - tenantRequestHandler = new TenantRequestHandler(globalComponentRegistry.getMetrics(), - tenantName, - List.of(globalComponentRegistry.getReloadListener()), - ConfigResponseFactory.create(globalComponentRegistry.getConfigserverConfig()), - globalComponentRegistry); - requestHandler = tenantRequestHandler; - } - - if (reloadHandler == null && tenantRequestHandler != null) - reloadHandler = tenantRequestHandler; - - HostValidator<ApplicationId> hostValidator = tenantRequestHandler; - TenantApplications applicationRepo = TenantApplications.create(globalComponentRegistry, - reloadHandler, - tenantName); - SessionFactory sessionFactory = new SessionFactoryImpl(globalComponentRegistry, applicationRepo, hostValidator, tenantName); - LocalSessionRepo localSessionRepo = new LocalSessionRepo(tenantName, globalComponentRegistry); - RemoteSessionRepo remoteSessionRepo = new RemoteSessionRepo(globalComponentRegistry, - new RemoteSessionFactory(globalComponentRegistry, tenantName), - reloadHandler, - tenantName, - applicationRepo); log.log(Level.INFO, "Creating tenant '" + tenantName + "'"); - Tenant tenant = new Tenant(tenantName, sessionFactory, localSessionRepo, remoteSessionRepo, requestHandler, - reloadHandler, applicationRepo, globalComponentRegistry.getCurator()); + Tenant tenant = builder.build(); notifyNewTenant(tenant); tenants.putIfAbsent(tenantName, tenant); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java index d44be294713..5771303ec4c 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 @@ -36,6 +36,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 org.hamcrest.core.Is; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -506,15 +507,11 @@ public class ApplicationRepositoryTest { } @Test - public void testPrepareAndActivateAlreadyActivatedSession() { + public void testAlreadyActivatedSession() { PrepareResult result = deployApp(testAppJdiscOnly); long sessionId = result.sessionId(); exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage(containsString("Session is active: 2")); - applicationRepository.prepare(tenantRepository.getTenant(tenant1), 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); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java index b939f1ab4c5..bc7e132e0a9 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.config.server.http; import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; +import com.yahoo.config.model.application.provider.FilesApplicationPackage; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; @@ -15,9 +16,11 @@ import com.yahoo.config.provision.Provisioner; import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.io.IOUtils; import com.yahoo.path.Path; import com.yahoo.transaction.NestedTransaction; import com.yahoo.transaction.Transaction; +import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.host.HostRegistry; @@ -26,16 +29,22 @@ import com.yahoo.vespa.config.server.session.LocalSession; import com.yahoo.vespa.config.server.session.MockSessionZKClient; import com.yahoo.vespa.config.server.session.PrepareParams; import com.yahoo.vespa.config.server.session.Session; +import com.yahoo.vespa.config.server.session.SessionFactory; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.time.Instant; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.logging.Level; + +import static com.yahoo.yolean.Exceptions.uncheck; /** * Base class for session handler tests @@ -88,6 +97,7 @@ public class SessionHandlerTest { public static class MockSession extends LocalSession { + public boolean doVerboseLogging = false; public Session.Status status; private ConfigChangeActions actions = new ConfigChangeActions(); private Instant createTime = Instant.now(); @@ -98,6 +108,11 @@ public class SessionHandlerTest { super(TenantName.defaultName(), sessionId, null, app, new MockSessionZKClient(app), null, null, new HostRegistry<>()); } + public MockSession(long sessionId, ApplicationPackage applicationPackage, ConfigChangeActions actions) { + this(sessionId, applicationPackage); + this.actions = actions; + } + public MockSession(long sessionId, ApplicationPackage app, ApplicationId applicationId) { this(sessionId, app); this.applicationId = applicationId; @@ -107,6 +122,9 @@ public class SessionHandlerTest { public ConfigChangeActions prepare(DeployLogger logger, PrepareParams params, Optional<ApplicationSet> application, Path tenantPath, Instant now) { status = Session.Status.PREPARE; this.dockerImageRepository = params.dockerImageRepository(); + if (doVerboseLogging) { + logger.log(Level.FINE, "debuglog"); + } return actions; } @@ -164,6 +182,38 @@ public class SessionHandlerTest { } } + public static class MockSessionFactory implements SessionFactory { + public boolean createCalled = false; + public boolean createFromCalled = false; + public boolean doThrow = false; + public File applicationPackage; + + @Override + public LocalSession createSession(File applicationDirectory, ApplicationId applicationId, TimeoutBudget timeoutBudget) { + createCalled = true; + if (doThrow) { + throw new RuntimeException("foo"); + } + File tempDir = uncheck(() -> Files.createTempDirectory("deploy")).toFile(); + try { + IOUtils.copyDirectory(applicationDirectory, tempDir); + } catch (IOException e) { + e.printStackTrace(); + } + this.applicationPackage = tempDir; + return new SessionHandlerTest.MockSession(0, FilesApplicationPackage.fromFile(applicationPackage), applicationId); + } + + @Override + public LocalSession createSessionFromExisting(Session existingSession, DeployLogger logger, boolean internalRedeploy, TimeoutBudget timeoutBudget) { + if (doThrow) { + throw new RuntimeException("foo"); + } + createFromCalled = true; + return new SessionHandlerTest.MockSession(existingSession.getSessionId() + 1, FilesApplicationPackage.fromFile(applicationPackage)); + } + } + public static class MockProvisioner implements Provisioner { public boolean activated = false; 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 09e84deb1a5..b7f55aa0670 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 @@ -2,18 +2,19 @@ package com.yahoo.vespa.config.server.http.v2; import com.yahoo.config.model.application.provider.FilesApplicationPackage; -import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; -import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.jdisc.Response; +import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.application.OrchestratorMock; import com.yahoo.vespa.config.server.http.ContentHandlerTestBase; import com.yahoo.vespa.config.server.session.Session; import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import org.junit.Before; import org.junit.Test; @@ -49,8 +50,8 @@ public class ApplicationContentHandlerTest extends ContentHandlerTestBase { @Before public void setupHandler() { TenantRepository tenantRepository = new TenantRepository(componentRegistry, false); - tenantRepository.addTenant(tenantName1); - tenantRepository.addTenant(tenantName2); + tenantRepository.addTenant(TenantBuilder.create(componentRegistry, tenantName1)); + tenantRepository.addTenant(TenantBuilder.create(componentRegistry, tenantName2)); session2 = new MockSession(2, FilesApplicationPackage.fromFile(new File("src/test/apps/content"))); Tenant tenant1 = tenantRepository.getTenant(tenantName1); 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 ff8f7a291ad..70f66cf8fde 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 @@ -26,6 +26,7 @@ import com.yahoo.vespa.config.server.http.StaticResponse; 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.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import org.junit.After; import org.junit.Before; @@ -67,6 +68,7 @@ public class ApplicationHandlerTest { private final static ConfigserverConfig configserverConfig = new ConfigserverConfig(new ConfigserverConfig.Builder()); private static final MockLogRetriever logRetriever = new MockLogRetriever(); + private TestComponentRegistry componentRegistry; private TenantRepository tenantRepository; private ApplicationRepository applicationRepository; private SessionHandlerTest.MockProvisioner provisioner; @@ -75,7 +77,7 @@ public class ApplicationHandlerTest { @Before public void setup() { - TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder().build(); + componentRegistry = new TestComponentRegistry.Builder().build(); tenantRepository = new TenantRepository(componentRegistry, false); provisioner = new SessionHandlerTest.MockProvisioner(); orchestrator = new OrchestratorMock(); @@ -96,8 +98,8 @@ public class ApplicationHandlerTest { @Test public void testDelete() throws Exception { - tenantRepository.addTenant(foobar); - tenantRepository.addTenant(mytenantName); + tenantRepository.addTenant(TenantBuilder.create(componentRegistry, foobar)); + tenantRepository.addTenant(TenantBuilder.create(componentRegistry, mytenantName)); { applicationRepository.deploy(testApp, prepareParams(applicationId)); 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 28fe4a7aa2c..1db70956407 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 @@ -4,15 +4,11 @@ package com.yahoo.vespa.config.server.http.v2; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.model.NullConfigModelRegistry; import com.yahoo.config.model.application.provider.FilesApplicationPackage; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.ApplicationName; -import com.yahoo.config.provision.InstanceName; -import com.yahoo.config.provision.TenantName; -import com.yahoo.config.provision.Zone; +import com.yahoo.config.provision.*; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.jdisc.Response; -import com.yahoo.vespa.config.server.TestComponentRegistry; +import com.yahoo.vespa.config.server.*; import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.vespa.config.server.http.HandlerTest; @@ -22,6 +18,7 @@ import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.session.MockSessionZKClient; import com.yahoo.vespa.config.server.session.RemoteSession; import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.model.VespaModelFactory; import org.junit.Before; @@ -63,7 +60,8 @@ public class HostHandlerTest { public void setup() { TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder().build(); tenantRepository = new TenantRepository(componentRegistry, false); - tenantRepository.addTenant(mytenant); + TenantBuilder tb = TenantBuilder.create(componentRegistry, mytenant); + tenantRepository.addTenant(tb); handler = createHostHandler(); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java index 46a17795acf..b72785876bc 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java @@ -15,6 +15,7 @@ import com.yahoo.vespa.config.server.http.HttpConfigRequest; import com.yahoo.vespa.config.server.http.HttpErrorResponse; import com.yahoo.vespa.config.server.http.SessionHandlerTest; import com.yahoo.vespa.config.server.rpc.MockRequestHandler; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import org.junit.Before; import org.junit.Test; @@ -47,7 +48,7 @@ public class HttpGetConfigHandlerTest { }} ); TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder().build(); TenantRepository tenantRepository = new TenantRepository(componentRegistry, false); - tenantRepository.addTenant(tenant, mockRequestHandler, mockRequestHandler); + tenantRepository.addTenant(TenantBuilder.create(componentRegistry, tenant).withRequestHandler(mockRequestHandler)); handler = new HttpGetConfigHandler(HttpGetConfigHandler.testOnlyContext(), tenantRepository); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java index e8484ad10fe..7789c5d88db 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java @@ -8,6 +8,7 @@ import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.rpc.MockRequestHandler; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.config.server.http.HandlerTest; import com.yahoo.vespa.config.server.http.HttpErrorResponse; @@ -45,7 +46,9 @@ public class HttpListConfigsHandlerTest { }} ); TenantName tenantName = TenantName.from("mytenant"); TenantRepository tenantRepository = new TenantRepository(componentRegistry, false); - tenantRepository.addTenant(tenantName, mockRequestHandler, mockRequestHandler); + TenantBuilder tenantBuilder = TenantBuilder.create(componentRegistry, tenantName) + .withRequestHandler(mockRequestHandler); + tenantRepository.addTenant(tenantBuilder); handler = new HttpListConfigsHandler(HttpListConfigsHandler.testOnlyContext(), tenantRepository, Zone.defaultZone()); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java index bef6369beb7..f97bc443a38 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java @@ -1,32 +1,27 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.http.v2; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.Environment; -import com.yahoo.config.provision.RegionName; -import com.yahoo.config.provision.TenantName; -import com.yahoo.config.provision.Zone; +import com.yahoo.config.provision.*; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.jdisc.Response; import com.yahoo.jdisc.http.HttpRequest.Method; +import com.yahoo.jdisc.Response; import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.http.SessionHandlerTest; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; -import org.junit.Before; import org.junit.Test; +import org.junit.Before; import java.io.IOException; -import static com.yahoo.jdisc.http.HttpRequest.Method.DELETE; -import static com.yahoo.jdisc.http.HttpRequest.Method.GET; -import static com.yahoo.jdisc.http.HttpRequest.Method.POST; -import static com.yahoo.jdisc.http.HttpRequest.Method.PUT; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; +import static com.yahoo.jdisc.http.HttpRequest.Method.*; + /** * @author Ulf Lilleengen */ @@ -42,8 +37,8 @@ public class ListApplicationsHandlerTest { @Before public void setup() { TenantRepository tenantRepository = new TenantRepository(componentRegistry, false); - tenantRepository.addTenant(mytenant); - tenantRepository.addTenant(foobar); + tenantRepository.addTenant(TenantBuilder.create(componentRegistry, mytenant)); + tenantRepository.addTenant(TenantBuilder.create(componentRegistry, foobar)); applicationRepo = tenantRepository.getTenant(mytenant).getApplicationRepo(); applicationRepo2 = tenantRepository.getTenant(foobar).getApplicationRepo(); handler = new ListApplicationsHandler(ListApplicationsHandler.testOnlyContext(), 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 edfe74ef3f9..ff77362cb24 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 @@ -22,6 +22,7 @@ import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.session.LocalSession; import com.yahoo.vespa.config.server.session.PrepareParams; import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.curator.mock.MockCurator; import com.yahoo.vespa.model.VespaModelFactory; @@ -77,7 +78,8 @@ public class SessionActiveHandlerTest { tenantRepository = new TenantRepository(componentRegistry, false); applicationRepository = new ApplicationRepository(tenantRepository, hostProvisioner, new OrchestratorMock(), componentRegistry.getClock()); - tenantRepository.addTenant(tenantName); + TenantBuilder tenantBuilder = TenantBuilder.create(componentRegistry, tenantName); + tenantRepository.addTenant(tenantBuilder); handler = createHandler(); } 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 bc1650ce923..a106f52e4d1 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 @@ -13,6 +13,7 @@ import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.application.OrchestratorMock; import com.yahoo.vespa.config.server.http.ContentHandlerTestBase; import com.yahoo.vespa.config.server.http.SessionHandlerTest; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import org.junit.Before; import org.junit.Ignore; @@ -42,7 +43,7 @@ public class SessionContentHandlerTest extends ContentHandlerTestBase { @Before public void setupHandler() throws Exception { tenantRepository = new TenantRepository(componentRegistry, false); - tenantRepository.addTenant(tenant); + tenantRepository.addTenant(TenantBuilder.create(componentRegistry, tenant)); tenantRepository.getTenant(tenant).getLocalSessionRepo().addSession(new MockSession(1L, FilesApplicationPackage.fromFile(createTestApp()))); handler = createHandler(); pathPrefix = "/application/v2/tenant/" + tenant + "/session/"; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java index 5c0b1764e70..9a1c476117d 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java @@ -1,7 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.http.v2; -import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpRequest; @@ -10,9 +9,11 @@ import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.application.CompressedApplicationInputStreamTest; import com.yahoo.vespa.config.server.application.OrchestratorMock; +import com.yahoo.vespa.config.server.http.HandlerTest; import com.yahoo.vespa.config.server.http.HttpErrorResponse; import com.yahoo.vespa.config.server.http.SessionHandlerTest; -import com.yahoo.vespa.config.server.session.LocalSession; +import com.yahoo.vespa.config.server.session.LocalSessionRepo; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import org.junit.Before; import org.junit.Ignore; @@ -21,7 +22,6 @@ import org.junit.Test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileWriter; import java.io.IOException; import java.util.Collections; import java.util.HashMap; @@ -33,7 +33,6 @@ import static com.yahoo.jdisc.Response.Status.METHOD_NOT_ALLOWED; import static com.yahoo.jdisc.Response.Status.OK; import static com.yahoo.jdisc.http.HttpRequest.Method.GET; import static com.yahoo.jdisc.http.HttpRequest.Method.POST; -import static com.yahoo.vespa.config.server.http.HandlerTest.assertHttpStatusCodeErrorCodeAndMessage; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -49,13 +48,15 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { private static final HashMap<String, String> postHeaders = new HashMap<>(); private final TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder().build(); - ApplicationRepository applicationRepository; private String pathPrefix = "/application/v2/session/"; private String createdMessage = " created.\""; private String tenantMessage = ""; public File testApp = new File("src/test/apps/app"); + private LocalSessionRepo localSessionRepo; + private TenantRepository tenantRepository; + private MockSessionFactory sessionFactory; static { postHeaders.put(ApplicationApiHandler.contentTypeHeader, ApplicationApiHandler.APPLICATION_X_GZIP); @@ -63,12 +64,13 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { @Before public void setupRepo() { - TenantRepository tenantRepository = new TenantRepository(componentRegistry, false); - applicationRepository = new ApplicationRepository(tenantRepository, - new SessionHandlerTest.MockProvisioner(), - new OrchestratorMock(), - componentRegistry.getClock()); - tenantRepository.addTenant(tenant); + localSessionRepo = new LocalSessionRepo(tenant, componentRegistry); + tenantRepository = new TenantRepository(componentRegistry, false); + sessionFactory = new MockSessionFactory(); + TenantBuilder tenantBuilder = TenantBuilder.create(componentRegistry, tenant) + .withSessionFactory(sessionFactory) + .withLocalSessionRepo(localSessionRepo); + tenantRepository.addTenant(tenantBuilder); pathPrefix = "/application/v2/tenant/" + tenant + "/session/"; createdMessage = " for tenant '" + tenant + "' created.\""; tenantMessage = ",\"tenant\":\"test\""; @@ -79,13 +81,13 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { public void require_that_from_parameter_cannot_be_set_if_data_in_request() throws IOException { HttpRequest request = post(Collections.singletonMap("from", "active")); HttpResponse response = createHandler().handle(request); - assertHttpStatusCodeErrorCodeAndMessage(response, BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, "Parameter 'from' is illegal for POST"); + HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(response, BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, "Parameter 'from' is illegal for POST"); } @Test public void require_that_post_request_must_contain_data() throws IOException { HttpResponse response = createHandler().handle(post()); - assertHttpStatusCodeErrorCodeAndMessage(response, BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, "Request contains no data"); + HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(response, BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, "Request contains no data"); } @Test @@ -93,13 +95,13 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { HashMap<String, String> headers = new HashMap<>(); // no Content-Type header File outFile = CompressedApplicationInputStreamTest.createTarFile(); HttpResponse response = createHandler().handle(post(outFile, headers, null)); - assertHttpStatusCodeErrorCodeAndMessage(response, BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, "Request contains no Content-Type header"); + HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(response, BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, "Request contains no Content-Type header"); } private void assertIllegalFromParameter(String fromValue) throws IOException { File outFile = CompressedApplicationInputStreamTest.createTarFile(); HttpRequest request = post(outFile, postHeaders, Collections.singletonMap("from", fromValue)); - assertHttpStatusCodeErrorCodeAndMessage(createHandler().handle(request), BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, "Parameter 'from' has illegal value '" + fromValue + "'"); + HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(createHandler().handle(request), BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, "Parameter 'from' has illegal value '" + fromValue + "'"); } @Test @@ -110,35 +112,54 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { assertNotNull(response); assertThat(response.getStatus(), is(OK)); assertThat(SessionHandlerTest.getRenderedString(response), - is("{\"log\":[]" + tenantMessage + ",\"session-id\":\"2\",\"prepared\":\"http://" + - hostname + ":" + port + pathPrefix + "2/prepared\",\"content\":\"http://" + - hostname + ":" + port + pathPrefix + "2/content/\",\"message\":\"Session 2" + createdMessage + "}")); + is("{\"log\":[]" + tenantMessage + ",\"session-id\":\"0\",\"prepared\":\"http://" + + hostname + ":" + port + pathPrefix + "0/prepared\",\"content\":\"http://" + + hostname + ":" + port + pathPrefix + "0/content/\",\"message\":\"Session 0" + createdMessage + "}")); + } + + @Test + public void require_that_session_factory_is_called() throws IOException { + File outFile = CompressedApplicationInputStreamTest.createTarFile(); + createHandler().handle(post(outFile)); + assertTrue(sessionFactory.createCalled); } @Test public void require_that_handler_does_not_support_get() throws IOException { HttpResponse response = createHandler().handle(HttpRequest.createTestRequest(pathPrefix, GET)); - assertHttpStatusCodeErrorCodeAndMessage(response, METHOD_NOT_ALLOWED, + HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(response, METHOD_NOT_ALLOWED, HttpErrorResponse.errorCodes.METHOD_NOT_ALLOWED, "Method 'GET' is not supported"); } @Test public void require_internal_error_when_exception() throws IOException { + sessionFactory.doThrow = true; File outFile = CompressedApplicationInputStreamTest.createTarFile(); - new FileWriter(outFile).write("rubbish"); HttpResponse response = createHandler().handle(post(outFile)); - assertHttpStatusCodeErrorCodeAndMessage(response, INTERNAL_SERVER_ERROR, - HttpErrorResponse.errorCodes.INTERNAL_SERVER_ERROR, - "Unable to create compressed application stream"); + HandlerTest.assertHttpStatusCodeErrorCodeAndMessage(response, INTERNAL_SERVER_ERROR, + HttpErrorResponse.errorCodes.INTERNAL_SERVER_ERROR, + "foo"); } @Test public void require_that_handler_unpacks_application() throws IOException { File outFile = CompressedApplicationInputStreamTest.createTarFile(); createHandler().handle(post(outFile)); - ApplicationFile applicationFile = applicationRepository.getApplicationFileFromSession(tenant, 2, "services.xml", LocalSession.Mode.READ); - assertTrue(applicationFile.exists()); + assertTrue(sessionFactory.createCalled); + final File applicationPackage = sessionFactory.applicationPackage; + assertNotNull(applicationPackage); + assertTrue(applicationPackage.exists()); + final File[] files = applicationPackage.listFiles(); + assertNotNull(files); + assertThat(files.length, is(3)); + } + + @Test + public void require_that_session_is_stored_in_repo() throws IOException { + File outFile = CompressedApplicationInputStreamTest.createTarFile(); + createHandler().handle(post(outFile)); + assertNotNull(localSessionRepo.getSession(0)); } @Test @@ -161,9 +182,14 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { } private SessionCreateHandler createHandler() { - return new SessionCreateHandler(SessionCreateHandler.testOnlyContext(), - applicationRepository, - componentRegistry.getConfigserverConfig()); + return new SessionCreateHandler( + SessionCreateHandler.testOnlyContext(), + new ApplicationRepository(tenantRepository, + new SessionHandlerTest.MockProvisioner(), + new OrchestratorMock(), + componentRegistry.getClock()), + componentRegistry.getConfigserverConfig()); + } private HttpRequest post() throws FileNotFoundException { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java index 535118ae5aa..aad715eb19e 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java @@ -1,26 +1,37 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.http.v2; +import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.UncheckedTimeoutException; -import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.application.api.ApplicationFile; +import com.yahoo.config.application.api.DeployLogger; +import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationLockException; -import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.DockerImage; -import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.OutOfCapacityException; import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.jdisc.http.HttpRequest; +import com.yahoo.path.Path; import com.yahoo.slime.JsonDecoder; import com.yahoo.slime.Slime; +import com.yahoo.transaction.NestedTransaction; +import com.yahoo.transaction.Transaction; import com.yahoo.vespa.config.server.ApplicationRepository; +import com.yahoo.vespa.config.server.MockReloadHandler; import com.yahoo.vespa.config.server.TestComponentRegistry; -import com.yahoo.vespa.config.server.TimeoutBudget; +import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.application.OrchestratorMock; -import com.yahoo.vespa.config.server.http.HttpErrorResponse; -import com.yahoo.vespa.config.server.http.SessionHandler; -import com.yahoo.vespa.config.server.http.SessionHandlerTest; +import com.yahoo.vespa.config.server.application.TenantApplications; +import com.yahoo.vespa.config.server.host.HostRegistry; +import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; +import com.yahoo.vespa.config.server.configchange.MockRefeedAction; +import com.yahoo.vespa.config.server.configchange.MockRestartAction; +import com.yahoo.vespa.config.server.http.*; +import com.yahoo.vespa.config.server.session.*; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.mock.MockCurator; @@ -28,11 +39,14 @@ import org.junit.Before; import org.junit.Test; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.time.Clock; -import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.Optional; import static com.yahoo.jdisc.Response.Status.BAD_REQUEST; import static com.yahoo.jdisc.Response.Status.METHOD_NOT_ALLOWED; @@ -51,13 +65,11 @@ import static org.junit.Assert.assertThat; */ public class SessionPrepareHandlerTest extends SessionHandlerTest { private static final TenantName tenant = TenantName.from("test"); - private static final File app = new File("src/test/resources/deploy/validapp"); private Curator curator = new MockCurator(); private final TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder().curator(curator).build(); private final Clock clock = componentRegistry.getClock(); - private final TimeoutBudget timeoutBudget = new TimeoutBudget(clock, Duration.ofSeconds(10)); - private ApplicationRepository applicationRepository; + private LocalSessionRepo localRepo; private String preparedMessage = " prepared.\"}"; private String tenantMessage = ""; @@ -65,15 +77,16 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { @Before public void setupRepo() { - tenantRepository = new TenantRepository(componentRegistry, false); - tenantRepository.addTenant(tenant); - applicationRepository = new ApplicationRepository(tenantRepository, - new MockProvisioner(), - new OrchestratorMock(), - clock); + localRepo = new LocalSessionRepo(tenant, componentRegistry); pathPrefix = "/application/v2/tenant/" + tenant + "/session/"; preparedMessage = " for tenant '" + tenant + "' prepared.\""; tenantMessage = ",\"tenant\":\"" + tenant + "\""; + tenantRepository = new TenantRepository(componentRegistry, false); + TenantBuilder tenantBuilder = TenantBuilder.create(componentRegistry, tenant) + .withSessionFactory(new MockSessionFactory()) + .withLocalSessionRepo(localRepo) + .withApplicationRepo(TenantApplications.create(componentRegistry, new MockReloadHandler(), tenant)); + tenantRepository.addTenant(tenantBuilder); } @Test @@ -94,8 +107,8 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { @Test public void require_that_handler_gives_error_for_unsupported_methods() throws Exception { - testUnsupportedMethod(createTestRequest(pathPrefix, HttpRequest.Method.POST, Cmd.PREPARED, 1L)); - testUnsupportedMethod(createTestRequest(pathPrefix, HttpRequest.Method.DELETE, Cmd.PREPARED, 1L)); + testUnsupportedMethod(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.POST, Cmd.PREPARED, 1L)); + testUnsupportedMethod(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.DELETE, Cmd.PREPARED, 1L)); } private void testUnsupportedMethod(com.yahoo.container.jdisc.HttpRequest request) throws Exception { @@ -107,61 +120,85 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { @Test public void require_that_activate_url_is_returned_on_success() throws Exception { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - HttpResponse response = request(HttpRequest.Method.PUT, sessionId); + MockSession session = new MockSession(1, null); + localRepo.addSession(session); + HttpResponse response = request(HttpRequest.Method.PUT, 1L); + assertThat(session.getStatus(), is(Session.Status.PREPARE)); assertNotNull(response); assertThat(response.getStatus(), is(OK)); - assertResponseContains(response, "\"activate\":\"http://foo:1337" + pathPrefix + sessionId + - "/active\",\"message\":\"Session " + sessionId + preparedMessage); + assertResponseContains(response, "\"activate\":\"http://foo:1337" + pathPrefix + "1/active\",\"message\":\"Session 1" + preparedMessage); } @Test public void require_debug() throws Exception { HttpResponse response = createHandler().handle( - createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 9999L, "?debug=true")); + SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 9999L, "?debug=true")); assertThat(response.getStatus(), is(NOT_FOUND)); assertThat(SessionHandlerTest.getRenderedString(response), containsString("NotFoundException")); } @Test public void require_verbose() throws Exception { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); + MockSession session = new MockSession(1, null); + session.doVerboseLogging = true; + localRepo.addSession(session); HttpResponse response = createHandler().handle( - createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, sessionId, "?verbose=true")); - System.out.println(getRenderedString(response)); + SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L, "?verbose=true")); assertThat(response.getStatus(), is(OK)); - assertThat(getRenderedString(response), containsString("Created application ")); + assertThat(SessionHandlerTest.getRenderedString(response), containsString("debuglog")); + } + + private SessionZooKeeperClient createSessionZooKeeperClient(LocalSession session) { + return new MockSessionZKClient(curator, tenant, session.getSessionId()); } @Test public void require_get_response_activate_url_on_ok() throws Exception { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - request(HttpRequest.Method.PUT, sessionId); - HttpResponse getResponse = request(HttpRequest.Method.GET, sessionId); + MockSession session = new MockSession(1, null); + localRepo.addSession(session); + request(HttpRequest.Method.PUT, 1L); + session.setStatus(Session.Status.PREPARE); + SessionZooKeeperClient zooKeeperClient = createSessionZooKeeperClient(session); + zooKeeperClient.writeStatus(Session.Status.PREPARE); + HttpResponse getResponse = request(HttpRequest.Method.GET, 1L); assertResponseContains(getResponse, "\"activate\":\"http://foo:1337" + pathPrefix + - sessionId + "/active\",\"message\":\"Session " + sessionId + preparedMessage); + "1/active\",\"message\":\"Session 1" + preparedMessage); } @Test public void require_get_response_error_on_not_prepared() throws Exception { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - - HttpResponse getResponse = request(HttpRequest.Method.GET, sessionId); + MockSession session = new MockSession(1, null); + localRepo.addSession(session); + session.setStatus(Session.Status.NEW); + SessionZooKeeperClient zooKeeperClient = createSessionZooKeeperClient(session); + zooKeeperClient.writeStatus(Session.Status.NEW); + HttpResponse getResponse = request(HttpRequest.Method.GET, 1L); assertHttpStatusCodeErrorCodeAndMessage(getResponse, BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, - "Session not prepared: " + sessionId); - - request(HttpRequest.Method.PUT, sessionId); - applicationRepository.activate(tenantRepository.getTenant(tenant), sessionId, timeoutBudget, false); - - getResponse = request(HttpRequest.Method.GET, sessionId); + "Session not prepared: 1"); + session.setStatus(Session.Status.ACTIVATE); + zooKeeperClient.writeStatus(Session.Status.ACTIVATE); + getResponse = request(HttpRequest.Method.GET, 1L); assertHttpStatusCodeErrorCodeAndMessage(getResponse, BAD_REQUEST, HttpErrorResponse.errorCodes.BAD_REQUEST, - "Session is active: " + sessionId); + "Session is active: 1"); + } + + @Test + public void require_cannot_prepare_active_session() throws Exception { + MockSession session = new MockSession(1, null); + localRepo.addSession(session); + session.setStatus(Session.Status.ACTIVATE); + HttpResponse putResponse = request(HttpRequest.Method.PUT, 1L); + assertHttpStatusCodeErrorCodeAndMessage(putResponse, BAD_REQUEST, + HttpErrorResponse.errorCodes.BAD_REQUEST, + "Session is active: 1"); } @Test public void require_get_response_error_when_session_id_does_not_exist() throws Exception { + MockSession session = new MockSession(1, null); + localRepo.addSession(session); HttpResponse getResponse = request(HttpRequest.Method.GET, 9999L); assertHttpStatusCodeErrorCodeAndMessage(getResponse, NOT_FOUND, HttpErrorResponse.errorCodes.NOT_FOUND, @@ -170,116 +207,137 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { @Test public void require_that_tenant_is_in_response() throws Exception { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - HttpResponse response = request(HttpRequest.Method.PUT, sessionId); + MockSession session = new MockSession(1, null); + localRepo.addSession(session); + HttpResponse response = request(HttpRequest.Method.PUT, 1L); assertNotNull(response); assertThat(response.getStatus(), is(OK)); + assertThat(session.getStatus(), is(Session.Status.PREPARE)); assertResponseContains(response, tenantMessage); } @Test public void require_that_preparing_with_multiple_tenants_work() throws Exception { - SessionHandler handler = createHandler(); - - TenantName defaultTenant = TenantName.from("test2"); - tenantRepository.addTenant(defaultTenant); - ApplicationId applicationId1 = ApplicationId.from(defaultTenant, ApplicationName.from("app"), InstanceName.defaultName()); - long sessionId = applicationRepository.createSession(applicationId1, timeoutBudget, app); - + final TenantName defaultTenant = TenantName.from("test2"); + // Need different repo for 'test2' tenant + LocalSessionRepo localRepoDefault = new LocalSessionRepo(defaultTenant, componentRegistry); + TenantBuilder defaultTenantBuilder = TenantBuilder.create(componentRegistry, defaultTenant) + .withLocalSessionRepo(localRepoDefault) + .withSessionFactory(new MockSessionFactory()); + tenantRepository.addTenant(defaultTenantBuilder); + final SessionHandler handler = createHandler(); + + long sessionId = 1; + // Deploy with default tenant + MockSession session = new MockSession(sessionId, null); + localRepoDefault.addSession(session); pathPrefix = "/application/v2/tenant/" + defaultTenant + "/session/"; + HttpResponse response = request(HttpRequest.Method.PUT, sessionId); assertNotNull(response); assertThat(SessionHandlerTest.getRenderedString(response), response.getStatus(), is(OK)); + assertThat(session.getStatus(), is(Session.Status.PREPARE)); + // Same session id, as this is for another tenant + session = new MockSession(sessionId, null); + localRepo.addSession(session); String applicationName = "myapp"; - ApplicationId applicationId2 = ApplicationId.from(tenant.value(), applicationName, "default"); - long sessionId2 = applicationRepository.createSession(applicationId2, timeoutBudget, app); - assertEquals(sessionId, sessionId2); // Want to test when they are equal (but for different tenants) - - pathPrefix = "/application/v2/tenant/" + tenant + "/session/" + sessionId2 + + pathPrefix = "/application/v2/tenant/" + tenant + "/session/" + sessionId + "/prepared?applicationName=" + applicationName; response = handler.handle(SessionHandlerTest.createTestRequest(pathPrefix)); assertNotNull(response); assertThat(SessionHandlerTest.getRenderedString(response), response.getStatus(), is(OK)); + assertThat(session.getStatus(), is(Session.Status.PREPARE)); - ApplicationId applicationId3 = ApplicationId.from(tenant.value(), applicationName, "quux"); - long sessionId3 = applicationRepository.createSession(applicationId3, timeoutBudget, app); - pathPrefix = "/application/v2/tenant/" + tenant + "/session/" + sessionId3 + + sessionId++; + session = new MockSession(sessionId, null); + localRepo.addSession(session); + pathPrefix = "/application/v2/tenant/" + tenant + "/session/" + sessionId + "/prepared?applicationName=" + applicationName + "&instance=quux"; response = handler.handle(SessionHandlerTest.createTestRequest(pathPrefix)); assertNotNull(response); assertThat(SessionHandlerTest.getRenderedString(response), response.getStatus(), is(OK)); + assertThat(session.getStatus(), is(Session.Status.PREPARE)); } @Test public void require_that_config_change_actions_are_in_response() throws Exception { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - HttpResponse response = request(HttpRequest.Method.PUT, sessionId); + MockSession session = new MockSession(1, null); + localRepo.addSession(session); + HttpResponse response = request(HttpRequest.Method.PUT, 1L); assertResponseContains(response, "\"configChangeActions\":{\"restart\":[],\"refeed\":[]}"); } @Test + public void require_that_config_change_actions_are_logged_if_existing() throws Exception { + List<ServiceInfo> services = Collections.singletonList( + new ServiceInfo("serviceName", "serviceType", null, + ImmutableMap.of("clustername", "foo", "clustertype", "bar"), "configId", "hostName")); + ConfigChangeActions actions = new ConfigChangeActions(Arrays.asList( + new MockRestartAction("change", services), + new MockRefeedAction("change-id", false, "other change", services, "test"))); + MockSession session = new MockSession(1, null, actions); + localRepo.addSession(session); + HttpResponse response = request(HttpRequest.Method.PUT, 1L); + assertResponseContains(response, + "Change(s) between active and new application that require restart:\\nIn cluster 'foo' of type 'bar"); + assertResponseContains(response, + "Change(s) between active and new application that may require re-feed:\\nchange-id: Consider removing data and re-feed document type 'test'"); + } + + @Test public void require_that_config_change_actions_are_not_logged_if_not_existing() throws Exception { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - HttpResponse response = request(HttpRequest.Method.PUT, sessionId); + MockSession session = new MockSession(1, null); + localRepo.addSession(session); + HttpResponse response = request(HttpRequest.Method.PUT, 1L); assertResponseNotContains(response, "Change(s) between active and new application that require restart"); assertResponseNotContains(response, "Change(s) between active and new application that require re-feed"); } @Test public void test_out_of_capacity_response() throws IOException { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - String exceptionMessage = "Out of capacity"; - FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testOnlyContext(), - applicationRepository, - componentRegistry.getConfigserverConfig(), - new OutOfCapacityException(exceptionMessage)); - HttpResponse response = handler.handle(createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, sessionId)); + String message = "Internal error"; + SessionThrowingException session = new SessionThrowingException(new OutOfCapacityException(message)); + localRepo.addSession(session); + HttpResponse response = request(HttpRequest.Method.PUT, 1L); assertEquals(400, response.getStatus()); Slime data = getData(response); assertThat(data.get().field("error-code").asString(), is(HttpErrorResponse.errorCodes.OUT_OF_CAPACITY.name())); - assertThat(data.get().field("message").asString(), is(exceptionMessage)); + assertThat(data.get().field("message").asString(), is(message)); } @Test public void test_that_nullpointerexception_gives_internal_server_error() throws IOException { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - String exceptionMessage = "nullpointer thrown in test handler"; - FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testOnlyContext(), - applicationRepository, - componentRegistry.getConfigserverConfig(), - new NullPointerException(exceptionMessage)); - HttpResponse response = handler.handle(createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, sessionId)); + String message = "No nodes available"; + SessionThrowingException session = new SessionThrowingException(new NullPointerException(message)); + localRepo.addSession(session); + HttpResponse response = request(HttpRequest.Method.PUT, 1L); assertEquals(500, response.getStatus()); Slime data = getData(response); assertThat(data.get().field("error-code").asString(), is(HttpErrorResponse.errorCodes.INTERNAL_SERVER_ERROR.name())); - assertThat(data.get().field("message").asString(), is(exceptionMessage)); + assertThat(data.get().field("message").asString(), is(message)); } @Test public void test_application_lock_failure() throws IOException { - String exceptionMessage = "Timed out after waiting PT1M to acquire lock '/provision/v1/locks/foo/bar/default'"; - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testOnlyContext(), - applicationRepository, - componentRegistry.getConfigserverConfig(), - new ApplicationLockException(new UncheckedTimeoutException(exceptionMessage))); - HttpResponse response = handler.handle(createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, sessionId)); + String message = "Timed out after waiting PT1M to acquire lock '/provision/v1/locks/foo/bar/default'"; + SessionThrowingException session = + new SessionThrowingException(new ApplicationLockException(new UncheckedTimeoutException(message))); + localRepo.addSession(session); + HttpResponse response = request(HttpRequest.Method.PUT, 1L); assertEquals(500, response.getStatus()); Slime data = getData(response); assertThat(data.get().field("error-code").asString(), is(HttpErrorResponse.errorCodes.APPLICATION_LOCK_FAILURE.name())); - assertThat(data.get().field("message").asString(), is(exceptionMessage)); + assertThat(data.get().field("message").asString(), is(message)); } @Test public void test_docker_image_repository() { - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); + MockSession session = new MockSession(1, null); + localRepo.addSession(session); String dockerImageRepository = "https://foo.bar.com:4443/baz"; - request(HttpRequest.Method.PUT, sessionId, Map.of("dockerImageRepository", dockerImageRepository, - "applicationName", applicationId().application().value())); - applicationRepository.activate(tenantRepository.getTenant(tenant), sessionId, timeoutBudget, false); - assertEquals(DockerImage.fromString(dockerImageRepository), - applicationRepository.getActiveSession(applicationId()).getDockerImageRepository().get()); + request(HttpRequest.Method.PUT, 1L, Map.of("dockerImageRepository", dockerImageRepository)); + assertEquals(DockerImage.fromString(dockerImageRepository), localRepo.getSession(1).getDockerImageRepository().get()); } private Slime getData(HttpResponse response) throws IOException { @@ -301,8 +359,12 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { private SessionHandler createHandler() { return new SessionPrepareHandler( SessionPrepareHandler.testOnlyContext(), - applicationRepository, + new ApplicationRepository(tenantRepository, + new MockProvisioner(), + new OrchestratorMock(), + clock), componentRegistry.getConfigserverConfig()); + } private HttpResponse request(HttpRequest.Method put, long l) { @@ -313,24 +375,50 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { return createHandler().handle(SessionHandlerTest.createTestRequest(pathPrefix, put, Cmd.PREPARED, l, "", null, requestParameters)); } - private ApplicationId applicationId() { - return ApplicationId.from(tenant.value(), "app", "default"); - } + public static class SessionThrowingException extends LocalSession { + private final RuntimeException exception; - private static class FailingSessionPrepareHandler extends SessionPrepareHandler { + SessionThrowingException(RuntimeException exception) { + super(TenantName.defaultName(), 1, null, null, + new MockSessionZKClient(MockApplicationPackage.createEmpty()), null, null, new HostRegistry<>()); + this.exception = exception; + } - private final RuntimeException exceptionToBeThrown; + @Override + public ConfigChangeActions prepare(DeployLogger logger, + PrepareParams params, + Optional<ApplicationSet> application, + Path tenantPath, + Instant now) { + throw exception; + } - public FailingSessionPrepareHandler(Context ctx, ApplicationRepository applicationRepository, - ConfigserverConfig configserverConfig, RuntimeException exceptionToBeThrown) { - super(ctx, applicationRepository, configserverConfig); - this.exceptionToBeThrown = exceptionToBeThrown; + @Override + public Session.Status getStatus() { + return null; } @Override - protected HttpResponse handlePUT(com.yahoo.container.jdisc.HttpRequest request) { - throw exceptionToBeThrown; + public Transaction createActivateTransaction() { + return null; + } + + @Override + public ApplicationFile getApplicationFile(Path relativePath, Mode mode) { + return null; + } + + @Override + public ApplicationId getApplicationId() { + return null; } - } + @Override + public Instant getCreateTime() { + return Instant.EPOCH; + } + + @Override + public void delete(NestedTransaction transaction) { } + } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java index 468dd5a15a7..3c5774a60e4 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java @@ -4,8 +4,10 @@ package com.yahoo.vespa.config.server.session; import com.yahoo.config.provision.TenantName; import com.yahoo.path.Path; import com.yahoo.text.Utf8; +import com.yahoo.vespa.config.server.GlobalComponentRegistry; import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.TenantBuilder; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; import com.yahoo.vespa.curator.Curator; @@ -31,17 +33,16 @@ public class RemoteSessionRepoTest { private RemoteSessionRepo remoteSessionRepo; private Curator curator; - TenantRepository tenantRepository; @Before public void setupFacade() { curator = new MockCurator(); - TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder() - .curator(curator) + Tenant tenant = TenantBuilder.create(new TestComponentRegistry.Builder() + .curator(curator) + .build(), + tenantName) .build(); - tenantRepository = new TenantRepository(componentRegistry, false); - tenantRepository.addTenant(tenantName); - this.remoteSessionRepo = tenantRepository.getTenant(tenantName).getRemoteSessionRepo(); + this.remoteSessionRepo = tenant.getRemoteSessionRepo(); curator.create(TenantRepository.getTenantPath(tenantName).append("/applications")); curator.create(TenantRepository.getSessionsPath(tenantName)); createSession(1L, false); @@ -96,9 +97,10 @@ public class RemoteSessionRepoTest { public void testBadApplicationRepoOnActivate() { long sessionId = 3L; TenantName mytenant = TenantName.from("mytenant"); + GlobalComponentRegistry registry = new TestComponentRegistry.Builder().curator(curator).build(); curator.set(TenantRepository.getApplicationsPath(mytenant).append("mytenant:appX:default"), new byte[0]); // Invalid data - tenantRepository.addTenant(mytenant); - Tenant tenant = tenantRepository.getTenant(mytenant); + Tenant tenant = TenantBuilder.create(registry, mytenant) + .build(); curator.create(TenantRepository.getSessionsPath(mytenant)); remoteSessionRepo = tenant.getRemoteSessionRepo(); assertThat(remoteSessionRepo.getSessions().size(), is(0)); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRepositoryTest.java index c3237c9fabb..9bd5c5f1614 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 @@ -11,8 +11,6 @@ import com.yahoo.config.provision.TenantName; import com.yahoo.component.Version; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.server.GlobalComponentRegistry; -import com.yahoo.vespa.config.server.ReloadHandler; -import com.yahoo.vespa.config.server.RequestHandler; import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.ServerCache; import com.yahoo.vespa.config.server.TestComponentRegistry; @@ -207,8 +205,8 @@ public class TenantRepositoryTest { } @Override - public void createTenant(TenantName tenantName) { - throw new RuntimeException("Failed to create: " + tenantName); + protected void createTenant(TenantBuilder builder) { + throw new RuntimeException("Failed to create: " + builder.getTenantName()); } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantTest.java index 74833da6d66..5b8f5299c01 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantTest.java @@ -3,7 +3,9 @@ package com.yahoo.vespa.config.server.tenant; import com.google.common.testing.EqualsTester; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.config.server.MockReloadHandler; import com.yahoo.vespa.config.server.TestComponentRegistry; +import com.yahoo.vespa.config.server.application.TenantApplications; import org.junit.Before; import org.junit.Test; @@ -34,7 +36,9 @@ public class TenantTest { private Tenant createTenant(String name) { TenantRepository tenantRepository = new TenantRepository(componentRegistry, false); TenantName tenantName = TenantName.from(name); - tenantRepository.addTenant(tenantName); + TenantBuilder tenantBuilder = TenantBuilder.create(componentRegistry, tenantName) + .withApplicationRepo(TenantApplications.create(componentRegistry, new MockReloadHandler(), tenantName)); + tenantRepository.addTenant(tenantBuilder); return tenantRepository.getTenant(tenantName); } |