summaryrefslogtreecommitdiffstats
path: root/config-model/src
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2020-11-25 11:18:56 +0100
committerMartin Polden <mpolden@mpolden.no>2020-11-26 12:58:07 +0100
commitf8fae6d64448b9a325932eedbbd3da24b6d33e02 (patch)
tree3983f1a7d4e5ebb847ad4823091d3bcc3fd38737 /config-model/src
parentbc24bf4c4f1aebad845bb82e45dc8a5a369719eb (diff)
Support configuring ZooKeeper service in container
Diffstat (limited to 'config-model/src')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java25
-rw-r--r--config-model/src/main/resources/schema/containercluster.rnc5
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java44
3 files changed, 73 insertions, 1 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
index b95571de936..b7d64483e57 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
@@ -112,6 +112,10 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
private static final String DEPRECATED_CONTAINER_TAG = "jdisc";
private static final String ENVIRONMENT_VARIABLES_ELEMENT = "environment-variables";
+ // The node count to enforce in a cluster running ZooKeeper
+ private static final int MIN_ZOOKEEPER_NODE_COUNT = 3;
+ private static final int MAX_ZOOKEEPER_NODE_COUNT = 7;
+
public enum Networking { disable, enable }
private ApplicationPackage app;
@@ -195,7 +199,26 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
addClientProviders(deployState, spec, cluster);
addServerProviders(deployState, spec, cluster);
- addAthensCopperArgos(cluster, context); // Must be added after nodes.
+ // Must be added after nodes:
+ addAthensCopperArgos(cluster, context);
+ addZooKeeper(cluster, spec);
+ }
+
+ private void addZooKeeper(ApplicationContainerCluster cluster, Element spec) {
+ Element zkElement = XML.getChild(spec, "zookeeper");
+ if (zkElement == null) return;
+ Element nodesElement = XML.getChild(spec, "nodes");
+ boolean isCombined = nodesElement != null && nodesElement.hasAttribute("of");
+ if (isCombined) {
+ throw new IllegalArgumentException("A combined cluster cannot run ZooKeeper");
+ }
+ int nodeCount = cluster.getContainers().size();
+ if (nodeCount < MIN_ZOOKEEPER_NODE_COUNT || nodeCount > MAX_ZOOKEEPER_NODE_COUNT || nodeCount % 2 == 0) {
+ throw new IllegalArgumentException("Clusters running ZooKeeper must have an odd number of nodes, between " +
+ MIN_ZOOKEEPER_NODE_COUNT + " and " + MAX_ZOOKEEPER_NODE_COUNT);
+ }
+ cluster.addSimpleComponent("com.yahoo.vespa.curator.Curator", null, "zkfacade");
+ // TODO: Add server component
}
private void addSecretStore(ApplicationContainerCluster cluster, Element spec) {
diff --git a/config-model/src/main/resources/schema/containercluster.rnc b/config-model/src/main/resources/schema/containercluster.rnc
index 25d10e0d9b3..ca7efd5a938 100644
--- a/config-model/src/main/resources/schema/containercluster.rnc
+++ b/config-model/src/main/resources/schema/containercluster.rnc
@@ -27,6 +27,7 @@ ContainerServices =
Http? &
AccessLog* &
SecretStore? &
+ ZooKeeper? &
GenericConfig*
# TODO(ogronnesby): Change this configuration syntax
@@ -91,6 +92,10 @@ SecretStore = element secret-store {
} +
}
+ZooKeeper = element zookeeper {
+ empty
+}
+
ModelEvaluation = element model-evaluation {
empty
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
index 13c1631e0ce..32dd5cc944c 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
@@ -40,11 +40,13 @@ import com.yahoo.vespa.defaults.Defaults;
import com.yahoo.vespa.model.AbstractService;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.container.ApplicationContainer;
+import com.yahoo.vespa.model.container.ApplicationContainerCluster;
import com.yahoo.vespa.model.container.ContainerCluster;
import com.yahoo.vespa.model.container.SecretStore;
import com.yahoo.vespa.model.container.component.Component;
import com.yahoo.vespa.model.container.http.ConnectorFactory;
import com.yahoo.vespa.model.content.utils.ContentClusterUtils;
+import com.yahoo.vespa.model.test.VespaModelTester;
import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithFilePkg;
import org.hamcrest.Matchers;
import org.junit.Rule;
@@ -59,6 +61,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.function.Function;
import java.util.logging.Level;
import java.util.stream.Collectors;
@@ -871,6 +874,46 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase {
assertThat(connectorConfig.ssl().caCertificate(), isEmptyString());
}
+ @Test
+ public void cluster_with_zookeeper() {
+ Function<Integer, String> servicesXml = (nodeCount) -> "<container version='1.0' id='default'>" +
+ "<nodes count='" + nodeCount + "'/>" +
+ "<zookeeper/>" +
+ "</container>";
+ VespaModelTester tester = new VespaModelTester();
+ tester.addHosts(3);
+ {
+ VespaModel model = tester.createModel(servicesXml.apply(3), true);
+ String componentId = "com.yahoo.vespa.curator.Curator";
+ ApplicationContainerCluster cluster = model.getContainerClusters().get("default");
+ assertNotNull(cluster);
+ Component<?, ?> curatorComponent = cluster.getComponentsMap().get(ComponentId.fromString(componentId));
+ assertNotNull(curatorComponent);
+ }
+ {
+ try {
+ tester.createModel(servicesXml.apply(1), true);
+ fail("Expected exception");
+ } catch (IllegalArgumentException ignored) {}
+ }
+ {
+ String xmlWithNodes =
+ "<?xml version='1.0' encoding='utf-8' ?>" +
+ "<services>" +
+ " <container version='1.0' id='container1'>" +
+ " <zookeeper/>" +
+ " <nodes of='content1'/>" +
+ " </container>" +
+ " <content version='1.0' id='content1'>" +
+ " <nodes count='3'/>" +
+ " </content>" +
+ "</services>";
+ try {
+ tester.createModel(xmlWithNodes, true);
+ fail("Expected exception");
+ } catch (IllegalArgumentException ignored) {}
+ }
+ }
private Element generateContainerElementWithRenderer(String rendererId) {
return DomBuilderTest.parse(
@@ -880,4 +923,5 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase {
" </search>",
"</container>");
}
+
}