summaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2019-03-11 09:06:47 +0100
committerHarald Musum <musum@verizonmedia.com>2019-03-11 09:06:47 +0100
commit2f6a31090c98fdbe1ffbb0515f30252d89b7cb78 (patch)
tree6f8f32b96924e719581ad2f949f68e7faa2a758c /configserver
parent804fa9e5f1e1fa4c482725b42d44a85b78b49829 (diff)
Add config for returning empty sentinel config when app is removed
For making it easier to create system test
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java6
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessorTest.java128
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcServerTest.java36
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/rpc/RpcTester.java16
5 files changed, 51 insertions, 138 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java
index a7c04f33d5f..bbdef71129a 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java
@@ -84,7 +84,7 @@ class GetConfigProcessor implements Runnable {
// If we are certain that this request is from a node that no longer belongs to this application,
// fabricate an empty request to cause the sentinel to stop all running services
- if (rpcServer.isHostedVespa() && rpcServer.allTenantsLoaded() && !tenant.isPresent() && isSentinelConfigRequest(request)) {
+ if (rpcServer.canReturnEmptySentinelConfig() && rpcServer.allTenantsLoaded() && tenant.isEmpty() && isSentinelConfigRequest(request)) {
returnEmpty(request);
return null;
}
@@ -164,6 +164,7 @@ class GetConfigProcessor implements Runnable {
}
private void returnEmpty(JRTServerConfigRequest request) {
+ log.log(LogLevel.INFO, "Returning empty sentinel config for request from " + request.getClientHostName());
ConfigPayload emptyPayload = ConfigPayload.empty();
String configMd5 = ConfigUtils.getMd5(emptyPayload);
ConfigResponse config = SlimeConfigResponse.fromConfigPayload(emptyPayload, null, 0, false, configMd5);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java
index 061a3b3302b..1df72522310 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/RpcServer.java
@@ -84,6 +84,7 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener {
private Spec spec;
private final boolean useRequestVersion;
private final boolean hostedVespa;
+ private final boolean canReturnEmptySentinelConfig;
private static final Logger log = Logger.getLogger(RpcServer.class.getName());
@@ -136,6 +137,7 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener {
hostRegistry = hostRegistries.getTenantHostRegistry();
this.useRequestVersion = config.useVespaVersionInRequest();
this.hostedVespa = config.hostedVespa();
+ this.canReturnEmptySentinelConfig = config.canReturnEmptySentinelConfig();
this.fileServer = fileServer;
downloader = fileServer.downloader();
setUpHandlers();
@@ -441,6 +443,10 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener {
/** Returns true if this rpc server is currently running in a hosted Vespa configuration */
public boolean isHostedVespa() { return hostedVespa; }
+
+ /** Returns true if empty sentinel config can be returned when a request from a host that is
+ * not part of an application asks for sentinel config */
+ public boolean canReturnEmptySentinelConfig() { return canReturnEmptySentinelConfig; }
MetricUpdaterFactory metricUpdaterFactory() {
return metricUpdaterFactory;
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessorTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessorTest.java
deleted file mode 100644
index 28f111a04d2..00000000000
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessorTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.config.server.rpc;
-
-import com.yahoo.cloud.config.SentinelConfig;
-import com.yahoo.config.provision.TenantName;
-import com.yahoo.text.Utf8;
-import com.yahoo.text.Utf8Array;
-import com.yahoo.text.Utf8String;
-import com.yahoo.vespa.config.ConfigKey;
-
-import com.yahoo.vespa.config.protocol.CompressionInfo;
-import com.yahoo.vespa.config.protocol.CompressionType;
-import com.yahoo.vespa.config.protocol.ConfigResponse;
-import com.yahoo.vespa.config.protocol.DefContent;
-import com.yahoo.vespa.config.protocol.JRTClientConfigRequestV3;
-import com.yahoo.vespa.config.protocol.JRTServerConfigRequest;
-import com.yahoo.vespa.config.protocol.JRTServerConfigRequestV3;
-import com.yahoo.vespa.config.protocol.Trace;
-import com.yahoo.vespa.config.server.tenant.MockTenantProvider;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-import static org.junit.Assert.assertFalse;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Ulf Lilleengen
- */
-public class GetConfigProcessorTest {
-
- @Rule
- public TemporaryFolder temporaryFolder = new TemporaryFolder();
-
- @Test
- public void testSentinelConfig() throws IOException {
- MockRpc rpc = new MockRpc(13337, false, temporaryFolder.newFolder());
- rpc.response = new MockConfigResponse("foo"); // should be a sentinel config, but it does not matter for this test
-
- // one tenant, which has host1 assigned
- boolean pretendToHaveLoadedApplications = true;
- TenantName testTenant = TenantName.from("test");
- rpc.onTenantCreate(testTenant, new MockTenantProvider(pretendToHaveLoadedApplications));
- rpc.hostsUpdated(testTenant, Collections.singleton("host1"));
-
- { // a config is returned normally
- JRTServerConfigRequest req = createV3SentinelRequest("host1");
- GetConfigProcessor proc = new GetConfigProcessor(rpc, req, false);
- proc.run();
- assertTrue(rpc.tryResolveConfig);
- assertTrue(rpc.tryRespond);
- assertThat(rpc.errorCode, is(0));
- }
-
- rpc.resetChecks();
- // host1 is replaced by host2 for this tenant
- rpc.hostsUpdated(testTenant, Collections.singleton("host2"));
-
- { // this causes us to get an empty config instead of normal config resolution
- JRTServerConfigRequest req = createV3SentinelRequest("host1");
- GetConfigProcessor proc = new GetConfigProcessor(rpc, req, false);
- proc.run();
- assertFalse(rpc.tryResolveConfig); // <-- no normal config resolution happening
- assertTrue(rpc.tryRespond);
- assertThat(rpc.errorCode, is(0));
- }
- }
-
- private static JRTServerConfigRequest createV3SentinelRequest(String fromHost) {
- final ConfigKey<?> configKey = new ConfigKey<>(SentinelConfig.CONFIG_DEF_NAME, "myid", SentinelConfig.CONFIG_DEF_NAMESPACE);
- return JRTServerConfigRequestV3.createFromRequest(JRTClientConfigRequestV3.
- createWithParams(configKey, DefContent.fromList(Arrays.asList(SentinelConfig.CONFIG_DEF_SCHEMA)),
- fromHost, "", 0, 100, Trace.createDummy(), CompressionType.UNCOMPRESSED,
- Optional.empty()).getRequest());
- }
-
- private class MockConfigResponse implements ConfigResponse {
-
- private final String line;
- public MockConfigResponse(String line) {
- this.line = line;
- }
-
- @Override
- public Utf8Array getPayload() {
- return new Utf8String("");
- }
-
- @Override
- public List<String> getLegacyPayload() {
- return Arrays.asList(line);
- }
-
- @Override
- public long getGeneration() {
- return 1;
- }
-
- @Override
- public boolean isInternalRedeploy() { return false; }
-
- @Override
- public String getConfigMd5() {
- return "mymd5";
- }
-
- @Override
- public void serialize(OutputStream os, CompressionType uncompressed) throws IOException {
- os.write(Utf8.toBytes(line));
- }
-
- @Override
- public CompressionInfo getCompressionInfo() {
- return CompressionInfo.uncompressed();
- }
- }
-
-}
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 972446ca267..c8bc9364922 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
@@ -2,7 +2,9 @@
package com.yahoo.vespa.config.server.rpc;
import com.google.common.base.Joiner;
+import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.cloud.config.LbServicesConfig;
+import com.yahoo.cloud.config.SentinelConfig;
import com.yahoo.config.SimpletypesConfig;
import com.yahoo.config.codegen.DefParser;
import com.yahoo.config.codegen.InnerCNode;
@@ -55,11 +57,12 @@ public class RpcServerTest {
testPrintStatistics(tester);
testGetConfig(tester);
testEnabled(tester);
- testEmptyConfigHostedVespa(tester);
+ testApplicationNotLoadedErrorWhenAppDeleted(tester);
+ testEmptySentinelConfigWhenAppDeletedOnHostedVespa();
}
}
- private void testEmptyConfigHostedVespa(RpcTester tester) throws InterruptedException, IOException {
+ private void testApplicationNotLoadedErrorWhenAppDeleted(RpcTester tester) throws InterruptedException, IOException {
tester.rpcServer().onTenantDelete(TenantName.defaultName());
tester.rpcServer().onTenantsLoaded();
JRTClientConfigRequest clientReq = createSimpleRequest();
@@ -74,6 +77,28 @@ public class RpcServerTest {
assertTrue(clientReq.validateResponse());
}
+ @Test
+ public void testEmptySentinelConfigWhenAppDeletedOnHostedVespa() throws IOException, InterruptedException {
+ ConfigserverConfig.Builder configBuilder = new ConfigserverConfig.Builder().canReturnEmptySentinelConfig(true);
+ try (RpcTester tester = new RpcTester(temporaryFolder, configBuilder)) {
+ tester.rpcServer().onTenantDelete(TenantName.defaultName());
+ tester.rpcServer().onTenantsLoaded();
+ JRTClientConfigRequest clientReq = createSentinelRequest();
+
+ // Should get empty sentinel config when on hosted vespa
+ tester.performRequest(clientReq.getRequest());
+ assertTrue(clientReq.validateResponse());
+ assertEquals(0, clientReq.errorCode());
+
+ ConfigPayload payload = ConfigPayload.fromUtf8Array(clientReq.getNewPayload().getData());
+ assertNotNull(payload);
+ SentinelConfig.Builder builder = new SentinelConfig.Builder();
+ new ConfigPayloadApplier<>(builder).applyPayload(payload);
+ SentinelConfig config = new SentinelConfig(builder);
+ assertEquals(0, config.service().size());
+ }
+ }
+
private JRTClientConfigRequest createSimpleRequest() {
ConfigKey<?> key = new ConfigKey<>(SimpletypesConfig.class, "");
JRTClientConfigRequest clientReq = createRequest(new RawConfig(key, SimpletypesConfig.getDefMd5()));
@@ -81,6 +106,13 @@ public class RpcServerTest {
return clientReq;
}
+ private JRTClientConfigRequest createSentinelRequest() {
+ ConfigKey<?> key = new ConfigKey<>(SentinelConfig.class, "");
+ JRTClientConfigRequest clientReq = createRequest(new RawConfig(key, SentinelConfig.getDefMd5()));
+ assertTrue(clientReq.validateParameters());
+ return clientReq;
+ }
+
private void testEnabled(RpcTester tester) throws IOException, SAXException {
tester.generationCounter().increment();
Application app = new Application(new VespaModel(MockApplicationPackage.createEmpty()),
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 3849fc899de..43a2c01f26a 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
@@ -51,19 +51,25 @@ public class RpcTester implements AutoCloseable {
private Thread t;
private Supervisor sup;
private Spec spec;
- private int port;
private List<Integer> allocatedPorts;
private final TemporaryFolder temporaryFolder;
+ private final ConfigserverConfig configserverConfig;
RpcTester(TemporaryFolder temporaryFolder) throws InterruptedException, IOException {
+ this(temporaryFolder, new ConfigserverConfig.Builder());
+ }
+
+ RpcTester(TemporaryFolder temporaryFolder, ConfigserverConfig.Builder configBuilder) throws InterruptedException, IOException {
this.temporaryFolder = temporaryFolder;
allocatedPorts = new ArrayList<>();
- port = allocatePort();
+ int port = allocatePort();
spec = createSpec(port);
tenantProvider = new MockTenantProvider();
generationCounter = new MemoryGenerationCounter();
+ configBuilder.rpcport(port);
+ configserverConfig = new ConfigserverConfig(configBuilder);
createAndStartRpcServer();
assertFalse(hostLivenessTracker.lastRequestFrom(myHostname).isPresent());
}
@@ -81,11 +87,7 @@ public class RpcTester implements AutoCloseable {
}
void createAndStartRpcServer() throws IOException {
- ConfigserverConfig configserverConfig = new ConfigserverConfig(new ConfigserverConfig.Builder());
- rpcServer = new RpcServer(new ConfigserverConfig(new ConfigserverConfig.Builder()
- .rpcport(port)
- .numRpcThreads(1)
- .maxgetconfigclients(1)),
+ rpcServer = new RpcServer(configserverConfig,
new SuperModelRequestHandler(new TestConfigDefinitionRepo(),
configserverConfig,
new SuperModelManager(