diff options
9 files changed, 84 insertions, 57 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java index 3cad8def541..5db0512aeea 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java @@ -39,6 +39,7 @@ import com.yahoo.vespa.config.server.host.HostRegistry; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import com.yahoo.vespa.config.server.monitoring.MetricUpdaterFactory; import com.yahoo.vespa.config.server.rpc.security.RpcAuthorizer; +import com.yahoo.vespa.config.server.tenant.Tenant; import com.yahoo.vespa.config.server.tenant.TenantHandlerProvider; import com.yahoo.vespa.config.server.tenant.TenantListener; import com.yahoo.vespa.config.server.tenant.TenantRepository; @@ -83,7 +84,7 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener { private static final int JRT_RPC_TRANSPORT_THREADS = threadsToUse(); private final Supervisor supervisor = new Supervisor(new Transport(JRT_RPC_TRANSPORT_THREADS)); - private Spec spec; + private final Spec spec; private final boolean useRequestVersion; private final boolean hostedVespa; private final boolean canReturnEmptySentinelConfig; @@ -93,7 +94,7 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener { private final DelayedConfigResponses delayedConfigResponses; private final HostRegistry<TenantName> hostRegistry; - private final Map<TenantName, TenantHandlerProvider> tenantProviders = new ConcurrentHashMap<>(); + private final Map<TenantName, Tenant> tenants = new ConcurrentHashMap<>(); private final Map<ApplicationId, ApplicationState> applicationStateMap = new ConcurrentHashMap<>(); private final SuperModelRequestHandler superModelRequestHandler; private final MetricUpdater metrics; @@ -395,7 +396,8 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener { TenantName tenant = optionalTenant.orElse(TenantName.defaultName()); // perhaps needed for non-hosted? Optional<RequestHandler> requestHandler = getRequestHandler(tenant); if (requestHandler.isEmpty()) { - String msg = TenantRepository.logPre(tenant) + "Unable to find request handler for tenant. Requested from host '" + request.getClientHostName() + "'"; + String msg = TenantRepository.logPre(tenant) + "Unable to find request handler for tenant '" + tenant + + "'. Request from host '" + request.getClientHostName() + "'"; metrics.incUnknownHostRequests(); trace.trace(TRACELEVEL, msg); log.log(Level.WARNING, msg); @@ -410,7 +412,7 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener { } Optional<RequestHandler> getRequestHandler(TenantName tenant) { - return Optional.ofNullable(tenantProviders.get(tenant)) + return Optional.ofNullable(tenants.get(tenant)) .map(TenantHandlerProvider::getRequestHandler); } @@ -421,7 +423,7 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener { @Override public void onTenantDelete(TenantName tenant) { log.log(Level.FINE, TenantRepository.logPre(tenant)+"Tenant deleted, removing request handler and cleaning host registry"); - tenantProviders.remove(tenant); + tenants.remove(tenant); hostRegistry.removeHostsForKey(tenant); } @@ -432,9 +434,8 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener { } @Override - public void onTenantCreate(TenantName tenant, TenantHandlerProvider tenantHandlerProvider) { - log.log(Level.FINE, TenantRepository.logPre(tenant)+"Tenant created, adding request handler"); - tenantProviders.put(tenant, tenantHandlerProvider); + public void onTenantCreate(Tenant tenant) { + tenants.put(tenant.getName(), tenant); } /** Returns true only after all tenants are loaded */ @@ -455,7 +456,7 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener { return useRequestVersion; } - class ChunkedFileReceiver implements FileServer.Receiver { + static class ChunkedFileReceiver implements FileServer.Receiver { Target target; ChunkedFileReceiver(Target target) { this.target = target; 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 492c9432646..2da93b7f243 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 @@ -525,7 +525,7 @@ public class SessionRepository { if (! sourceDir.isDirectory()) throw new IllegalArgumentException(sourceDir.getAbsolutePath() + " is not a directory"); - // Copy app it atomically: Copy to default tmp dir and move to destination + // Copy app atomically: Copy to a temp dir and move to destination java.nio.file.Path tempDestinationDir = Files.createTempDirectory(destinationDir.getParentFile().toPath(), "app-package"); log.log(Level.FINE, "Copying dir " + sourceDir.getAbsolutePath() + " to " + tempDestinationDir.toFile().getAbsolutePath()); IOUtils.copyDirectory(sourceDir, tempDestinationDir.toFile()); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantListener.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantListener.java index ea407ba917a..28be2764ad0 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantListener.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantListener.java @@ -8,16 +8,14 @@ import com.yahoo.vespa.config.server.tenant.TenantHandlerProvider; * Interface for something that listens for created and deleted tenants. * * @author Ulf Lilleengen - * @since 5.8 */ public interface TenantListener { /** * Called whenever a new tenant is created. * - * @param tenant name of newly created tenant. - * @param provider provider of request and reload handlers for new tenant. + * @param tenant newly created tenant. */ - void onTenantCreate(TenantName tenant, TenantHandlerProvider provider); + void onTenantCreate(Tenant tenant); /** * Called whenever a tenant is deleted. 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 5afb99e81e3..4316f03272a 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 @@ -255,7 +255,7 @@ public class TenantRepository { private void notifyNewTenant(Tenant tenant) { for (TenantListener listener : tenantListeners) { - listener.onTenantCreate(tenant.getName(), tenant); + listener.onTenantCreate(tenant); } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java index 2e0466c27b1..f03550c0a80 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java @@ -170,6 +170,11 @@ public class TestComponentRegistry implements GlobalComponentRegistry { return this; } + public Builder configDefinitionRepo(ConfigDefinitionRepo configDefinitionRepo) { + this.defRepo = configDefinitionRepo; + return this; + } + public TestComponentRegistry build() { final PermanentApplicationPackage permApp = this.permanentApplicationPackage .orElse(new PermanentApplicationPackage(configserverConfig)); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TestConfigDefinitionRepo.java b/configserver/src/test/java/com/yahoo/vespa/config/server/TestConfigDefinitionRepo.java index d472f64d228..5878b250bc8 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TestConfigDefinitionRepo.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/TestConfigDefinitionRepo.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.config.server; import com.yahoo.cloud.config.LbServicesConfig; +import com.yahoo.cloud.config.SentinelConfig; import com.yahoo.config.SimpletypesConfig; import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.vespa.config.ConfigDefinitionKey; @@ -20,6 +21,8 @@ public class TestConfigDefinitionRepo implements ConfigDefinitionRepo { new ConfigDefinition(SimpletypesConfig.CONFIG_DEF_NAME, SimpletypesConfig.CONFIG_DEF_SCHEMA)); repo.put(new ConfigDefinitionKey(LbServicesConfig.CONFIG_DEF_NAME, LbServicesConfig.CONFIG_DEF_NAMESPACE), new ConfigDefinition(LbServicesConfig.CONFIG_DEF_NAME, LbServicesConfig.CONFIG_DEF_SCHEMA)); + repo.put(new ConfigDefinitionKey(SentinelConfig.CONFIG_DEF_NAME, SentinelConfig.CONFIG_DEF_NAMESPACE), + new ConfigDefinition(SentinelConfig.CONFIG_DEF_NAME, SentinelConfig.CONFIG_DEF_SCHEMA)); } @Override diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcServerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcServerTest.java index de9ad60ddf8..ae6bd5feeab 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcServerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcServerTest.java @@ -8,6 +8,8 @@ import com.yahoo.component.Version; import com.yahoo.config.SimpletypesConfig; import com.yahoo.config.model.test.MockApplicationPackage; 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.jrt.Request; import com.yahoo.vespa.config.ConfigKey; @@ -16,22 +18,23 @@ import com.yahoo.vespa.config.ConfigPayloadApplier; import com.yahoo.vespa.config.ErrorCode; import com.yahoo.vespa.config.RawConfig; import com.yahoo.vespa.config.protocol.CompressionType; -import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.protocol.JRTClientConfigRequest; import com.yahoo.vespa.config.protocol.JRTClientConfigRequestV3; -import com.yahoo.vespa.config.protocol.SlimeConfigResponse; import com.yahoo.vespa.config.protocol.Trace; +import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.ServerCache; import com.yahoo.vespa.config.server.application.Application; import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; -import com.yahoo.vespa.config.util.ConfigUtils; +import com.yahoo.vespa.config.server.session.PrepareParams; import com.yahoo.vespa.model.VespaModel; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.xml.sax.SAXException; +import java.io.File; import java.io.IOException; import java.util.Optional; @@ -47,12 +50,21 @@ import static org.junit.Assert.assertTrue; */ public class RpcServerTest { + private static final TenantName tenantName = TenantName.from("testTenant"); + private static final ApplicationId applicationId = + ApplicationId.from(tenantName, ApplicationName.defaultName(), InstanceName.defaultName()); + private final static File testApp = new File("src/test/resources/deploy/validapp"); + @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Test public void testRpcServer() throws IOException, SAXException, InterruptedException { - try (RpcTester tester = new RpcTester(ApplicationId.defaultId(), temporaryFolder)) { + try (RpcTester tester = new RpcTester(applicationId, temporaryFolder)) { + ApplicationRepository applicationRepository = tester.applicationRepository(); + applicationRepository.deploy(testApp, new PrepareParams.Builder().applicationId(applicationId).build()); + TenantApplications applicationRepo = tester.tenant().getApplicationRepo(); + applicationRepo.reloadConfig(applicationRepository.getActiveSession(applicationId).ensureApplicationLoaded()); testPrintStatistics(tester); testGetConfig(tester); testEnabled(tester); @@ -62,7 +74,7 @@ public class RpcServerTest { } private void testApplicationNotLoadedErrorWhenAppDeleted(RpcTester tester) throws InterruptedException, IOException { - tester.rpcServer().onTenantDelete(TenantName.defaultName()); + tester.rpcServer().onTenantDelete(tenantName); tester.rpcServer().onTenantsLoaded(); JRTClientConfigRequest clientReq = createSimpleRequest(); tester.performRequest(clientReq.getRequest()); @@ -79,8 +91,8 @@ public class RpcServerTest { @Test public void testEmptySentinelConfigWhenAppDeletedOnHostedVespa() throws IOException, InterruptedException { ConfigserverConfig.Builder configBuilder = new ConfigserverConfig.Builder().canReturnEmptySentinelConfig(true); - try (RpcTester tester = new RpcTester(ApplicationId.defaultId(), temporaryFolder, configBuilder)) { - tester.rpcServer().onTenantDelete(TenantName.defaultName()); + try (RpcTester tester = new RpcTester(applicationId, temporaryFolder, configBuilder)) { + tester.rpcServer().onTenantDelete(tenantName); tester.rpcServer().onTenantsLoaded(); JRTClientConfigRequest clientReq = createSentinelRequest(); @@ -119,7 +131,7 @@ public class RpcServerTest { false, new Version(1, 2, 3), MetricUpdater.createTestUpdater(), - ApplicationId.defaultId()); + applicationId); ApplicationSet appSet = ApplicationSet.fromSingle(app); tester.rpcServer().configActivated(appSet); ConfigKey<?> key = new ConfigKey<>(LbServicesConfig.class, "*"); @@ -141,29 +153,16 @@ public class RpcServerTest { private void testGetConfig(RpcTester tester) { ConfigKey<?> key = new ConfigKey<>(SimpletypesConfig.class, "brim"); JRTClientConfigRequest req = createRequest(new RawConfig(key, SimpletypesConfig.getDefMd5())); - ((MockRequestHandler)tester.tenantProvider().getRequestHandler()).responses.put(ApplicationId.defaultId(), createResponse()); assertTrue(req.validateParameters()); tester.performRequest(req.getRequest()); assertThat(req.errorCode(), is(0)); assertTrue(req.validateResponse()); - assertTrue(req.responseIsInternalRedeploy()); ConfigPayload payload = ConfigPayload.fromUtf8Array(req.getNewPayload().getData()); assertNotNull(payload); SimpletypesConfig.Builder builder = new SimpletypesConfig.Builder(); new ConfigPayloadApplier<>(builder).applyPayload(payload); SimpletypesConfig config = new SimpletypesConfig(builder); - assertThat(config.intval(), is(123)); - } - - private ConfigResponse createResponse() { - SimpletypesConfig.Builder builder = new SimpletypesConfig.Builder(); - builder.intval(123); - SimpletypesConfig responseConfig = new SimpletypesConfig(builder); - ConfigPayload responsePayload = ConfigPayload.fromInstance(responseConfig); - return SlimeConfigResponse.fromConfigPayload(responsePayload, - 3L, - true, /* internalRedeploy */ - ConfigUtils.getMd5(responsePayload)); + assertThat(config.intval(), is(0)); } private void testPrintStatistics(RpcTester tester) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcTester.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcTester.java index fd8c791b567..868846674df 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcTester.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcTester.java @@ -13,23 +13,28 @@ import com.yahoo.jrt.Transport; import com.yahoo.net.HostName; import com.yahoo.test.ManualClock; import com.yahoo.vespa.config.GenerationCounter; +import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.MemoryGenerationCounter; import com.yahoo.vespa.config.server.PortRangeAllocator; import com.yahoo.vespa.config.server.SuperModelManager; import com.yahoo.vespa.config.server.SuperModelRequestHandler; +import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.TestConfigDefinitionRepo; +import com.yahoo.vespa.config.server.application.OrchestratorMock; import com.yahoo.vespa.config.server.filedistribution.FileServer; import com.yahoo.vespa.config.server.host.ConfigRequestHostLivenessTracker; import com.yahoo.vespa.config.server.host.HostRegistries; +import com.yahoo.vespa.config.server.http.SessionHandlerTest; import com.yahoo.vespa.config.server.monitoring.Metrics; import com.yahoo.vespa.config.server.rpc.security.NoopRpcAuthorizer; -import com.yahoo.vespa.config.server.tenant.MockTenantProvider; -import com.yahoo.vespa.config.server.tenant.TenantHandlerProvider; +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.rules.TemporaryFolder; import java.io.IOException; +import java.time.Clock; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; @@ -51,16 +56,18 @@ public class RpcTester implements AutoCloseable { private final ManualClock clock = new ManualClock(Instant.ofEpochMilli(100)); private final String myHostname = HostName.getLocalhost(); private final HostLivenessTracker hostLivenessTracker = new ConfigRequestHostLivenessTracker(clock); - private final MockTenantProvider tenantProvider; private final GenerationCounter generationCounter; private final Spec spec; private RpcServer rpcServer; private Thread t; private Supervisor sup; + private final ApplicationId applicationId; + private final TenantName tenantName; + private final TenantRepository tenantRepository; - private final List<Integer> allocatedPorts; - + private final ApplicationRepository applicationRepository; + private final List<Integer> allocatedPorts = new ArrayList<>(); private final TemporaryFolder temporaryFolder; private final ConfigserverConfig configserverConfig; @@ -70,13 +77,25 @@ public class RpcTester implements AutoCloseable { RpcTester(ApplicationId applicationId, TemporaryFolder temporaryFolder, ConfigserverConfig.Builder configBuilder) throws InterruptedException, IOException { this.temporaryFolder = temporaryFolder; - allocatedPorts = new ArrayList<>(); + this.applicationId = applicationId; + this.tenantName = applicationId.tenant(); int port = allocatePort(); spec = createSpec(port); - tenantProvider = new MockTenantProvider(applicationId); - generationCounter = new MemoryGenerationCounter(); - configBuilder.rpcport(port); + configBuilder.rpcport(port) + .configServerDBDir(temporaryFolder.newFolder().getAbsolutePath()) + .configDefinitionsDir(temporaryFolder.newFolder().getAbsolutePath()); configserverConfig = new ConfigserverConfig(configBuilder); + TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder() + .configDefinitionRepo(new TestConfigDefinitionRepo()) + .configServerConfig(configserverConfig) + .build(); + tenantRepository = new TenantRepository(componentRegistry, false); + tenantRepository.addTenant(tenantName); + applicationRepository = new ApplicationRepository(tenantRepository, + new SessionHandlerTest.MockProvisioner(), + new OrchestratorMock(), + Clock.systemUTC()); + generationCounter = new MemoryGenerationCounter(); createAndStartRpcServer(); assertFalse(hostLivenessTracker.lastRequestFrom(myHostname).isPresent()); } @@ -94,6 +113,9 @@ public class RpcTester implements AutoCloseable { } void createAndStartRpcServer() throws IOException { + HostRegistries hostRegistries = new HostRegistries(); + hostRegistries.createApplicationHostRegistry(tenantName).update(applicationId, List.of("localhost")); + hostRegistries.getTenantHostRegistry().update(tenantName, List.of("localhost")); rpcServer = new RpcServer(configserverConfig, new SuperModelRequestHandler(new TestConfigDefinitionRepo(), configserverConfig, @@ -102,11 +124,13 @@ public class RpcTester implements AutoCloseable { Zone.defaultZone() , generationCounter, new InMemoryFlagSource())), - Metrics.createTestMetrics(), new HostRegistries(), - hostLivenessTracker, new FileServer(temporaryFolder.newFolder()), + Metrics.createTestMetrics(), + hostRegistries, + hostLivenessTracker, + new FileServer(temporaryFolder.newFolder()), new NoopRpcAuthorizer(), new RpcRequestHandlerProvider()); - rpcServer.onTenantCreate(TenantName.from("default"), tenantProvider); + rpcServer.onTenantCreate(tenantRepository.getTenant(tenantName)); t = new Thread(rpcServer); t.start(); sup = new Supervisor(new Transport()); @@ -149,8 +173,8 @@ public class RpcTester implements AutoCloseable { return rpcServer; } - TenantHandlerProvider tenantProvider() { - return tenantProvider; - } + Tenant tenant() { return tenantRepository.getTenant(tenantName); } + + public ApplicationRepository applicationRepository() { return applicationRepository; } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/MockTenantListener.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/MockTenantListener.java index 109a2220e0d..0ad8e43f066 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/MockTenantListener.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/MockTenantListener.java @@ -7,16 +7,13 @@ import com.yahoo.config.provision.TenantName; * @author Ulf Lilleengen */ public class MockTenantListener implements TenantListener { + TenantName tenantCreatedName; - TenantHandlerProvider provider; TenantName tenantDeletedName; boolean tenantsLoaded; @Override - public void onTenantCreate(TenantName tenantName, TenantHandlerProvider provider) { - this.tenantCreatedName = tenantName; - this.provider = provider; - } + public void onTenantCreate(Tenant tenant) { this.tenantCreatedName = tenant.getName(); } @Override public void onTenantDelete(TenantName tenantName) { |