summaryrefslogtreecommitdiffstats
path: root/configserver/src/test/java
diff options
context:
space:
mode:
Diffstat (limited to 'configserver/src/test/java')
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java73
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java5
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java7
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/MockSecretStore.java35
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java13
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java22
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java40
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/CompressedApplicationInputStreamTest.java (renamed from configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java)6
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java6
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java49
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java7
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainerTest.java1
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java108
-rwxr-xr-xconfigserver/src/test/java/com/yahoo/vespa/config/server/model/RoutingProducerTest.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRequestHandler.java6
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcServerTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcTester.java14
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java324
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java8
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java9
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java50
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/RemoteSessionRepoTest.java10
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java106
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializerTest.java50
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointsCacheTest.java36
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java10
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java36
36 files changed, 871 insertions, 192 deletions
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 e0fa760b35d..9b76c349259 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
@@ -1,7 +1,6 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.google.common.io.Files;
import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.component.Version;
@@ -21,6 +20,7 @@ import com.yahoo.test.ManualClock;
import com.yahoo.text.Utf8;
import com.yahoo.vespa.config.server.application.OrchestratorMock;
import com.yahoo.vespa.config.server.deploy.DeployTester;
+import com.yahoo.vespa.config.server.http.LogRetriever;
import com.yahoo.vespa.config.server.http.SessionHandlerTest;
import com.yahoo.vespa.config.server.http.v2.PrepareResult;
import com.yahoo.vespa.config.server.session.LocalSession;
@@ -37,6 +37,8 @@ import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
@@ -46,17 +48,11 @@ import java.util.Collections;
import java.util.Optional;
import java.util.Set;
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.get;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
@@ -83,21 +79,22 @@ public class ApplicationRepositoryTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
- @Rule
- public final WireMockRule wireMock = new WireMockRule(options().port(8080), true);
-
@Before
public void setup() {
Curator curator = new MockCurator();
tenantRepository = new TenantRepository(new TestComponentRegistry.Builder()
.curator(curator)
.build());
+ tenantRepository.addTenant(TenantRepository.HOSTED_VESPA_TENANT);
tenantRepository.addTenant(tenant1);
tenantRepository.addTenant(tenant2);
tenantRepository.addTenant(tenant3);
orchestrator = new OrchestratorMock();
provisioner = new SessionHandlerTest.MockProvisioner();
- applicationRepository = new ApplicationRepository(tenantRepository, provisioner, orchestrator, clock);
+ applicationRepository = new ApplicationRepository(tenantRepository,
+ provisioner,
+ orchestrator,
+ clock);
timeoutBudget = new TimeoutBudget(clock, Duration.ofSeconds(60));
}
@@ -151,7 +148,11 @@ public class ApplicationRepositoryTest {
@Test
public void getLogs() {
- wireMock.stubFor(get(urlEqualTo("/logs")).willReturn(aResponse().withStatus(200)));
+ applicationRepository = new ApplicationRepository(tenantRepository,
+ provisioner,
+ orchestrator,
+ new MockLogRetriever(),
+ clock);
deployApp(testAppLogServerWithContainer);
HttpResponse response = applicationRepository.getLogs(applicationId(), Optional.empty(), "");
assertEquals(200, response.getStatus());
@@ -159,14 +160,24 @@ public class ApplicationRepositoryTest {
@Test
public void getLogsForHostname() {
- wireMock.stubFor(get(urlEqualTo("/logs")).willReturn(aResponse().withStatus(200)));
- deployApp(testAppLogServerWithContainer);
- HttpResponse response = applicationRepository.getLogs(applicationId(), Optional.of("localhost"), "");
+ applicationRepository = new ApplicationRepository(tenantRepository,
+ provisioner,
+ orchestrator,
+ new MockLogRetriever(),
+ clock);
+ ApplicationId applicationId = ApplicationId.from("hosted-vespa", "tenant-host", "default");
+ deployApp(testAppLogServerWithContainer, new PrepareParams.Builder().applicationId(applicationId).build());
+ HttpResponse response = applicationRepository.getLogs(applicationId, Optional.of("localhost"), "");
assertEquals(200, response.getStatus());
}
@Test(expected = IllegalArgumentException.class)
public void refuseToGetLogsFromHostnameNotInApplication() {
+ applicationRepository = new ApplicationRepository(tenantRepository,
+ provisioner,
+ orchestrator,
+ new MockLogRetriever(),
+ clock);
deployApp(testAppLogServerWithContainer);
HttpResponse response = applicationRepository.getLogs(applicationId(), Optional.of("host123.fake.yahoo.com"), "");
assertEquals(200, response.getStatus());
@@ -273,8 +284,8 @@ public class ApplicationRepositoryTest {
assertNull(tenant.getLocalSessionRepo().getSession(sessionId));
assertNull(tenant.getRemoteSessionRepo().getSession(sessionId));
assertTrue(provisioner.removed);
- assertThat(provisioner.lastApplicationId.tenant(), is(tenant.getName()));
- assertThat(provisioner.lastApplicationId, is(applicationId()));
+ assertEquals(tenant.getName(), provisioner.lastApplicationId.tenant());
+ assertEquals(applicationId(), provisioner.lastApplicationId);
assertFalse(applicationRepository.delete(applicationId()));
}
@@ -292,7 +303,7 @@ public class ApplicationRepositoryTest {
// Delete app with id fooId, should not affect original app
assertTrue(applicationRepository.delete(fooId));
- assertThat(provisioner.lastApplicationId, is(fooId));
+ assertEquals(fooId, provisioner.lastApplicationId);
assertNotNull(applicationRepository.getActiveSession(applicationId()));
assertTrue(applicationRepository.delete(applicationId()));
@@ -332,7 +343,7 @@ public class ApplicationRepositoryTest {
// All sessions except 3 should be removed after the call to deleteExpiredLocalSessions
tester.applicationRepository().deleteExpiredLocalSessions();
- final Collection<LocalSession> sessions = tester.tenant().getLocalSessionRepo().listSessions();
+ Collection<LocalSession> sessions = tester.tenant().getLocalSessionRepo().listSessions();
assertEquals(1, sessions.size());
assertEquals(3, new ArrayList<>(sessions).get(0).getSessionId());
@@ -372,4 +383,28 @@ public class ApplicationRepositoryTest {
Tenant tenant = tenantRepository.getTenant(applicationId.tenant());
return applicationRepository.getMetadataFromSession(tenant, sessionId);
}
+
+ private static class MockLogRetriever extends LogRetriever {
+
+ @Override
+ public HttpResponse getLogs(String logServerHostname) {
+ return new MockHttpResponse();
+ }
+
+ private static class MockHttpResponse extends HttpResponse {
+
+ private MockHttpResponse() {
+ super(200);
+ }
+
+ @Override
+ public void render(OutputStream outputStream) throws IOException {
+ outputStream.write("log line".getBytes(StandardCharsets.UTF_8));
+ }
+
+ }
+
+
+ }
+
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java
index 2e7b5a1f4d9..0b56591d6a1 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java
@@ -12,7 +12,6 @@ import com.yahoo.config.provision.RegionName;
import com.yahoo.component.Version;
import com.yahoo.config.provision.Zone;
import com.yahoo.container.QrSearchersConfig;
-import com.yahoo.container.core.VipStatusConfig;
import com.yahoo.container.handler.ClustersStatus;
import com.yahoo.container.handler.VipStatus;
import com.yahoo.container.jdisc.config.HealthMonitorConfig;
@@ -61,7 +60,7 @@ public class ConfigServerBootstrapTest {
@Test
public void testBootstrap() throws Exception {
ConfigserverConfig configserverConfig = createConfigserverConfig(temporaryFolder);
- InMemoryProvisioner provisioner = new InMemoryProvisioner(true, "host0", "host1", "host3");
+ InMemoryProvisioner provisioner = new InMemoryProvisioner(true, "host0", "host1", "host3", "host4");
DeployTester tester = new DeployTester(configserverConfig, provisioner);
tester.deployApp("src/test/apps/hosted/");
@@ -94,7 +93,7 @@ public class ConfigServerBootstrapTest {
@Test
public void testBootstrapWithVipStatusFile() throws Exception {
ConfigserverConfig configserverConfig = createConfigserverConfig(temporaryFolder);
- InMemoryProvisioner provisioner = new InMemoryProvisioner(true, "host0", "host1", "host3");
+ InMemoryProvisioner provisioner = new InMemoryProvisioner(true, "host0", "host1", "host3", "host4");
DeployTester tester = new DeployTester(configserverConfig, provisioner);
tester.deployApp("src/test/apps/hosted/");
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java
index 476f77ae1db..e4ff8702ff1 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java
@@ -14,6 +14,8 @@ import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
import com.yahoo.vespa.config.server.monitoring.Metrics;
import com.yahoo.vespa.config.server.provision.HostProvisionerProvider;
import com.yahoo.vespa.config.server.rpc.RpcServer;
+import com.yahoo.vespa.config.server.rpc.RpcRequestHandlerProvider;
+import com.yahoo.vespa.config.server.rpc.security.NoopRpcAuthorizer;
import com.yahoo.vespa.config.server.session.SessionPreparer;
import com.yahoo.vespa.config.server.session.SessionTest;
import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
@@ -66,7 +68,7 @@ public class InjectedGlobalComponentRegistryTest {
.configDefinitionsDir(temporaryFolder.newFolder("configdefinitions").getAbsolutePath()));
sessionPreparer = new SessionTest.MockSessionPreparer();
rpcServer = new RpcServer(configserverConfig, null, Metrics.createTestMetrics(),
- new HostRegistries(), new ConfigRequestHostLivenessTracker(), new FileServer(temporaryFolder.newFolder("filereferences")));
+ new HostRegistries(), new ConfigRequestHostLivenessTracker(), new FileServer(temporaryFolder.newFolder("filereferences")), new NoopRpcAuthorizer(), new RpcRequestHandlerProvider());
generationCounter = new SuperModelGenerationCounter(curator);
defRepo = new StaticConfigDefinitionRepo();
permanentApplicationPackage = new PermanentApplicationPackage(configserverConfig);
@@ -76,7 +78,7 @@ public class InjectedGlobalComponentRegistryTest {
globalComponentRegistry =
new InjectedGlobalComponentRegistry(curator, configCurator, metrics, modelFactoryRegistry, sessionPreparer, rpcServer, configserverConfig,
generationCounter, defRepo, permanentApplicationPackage, hostRegistries, hostProvisionerProvider, zone,
- new ConfigServerDB(configserverConfig), new InMemoryFlagSource());
+ new ConfigServerDB(configserverConfig), new InMemoryFlagSource(), new MockSecretStore());
}
@Test
@@ -88,7 +90,6 @@ public class InjectedGlobalComponentRegistryTest {
assertThat(globalComponentRegistry.getConfigserverConfig(), is(configserverConfig));
assertThat(globalComponentRegistry.getReloadListener().hashCode(), is(rpcServer.hashCode()));
assertThat(globalComponentRegistry.getTenantListener().hashCode(), is(rpcServer.hashCode()));
- assertThat(globalComponentRegistry.getSuperModelGenerationCounter(), is(generationCounter));
assertThat(globalComponentRegistry.getStaticConfigDefinitionRepo(), is(defRepo));
assertThat(globalComponentRegistry.getPermanentApplicationPackage(), is(permanentApplicationPackage));
assertThat(globalComponentRegistry.getHostRegistries(), is(hostRegistries));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockSecretStore.java b/configserver/src/test/java/com/yahoo/vespa/config/server/MockSecretStore.java
new file mode 100644
index 00000000000..8a77b53875e
--- /dev/null
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/MockSecretStore.java
@@ -0,0 +1,35 @@
+// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.config.server;
+
+import com.yahoo.container.jdisc.secretstore.SecretStore;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MockSecretStore implements SecretStore {
+ Map<String, String> secrets = new HashMap<>();
+
+ @Override
+ public String getSecret(String key) {
+ if(secrets.containsKey(key))
+ return secrets.get(key);
+ throw new RuntimeException("Key not found: " + key);
+ }
+
+ @Override
+ public String getSecret(String key, int version) {
+ return getSecret(key);
+ }
+
+ public void put(String key, String value) {
+ secrets.put(key, value);
+ }
+
+ public void remove(String key) {
+ secrets.remove(key);
+ }
+
+ public void clear() {
+ secrets.clear();
+ }
+}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java
index 1b4ed2283ba..860bbdc134c 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.config.server;
import com.yahoo.component.Version;
+import com.yahoo.config.model.api.ContainerEndpoint;
import com.yahoo.config.model.api.ModelContext;
import com.yahoo.config.model.application.provider.BaseDeployLogger;
import com.yahoo.config.model.application.provider.MockFileRegistry;
@@ -14,6 +15,7 @@ import com.yahoo.vespa.flags.InMemoryFlagSource;
import org.junit.Test;
import java.util.Collections;
+import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -33,6 +35,10 @@ public class ModelContextImplTest {
final Rotation rotation = new Rotation("this.is.a.mock.rotation");
final Set<Rotation> rotations = Collections.singleton(rotation);
+
+ final ContainerEndpoint endpoint = new ContainerEndpoint("foo", List.of("a", "b"));
+ final Set<ContainerEndpoint> endpoints = Collections.singleton(endpoint);
+
final InMemoryFlagSource flagSource = new InMemoryFlagSource();
ModelContext context = new ModelContextImpl(
@@ -53,9 +59,11 @@ public class ModelContextImplTest {
false,
Zone.defaultZone(),
rotations,
+ endpoints,
false,
false,
- flagSource),
+ flagSource,
+ null),
Optional.empty(),
new Version(6),
new Version(6));
@@ -71,7 +79,8 @@ public class ModelContextImplTest {
assertNotNull(context.properties().zone());
assertFalse(context.properties().hostedVespa());
assertThat(context.properties().rotations(), equalTo(rotations));
+ assertThat(context.properties().endpoints(), equalTo(endpoints));
assertThat(context.properties().isFirstTimeDeployment(), equalTo(false));
- assertThat(context.properties().useDedicatedNodeForLogserver(), equalTo(false));
+ assertThat(context.properties().useDedicatedNodeForLogserver(), equalTo(true));
}
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java
index 35ad97b7b43..f7b900c8f02 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelRequestHandlerTest.java
@@ -56,17 +56,16 @@ public class SuperModelRequestHandlerTest {
ApplicationId bar = applicationId("a", "foo");
assertNotNull(controller.getHandler());
- long gen = counter.increment();
+ long gen = counter.get();
controller.reloadConfig(createApp(foo, 3l));
assertNotNull(controller.getHandler());
- assertThat(controller.getHandler().getGeneration(), is(gen));
+ assertThat(controller.getHandler().getGeneration(), is(gen + 1));
controller.reloadConfig(createApp(foo, 4l));
- assertThat(controller.getHandler().getGeneration(), is(gen));
+ assertThat(controller.getHandler().getGeneration(), is(gen + 2));
// Test that a new app is used when there already exist an application with the same id
assertThat(controller.getHandler().getSuperModel().applicationModels().get(foo).getGeneration(), is(4l));
- gen = counter.increment();
controller.reloadConfig(createApp(bar, 2l));
- assertThat(controller.getHandler().getGeneration(), is(gen));
+ assertThat(controller.getHandler().getGeneration(), is(gen + 3));
}
@Test
@@ -75,22 +74,21 @@ public class SuperModelRequestHandlerTest {
ApplicationId bar = applicationId("a", "bar");
ApplicationId baz = applicationId("b", "baz");
- long gen = counter.increment();
+ long gen = counter.get();
controller.reloadConfig(createApp(foo, 3l));
controller.reloadConfig(createApp(bar, 30l));
controller.reloadConfig(createApp(baz, 9l));
- assertThat(controller.getHandler().getGeneration(), is(gen));
+ assertThat(controller.getHandler().getGeneration(), is(gen + 3));
assertThat(controller.getHandler().getSuperModel().applicationModels().size(), is(3));
assertEquals(Arrays.asList(foo, bar, baz), new ArrayList<>(controller.getHandler().getSuperModel().applicationModels().keySet()));
controller.removeApplication(new ApplicationId.Builder().tenant("a").applicationName("unknown").build());
- assertThat(controller.getHandler().getGeneration(), is(gen));
+ assertThat(controller.getHandler().getGeneration(), is(gen + 4));
assertThat(controller.getHandler().getSuperModel().applicationModels().size(), is(3));
assertEquals(Arrays.asList(foo, bar, baz), new ArrayList<>(controller.getHandler().getSuperModel().applicationModels().keySet()));
- gen = counter.increment();
controller.removeApplication(bar);
assertThat(controller.getHandler().getSuperModel().applicationModels().size(), is(2));
assertEquals(Arrays.asList(foo, baz), new ArrayList<>(controller.getHandler().getSuperModel().applicationModels().keySet()));
- assertThat(controller.getHandler().getGeneration(), is(gen));
+ assertThat(controller.getHandler().getGeneration(), is(gen + 5));
}
@Test
@@ -101,9 +99,9 @@ public class SuperModelRequestHandlerTest {
manager = new SuperModelManager(configserverConfig, emptyNodeFlavors(), counter, new InMemoryFlagSource());
controller = new SuperModelRequestHandler(new TestConfigDefinitionRepo(), configserverConfig, manager);
- long gen = counter.increment();
+ long gen = counter.get();
controller.reloadConfig(createApp(foo, 3L));
- assertThat(controller.getHandler().getGeneration(), is(masterGen + gen));
+ assertThat(controller.getHandler().getGeneration(), is(masterGen + gen + 1));
}
@Test
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 ef1f0f380e3..a304f74858b 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
@@ -3,10 +3,14 @@ package com.yahoo.vespa.config.server;
import com.google.common.io.Files;
import com.yahoo.cloud.config.ConfigserverConfig;
+import com.yahoo.concurrent.InThreadExecutorService;
+import com.yahoo.concurrent.StripedExecutor;
import com.yahoo.config.model.NullConfigModelRegistry;
import com.yahoo.config.model.api.ConfigDefinitionRepo;
import com.yahoo.config.provision.Provisioner;
+import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
+import com.yahoo.container.jdisc.secretstore.SecretStore;
import com.yahoo.vespa.config.server.application.PermanentApplicationPackage;
import com.yahoo.vespa.config.server.host.HostRegistries;
import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
@@ -28,6 +32,7 @@ import com.yahoo.vespa.model.VespaModelFactory;
import java.time.Clock;
import java.util.Collections;
import java.util.Optional;
+import java.util.concurrent.ExecutorService;
/**
@@ -40,7 +45,6 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
private final Metrics metrics;
private final SessionPreparer sessionPreparer;
private final ConfigserverConfig configserverConfig;
- private final SuperModelGenerationCounter superModelGenerationCounter;
private final ConfigDefinitionRepo defRepo;
private final ReloadListener reloadListener;
private final TenantListener tenantListener;
@@ -52,6 +56,9 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
private final Zone zone;
private final Clock clock;
private final ConfigServerDB configServerDB;
+ private final StripedExecutor<TenantName> zkWatcherExecutor;
+ private final ExecutorService zkCacheExecutor;
+ private final SecretStore secretStore;
private TestComponentRegistry(Curator curator, ConfigCurator configCurator, Metrics metrics,
ModelFactoryRegistry modelFactoryRegistry,
@@ -65,14 +72,14 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
ReloadListener reloadListener,
TenantListener tenantListener,
Zone zone,
- Clock clock) {
+ Clock clock,
+ SecretStore secretStore) {
this.curator = curator;
this.configCurator = configCurator;
this.metrics = metrics;
this.configserverConfig = configserverConfig;
this.reloadListener = reloadListener;
this.tenantListener = tenantListener;
- this.superModelGenerationCounter = new SuperModelGenerationCounter(curator);
this.defRepo = defRepo;
this.permanentApplicationPackage = permanentApplicationPackage;
this.hostRegistries = hostRegistries;
@@ -83,6 +90,9 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
this.zone = zone;
this.clock = clock;
this.configServerDB = new ConfigServerDB(configserverConfig);
+ this.zkWatcherExecutor = new StripedExecutor<>(new InThreadExecutorService());
+ this.zkCacheExecutor = new InThreadExecutorService();
+ this.secretStore = secretStore;
}
public static class Builder {
@@ -92,6 +102,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
private ConfigserverConfig configserverConfig = new ConfigserverConfig(
new ConfigserverConfig.Builder()
.configServerDBDir(Files.createTempDir().getAbsolutePath())
+ .sessionLifetime(5)
.configDefinitionsDir(Files.createTempDir().getAbsolutePath()));
private ConfigDefinitionRepo defRepo = new StaticConfigDefinitionRepo();
private TenantRequestHandlerTest.MockReloadListener reloadListener = new TenantRequestHandlerTest.MockReloadListener();
@@ -151,14 +162,15 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
.orElse(new MockFileDistributionFactory(configserverConfig));
HostProvisionerProvider hostProvisionerProvider = hostProvisioner.
map(HostProvisionerProvider::withProvisioner).orElseGet(HostProvisionerProvider::empty);
+ SecretStore secretStore = new MockSecretStore();
SessionPreparer sessionPreparer = new SessionPreparer(modelFactoryRegistry, fileDistributionFactory,
hostProvisionerProvider, permApp,
configserverConfig, defRepo, curator,
- zone, new InMemoryFlagSource());
+ zone, new InMemoryFlagSource(), secretStore);
return new TestComponentRegistry(curator, ConfigCurator.create(curator), metrics, modelFactoryRegistry,
permApp, fileDistributionFactory, hostRegistries, configserverConfig,
sessionPreparer, hostProvisioner, defRepo, reloadListener, tenantListener,
- zone, clock);
+ zone, clock, secretStore);
}
}
@@ -177,8 +189,6 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
@Override
public ReloadListener getReloadListener() { return reloadListener; }
@Override
- public SuperModelGenerationCounter getSuperModelGenerationCounter() { return superModelGenerationCounter; }
- @Override
public ConfigDefinitionRepo getStaticConfigDefinitionRepo() { return defRepo; }
@Override
public PermanentApplicationPackage getPermanentApplicationPackage() { return permanentApplicationPackage; }
@@ -198,9 +208,25 @@ public class TestComponentRegistry implements GlobalComponentRegistry {
public Clock getClock() { return clock;}
@Override
public ConfigServerDB getConfigServerDB() { return configServerDB;}
+
+ @Override
+ public StripedExecutor<TenantName> getZkWatcherExecutor() {
+ return zkWatcherExecutor;
+ }
+
@Override
public FlagSource getFlagSource() { return new InMemoryFlagSource(); }
+ @Override
+ public ExecutorService getZkCacheExecutor() {
+ return zkCacheExecutor;
+ }
+
+ @Override
+ public SecretStore getSecretStore() {
+ return secretStore;
+ }
+
public FileDistributionFactory getFileDistributionFactory() { return fileDistributionFactory; }
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/CompressedApplicationInputStreamTest.java
index 7faf33b2ff2..496da2cf809 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/CompressedApplicationInputStreamTest.java
@@ -1,8 +1,9 @@
-// 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;
+// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.config.server.application;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
+import com.yahoo.vespa.config.server.application.CompressedApplicationInputStream;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
@@ -26,7 +27,6 @@ import static org.junit.Assert.assertTrue;
/**
* @author Ulf Lilleengen
- * @since 5.1
*/
public class CompressedApplicationInputStreamTest {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
index ac7ff1e85c5..e3335dded4c 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
@@ -6,6 +6,7 @@ import com.yahoo.config.provision.TenantName;
import com.yahoo.text.Utf8;
import com.yahoo.vespa.config.server.MockReloadHandler;
+import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
@@ -115,7 +116,7 @@ public class TenantApplicationsTest {
}
private TenantApplications createZKAppRepo(MockReloadHandler reloadHandler) {
- return TenantApplications.create(curator, reloadHandler, tenantName);
+ return TenantApplications.create(new TestComponentRegistry.Builder().curator(curator).build(), reloadHandler, tenantName);
}
private static ApplicationId createApplicationId(String name) {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
index 6b67dcc4e9a..f619bd92bef 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
@@ -30,6 +30,7 @@ import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.TimeoutBudget;
import com.yahoo.vespa.config.server.application.OrchestratorMock;
+import com.yahoo.vespa.config.server.http.LogRetriever;
import com.yahoo.vespa.config.server.http.v2.PrepareResult;
import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
import com.yahoo.vespa.config.server.monitoring.Metrics;
@@ -126,8 +127,9 @@ public class DeployTester {
applicationRepository = new ApplicationRepository(tenantRepository,
new ProvisionerAdapter(provisioner),
new OrchestratorMock(),
- clock,
- configserverConfig);
+ configserverConfig,
+ new LogRetriever(),
+ clock);
}
public Tenant tenant() {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
index c5d1e8dc0a1..b363c749212 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
@@ -15,11 +15,8 @@ import com.yahoo.config.model.provision.Host;
import com.yahoo.config.model.provision.Hosts;
import com.yahoo.config.model.provision.InMemoryProvisioner;
import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
-import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.RegionName;
-import com.yahoo.config.provision.RotationName;
import com.yahoo.config.provision.Zone;
import com.yahoo.test.ManualClock;
import com.yahoo.vespa.config.server.configchange.MockRestartAction;
@@ -39,7 +36,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
-import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -97,7 +93,7 @@ public class HostedDeployTest {
DeployTester.createModelFactory(Version.fromString("7.0.0"), clock));
DeployTester tester = new DeployTester(modelFactories, createConfigserverConfig(), clock, Zone.defaultZone());
tester.deployApp("src/test/apps/hosted/", "6.2.0", Instant.now());
- assertEquals(3, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
+ assertEquals(4, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
}
/**
@@ -108,7 +104,8 @@ public class HostedDeployTest {
public void testCreateOnlyNeededModelVersions() {
List<Host> hosts = Arrays.asList(createHost("host1", "6.0.0"),
createHost("host2", "6.1.0"),
- createHost("host3")); //Use a host with no version as well
+ createHost("host3"), //Use a host with no version as well
+ createHost("host4", "6.1.0"));
InMemoryProvisioner provisioner = new InMemoryProvisioner(new Hosts(hosts), true);
CountingModelFactory factory600 = DeployTester.createModelFactory(Version.fromString("6.0.0"));
@@ -127,7 +124,7 @@ public class HostedDeployTest {
DeployTester tester = new DeployTester(modelFactories, createConfigserverConfig(), Clock.systemUTC(), provisioner);
// Deploy with version that does not exist on hosts, the model for this version should also be created
tester.deployApp("src/test/apps/hosted/", "7.0.0", Instant.now());
- assertEquals(3, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
+ assertEquals(4, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
// Check >0 not ==0 as the session watcher thread is running and will redeploy models in the background
assertTrue(factory600.creationCount() > 0);
@@ -145,7 +142,7 @@ public class HostedDeployTest {
*/
@Test
public void testCreateOnlyNeededModelVersionsNewNodes() {
- List<Host> hosts = Arrays.asList(createHost("host1"), createHost("host2"), createHost("host3"));
+ List<Host> hosts = Arrays.asList(createHost("host1"), createHost("host2"), createHost("host3"), createHost("host4"));
InMemoryProvisioner provisioner = new InMemoryProvisioner(new Hosts(hosts), true);
CountingModelFactory factory600 = DeployTester.createModelFactory(Version.fromString("6.0.0"));
@@ -157,7 +154,7 @@ public class HostedDeployTest {
DeployTester tester = new DeployTester(modelFactories, createConfigserverConfig(), Clock.systemUTC(), provisioner);
// Deploy with version that does not exist on hosts, the model for this version should also be created
tester.deployApp("src/test/apps/hosted/", "7.0.0", Instant.now());
- assertEquals(3, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
+ assertEquals(4, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
// Check >0 not ==0 as the session watcher thread is running and will redeploy models in the background
assertTrue(factory700.creationCount() > 0);
@@ -195,7 +192,8 @@ public class HostedDeployTest {
String newestOnNewMajorVersion = newestMajorVersion + ".2.0";
List<Host> hosts = Arrays.asList(createHost("host1", oldestVersion),
createHost("host2", newestOnOldMajorVersion),
- createHost("host3", newestOnOldMajorVersion));
+ createHost("host3", newestOnOldMajorVersion),
+ createHost("host4", newestOnOldMajorVersion));
InMemoryProvisioner provisioner = new InMemoryProvisioner(new Hosts(hosts), true);
CountingModelFactory factory1 = DeployTester.createModelFactory(Version.fromString(oldestVersion));
@@ -205,7 +203,7 @@ public class HostedDeployTest {
DeployTester tester = new DeployTester(modelFactories, createConfigserverConfig(), Clock.systemUTC(), provisioner);
tester.deployApp("src/test/apps/hosted/", oldestVersion, Instant.now());
- assertEquals(3, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
+ assertEquals(4, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
// Check >0 not ==0 as the session watcher thread is running and will redeploy models in the background
assertTrue(factory1.creationCount() > 0);
@@ -256,7 +254,7 @@ public class HostedDeployTest {
@Test
public void testAccessControlIsOnlyCheckedWhenNoProdDeploymentExists() {
// Provisioner does not reuse hosts, so need twice as many hosts as app requires
- List<Host> hosts = IntStream.rangeClosed(1,6).mapToObj(i -> createHost("host" + i, "6.0.0")).collect(Collectors.toList());
+ List<Host> hosts = IntStream.rangeClosed(1,8).mapToObj(i -> createHost("host" + i, "6.0.0")).collect(Collectors.toList());
InMemoryProvisioner provisioner = new InMemoryProvisioner(new Hosts(hosts), true);
CountingModelFactory factory600 = DeployTester.createModelFactory(Version.fromString("6.0.0"));
@@ -269,12 +267,12 @@ public class HostedDeployTest {
ApplicationId applicationId = tester.applicationId();
// Deploy with oldest version
tester.deployApp("src/test/apps/hosted/", "6.0.0", Instant.now());
- assertEquals(3, tester.getAllocatedHostsOf(applicationId).getHosts().size());
+ assertEquals(4, tester.getAllocatedHostsOf(applicationId).getHosts().size());
// Deploy with version that does not exist on hosts and with app package that has no write access control,
// validation of access control should not be done, since the app is already deployed in prod
tester.deployApp("src/test/apps/hosted-no-write-access-control", "6.1.0", Instant.now());
- assertEquals(3, tester.getAllocatedHostsOf(applicationId).getHosts().size());
+ assertEquals(4, tester.getAllocatedHostsOf(applicationId).getHosts().size());
}
@Test
@@ -321,7 +319,8 @@ public class HostedDeployTest {
public void testThatConfigChangeActionsAreCollectedFromAllModels() {
List<Host> hosts = Arrays.asList(createHost("host1", "6.1.0"),
createHost("host2", "6.2.0"),
- createHost("host3", "6.2.0"));
+ createHost("host3", "6.2.0"),
+ createHost("host4", "6.2.0"));
InMemoryProvisioner provisioner = new InMemoryProvisioner(new Hosts(hosts), true);
List<ServiceInfo> services = Collections.singletonList(
new ServiceInfo("serviceName", "serviceType", null, new HashMap<>(), "configId", "hostName"));
@@ -333,30 +332,12 @@ public class HostedDeployTest {
DeployTester tester = new DeployTester(modelFactories, createConfigserverConfig(), Clock.systemUTC(), provisioner);
PrepareResult prepareResult = tester.deployApp("src/test/apps/hosted/", "6.2.0", Instant.now());
- assertEquals(3, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
+ assertEquals(4, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size());
List<RestartActions.Entry> actions = prepareResult.configChangeActions().getRestartActions().getEntries();
assertThat(actions.size(), is(1));
assertThat(actions.get(0).getMessages(), equalTo(ImmutableSet.of("change", "other change")));
}
- @Test
- public void testDeployWithClusterRotations() {
- CountingModelFactory modelFactory = DeployTester.createModelFactory(Version.fromString("4.5.6"), Clock.systemUTC());
- DeployTester tester = new DeployTester(Collections.singletonList(modelFactory), createConfigserverConfig());
- ApplicationId applicationId = tester.applicationId();
-
- tester.deployApp("src/test/apps/hosted/", "4.5.6", Instant.now());
- Set<HostSpec> containers = tester.getAllocatedHostsOf(applicationId).getHosts().stream()
- .filter(h -> h.membership().get().cluster().type() == ClusterSpec.Type.container)
- .collect(Collectors.toSet());
- assertFalse("Allocated container hosts", containers.isEmpty());
-
- Set<RotationName> expected = Set.of(RotationName.from("eu-cluster"), RotationName.from("us-cluster"));
- for (HostSpec container : containers) {
- assertEquals(expected, container.membership().get().cluster().rotations());
- }
- }
-
private static ConfigserverConfig createConfigserverConfig() {
return new ConfigserverConfig(new ConfigserverConfig.Builder()
.configServerDBDir(Files.createTempDir().getAbsolutePath())
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
index e01b2eccb35..918670d71f2 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java
@@ -13,9 +13,9 @@ import com.yahoo.config.model.application.provider.MockFileRegistry;
import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.path.Path;
+import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
import com.yahoo.vespa.config.server.zookeeper.ZKApplicationPackage;
import com.yahoo.vespa.curator.mock.MockCurator;
-import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
@@ -30,10 +30,11 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
+import static com.yahoo.config.provision.serialization.AllocatedHostsSerializer.fromJson;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
/**
* Unit tests for ZooKeeperClient.
@@ -199,7 +200,7 @@ public class ZooKeeperClientTest {
Path hostsPath = app.append(ZKApplicationPackage.allocatedHostsNode);
assertTrue(zk.exists(hostsPath.getAbsolute()));
- AllocatedHosts deserialized = AllocatedHosts.fromJson(zk.getBytes(hostsPath.getAbsolute()), Optional.empty());
+ AllocatedHosts deserialized = fromJson(zk.getBytes(hostsPath.getAbsolute()), Optional.empty());
assertEquals(hosts, deserialized.getHosts());
}
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 b818c39d433..0381af57cc3 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
@@ -99,7 +99,7 @@ public class SessionHandlerTest {
}
private MockSession(long id, ApplicationPackage app, InMemoryFlagSource flagSource) {
- super(TenantName.defaultName(), id, null, new SessionContext(null, new MockSessionZKClient(MockApplicationPackage.createEmpty()), null, null, new HostRegistry<>(), null, flagSource));
+ super(TenantName.defaultName(), id, null, new SessionContext(null, new MockSessionZKClient(MockApplicationPackage.createEmpty()), null, null, new HostRegistry<>(), flagSource));
this.app = app;
this.preparer = new SessionTest.MockSessionPreparer();
this.flagSource = flagSource;
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 a843212927b..41db57ab1e0 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
@@ -197,7 +197,7 @@ public class ApplicationHandlerTest {
ApplicationId unknown = new ApplicationId.Builder().applicationName("unknown").tenant(mytenantName).build();
HttpResponse responseForUnknown = fileDistributionStatus(unknown, zone);
assertEquals(404, responseForUnknown.getStatus());
- assertEquals("{\"error-code\":\"NOT_FOUND\",\"message\":\"No such application id: mytenant.unknown\"}",
+ assertEquals("{\"error-code\":\"NOT_FOUND\",\"message\":\"No such application id: 'mytenant.unknown'\"}",
SessionHandlerTest.getRenderedString(responseForUnknown));
}
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 858d1e0eaa7..d94194e58d9 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
@@ -105,7 +105,7 @@ public class SessionActiveHandlerTest extends SessionHandlerTest {
.modelFactoryRegistry(new ModelFactoryRegistry(Collections.singletonList(modelFactory)))
.build();
tenantRepository = new TenantRepository(componentRegistry, false);
- applicationRepo = TenantApplications.create(curator, new MockReloadHandler(), tenantName);
+ applicationRepo = TenantApplications.create(componentRegistry, new MockReloadHandler(), tenantName);
localRepo = new LocalSessionRepo(clock, curator);
pathPrefix = "/application/v2/tenant/" + tenantName + "/session/";
hostProvisioner = new MockProvisioner();
@@ -232,7 +232,7 @@ public class SessionActiveHandlerTest extends SessionHandlerTest {
ApplicationPackage app = FilesApplicationPackage.fromFileWithDeployData(testApp, deployData);
localRepo.addSession(new LocalSession(tenantName, sessionId, new SessionTest.MockSessionPreparer(),
new SessionContext(app, zkc, new File(tenantFileSystemDirs.sessionsPath(), String.valueOf(sessionId)),
- applicationRepo, new HostRegistry<>(), new SuperModelGenerationCounter(curator),
+ applicationRepo, new HostRegistry<>(),
flagSource)));
}
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 0946ef3992c..ac4b4ea9005 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
@@ -11,7 +11,7 @@ import com.yahoo.vespa.config.server.MockReloadHandler;
import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.application.OrchestratorMock;
import com.yahoo.vespa.config.server.application.TenantApplications;
-import com.yahoo.vespa.config.server.http.CompressedApplicationInputStreamTest;
+import com.yahoo.vespa.config.server.application.CompressedApplicationInputStreamTest;
import com.yahoo.vespa.config.server.http.HandlerTest;
import com.yahoo.vespa.config.server.http.HttpErrorResponse;
import com.yahoo.vespa.config.server.http.SessionHandlerTest;
@@ -72,7 +72,7 @@ public class SessionCreateHandlerTest extends SessionHandlerTest {
@Before
public void setupRepo() {
Curator curator = new MockCurator();
- applicationRepo = TenantApplications.create(curator, new MockReloadHandler(), tenant);
+ applicationRepo = TenantApplications.create(componentRegistry, new MockReloadHandler(), tenant);
localSessionRepo = new LocalSessionRepo(Clock.systemUTC(), curator);
tenantRepository = new TenantRepository(componentRegistry, false);
sessionFactory = new MockSessionFactory();
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 11c0cf057cc..b6c3de8a1b1 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
@@ -87,7 +87,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
.withSessionFactory(new MockSessionFactory())
.withLocalSessionRepo(localRepo)
.withRemoteSessionRepo(remoteSessionRepo)
- .withApplicationRepo(TenantApplications.create(curator, new MockReloadHandler(), tenant));
+ .withApplicationRepo(TenantApplications.create(componentRegistry, new MockReloadHandler(), tenant));
tenantRepository.addTenant(tenantBuilder);
}
@@ -403,7 +403,6 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
null,
null,
new HostRegistry<>(),
- null,
null));
this.exception = exception;
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainerTest.java
index a2f52bc5321..fdc6ffeacf0 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainerTest.java
@@ -37,6 +37,7 @@ public class TenantsMaintainerTest {
assertNotNull(tenantRepository.getTenant(shouldNotBeDeleted));
new TenantsMaintainer(applicationRepository, tester.curator(), Duration.ofDays(1)).run();
+ tenantRepository.updateTenants();
// One tenant should now have been deleted
assertNull(tenantRepository.getTenant(shouldBeDeleted));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java
index 0e124addaf7..34a4074c7cf 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java
@@ -5,6 +5,7 @@ import com.yahoo.cloud.config.LbServicesConfig;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.model.NullConfigModelRegistry;
import com.yahoo.config.model.api.ApplicationInfo;
+import com.yahoo.config.model.api.ContainerEndpoint;
import com.yahoo.config.model.api.Model;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.deploy.TestProperties;
@@ -20,11 +21,14 @@ import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.model.VespaModel;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -33,20 +37,34 @@ import java.util.Random;
import java.util.Set;
import static com.yahoo.config.model.api.container.ContainerServiceType.QRSERVER;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
/**
* @author Ulf Lilleengen
*/
+@RunWith(Parameterized.class)
public class LbServicesProducerTest {
private static final String rotation1 = "rotation-1";
private static final String rotation2 = "rotation-2";
private static final String rotationString = rotation1 + "," + rotation2;
private static final Set<Rotation> rotations = Collections.singleton(new Rotation(rotationString));
+ private static final Set<ContainerEndpoint> endpoints = Set.of(
+ new ContainerEndpoint("mydisc", List.of("rotation-1", "rotation-2"))
+ );
private final InMemoryFlagSource flagSource = new InMemoryFlagSource();
+ private final boolean useGlobalServiceId;
+
+ @Parameterized.Parameters
+ public static Object[] useGlobalServiceId() {
+ return new Object[] { true, false };
+ }
+
+ public LbServicesProducerTest(boolean useGlobalServiceId) {
+ this.useGlobalServiceId = useGlobalServiceId;
+ }
@Test
public void testDeterministicGetConfig() throws IOException, SAXException {
@@ -110,7 +128,7 @@ public class LbServicesProducerTest {
Zone zone = new Zone(Environment.prod, regionName);
Map<TenantName, Set<ApplicationInfo>> testModel = createTestModel(new DeployState.Builder()
.zone(zone)
- .properties(new TestProperties()));
+ .properties(new TestProperties().setHostedVespa(true)));
return getLbServicesConfig(new Zone(Environment.prod, regionName), testModel);
}
@@ -123,18 +141,40 @@ public class LbServicesProducerTest {
@Test
public void testConfigAliasesWithRotations() throws IOException, SAXException {
- Map<TenantName, Set<ApplicationInfo>> testModel = createTestModel(new DeployState.Builder().rotations(rotations));
+ assumeTrue(useGlobalServiceId);
+
+ Map<TenantName, Set<ApplicationInfo>> testModel = createTestModel(new DeployState.Builder()
+ .rotations(rotations)
+ .properties(new TestProperties().setHostedVespa(true)));
RegionName regionName = RegionName.from("us-east-1");
- LbServicesConfig conf = getLbServicesConfig(new Zone(Environment.prod, regionName), testModel);
- final LbServicesConfig.Tenants.Applications.Hosts.Services services = conf.tenants("foo").applications("foo:prod:" + regionName.value() + ":default").hosts("foo.foo.yahoo.com").services(QRSERVER.serviceName);
- assertThat(services.servicealiases().size(), is(1));
- assertThat(services.endpointaliases().size(), is(4));
- assertThat(services.servicealiases(0), is("service1"));
- assertThat(services.endpointaliases(0), is("foo1.bar1.com"));
- assertThat(services.endpointaliases(1), is("foo2.bar2.com"));
- assertThat(services.endpointaliases(2), is(rotation1));
- assertThat(services.endpointaliases(3), is(rotation2));
+ var services = getLbServicesConfig(new Zone(Environment.prod, regionName), testModel)
+ .tenants("foo")
+ .applications("foo:prod:" + regionName.value() + ":default")
+ .hosts("foo.foo.yahoo.com")
+ .services(QRSERVER.serviceName);
+
+ assertThat(services.servicealiases(), contains("service1"));
+ assertThat("Missing rotations in list: " + services.endpointaliases(), services.endpointaliases(), containsInAnyOrder("foo1.bar1.com", "foo2.bar2.com", rotation1, rotation2));
+ }
+
+ @Test
+ public void testConfigAliasesWithEndpoints() throws IOException, SAXException {
+ assumeFalse(useGlobalServiceId);
+
+ Map<TenantName, Set<ApplicationInfo>> testModel = createTestModel(new DeployState.Builder()
+ .endpoints(endpoints)
+ .properties(new TestProperties().setHostedVespa(true)));
+ RegionName regionName = RegionName.from("us-east-1");
+
+ var services = getLbServicesConfig(new Zone(Environment.prod, regionName), testModel)
+ .tenants("foo")
+ .applications("foo:prod:" + regionName.value() + ":default")
+ .hosts("foo.foo.yahoo.com")
+ .services(QRSERVER.serviceName);
+
+ assertThat(services.servicealiases(), contains("service1"));
+ assertThat("Missing endpoints in list: " + services.endpointaliases(), services.endpointaliases(), containsInAnyOrder("foo1.bar1.com", "foo2.bar2.com", rotation1, rotation2));
}
private Map<TenantName, Set<ApplicationInfo>> randomizeApplications(Map<TenantName, Set<ApplicationInfo>> testModel, int seed) {
@@ -181,7 +221,7 @@ public class LbServicesProducerTest {
private ApplicationPackage createApplicationPackage(String host1, String host2) {
String hosts = "<hosts><host name='" + host1 + "'><alias>node1</alias></host><host name='" + host2 + "'><alias>node2</alias></host></hosts>";
String services = "<services><admin version='2.0'><adminserver hostalias='node1' /><logserver hostalias='node1' /><slobroks><slobrok hostalias='node1' /><slobrok hostalias='node2' /></slobroks></admin>"
- + "<jdisc id='mydisc' version='1.0'>" +
+ + "<container id='mydisc' version='1.0'>" +
" <aliases>" +
" <endpoint-alias>foo2.bar2.com</endpoint-alias>" +
" <service-alias>service1</service-alias>" +
@@ -191,16 +231,34 @@ public class LbServicesProducerTest {
" <node hostalias='node1' />" +
" </nodes>" +
" <search/>" +
- "</jdisc>" +
+ "</container>" +
"</services>";
- String deploymentInfo ="<?xml version='1.0' encoding='UTF-8'?>" +
- "<deployment version='1.0'>" +
- " <test />" +
- " <prod global-service-id='mydisc'>" +
- " <region active='true'>us-east-1</region>" +
- " <region active='false'>us-east-2</region>" +
- " </prod>" +
- "</deployment>";
+
+ String deploymentInfo;
+
+ if (useGlobalServiceId) {
+ deploymentInfo ="<?xml version='1.0' encoding='UTF-8'?>" +
+ "<deployment version='1.0'>" +
+ " <test />" +
+ " <prod global-service-id='mydisc'>" +
+ " <region active='true'>us-east-1</region>" +
+ " <region active='false'>us-east-2</region>" +
+ " </prod>" +
+ "</deployment>";
+ } else {
+ deploymentInfo ="<?xml version='1.0' encoding='UTF-8'?>" +
+ "<deployment version='1.0'>" +
+ " <test />" +
+ " <prod>" +
+ " <region active='true'>us-east-1</region>" +
+ " <region active='false'>us-east-2</region>" +
+ " </prod>" +
+ " <endpoints>" +
+ " <endpoint container-id='mydisc' />" +
+ " </endpoints>" +
+ "</deployment>";
+ }
+
return new MockApplicationPackage.Builder().withHosts(hosts).withServices(services).withDeploymentSpec(deploymentInfo).build();
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/model/RoutingProducerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/model/RoutingProducerTest.java
index c6a607f81b1..7ce2c39c6a4 100755
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/model/RoutingProducerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/model/RoutingProducerTest.java
@@ -77,7 +77,7 @@ public class RoutingProducerTest {
private ApplicationPackage createApplicationPackage(String host1, String host2) {
String hosts = "<hosts><host name='" + host1 + "'><alias>node1</alias></host><host name='" + host2 + "'><alias>node2</alias></host></hosts>";
String services = "<services><admin version='2.0'><adminserver hostalias='node1' /><logserver hostalias='node1' /><slobroks><slobrok hostalias='node1' /><slobrok hostalias='node2' /></slobroks></admin>"
- + "<jdisc id='mydisc' version='1.0'>" +
+ + "<container id='mydisc' version='1.0'>" +
" <aliases>" +
" <endpoint-alias>foo2.bar2.com</endpoint-alias>" +
" <service-alias>service1</service-alias>" +
@@ -87,7 +87,7 @@ public class RoutingProducerTest {
" <node hostalias='node1' />" +
" </nodes>" +
" <search/>" +
- "</jdisc>" +
+ "</container>" +
"</services>";
String deploymentInfo ="<?xml version='1.0' encoding='UTF-8'?>" +
"<deployment version='1.0'>" +
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRequestHandler.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRequestHandler.java
index bfc06a58b16..0f6cd10d564 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRequestHandler.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRequestHandler.java
@@ -1,6 +1,7 @@
// 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.rpc;
+import com.yahoo.config.FileReference;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.component.Version;
import com.yahoo.vespa.config.ConfigKey;
@@ -91,6 +92,11 @@ public class MockRequestHandler implements RequestHandler, ReloadHandler, Tenant
}
@Override
+ public Set<FileReference> listFileReferences(ApplicationId applicationId) {
+ return Set.of();
+ }
+
+ @Override
public RequestHandler getRequestHandler() {
return this;
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java
index 0f8bfa5068c..5fa51e1c404 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/MockRpc.java
@@ -11,6 +11,7 @@ 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.monitoring.Metrics;
+import com.yahoo.vespa.config.server.rpc.security.NoopRpcAuthorizer;
import com.yahoo.vespa.config.server.tenant.MockTenantProvider;
import java.io.File;
@@ -38,7 +39,7 @@ public class MockRpc extends RpcServer {
public MockRpc(int port, boolean createDefaultTenant, boolean pretendToHaveLoadedAnyApplication, File tempDir) {
super(createConfig(port), null, Metrics.createTestMetrics(),
- new HostRegistries(), new ConfigRequestHostLivenessTracker(), new FileServer(tempDir));
+ new HostRegistries(), new ConfigRequestHostLivenessTracker(), new FileServer(tempDir), new NoopRpcAuthorizer(), new RpcRequestHandlerProvider());
if (createDefaultTenant) {
onTenantCreate(TenantName.from("default"), new MockTenantProvider(pretendToHaveLoadedAnyApplication));
}
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 c8bc9364922..086dfa5d0d3 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
@@ -114,7 +114,6 @@ public class RpcServerTest {
}
private void testEnabled(RpcTester tester) throws IOException, SAXException {
- tester.generationCounter().increment();
Application app = new Application(new VespaModel(MockApplicationPackage.createEmpty()),
new ServerCache(),
2L,
@@ -174,7 +173,7 @@ public class RpcServerTest {
private void testPrintStatistics(RpcTester tester) {
Request req = new Request("printStatistics");
- tester.rpcServer().printStatistics(req);
+ tester.performRequest(req);
assertThat(req.returnValues().get(0).asString(), is("Delayed responses queue size: 0"));
}
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 dd66f720b1f..53463585582 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
@@ -16,6 +16,7 @@ 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.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.flags.InMemoryFlagSource;
@@ -45,13 +46,13 @@ 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 MockTenantProvider tenantProvider;
- private GenerationCounter generationCounter;
private Thread t;
private Supervisor sup;
- private Spec spec;
private List<Integer> allocatedPorts;
@@ -97,7 +98,9 @@ public class RpcTester implements AutoCloseable {
generationCounter,
new InMemoryFlagSource())),
Metrics.createTestMetrics(), new HostRegistries(),
- hostLivenessTracker, new FileServer(temporaryFolder.newFolder()));
+ hostLivenessTracker, new FileServer(temporaryFolder.newFolder()),
+ new NoopRpcAuthorizer(),
+ new RpcRequestHandlerProvider());
rpcServer.onTenantCreate(TenantName.from("default"), tenantProvider);
t = new Thread(rpcServer);
t.start();
@@ -145,7 +148,4 @@ public class RpcTester implements AutoCloseable {
return tenantProvider;
}
- GenerationCounter generationCounter() {
- return generationCounter;
- }
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java
new file mode 100644
index 00000000000..a1d4f28cb74
--- /dev/null
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java
@@ -0,0 +1,324 @@
+package com.yahoo.vespa.config.server.rpc.security;// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+import com.yahoo.cloud.config.LbServicesConfig;
+import com.yahoo.cloud.config.RoutingConfig;
+import com.yahoo.cloud.config.SentinelConfig;
+import com.yahoo.config.FileReference;
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.HostName;
+import com.yahoo.config.provision.NodeType;
+import com.yahoo.config.provision.TenantName;
+import com.yahoo.config.provision.security.NodeIdentifier;
+import com.yahoo.config.provision.security.NodeIdentifierException;
+import com.yahoo.config.provision.security.NodeIdentity;
+import com.yahoo.jrt.Request;
+import com.yahoo.jrt.SecurityContext;
+import com.yahoo.jrt.StringValue;
+import com.yahoo.jrt.Target;
+import com.yahoo.jrt.Values;
+import com.yahoo.security.KeyAlgorithm;
+import com.yahoo.security.KeyUtils;
+import com.yahoo.security.SignatureAlgorithm;
+import com.yahoo.security.X509CertificateBuilder;
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.JsonFormat;
+import com.yahoo.slime.Slime;
+import com.yahoo.vespa.config.ConfigKey;
+import com.yahoo.vespa.config.server.RequestHandler;
+import com.yahoo.vespa.config.server.host.HostRegistry;
+import com.yahoo.vespa.config.server.rpc.RequestHandlerProvider;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import javax.security.auth.x500.X500Principal;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.time.Instant;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
+import static com.yahoo.vespa.config.server.rpc.security.MultiTenantRpcAuthorizer.Mode.ENFORCE;
+import static java.time.temporal.ChronoUnit.DAYS;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author bjorncs
+ */
+public class MultiTenantRpcAuthorizerTest {
+
+ private static final List<X509Certificate> PEER_CERTIFICATE_CHAIN = List.of(createDummyCertificate());
+ private static final ApplicationId APPLICATION_ID = ApplicationId.from("mytenant", "myapplication", "default");
+ private static final ApplicationId EVIL_APP_ID = ApplicationId.from("malice", "malice-app", "default");
+ private static final HostName HOSTNAME = HostName.from("myhostname");
+ private static final FileReference FILE_REFERENCE = new FileReference("myfilereference");
+
+ @Rule
+ public ExpectedException exceptionRule = ExpectedException.none();
+
+ @Test
+ public void configserver_can_access_files_and_config() throws InterruptedException, ExecutionException {
+ RpcAuthorizer authorizer = createAuthorizer(new NodeIdentity.Builder(NodeType.config).build(),
+ new HostRegistry<>());
+
+ Request configRequest = createConfigRequest(new ConfigKey<>("name", "configid", "namespace"), HOSTNAME);
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+
+ Request fileRequest = createFileRequest(FILE_REFERENCE);
+ authorizer.authorizeFileRequest(fileRequest)
+ .get();
+ }
+
+ @Test
+ public void tenant_node_can_access_its_own_files_and_config() throws ExecutionException, InterruptedException {
+ NodeIdentity identity = new NodeIdentity.Builder(NodeType.tenant)
+ .applicationId(APPLICATION_ID)
+ .build();
+
+ HostRegistry<TenantName> hostRegistry = new HostRegistry<>();
+ hostRegistry.update(APPLICATION_ID.tenant(), List.of(HOSTNAME.value()));
+
+ RpcAuthorizer authorizer = createAuthorizer(identity, hostRegistry);
+
+ Request configRequest = createConfigRequest(new ConfigKey<>("name", "configid", "namespace"), HOSTNAME);
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+
+ Request fileRequest = createFileRequest(FILE_REFERENCE);
+ authorizer.authorizeFileRequest(fileRequest)
+ .get();
+ }
+
+ @Test
+ public void proxy_node_can_access_lbservice_config() throws ExecutionException, InterruptedException {
+ RpcAuthorizer authorizer = createAuthorizer(new NodeIdentity.Builder(NodeType.proxy).build(), new HostRegistry<>());
+
+ Request configRequest = createConfigRequest(
+ new ConfigKey<>(LbServicesConfig.CONFIG_DEF_NAME, "*", LbServicesConfig.CONFIG_DEF_NAMESPACE),
+ HOSTNAME);
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+ }
+
+ @Test
+ public void tenant_node_can_access_routing_config() throws ExecutionException, InterruptedException {
+ RpcAuthorizer authorizer = createAuthorizer(new NodeIdentity.Builder(NodeType.tenant).build(), new HostRegistry<>());
+
+ Request configRequest = createConfigRequest(
+ new ConfigKey<>(RoutingConfig.CONFIG_DEF_NAME, "*", RoutingConfig.CONFIG_DEF_NAMESPACE),
+ HOSTNAME);
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+ }
+
+ @Test
+ public void tenant_node_cannot_access_lbservice_config() throws ExecutionException, InterruptedException {
+ RpcAuthorizer authorizer = createAuthorizer(new NodeIdentity.Builder(NodeType.tenant).build(), new HostRegistry<>());
+
+ Request configRequest = createConfigRequest(
+ new ConfigKey<>(LbServicesConfig.CONFIG_DEF_NAME, "*", LbServicesConfig.CONFIG_DEF_NAMESPACE),
+ HOSTNAME);
+
+ exceptionRule.expectMessage("Node with type 'tenant' is not allowed to access global config [name=lb-services,namespace=cloud.config,configId=*]");
+ exceptionRule.expectCause(instanceOf(AuthorizationException.class));
+
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+ }
+
+ @Test
+ public void tenant_node_cannot_access_other_files() throws ExecutionException, InterruptedException {
+ NodeIdentity identity = new NodeIdentity.Builder(NodeType.tenant)
+ .applicationId(APPLICATION_ID)
+ .build();
+
+ HostRegistry<TenantName> hostRegistry = new HostRegistry<>();
+ hostRegistry.update(APPLICATION_ID.tenant(), List.of(HOSTNAME.value()));
+
+ RpcAuthorizer authorizer = createAuthorizer(identity, hostRegistry);
+
+ Request fileRequest = createFileRequest(new FileReference("other-file-reference"));
+
+ exceptionRule.expectMessage("Peer is not allowed to access file other-file-reference");
+ exceptionRule.expectCause(instanceOf(AuthorizationException.class));
+
+ authorizer.authorizeFileRequest(fileRequest)
+ .get();
+ }
+
+ @Test
+ public void tenant_node_cannot_access_other_config() throws ExecutionException, InterruptedException {
+ NodeIdentity identity = new NodeIdentity.Builder(NodeType.tenant)
+ .applicationId(EVIL_APP_ID)
+ .build();
+
+ HostRegistry<TenantName> hostRegistry = new HostRegistry<>();
+ hostRegistry.update(APPLICATION_ID.tenant(), List.of(HOSTNAME.value()));
+
+ RpcAuthorizer authorizer = createAuthorizer(identity, hostRegistry);
+
+ Request configRequest = createConfigRequest(new ConfigKey<>("name", "configid", "namespace"), HOSTNAME);
+
+ exceptionRule.expectMessage("Peer is not allowed to access config for owned by mytenant.myapplication. Peer is owned by malice.malice-app");
+ exceptionRule.expectCause(instanceOf(AuthorizationException.class));
+
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+ }
+
+ @Test
+ public void tenant_node_must_be_registered_in_host_registry() throws ExecutionException, InterruptedException {
+ NodeIdentity identity = new NodeIdentity.Builder(NodeType.tenant)
+ .applicationId(EVIL_APP_ID)
+ .build();
+
+ HostRegistry<TenantName> hostRegistry = new HostRegistry<>();
+
+ RpcAuthorizer authorizer = createAuthorizer(identity, hostRegistry);
+
+ Request configRequest = createConfigRequest(new ConfigKey<>("name", "configid", "namespace"), HOSTNAME);
+
+ exceptionRule.expectMessage("Host 'myhostname' not found in host registry");
+ exceptionRule.expectCause(instanceOf(AuthorizationException.class));
+
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+ }
+
+ @Test
+ public void tenant_must_have_a_request_handler() throws ExecutionException, InterruptedException {
+ NodeIdentity identity = new NodeIdentity.Builder(NodeType.tenant)
+ .applicationId(EVIL_APP_ID)
+ .build();
+
+ HostRegistry<TenantName> hostRegistry = new HostRegistry<>();
+ hostRegistry.update(EVIL_APP_ID.tenant(), List.of(HOSTNAME.value()));
+
+ RpcAuthorizer authorizer = createAuthorizer(identity, hostRegistry);
+
+ Request configRequest = createConfigRequest(new ConfigKey<>("name", "configid", "namespace"), HOSTNAME);
+
+ exceptionRule.expectMessage("No handler exists for tenant 'malice'");
+ exceptionRule.expectCause(instanceOf(AuthorizationException.class));
+
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+ }
+
+ @Test
+ public void tenant_node_not_in_hostregistry_allowed_to_access_sentinel_config() throws ExecutionException, InterruptedException {
+ NodeIdentity identity = new NodeIdentity.Builder(NodeType.tenant)
+ .applicationId(APPLICATION_ID)
+ .build();
+
+ HostRegistry<TenantName> hostRegistry = new HostRegistry<>();
+
+ RpcAuthorizer authorizer = createAuthorizer(identity, hostRegistry);
+
+ Request configRequest = createConfigRequest(new ConfigKey<>(SentinelConfig.CONFIG_DEF_NAME, "configid", SentinelConfig.CONFIG_DEF_NAMESPACE), HOSTNAME);
+
+ authorizer.authorizeConfigRequest(configRequest)
+ .get();
+ }
+
+
+ private static RpcAuthorizer createAuthorizer(NodeIdentity identity, HostRegistry<TenantName> hostRegistry) {
+ return new MultiTenantRpcAuthorizer(
+ new StaticNodeIdentifier(identity),
+ hostRegistry,
+ createRequestHandlerProviderMock(),
+ new DirectExecutor(),
+ ENFORCE);
+ }
+
+ private static Request createConfigRequest(ConfigKey<?> configKey, HostName hostName) {
+ return mockJrtRpcRequest(createConfigPayload(configKey, hostName.value()));
+ }
+
+ private static Request createFileRequest(FileReference fileReference) {
+ return mockJrtRpcRequest(fileReference.value());
+ }
+
+ private static RequestHandlerProvider createRequestHandlerProviderMock() {
+ RequestHandler requestHandler = mock(RequestHandler.class);
+ when(requestHandler.hasApplication(APPLICATION_ID, Optional.empty())).thenReturn(true);
+ when(requestHandler.resolveApplicationId(HOSTNAME.value())).thenReturn(APPLICATION_ID);
+ when(requestHandler.listFileReferences(APPLICATION_ID)).thenReturn(Set.of(FILE_REFERENCE));
+
+ RequestHandlerProvider handlerProvider = mock(RequestHandlerProvider.class);
+ when(handlerProvider.getRequestHandler(APPLICATION_ID.tenant())).thenReturn(Optional.of(requestHandler));
+ when(handlerProvider.getRequestHandler(EVIL_APP_ID.tenant())).thenReturn(Optional.empty());
+ return handlerProvider;
+ }
+
+ private static Request mockJrtRpcRequest(String payload) {
+ SecurityContext securityContext = mock(SecurityContext.class);
+ when(securityContext.peerCertificateChain()).thenReturn(PEER_CERTIFICATE_CHAIN);
+ Target target = mock(Target.class);
+ when(target.getSecurityContext()).thenReturn(Optional.of(securityContext));
+ Request request = mock(Request.class);
+ when(request.target()).thenReturn(target);
+ Values values = new Values();
+ values.add(new StringValue(payload));
+ when(request.parameters()).thenReturn(values);
+ return request;
+ }
+
+ private static String createConfigPayload(ConfigKey<?> configKey, String hostname) {
+ Slime data = new Slime();
+ Cursor request = data.setObject();
+ request.setString("defName", configKey.getName());
+ request.setString("defNamespace", configKey.getNamespace());
+ request.setString("defMD5", configKey.getMd5());
+ request.setString("configId", configKey.getConfigId());
+ request.setString("clientHostname", hostname);
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ new JsonFormat(false).encode(out, data);
+ return new String(out.toByteArray());
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private static X509Certificate createDummyCertificate() {
+ return X509CertificateBuilder.fromKeypair(
+ KeyUtils.generateKeypair(KeyAlgorithm.EC),
+ new X500Principal("CN=" + HOSTNAME),
+ Instant.EPOCH,
+ Instant.EPOCH.plus(1, DAYS),
+ SignatureAlgorithm.SHA256_WITH_ECDSA,
+ BigInteger.ONE)
+ .build();
+ }
+
+ private static class DirectExecutor implements Executor {
+
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+ }
+
+ private static class StaticNodeIdentifier implements NodeIdentifier {
+ final NodeIdentity identity;
+
+ StaticNodeIdentifier(NodeIdentity identity) {
+ this.identity = identity;
+ }
+
+ @Override
+ public NodeIdentity identifyNode(List<X509Certificate> peerCertificateChain) throws NodeIdentifierException {
+ return identity;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java
index 3626c6269cc..d3f364e30ac 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionRepoTest.java
@@ -46,7 +46,6 @@ public class LocalSessionRepoTest {
}
private void setupSessions(TenantName tenantName, boolean createInitialSessions) throws Exception {
- GlobalComponentRegistry globalComponentRegistry = new TestComponentRegistry.Builder().curator(new MockCurator()).build();
TenantFileSystemDirs tenantFileSystemDirs = new TenantFileSystemDirs(temporaryFolder.newFolder(), tenantName);
if (createInitialSessions) {
IOUtils.copyDirectory(testApp, new File(tenantFileSystemDirs.sessionsPath(), "1"));
@@ -54,11 +53,14 @@ public class LocalSessionRepoTest {
IOUtils.copyDirectory(testApp, new File(tenantFileSystemDirs.sessionsPath(), "3"));
}
clock = new ManualClock(Instant.ofEpochSecond(1));
+ GlobalComponentRegistry globalComponentRegistry = new TestComponentRegistry.Builder().curator(new MockCurator())
+ .clock(clock)
+ .build();
LocalSessionLoader loader = new SessionFactoryImpl(globalComponentRegistry,
- TenantApplications.create(new MockCurator(), new MockReloadHandler(), tenantName),
+ TenantApplications.create(globalComponentRegistry, new MockReloadHandler(), tenantName),
tenantFileSystemDirs, new HostRegistry<>(),
tenantName);
- repo = new LocalSessionRepo(tenantFileSystemDirs, loader, clock, 5, globalComponentRegistry.getCurator());
+ repo = new LocalSessionRepo(tenantName, globalComponentRegistry, tenantFileSystemDirs, loader);
}
@Test
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
index a4432dcbfcd..96caff9b3a7 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java
@@ -16,7 +16,7 @@ import com.yahoo.path.Path;
import com.yahoo.slime.Slime;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.config.server.MockReloadHandler;
-import com.yahoo.vespa.config.server.SuperModelGenerationCounter;
+import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.application.TenantApplications;
import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger;
import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs;
@@ -54,13 +54,11 @@ public class LocalSessionTest {
private Curator curator;
private ConfigCurator configCurator;
private TenantFileSystemDirs tenantFileSystemDirs;
- private SuperModelGenerationCounter superModelGenerationCounter;
@Before
public void setupTest() {
curator = new MockCurator();
configCurator = ConfigCurator.create(curator);
- superModelGenerationCounter = new SuperModelGenerationCounter(curator);
tenantFileSystemDirs = new TenantFileSystemDirs(Files.createTempDir(), TenantName.from("test_tenant"));
}
@@ -130,11 +128,9 @@ public class LocalSessionTest {
String sessionNode = TenantRepository.getSessionsPath(tenantName).append(String.valueOf(3)).getAbsolute();
assertTrue(configCurator.exists(sessionNode));
assertTrue(new File(tenantFileSystemDirs.sessionsPath(), "3").exists());
- long gen = superModelGenerationCounter.get();
NestedTransaction transaction = new NestedTransaction();
session.delete(transaction);
transaction.commit();
- assertThat(superModelGenerationCounter.get(), is(gen + 1));
assertFalse(configCurator.exists(sessionNode));
assertFalse(new File(tenantFileSystemDirs.sessionsPath(), "3").exists());
}
@@ -196,7 +192,7 @@ public class LocalSessionTest {
zkClient.write(Collections.singletonMap(new Version(0, 0, 0), new MockFileRegistry()));
File sessionDir = new File(tenantFileSystemDirs.sessionsPath(), String.valueOf(sessionId));
sessionDir.createNewFile();
- TenantApplications applications = TenantApplications.create(curator, new MockReloadHandler(), tenant);
+ TenantApplications applications = TenantApplications.create(new TestComponentRegistry.Builder().curator(curator).build(), new MockReloadHandler(), tenant);
applications.createApplication(zkc.readApplicationId());
return new LocalSession(tenant, sessionId, preparer,
new SessionContext(
@@ -205,7 +201,6 @@ public class LocalSessionTest {
sessionDir,
applications,
new HostRegistry<>(),
- superModelGenerationCounter,
flagSource));
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
index f2fb4aa1c40..f5fd6053b07 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
@@ -6,10 +6,13 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Rotation;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
-
+import com.yahoo.config.model.api.ContainerEndpoint;
import org.junit.Test;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.time.Duration;
+import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -17,6 +20,7 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -26,6 +30,15 @@ import static org.junit.Assert.assertTrue;
*/
public class PrepareParamsTest {
+ private static final String rotation = "rotation-042.vespa.a02.yahoodns.net";
+ private static final String vespaVersion = "6.37.49";
+ private static final String request = "http://foo:19071/application/v2/tenant/foo/application/bar?" +
+ PrepareParams.DRY_RUN_PARAM_NAME + "=true&" +
+ PrepareParams.VERBOSE_PARAM_NAME+ "=true&" +
+ PrepareParams.IGNORE_VALIDATION_PARAM_NAME + "=false&" +
+ PrepareParams.APPLICATION_NAME_PARAM_NAME + "=baz&" +
+ PrepareParams.VESPA_VERSION_PARAM_NAME + "=" + vespaVersion;
+
@Test
public void testCorrectParsing() {
PrepareParams prepareParams = createParams("http://foo:19071/application/v2/", TenantName.defaultName());
@@ -38,15 +51,6 @@ public class PrepareParamsTest {
assertTrue(prepareParams.getTimeoutBudget().hasTimeLeft());
assertThat(prepareParams.rotations().size(), is(0));
}
-
- private static final String rotation = "rotation-042.vespa.a02.yahoodns.net";
- private static final String vespaVersion = "6.37.49";
- private static final String request = "http://foo:19071/application/v2/tenant/foo/application/bar?" +
- PrepareParams.DRY_RUN_PARAM_NAME + "=true&" +
- PrepareParams.VERBOSE_PARAM_NAME+ "=true&" +
- PrepareParams.IGNORE_VALIDATION_PARAM_NAME + "=false&" +
- PrepareParams.APPLICATION_NAME_PARAM_NAME + "=baz&" +
- PrepareParams.VESPA_VERSION_PARAM_NAME + "=" + vespaVersion;
@Test
public void testCorrectParsingWithRotation() {
@@ -77,6 +81,31 @@ public class PrepareParamsTest {
assertThat(rotations, containsInAnyOrder(new Rotation(rotation), new Rotation(rotationTwo)));
}
+ @Test
+ public void testCorrectParsingWithContainerEndpoints() {
+ var endpoints = List.of(new ContainerEndpoint("qrs1",
+ List.of("c1.example.com",
+ "c2.example.com")),
+ new ContainerEndpoint("qrs2",
+ List.of("c3.example.com",
+ "c4.example.com")));
+ var param = "[\n" +
+ " {\n" +
+ " \"clusterId\": \"qrs1\",\n" +
+ " \"names\": [\"c1.example.com\", \"c2.example.com\"]\n" +
+ " },\n" +
+ " {\n" +
+ " \"clusterId\": \"qrs2\",\n" +
+ " \"names\": [\"c3.example.com\", \"c4.example.com\"]\n" +
+ " }\n" +
+ "]";
+
+ var encoded = URLEncoder.encode(param, StandardCharsets.UTF_8);
+ var prepareParams = createParams(request + "&" + PrepareParams.CONTAINER_ENDPOINTS_PARAM_NAME +
+ "=" + encoded, TenantName.from("foo"));
+ assertEquals(endpoints, prepareParams.containerEndpoints());
+ }
+
// Create PrepareParams from a request (based on uri and tenant name)
private static PrepareParams createParams(String uri, TenantName tenantName) {
return PrepareParams.fromHttpRequest(
@@ -84,4 +113,5 @@ public class PrepareParamsTest {
tenantName,
Duration.ofSeconds(60));
}
+
}
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 9dda653dbc1..83183a27666 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
@@ -10,6 +10,7 @@ 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.MockReloadHandler;
import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.application.TenantApplications;
@@ -100,11 +101,12 @@ public class RemoteSessionRepoTest {
public void testBadApplicationRepoOnActivate() {
long sessionId = 3L;
TenantName mytenant = TenantName.from("mytenant");
- TenantApplications applicationRepo = TenantApplications.create(curator, new MockReloadHandler(), mytenant);
+ GlobalComponentRegistry registry = new TestComponentRegistry.Builder().curator(curator).build();
+ TenantApplications applicationRepo = TenantApplications.create(registry, new MockReloadHandler(), mytenant);
curator.set(TenantRepository.getApplicationsPath(mytenant).append("mytenant:appX:default"), new byte[0]); // Invalid data
- Tenant tenant = TenantBuilder.create(new TestComponentRegistry.Builder().curator(curator).build(), mytenant)
- .withApplicationRepo(applicationRepo)
- .build();
+ Tenant tenant = TenantBuilder.create(registry, mytenant)
+ .withApplicationRepo(applicationRepo)
+ .build();
curator.create(TenantRepository.getSessionsPath(mytenant));
remoteSessionRepo = tenant.getRemoteSessionRepo();
assertThat(remoteSessionRepo.listSessions().size(), is(0));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
index 9ad90e84d86..651dde375ee 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java
@@ -1,22 +1,24 @@
// 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.session;
+import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.model.api.ModelContext;
+import com.yahoo.config.model.api.TlsSecrets;
import com.yahoo.config.model.application.provider.BaseDeployLogger;
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.CertificateNotReadyException;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.Rotation;
import com.yahoo.config.provision.TenantName;
-import com.yahoo.component.Version;
import com.yahoo.io.IOUtils;
import com.yahoo.log.LogLevel;
import com.yahoo.path.Path;
import com.yahoo.slime.Slime;
-import com.yahoo.config.provision.ApplicationId;
import com.yahoo.vespa.config.server.MockReloadHandler;
-import com.yahoo.vespa.config.server.SuperModelGenerationCounter;
+import com.yahoo.vespa.config.server.MockSecretStore;
import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.TimeoutBudgetTest;
import com.yahoo.vespa.config.server.application.PermanentApplicationPackage;
@@ -27,9 +29,11 @@ import com.yahoo.vespa.config.server.http.InvalidApplicationException;
import com.yahoo.vespa.config.server.model.TestModelFactory;
import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry;
import com.yahoo.vespa.config.server.provision.HostProvisionerProvider;
+import com.yahoo.config.model.api.ContainerEndpoint;
+import com.yahoo.vespa.config.server.tenant.ContainerEndpointsCache;
import com.yahoo.vespa.config.server.tenant.Rotations;
+import com.yahoo.vespa.config.server.tenant.TlsSecretsKeys;
import com.yahoo.vespa.config.server.zookeeper.ConfigCurator;
-
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.flags.InMemoryFlagSource;
import org.junit.Before;
@@ -42,6 +46,7 @@ import java.io.IOException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -49,8 +54,8 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.contains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
/**
* @author Ulf Lilleengen
@@ -70,7 +75,7 @@ public class SessionPreparerTest {
private SessionPreparer preparer;
private TestComponentRegistry componentRegistry;
private MockFileDistributionFactory fileDistributionFactory;
-
+ private MockSecretStore secretStore = new MockSecretStore();
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@@ -105,7 +110,8 @@ public class SessionPreparerTest {
componentRegistry.getStaticConfigDefinitionRepo(),
curator,
componentRegistry.getZone(),
- flagSource);
+ flagSource,
+ secretStore);
}
@Test(expected = InvalidApplicationException.class)
@@ -170,6 +176,10 @@ public class SessionPreparerTest {
assertThat(zkc.readApplicationId(), is(origId));
}
+ private List<ContainerEndpoint> readContainerEndpoints(ApplicationId application) {
+ return new ContainerEndpointsCache(tenantPath, curator).read(application);
+ }
+
private Set<Rotation> readRotationsFromZK(ApplicationId applicationId) {
return new Rotations(curator, tenantPath).readRotationsFromZooKeeper(applicationId);
}
@@ -205,6 +215,85 @@ public class SessionPreparerTest {
assertThat(readRotationsFromZK(applicationId), contains(new Rotation(rotations)));
}
+ @Test
+ public void require_that_rotations_are_written_as_container_endpoints() throws Exception {
+ var rotations = "app1.tenant1.global.vespa.example.com,rotation-042.vespa.global.routing";
+ var applicationId = applicationId("test");
+ var params = new PrepareParams.Builder().applicationId(applicationId).rotations(rotations).build();
+ prepare(new File("src/test/resources/deploy/hosted-app"), params);
+
+ var expected = List.of(new ContainerEndpoint("qrs",
+ List.of("app1.tenant1.global.vespa.example.com",
+ "rotation-042.vespa.global.routing")));
+ assertEquals(expected, readContainerEndpoints(applicationId));
+ }
+
+ @Test
+ public void require_that_container_endpoints_are_written() throws Exception {
+ var endpoints = "[\n" +
+ " {\n" +
+ " \"clusterId\": \"foo\",\n" +
+ " \"names\": [\n" +
+ " \"foo.app1.tenant1.global.vespa.example.com\",\n" +
+ " \"rotation-042.vespa.global.routing\"\n" +
+ " ]\n" +
+ " },\n" +
+ " {\n" +
+ " \"clusterId\": \"bar\",\n" +
+ " \"names\": [\n" +
+ " \"bar.app1.tenant1.global.vespa.example.com\",\n" +
+ " \"rotation-043.vespa.global.routing\"\n" +
+ " ]\n" +
+ " }\n" +
+ "]";
+ var applicationId = applicationId("test");
+ var params = new PrepareParams.Builder().applicationId(applicationId)
+ .containerEndpoints(endpoints)
+ .build();
+ prepare(new File("src/test/resources/deploy/hosted-app"), params);
+
+ var expected = List.of(new ContainerEndpoint("foo",
+ List.of("foo.app1.tenant1.global.vespa.example.com",
+ "rotation-042.vespa.global.routing")),
+ new ContainerEndpoint("bar",
+ List.of("bar.app1.tenant1.global.vespa.example.com",
+ "rotation-043.vespa.global.routing")));
+ assertEquals(expected, readContainerEndpoints(applicationId));
+ }
+
+ @Test
+ public void require_that_tlssecretkey_is_written() throws IOException {
+ var tlskey = "vespa.tlskeys.tenant1--app1";
+ var applicationId = applicationId("test");
+ var params = new PrepareParams.Builder().applicationId(applicationId).tlsSecretsKeyName(tlskey).build();
+ secretStore.put(tlskey+"-cert", "CERT");
+ secretStore.put(tlskey+"-key", "KEY");
+ prepare(new File("src/test/resources/deploy/hosted-app"), params);
+
+ // Read from zk and verify cert and key are available
+ Optional<TlsSecrets> tlsSecrets = new TlsSecretsKeys(curator, tenantPath, secretStore).readTlsSecretsKeyFromZookeeper(applicationId);
+ assertTrue(tlsSecrets.isPresent());
+ assertEquals("KEY", tlsSecrets.get().key());
+ assertEquals("CERT", tlsSecrets.get().certificate());
+ }
+
+ @Test(expected = CertificateNotReadyException.class)
+ public void require_that_tlssecretkey_is_missing_when_not_in_secretstore() throws IOException {
+ var tlskey = "vespa.tlskeys.tenant1--app1";
+ var applicationId = applicationId("test");
+ var params = new PrepareParams.Builder().applicationId(applicationId).tlsSecretsKeyName(tlskey).build();
+ prepare(new File("src/test/resources/deploy/hosted-app"), params);
+ }
+
+ @Test(expected = CertificateNotReadyException.class)
+ public void require_that_tlssecretkey_is_missing_when_certificate_not_in_secretstore() throws IOException {
+ var tlskey = "vespa.tlskeys.tenant1--app1";
+ var applicationId = applicationId("test");
+ var params = new PrepareParams.Builder().applicationId(applicationId).tlsSecretsKeyName(tlskey).build();
+ secretStore.put(tlskey+"-key", "KEY");
+ prepare(new File("src/test/resources/deploy/hosted-app"), params);
+ }
+
private void prepare(File app) throws IOException {
prepare(app, new PrepareParams.Builder().build());
}
@@ -217,9 +306,8 @@ public class SessionPreparerTest {
return new SessionContext(app,
new SessionZooKeeperClient(curator, sessionsPath),
app.getAppDir(),
- TenantApplications.create(curator, new MockReloadHandler(), TenantName.from("tenant")),
+ TenantApplications.create(componentRegistry, new MockReloadHandler(), TenantName.from("tenant")),
new HostRegistry<>(),
- new SuperModelGenerationCounter(curator),
flagSource);
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java
index 95f6c7718e2..b2ad0af8f9a 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java
@@ -21,7 +21,7 @@ public class SessionTest {
public boolean isPrepared = false;
public MockSessionPreparer() {
- super(null, null, null, null, null, null, new MockCurator(), null, null);
+ super(null, null, null, null, null, null, new MockCurator(), null, null, null);
}
@Override
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializerTest.java
new file mode 100644
index 00000000000..053a3f7a15d
--- /dev/null
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializerTest.java
@@ -0,0 +1,50 @@
+package com.yahoo.vespa.config.server.tenant;
+
+import com.yahoo.config.model.api.ContainerEndpoint;
+import com.yahoo.slime.Slime;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author ogronnesby
+ */
+public class ContainerEndpointSerializerTest {
+
+ @Test
+ public void readSingleEndpoint() {
+ final var slime = new Slime();
+ final var entry = slime.setObject();
+
+ entry.setString("clusterId", "foobar");
+ final var entryNames = entry.setArray("names");
+ entryNames.addString("a");
+ entryNames.addString("b");
+
+ final var endpoint = ContainerEndpointSerializer.endpointFromSlime(slime.get());
+ assertEquals("foobar", endpoint.clusterId().toString());
+ assertEquals(List.of("a", "b"), endpoint.names());
+ }
+
+ @Test
+ public void writeReadSingleEndpoint() {
+ final var endpoint = new ContainerEndpoint("foo", List.of("a", "b"));
+ final var serialized = new Slime();
+ ContainerEndpointSerializer.endpointToSlime(serialized.setObject(), endpoint);
+ final var deserialized = ContainerEndpointSerializer.endpointFromSlime(serialized.get());
+
+ assertEquals(endpoint, deserialized);
+ }
+
+ @Test
+ public void writeReadEndpoints() {
+ final var endpoints = List.of(new ContainerEndpoint("foo", List.of("a", "b")));
+ final var serialized = ContainerEndpointSerializer.endpointListToSlime(endpoints);
+ final var deserialized = ContainerEndpointSerializer.endpointListFromSlime(serialized);
+
+ assertEquals(endpoints, deserialized);
+ }
+
+}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointsCacheTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointsCacheTest.java
new file mode 100644
index 00000000000..4400b424d1b
--- /dev/null
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointsCacheTest.java
@@ -0,0 +1,36 @@
+// Copyright 2019 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.model.api.ContainerEndpoint;
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.path.Path;
+import com.yahoo.vespa.curator.mock.MockCurator;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ContainerEndpointsCacheTest {
+ @Test
+ public void readWriteFromCache() {
+ final var cache = new ContainerEndpointsCache(Path.createRoot(), new MockCurator());
+ final var endpoints = List.of(
+ new ContainerEndpoint("the-cluster-1", List.of("a", "b", "c"))
+ );
+
+ cache.write(ApplicationId.defaultId(), endpoints);
+
+ final var deserialized = cache.read(ApplicationId.defaultId());
+
+ assertEquals(endpoints, deserialized);
+ }
+
+ @Test
+ public void readingNonExistingEntry() {
+ final var cache = new ContainerEndpointsCache(Path.createRoot(), new MockCurator());
+ final var endpoints = cache.read(ApplicationId.defaultId());
+ assertTrue(endpoints.isEmpty());
+ }
+} \ No newline at end of file
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
index 6aa5aa7cd70..36bb7a926b5 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java
@@ -93,11 +93,11 @@ public class TenantRequestHandlerTest {
Metrics sh = Metrics.createTestMetrics();
List<ReloadListener> listeners = new ArrayList<>();
listeners.add(listener);
- server = new TenantRequestHandler(sh, tenant, listeners, new UncompressedConfigResponseFactory(), new HostRegistries(), curator);
componentRegistry = new TestComponentRegistry.Builder()
.curator(curator)
.modelFactoryRegistry(createRegistry())
.build();
+ server = new TenantRequestHandler(sh, tenant, listeners, new UncompressedConfigResponseFactory(), componentRegistry);
}
private void feedApp(File appDir, long sessionId, ApplicationId appId, boolean internalRedeploy) throws IOException {
@@ -357,12 +357,12 @@ public class TenantRequestHandlerTest {
configNames = server.listConfigs(ApplicationId.defaultId(), Optional.of(vespaVersion), true);
System.out.println(configNames);
- assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "jdisc", "document.config")));
+ assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "container", "document.config")));
assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "", "document.config")));
assertTrue(configNames.contains(new ConfigKey<>("documenttypes", "", "document")));
- assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "jdisc", "document.config")));
- assertTrue(configNames.contains(new ConfigKey<>("health-monitor", "jdisc", "container.jdisc.config")));
- assertTrue(configNames.contains(new ConfigKey<>("specific", "jdisc", "project")));
+ assertTrue(configNames.contains(new ConfigKey<>("documentmanager", "container", "document.config")));
+ assertTrue(configNames.contains(new ConfigKey<>("health-monitor", "container", "container.jdisc.config")));
+ assertTrue(configNames.contains(new ConfigKey<>("specific", "container", "project")));
}
@Test
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 baab250a508..e140dae3650 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
@@ -38,7 +38,7 @@ public class TenantTest {
TenantRepository tenantRepository = new TenantRepository(componentRegistry, false);
TenantName tenantName = TenantName.from(name);
TenantBuilder tenantBuilder = TenantBuilder.create(componentRegistry, tenantName)
- .withApplicationRepo(TenantApplications.create(new MockCurator(), new MockReloadHandler(), tenantName));
+ .withApplicationRepo(TenantApplications.create(componentRegistry, new MockReloadHandler(), tenantName));
tenantRepository.addTenant(tenantBuilder);
return tenantRepository.getTenant(tenantName);
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
index e8e2dd07756..8b8be1a27d7 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java
@@ -1,27 +1,15 @@
// 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.zookeeper;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertThat;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.regex.Pattern;
-
+import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.model.deploy.DeployState;
+import com.yahoo.config.provision.AllocatedHosts;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeFlavors;
-import com.yahoo.config.provision.AllocatedHosts;
-import com.yahoo.component.Version;
import com.yahoo.config.provisioning.FlavorsConfig;
+import com.yahoo.io.IOUtils;
import com.yahoo.path.Path;
import com.yahoo.text.Utf8;
import com.yahoo.vespa.curator.mock.MockCurator;
@@ -30,7 +18,19 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import com.yahoo.io.IOUtils;
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.regex.Pattern;
+
+import static com.yahoo.config.provision.serialization.AllocatedHostsSerializer.toJson;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
public class ZKApplicationPackageTest {
@@ -77,7 +77,7 @@ public class ZKApplicationPackageTest {
assertFalse(zkApp.getFileRegistries().containsKey(new Version(0, 0, 0)));
assertThat(zkApp.getFileRegistries().get(goodVersion).fileSourceHost(), is("dummyfiles"));
AllocatedHosts readInfo = zkApp.getAllocatedHosts().get();
- assertThat(Utf8.toString(readInfo.toJson()), is(Utf8.toString(ALLOCATED_HOSTS.toJson())));
+ assertThat(Utf8.toString(toJson(readInfo)), is(Utf8.toString(toJson(ALLOCATED_HOSTS))));
assertThat(readInfo.getHosts().iterator().next().flavor(), is(TEST_FLAVOR));
assertEquals("6.0.1", readInfo.getHosts().iterator().next().version().get().toString());
assertTrue(zkApp.getDeployment().isPresent());
@@ -90,7 +90,7 @@ public class ZKApplicationPackageTest {
String metaData = "{\"deploy\":{\"user\":\"foo\",\"from\":\"bar\",\"timestamp\":1},\"application\":{\"name\":\"foo\",\"checksum\":\"abc\",\"generation\":4,\"previousActiveGeneration\":3}}";
zk.putData("/0", ConfigCurator.META_ZK_PATH, metaData);
zk.putData("/0/" + ZKApplicationPackage.fileRegistryNode + "/3.0.0", "dummyfiles");
- zk.putData("/0/" + ZKApplicationPackage.allocatedHostsNode, ALLOCATED_HOSTS.toJson());
+ zk.putData("/0/" + ZKApplicationPackage.allocatedHostsNode, toJson(ALLOCATED_HOSTS));
}
private static class MockNodeFlavors extends NodeFlavors{