summaryrefslogtreecommitdiff
path: root/core/src/test/java/org/elasticsearch/node
diff options
context:
space:
mode:
authorJason Tedor <jason@tedor.me>2017-04-24 09:31:54 -0400
committerGitHub <noreply@github.com>2017-04-24 09:31:54 -0400
commit1500beafc7baad4e8cbce0682ed76e429498ea13 (patch)
tree3e43b8d5c8941ba8e86704e8ba5f1ee340d798ce /core/src/test/java/org/elasticsearch/node
parenta7947b404b3f32df9ebdaa35da836bd4bc0fa760 (diff)
Check for default.path.data included in path.data
If the user explicitly configured path.data to include default.path.data, then we should not fail the node if we find indices in default.path.data. This commit addresses this. Relates #24285
Diffstat (limited to 'core/src/test/java/org/elasticsearch/node')
-rw-r--r--core/src/test/java/org/elasticsearch/node/NodeTests.java255
1 files changed, 255 insertions, 0 deletions
diff --git a/core/src/test/java/org/elasticsearch/node/NodeTests.java b/core/src/test/java/org/elasticsearch/node/NodeTests.java
new file mode 100644
index 0000000000..e99c7b9063
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/node/NodeTests.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.node;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.lucene.util.LuceneTestCase;
+import org.elasticsearch.Version;
+import org.elasticsearch.bootstrap.BootstrapCheck;
+import org.elasticsearch.cluster.ClusterName;
+import org.elasticsearch.common.UUIDs;
+import org.elasticsearch.common.network.NetworkModule;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.BoundTransportAddress;
+import org.elasticsearch.env.Environment;
+import org.elasticsearch.env.NodeEnvironment;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.test.InternalTestCluster;
+import org.elasticsearch.transport.MockTcpTransportPlugin;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasToString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+@LuceneTestCase.SuppressFileSystems(value = "ExtrasFS")
+public class NodeTests extends ESTestCase {
+
+ public void testNodeName() throws IOException {
+ final Path tempDir = createTempDir();
+ final String name = randomBoolean() ? randomAlphaOfLength(10) : null;
+ Settings.Builder settings = Settings.builder()
+ .put(ClusterName.CLUSTER_NAME_SETTING.getKey(), InternalTestCluster.clusterName("single-node-cluster", randomLong()))
+ .put(Environment.PATH_HOME_SETTING.getKey(), tempDir)
+ .put(NetworkModule.HTTP_ENABLED.getKey(), false)
+ .put("transport.type", "mock-socket-network")
+ .put(Node.NODE_DATA_SETTING.getKey(), true);
+ if (name != null) {
+ settings.put(Node.NODE_NAME_SETTING.getKey(), name);
+ }
+ try (Node node = new MockNode(settings.build(), Collections.singleton(MockTcpTransportPlugin.class))) {
+ final Settings nodeSettings = randomBoolean() ? node.settings() : node.getEnvironment().settings();
+ if (name == null) {
+ assertThat(Node.NODE_NAME_SETTING.get(nodeSettings), equalTo(node.getNodeEnvironment().nodeId().substring(0, 7)));
+ } else {
+ assertThat(Node.NODE_NAME_SETTING.get(nodeSettings), equalTo(name));
+ }
+ }
+ }
+
+ public static class CheckPlugin extends Plugin {
+ public static final BootstrapCheck CHECK = new BootstrapCheck() {
+ @Override
+ public boolean check() {
+ return false;
+ }
+
+ @Override
+ public String errorMessage() {
+ return "boom";
+ }
+ };
+ @Override
+ public List<BootstrapCheck> getBootstrapChecks() {
+ return Collections.singletonList(CHECK);
+ }
+ }
+
+ public void testLoadPluginBootstrapChecks() throws IOException {
+ final Path tempDir = createTempDir();
+ final String name = randomBoolean() ? randomAlphaOfLength(10) : null;
+ Settings.Builder settings = Settings.builder()
+ .put(ClusterName.CLUSTER_NAME_SETTING.getKey(), InternalTestCluster.clusterName("single-node-cluster", randomLong()))
+ .put(Environment.PATH_HOME_SETTING.getKey(), tempDir)
+ .put(NetworkModule.HTTP_ENABLED.getKey(), false)
+ .put("transport.type", "mock-socket-network")
+ .put(Node.NODE_DATA_SETTING.getKey(), true);
+ if (name != null) {
+ settings.put(Node.NODE_NAME_SETTING.getKey(), name);
+ }
+ AtomicBoolean executed = new AtomicBoolean(false);
+ try (Node node = new MockNode(settings.build(), Arrays.asList(MockTcpTransportPlugin.class, CheckPlugin.class)) {
+ @Override
+ protected void validateNodeBeforeAcceptingRequests(Settings settings, BoundTransportAddress boundTransportAddress,
+ List<BootstrapCheck> bootstrapChecks) throws NodeValidationException {
+ assertEquals(1, bootstrapChecks.size());
+ assertSame(CheckPlugin.CHECK, bootstrapChecks.get(0));
+ executed.set(true);
+ throw new NodeValidationException("boom");
+ }
+ }) {
+ expectThrows(NodeValidationException.class, () -> node.start());
+ assertTrue(executed.get());
+ }
+ }
+
+ public void testWarnIfPreRelease() {
+ final Logger logger = mock(Logger.class);
+
+ final int id = randomIntBetween(1, 9) * 1000000;
+ final Version releaseVersion = Version.fromId(id + 99);
+ final Version preReleaseVersion = Version.fromId(id + randomIntBetween(0, 98));
+
+ Node.warnIfPreRelease(releaseVersion, false, logger);
+ verifyNoMoreInteractions(logger);
+
+ reset(logger);
+ Node.warnIfPreRelease(releaseVersion, true, logger);
+ verify(logger).warn(
+ "version [{}] is a pre-release version of Elasticsearch and is not suitable for production", releaseVersion + "-SNAPSHOT");
+
+ reset(logger);
+ final boolean isSnapshot = randomBoolean();
+ Node.warnIfPreRelease(preReleaseVersion, isSnapshot, logger);
+ verify(logger).warn(
+ "version [{}] is a pre-release version of Elasticsearch and is not suitable for production",
+ preReleaseVersion + (isSnapshot ? "-SNAPSHOT" : ""));
+
+ }
+
+ public void testNodeAttributes() throws IOException {
+ String attr = randomAlphaOfLength(5);
+ Settings.Builder settings = baseSettings().put(Node.NODE_ATTRIBUTES.getKey() + "test_attr", attr);
+ try (Node node = new MockNode(settings.build(), Collections.singleton(MockTcpTransportPlugin.class))) {
+ final Settings nodeSettings = randomBoolean() ? node.settings() : node.getEnvironment().settings();
+ assertEquals(attr, Node.NODE_ATTRIBUTES.get(nodeSettings).getAsMap().get("test_attr"));
+ }
+
+ // leading whitespace not allowed
+ attr = " leading";
+ settings = baseSettings().put(Node.NODE_ATTRIBUTES.getKey() + "test_attr", attr);
+ try (Node node = new MockNode(settings.build(), Collections.singleton(MockTcpTransportPlugin.class))) {
+ fail("should not allow a node attribute with leading whitespace");
+ } catch (IllegalArgumentException e) {
+ assertEquals("node.attr.test_attr cannot have leading or trailing whitespace [ leading]", e.getMessage());
+ }
+
+ // trailing whitespace not allowed
+ attr = "trailing ";
+ settings = baseSettings().put(Node.NODE_ATTRIBUTES.getKey() + "test_attr", attr);
+ try (Node node = new MockNode(settings.build(), Collections.singleton(MockTcpTransportPlugin.class))) {
+ fail("should not allow a node attribute with trailing whitespace");
+ } catch (IllegalArgumentException e) {
+ assertEquals("node.attr.test_attr cannot have leading or trailing whitespace [trailing ]", e.getMessage());
+ }
+ }
+
+ public void testDefaultPathDataSet() throws IOException {
+ final Path zero = createTempDir().toAbsolutePath();
+ final Path one = createTempDir().toAbsolutePath();
+ final Path defaultPathData = createTempDir().toAbsolutePath();
+ final Settings settings = Settings.builder()
+ .put("path.home", "/home")
+ .put("path.data.0", zero)
+ .put("path.data.1", one)
+ .put("default.path.data", defaultPathData)
+ .build();
+ try (NodeEnvironment nodeEnv = new NodeEnvironment(settings, new Environment(settings))) {
+ final Path defaultPathDataWithNodesAndId = defaultPathData.resolve("nodes/0");
+ Files.createDirectories(defaultPathDataWithNodesAndId);
+ final NodeEnvironment.NodePath defaultNodePath = new NodeEnvironment.NodePath(defaultPathDataWithNodesAndId);
+ final boolean indexExists = randomBoolean();
+ final List<String> indices;
+ if (indexExists) {
+ indices = IntStream.range(0, randomIntBetween(1, 3)).mapToObj(i -> UUIDs.randomBase64UUID()).collect(Collectors.toList());
+ for (final String index : indices) {
+ Files.createDirectories(defaultNodePath.indicesPath.resolve(index));
+ }
+ } else {
+ indices = Collections.emptyList();
+ }
+ final Logger mock = mock(Logger.class);
+ if (indexExists) {
+ final IllegalStateException e = expectThrows(
+ IllegalStateException.class,
+ () -> Node.checkForIndexDataInDefaultPathData(settings, nodeEnv, mock));
+ final String message = String.format(
+ Locale.ROOT,
+ "detected index data in default.path.data [%s] where there should not be any; check the logs for details",
+ defaultPathData);
+ assertThat(e, hasToString(containsString(message)));
+ verify(mock)
+ .error("detected index data in default.path.data [{}] where there should not be any", defaultNodePath.indicesPath);
+ for (final String index : indices) {
+ verify(mock).info(
+ "index folder [{}] in default.path.data [{}] must be moved to any of {}",
+ index,
+ defaultNodePath.indicesPath,
+ Arrays.stream(nodeEnv.nodePaths()).map(np -> np.indicesPath).collect(Collectors.toList()));
+ }
+ verifyNoMoreInteractions(mock);
+ } else {
+ Node.checkForIndexDataInDefaultPathData(settings, nodeEnv, mock);
+ verifyNoMoreInteractions(mock);
+ }
+ }
+ }
+
+ public void testDefaultPathDataNotSet() throws IOException {
+ final Path zero = createTempDir().toAbsolutePath();
+ final Path one = createTempDir().toAbsolutePath();
+ final Settings settings = Settings.builder()
+ .put("path.home", "/home")
+ .put("path.data.0", zero)
+ .put("path.data.1", one)
+ .build();
+ try (NodeEnvironment nodeEnv = new NodeEnvironment(settings, new Environment(settings))) {
+ final Logger mock = mock(Logger.class);
+ Node.checkForIndexDataInDefaultPathData(settings, nodeEnv, mock);
+ verifyNoMoreInteractions(mock);
+ }
+ }
+
+ private static Settings.Builder baseSettings() {
+ final Path tempDir = createTempDir();
+ return Settings.builder()
+ .put(ClusterName.CLUSTER_NAME_SETTING.getKey(), InternalTestCluster.clusterName("single-node-cluster", randomLong()))
+ .put(Environment.PATH_HOME_SETTING.getKey(), tempDir)
+ .put(NetworkModule.HTTP_ENABLED.getKey(), false)
+ .put("transport.type", "mock-socket-network")
+ .put(Node.NODE_DATA_SETTING.getKey(), true);
+ }
+
+
+}