diff --git a/docs/reference/setup/configuration.asciidoc b/docs/reference/setup/configuration.asciidoc index b822b223ce576..2bff0957690ff 100644 --- a/docs/reference/setup/configuration.asciidoc +++ b/docs/reference/setup/configuration.asciidoc @@ -264,6 +264,29 @@ file which will resolve to an environment setting, for example: } -------------------------------------------------- +Additionally, for settings that you do not wish to store in the configuration +file, you can use the value `${prompt::text}` or `${prompt::secret}` and start +Elasticsearch in the foreground. `${prompt::secret}` has echoing disabled so +that the value entered will not be shown in your terminal; `${prompt::text}` +will allow you to see the value as you type it in. For example: + +[source,yaml] +-------------------------------------------------- +node: + name: ${prompt::text} +-------------------------------------------------- + +On execution of the `elasticsearch` command, you will be prompted to enter +the actual value like so: + +[source,sh] +-------------------------------------------------- +Enter value for [node.name]: +-------------------------------------------------- + +NOTE: Elasticsearch will not start if `${prompt::text}` or `${prompt::secret}` +is used in the settings and the process is run as a service or in the background. + The location of the configuration file can be set externally using a system property: diff --git a/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java b/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java index 84663f60a4dbb..912d0800533cb 100644 --- a/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java +++ b/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java @@ -25,6 +25,7 @@ import org.elasticsearch.Version; import org.elasticsearch.common.PidFile; import org.elasticsearch.common.SuppressForbidden; +import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.inject.CreationException; import org.elasticsearch.common.inject.spi.Message; @@ -163,8 +164,16 @@ public void run() { // install SM after natives, shutdown hooks, etc. setupSecurity(settings, environment); - - NodeBuilder nodeBuilder = NodeBuilder.nodeBuilder().settings(settings).loadConfigSettings(false); + + // We do not need to reload system properties here as we have already applied them in building the settings and + // reloading could cause multiple prompts to the user for values if a system property was specified with a prompt + // placeholder + Settings nodeSettings = Settings.settingsBuilder() + .put(settings) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) + .build(); + + NodeBuilder nodeBuilder = NodeBuilder.nodeBuilder().settings(nodeSettings).loadConfigSettings(false); node = nodeBuilder.build(); } @@ -195,8 +204,9 @@ private static void setupLogging(Settings settings, Environment environment) { } } - private static Tuple initialSettings() { - return InternalSettingsPreparer.prepareSettings(EMPTY_SETTINGS, true); + private static Tuple initialSettings(boolean foreground) { + Terminal terminal = foreground ? Terminal.DEFAULT : null; + return InternalSettingsPreparer.prepareSettings(EMPTY_SETTINGS, true, terminal); } private void start() { @@ -227,7 +237,7 @@ public static void main(String[] args) { Settings settings = null; Environment environment = null; try { - Tuple tuple = initialSettings(); + Tuple tuple = initialSettings(foreground); settings = tuple.v1(); environment = tuple.v2(); diff --git a/src/main/java/org/elasticsearch/common/cli/CliTool.java b/src/main/java/org/elasticsearch/common/cli/CliTool.java index 71e87943349e2..b0784a57ca7cd 100644 --- a/src/main/java/org/elasticsearch/common/cli/CliTool.java +++ b/src/main/java/org/elasticsearch/common/cli/CliTool.java @@ -93,7 +93,7 @@ protected CliTool(CliToolConfig config, Terminal terminal) { Preconditions.checkArgument(config.cmds().size() != 0, "At least one command must be configured"); this.config = config; this.terminal = terminal; - Tuple tuple = InternalSettingsPreparer.prepareSettings(EMPTY_SETTINGS, true); + Tuple tuple = InternalSettingsPreparer.prepareSettings(EMPTY_SETTINGS, true, terminal); settings = tuple.v1(); env = tuple.v2(); } diff --git a/src/main/java/org/elasticsearch/common/settings/Settings.java b/src/main/java/org/elasticsearch/common/settings/Settings.java index 67bd3b00f443e..7c79b3fc1d458 100644 --- a/src/main/java/org/elasticsearch/common/settings/Settings.java +++ b/src/main/java/org/elasticsearch/common/settings/Settings.java @@ -1211,7 +1211,7 @@ public Builder putProperties(String prefix, Properties properties, String[] igno * tries and resolve it against an environment variable ({@link System#getenv(String)}), and last, tries * and replace it with another setting already set on this builder. */ - public Builder replacePropertyPlaceholders() { + public Builder replacePropertyPlaceholders(String... ignoredValues) { PropertyPlaceholder propertyPlaceholder = new PropertyPlaceholder("${", "}", false); PropertyPlaceholder.PlaceholderResolver placeholderResolver = new PropertyPlaceholder.PlaceholderResolver() { @Override @@ -1241,7 +1241,19 @@ public boolean shouldIgnoreMissing(String placeholderName) { } }; for (Map.Entry entry : Maps.newHashMap(map).entrySet()) { - String value = propertyPlaceholder.replacePlaceholders(entry.getValue(), placeholderResolver); + String possiblePlaceholder = entry.getValue(); + boolean ignored = false; + for (String ignoredValue : ignoredValues) { + if (ignoredValue.equals(possiblePlaceholder)) { + ignored = true; + break; + } + } + if (ignored) { + continue; + } + + String value = propertyPlaceholder.replacePlaceholders(possiblePlaceholder, placeholderResolver); // if the values exists and has length, we should maintain it in the map // otherwise, the replace process resolved into removing it if (Strings.hasLength(value)) { diff --git a/src/main/java/org/elasticsearch/node/internal/InternalSettingsPreparer.java b/src/main/java/org/elasticsearch/node/internal/InternalSettingsPreparer.java index e8973753b2a73..68c2722940e18 100644 --- a/src/main/java/org/elasticsearch/node/internal/InternalSettingsPreparer.java +++ b/src/main/java/org/elasticsearch/node/internal/InternalSettingsPreparer.java @@ -20,9 +20,11 @@ package org.elasticsearch.node.internal; import com.google.common.collect.ImmutableList; +import com.google.common.collect.UnmodifiableIterator; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.common.Names; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; @@ -41,10 +43,38 @@ public class InternalSettingsPreparer { static final List ALLOWED_SUFFIXES = ImmutableList.of(".yml", ".yaml", ".json", ".properties"); + public static final String SECRET_PROMPT_VALUE = "${prompt::secret}"; + public static final String TEXT_PROMPT_VALUE = "${prompt::text}"; + public static final String IGNORE_SYSTEM_PROPERTIES_SETTING = "config.ignore_system_properties"; + + /** + * Prepares the settings by gathering all elasticsearch system properties, optionally loading the configuration settings, + * and then replacing all property placeholders. This method will not work with settings that have __prompt__ + * as their value unless they have been resolved previously. + * @param pSettings The initial settings to use + * @param loadConfigSettings flag to indicate whether to load settings from the configuration directory/file + * @return the {@link Settings} and {@link Environment} as a {@link Tuple} + */ public static Tuple prepareSettings(Settings pSettings, boolean loadConfigSettings) { + return prepareSettings(pSettings, loadConfigSettings, null); + } + + /** + * Prepares the settings by gathering all elasticsearch system properties, optionally loading the configuration settings, + * and then replacing all property placeholders. If a {@link Terminal} is provided and configuration settings are loaded, + * settings with the __prompt__ value will result in a prompt for the setting to the user. + * @param pSettings The initial settings to use + * @param loadConfigSettings flag to indicate whether to load settings from the configuration directory/file + * @param terminal the Terminal to use for input/output + * @return the {@link Settings} and {@link Environment} as a {@link Tuple} + */ + public static Tuple prepareSettings(Settings pSettings, boolean loadConfigSettings, Terminal terminal) { // ignore this prefixes when getting properties from es. and elasticsearch. String[] ignorePrefixes = new String[]{"es.default.", "elasticsearch.default."}; - boolean useSystemProperties = !pSettings.getAsBoolean("config.ignore_system_properties", false); + // ignore the special prompt placeholders since they have the same format as property placeholders and will be resolved + // as having a default value because of the ':' in the format + String[] ignoredPlaceholders = new String[] { SECRET_PROMPT_VALUE, TEXT_PROMPT_VALUE }; + boolean useSystemProperties = !pSettings.getAsBoolean(IGNORE_SYSTEM_PROPERTIES_SETTING, false); // just create enough settings to build the environment Settings.Builder settingsBuilder = settingsBuilder().put(pSettings); if (useSystemProperties) { @@ -53,7 +83,7 @@ public static Tuple prepareSettings(Settings pSettings, b .putProperties("elasticsearch.", System.getProperties(), ignorePrefixes) .putProperties("es.", System.getProperties(), ignorePrefixes); } - settingsBuilder.replacePropertyPlaceholders(); + settingsBuilder.replacePropertyPlaceholders(ignoredPlaceholders); Environment environment = new Environment(settingsBuilder.build()); @@ -91,17 +121,17 @@ public static Tuple prepareSettings(Settings pSettings, b settingsBuilder.putProperties("elasticsearch.", System.getProperties(), ignorePrefixes) .putProperties("es.", System.getProperties(), ignorePrefixes); } - settingsBuilder.replacePropertyPlaceholders(); + settingsBuilder.replacePropertyPlaceholders(ignoredPlaceholders); // allow to force set properties based on configuration of the settings provided for (Map.Entry entry : pSettings.getAsMap().entrySet()) { String setting = entry.getKey(); if (setting.startsWith("force.")) { settingsBuilder.remove(setting); - settingsBuilder.put(setting.substring(".force".length()), entry.getValue()); + settingsBuilder.put(setting.substring("force.".length()), entry.getValue()); } } - settingsBuilder.replacePropertyPlaceholders(); + settingsBuilder.replacePropertyPlaceholders(ignoredPlaceholders); // generate the name if (settingsBuilder.get("name") == null) { @@ -123,7 +153,7 @@ public static Tuple prepareSettings(Settings pSettings, b settingsBuilder.put(ClusterName.SETTING, ClusterName.DEFAULT.value()); } - Settings v1 = settingsBuilder.build(); + Settings v1 = replacePromptPlaceholders(settingsBuilder.build(), terminal); environment = new Environment(v1); // put back the env settings @@ -135,4 +165,45 @@ public static Tuple prepareSettings(Settings pSettings, b return new Tuple<>(v1, environment); } + + static Settings replacePromptPlaceholders(Settings settings, Terminal terminal) { + UnmodifiableIterator> iter = settings.getAsMap().entrySet().iterator(); + Settings.Builder builder = Settings.builder(); + + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + String value = entry.getValue(); + String key = entry.getKey(); + switch (value) { + case SECRET_PROMPT_VALUE: + String secretValue = promptForValue(key, terminal, true); + if (Strings.hasLength(secretValue)) { + builder.put(key, secretValue); + } + break; + case TEXT_PROMPT_VALUE: + String textValue = promptForValue(key, terminal, false); + if (Strings.hasLength(textValue)) { + builder.put(key, textValue); + } + break; + default: + builder.put(key, value); + break; + } + } + + return builder.build(); + } + + static String promptForValue(String key, Terminal terminal, boolean secret) { + if (terminal == null) { + throw new UnsupportedOperationException("found property [" + key + "] with value [" + (secret ? SECRET_PROMPT_VALUE : TEXT_PROMPT_VALUE) +"]. prompting for property values is only supported when running elasticsearch in the foreground"); + } + + if (secret) { + return new String(terminal.readSecret("Enter value for [%s]: ", key)); + } + return terminal.readText("Enter value for [%s]: ", key); + } } diff --git a/src/main/java/org/elasticsearch/plugins/PluginManager.java b/src/main/java/org/elasticsearch/plugins/PluginManager.java index f8802b658c296..31b235ceda77a 100644 --- a/src/main/java/org/elasticsearch/plugins/PluginManager.java +++ b/src/main/java/org/elasticsearch/plugins/PluginManager.java @@ -25,6 +25,7 @@ import org.apache.lucene.util.IOUtils; import org.elasticsearch.*; import org.elasticsearch.common.SuppressForbidden; +import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.http.client.HttpDownloadHelper; import org.elasticsearch.common.io.FileSystemUtils; @@ -338,7 +339,7 @@ public void listInstalledPlugins() throws IOException { private static final int EXIT_CODE_ERROR = 70; public static void main(String[] args) { - Tuple initialSettings = InternalSettingsPreparer.prepareSettings(EMPTY_SETTINGS, true); + Tuple initialSettings = InternalSettingsPreparer.prepareSettings(EMPTY_SETTINGS, true, Terminal.DEFAULT); try { Files.createDirectories(initialSettings.v2().pluginsFile()); diff --git a/src/main/java/org/elasticsearch/tribe/TribeService.java b/src/main/java/org/elasticsearch/tribe/TribeService.java index 546977c3acad6..f2f21a1d1ca77 100644 --- a/src/main/java/org/elasticsearch/tribe/TribeService.java +++ b/src/main/java/org/elasticsearch/tribe/TribeService.java @@ -45,6 +45,7 @@ import org.elasticsearch.gateway.GatewayService; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeBuilder; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.rest.RestStatus; import java.util.EnumSet; @@ -128,7 +129,7 @@ public TribeService(Settings settings, ClusterService clusterService, DiscoveryS sb.put("node.name", settings.get("name") + "/" + entry.getKey()); sb.put("path.home", settings.get("path.home")); // pass through ES home dir sb.put(TRIBE_NAME, entry.getKey()); - sb.put("config.ignore_system_properties", true); + sb.put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true); if (sb.get("http.enabled") == null) { sb.put("http.enabled", false); } diff --git a/src/test/java/org/elasticsearch/client/transport/TransportClientRetryTests.java b/src/test/java/org/elasticsearch/client/transport/TransportClientRetryTests.java index 724e5ff50a956..dec47e58008f9 100644 --- a/src/test/java/org/elasticsearch/client/transport/TransportClientRetryTests.java +++ b/src/test/java/org/elasticsearch/client/transport/TransportClientRetryTests.java @@ -28,6 +28,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.plugins.PluginsService; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.InternalTestCluster; @@ -61,7 +62,7 @@ public void testRetry() throws IOException, ExecutionException, InterruptedExcep .put("node.mode", InternalTestCluster.nodeMode()) .put("plugins." + PluginsService.LOAD_PLUGIN_FROM_CLASSPATH, false) .put(ClusterName.SETTING, internalCluster().getClusterName()) - .put("config.ignore_system_properties", true) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) .put("path.home", createTempDir()); try (TransportClient transportClient = TransportClient.builder().settings(builder.build()).build()) { diff --git a/src/test/java/org/elasticsearch/client/transport/TransportClientTests.java b/src/test/java/org/elasticsearch/client/transport/TransportClientTests.java index 86d39bb936b8b..70f96f2ede09d 100644 --- a/src/test/java/org/elasticsearch/client/transport/TransportClientTests.java +++ b/src/test/java/org/elasticsearch/client/transport/TransportClientTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.node.Node; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; import org.elasticsearch.transport.TransportService; @@ -59,7 +60,7 @@ public void testNodeVersionIsUpdated() { .put("path.home", createTempDir()) .put("node.name", "testNodeVersionIsUpdated") .put("http.enabled", false) - .put("config.ignore_system_properties", true) // make sure we get what we set :) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) // make sure we get what we set :) .build()).clusterName("foobar").build(); node.start(); try { diff --git a/src/test/java/org/elasticsearch/common/cli/CliToolTests.java b/src/test/java/org/elasticsearch/common/cli/CliToolTests.java index 72db9950ded13..eea1d0614a140 100644 --- a/src/test/java/org/elasticsearch/common/cli/CliToolTests.java +++ b/src/test/java/org/elasticsearch/common/cli/CliToolTests.java @@ -25,10 +25,12 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.junit.Test; import java.io.IOException; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import static org.elasticsearch.common.cli.CliToolConfig.Builder.cmd; @@ -271,6 +273,49 @@ public CliTool.ExitStatus execute(Settings settings, Environment env) { tool.parse("cmd", Strings.splitStringByCommaToArray("--help")); } + @Test + public void testPromptForSetting() throws Exception { + final AtomicInteger counter = new AtomicInteger(); + final AtomicReference promptedSecretValue = new AtomicReference<>(null); + final AtomicReference promptedTextValue = new AtomicReference<>(null); + final Terminal terminal = new MockTerminal() { + @Override + public char[] readSecret(String text, Object... args) { + counter.incrementAndGet(); + assertThat(args, arrayContaining((Object) "foo.password")); + return "changeit".toCharArray(); + } + + @Override + public String readText(String text, Object... args) { + counter.incrementAndGet(); + assertThat(args, arrayContaining((Object) "replace")); + return "replaced"; + } + }; + final NamedCommand cmd = new NamedCommand("noop", terminal) { + @Override + public CliTool.ExitStatus execute(Settings settings, Environment env) { + promptedSecretValue.set(settings.get("foo.password")); + promptedTextValue.set(settings.get("replace")); + return CliTool.ExitStatus.OK; + } + }; + + System.setProperty("es.foo.password", InternalSettingsPreparer.SECRET_PROMPT_VALUE); + System.setProperty("es.replace", InternalSettingsPreparer.TEXT_PROMPT_VALUE); + try { + new SingleCmdTool("tool", terminal, cmd).execute(); + } finally { + System.clearProperty("es.foo.password"); + System.clearProperty("es.replace"); + } + + assertThat(counter.intValue(), is(2)); + assertThat(promptedSecretValue.get(), is("changeit")); + assertThat(promptedTextValue.get(), is("replaced")); + } + private void assertStatus(int status, CliTool.ExitStatus expectedStatus) { assertThat(status, is(expectedStatus.status())); } diff --git a/src/test/java/org/elasticsearch/common/settings/SettingsTests.java b/src/test/java/org/elasticsearch/common/settings/SettingsTests.java index c8334ba069194..1dbaf32f06c12 100644 --- a/src/test/java/org/elasticsearch/common/settings/SettingsTests.java +++ b/src/test/java/org/elasticsearch/common/settings/SettingsTests.java @@ -137,6 +137,17 @@ public void testReplacePropertiesPlaceholderIgnoreEnvUnset() { assertThat(settings.get("setting1"), is(nullValue())); } + @Test + public void testReplacePropertiesPlaceholderIgnores() { + Settings settings = settingsBuilder() + .put("setting1", "${foo.bar}") + .put("setting2", "${foo.bar1}") + .replacePropertyPlaceholders("${foo.bar}", "${foo.bar1}") + .build(); + assertThat(settings.get("setting1"), is("${foo.bar}")); + assertThat(settings.get("setting2"), is("${foo.bar1}")); + } + @Test public void testUnFlattenedSettings() { Settings settings = settingsBuilder() diff --git a/src/test/java/org/elasticsearch/indices/memory/IndexingMemoryControllerTests.java b/src/test/java/org/elasticsearch/indices/memory/IndexingMemoryControllerTests.java index a7e09a3af8815..6914bcb95d471 100644 --- a/src/test/java/org/elasticsearch/indices/memory/IndexingMemoryControllerTests.java +++ b/src/test/java/org/elasticsearch/indices/memory/IndexingMemoryControllerTests.java @@ -27,6 +27,7 @@ import org.elasticsearch.index.engine.EngineConfig; import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.indices.IndicesService; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.junit.Test; @@ -143,7 +144,7 @@ private void createNode(Settings settings) { .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) .put(EsExecutors.PROCESSORS, 1) // limit the number of threads created .put("http.enabled", false) - .put("config.ignore_system_properties", true) // make sure we get what we set :) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) // make sure we get what we set :) .put("indices.memory.interval", "100ms") .put(settings) ); diff --git a/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java b/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java index 315a5f7f2bd9f..82b6a2a601b2c 100644 --- a/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java +++ b/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java @@ -19,6 +19,8 @@ package org.elasticsearch.node.internal; +import org.elasticsearch.common.cli.CliToolTestCase; +import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; @@ -27,11 +29,16 @@ import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; +import java.util.List; + import static org.elasticsearch.common.settings.Settings.settingsBuilder; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; public class InternalSettingsPreparerTests extends ElasticsearchTestCase { + @Before public void setupSystemProperties() { System.setProperty("es.node.zone", "foo"); @@ -53,7 +60,7 @@ public void testIgnoreSystemProperties() { assertThat(tuple.v1().get("node.zone"), equalTo("foo")); settings = settingsBuilder() - .put("config.ignore_system_properties", true) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) .put("node.zone", "bar") .put("path.home", createTempDir().toString()) .build(); @@ -74,4 +81,74 @@ public void testAlternateConfigFileSuffixes() { assertThat(tuple.v1().get("json.config.exists"), equalTo("true")); assertThat(tuple.v1().get("properties.config.exists"), equalTo("true")); } + + @Test + public void testReplacePromptPlaceholders() { + final List replacedSecretProperties = new ArrayList<>(); + final List replacedTextProperties = new ArrayList<>(); + final Terminal terminal = new CliToolTestCase.MockTerminal() { + @Override + public char[] readSecret(String message, Object... args) { + for (Object arg : args) { + replacedSecretProperties.add((String) arg); + } + return "replaced".toCharArray(); + } + + @Override + public String readText(String message, Object... args) { + for (Object arg : args) { + replacedTextProperties.add((String) arg); + } + return "text"; + } + }; + + Settings.Builder builder = settingsBuilder() + .put("password.replace", InternalSettingsPreparer.SECRET_PROMPT_VALUE) + .put("dont.replace", "prompt:secret") + .put("dont.replace2", "_prompt:secret_") + .put("dont.replace3", "_prompt:text__") + .put("dont.replace4", "__prompt:text_") + .put("dont.replace5", "prompt:secret__") + .put("replace_me", InternalSettingsPreparer.TEXT_PROMPT_VALUE); + Settings settings = builder.build(); + settings = InternalSettingsPreparer.replacePromptPlaceholders(settings, terminal); + + assertThat(replacedSecretProperties.size(), is(1)); + assertThat(replacedTextProperties.size(), is(1)); + assertThat(settings.get("password.replace"), equalTo("replaced")); + assertThat(settings.get("replace_me"), equalTo("text")); + + // verify other values unchanged + assertThat(settings.get("dont.replace"), equalTo("prompt:secret")); + assertThat(settings.get("dont.replace2"), equalTo("_prompt:secret_")); + assertThat(settings.get("dont.replace3"), equalTo("_prompt:text__")); + assertThat(settings.get("dont.replace4"), equalTo("__prompt:text_")); + assertThat(settings.get("dont.replace5"), equalTo("prompt:secret__")); + } + + @Test + public void testReplaceSecretPromptPlaceholderWithNullTerminal() { + Settings.Builder builder = settingsBuilder() + .put("replace_me1", InternalSettingsPreparer.SECRET_PROMPT_VALUE); + try { + InternalSettingsPreparer.replacePromptPlaceholders(builder.build(), null); + fail("an exception should have been thrown since no terminal was provided!"); + } catch (UnsupportedOperationException e) { + assertThat(e.getMessage(), containsString("with value [" + InternalSettingsPreparer.SECRET_PROMPT_VALUE + "]")); + } + } + + @Test + public void testReplaceTextPromptPlaceholderWithNullTerminal() { + Settings.Builder builder = settingsBuilder() + .put("replace_me1", InternalSettingsPreparer.TEXT_PROMPT_VALUE); + try { + InternalSettingsPreparer.replacePromptPlaceholders(builder.build(), null); + fail("an exception should have been thrown since no terminal was provided!"); + } catch (UnsupportedOperationException e) { + assertThat(e.getMessage(), containsString("with value [" + InternalSettingsPreparer.TEXT_PROMPT_VALUE + "]")); + } + } } diff --git a/src/test/java/org/elasticsearch/test/ElasticsearchSingleNodeTest.java b/src/test/java/org/elasticsearch/test/ElasticsearchSingleNodeTest.java index 49be171eba222..bc868417c75e1 100644 --- a/src/test/java/org/elasticsearch/test/ElasticsearchSingleNodeTest.java +++ b/src/test/java/org/elasticsearch/test/ElasticsearchSingleNodeTest.java @@ -39,6 +39,7 @@ import org.elasticsearch.indices.IndicesService; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeBuilder; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.threadpool.ThreadPool; import org.junit.After; @@ -127,7 +128,7 @@ private static Node newNode() { .put("script.indexed", "on") .put(EsExecutors.PROCESSORS, 1) // limit the number of threads created .put("http.enabled", false) - .put("config.ignore_system_properties", true) // make sure we get what we set :) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) // make sure we get what we set :) ).build(); build.start(); assertThat(DiscoveryNode.localNode(build.settings()), is(true)); diff --git a/src/test/java/org/elasticsearch/test/ExternalNode.java b/src/test/java/org/elasticsearch/test/ExternalNode.java index 40a6223aca918..4116632fd2721 100644 --- a/src/test/java/org/elasticsearch/test/ExternalNode.java +++ b/src/test/java/org/elasticsearch/test/ExternalNode.java @@ -33,6 +33,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.discovery.DiscoveryModule; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.transport.TransportModule; import java.io.Closeable; @@ -53,7 +54,7 @@ final class ExternalNode implements Closeable { public static final Settings REQUIRED_SETTINGS = Settings.builder() - .put("config.ignore_system_properties", true) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) .put(DiscoveryModule.DISCOVERY_TYPE_KEY, "zen") .put("node.mode", "network").build(); // we need network mode for this @@ -115,7 +116,7 @@ synchronized void startInternal(Client client, Settings settings, String nodeNam case TransportModule.TRANSPORT_TYPE_KEY: case DiscoveryModule.DISCOVERY_TYPE_KEY: case TransportModule.TRANSPORT_SERVICE_TYPE_KEY: - case "config.ignore_system_properties": + case InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING: continue; default: externaNodeSettingsBuilder.put(entry.getKey(), entry.getValue()); diff --git a/src/test/java/org/elasticsearch/test/ExternalTestCluster.java b/src/test/java/org/elasticsearch/test/ExternalTestCluster.java index fcb977a610401..228bf05ff4133 100644 --- a/src/test/java/org/elasticsearch/test/ExternalTestCluster.java +++ b/src/test/java/org/elasticsearch/test/ExternalTestCluster.java @@ -33,6 +33,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import java.io.IOException; import java.net.InetSocketAddress; @@ -67,7 +68,7 @@ public ExternalTestCluster(TransportAddress... transportAddresses) { super(0); Settings clientSettings = Settings.settingsBuilder() .put("name", InternalTestCluster.TRANSPORT_CLIENT_PREFIX + EXTERNAL_CLUSTER_PREFIX + counter.getAndIncrement()) - .put("config.ignore_system_properties", true) // prevents any settings to be replaced by system properties. + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) // prevents any settings to be replaced by system properties. .put("client.transport.ignore_cluster_name", true) .put("node.mode", "network").build(); // we require network here! diff --git a/src/test/java/org/elasticsearch/test/InternalTestCluster.java b/src/test/java/org/elasticsearch/test/InternalTestCluster.java index 285463a176bb4..77135db864692 100644 --- a/src/test/java/org/elasticsearch/test/InternalTestCluster.java +++ b/src/test/java/org/elasticsearch/test/InternalTestCluster.java @@ -88,6 +88,7 @@ import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache; import org.elasticsearch.indices.recovery.RecoverySettings; import org.elasticsearch.node.Node; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.node.service.NodeService; import org.elasticsearch.plugins.PluginsService; import org.elasticsearch.search.SearchService; @@ -279,7 +280,7 @@ public InternalTestCluster(long clusterSeed, Path baseDir, builder.put("path.repo", baseDir.resolve("repos")); builder.put("transport.tcp.port", BASE_PORT + "-" + (BASE_PORT+100)); builder.put("http.port", BASE_PORT+101 + "-" + (BASE_PORT+200)); - builder.put("config.ignore_system_properties", true); + builder.put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true); builder.put("node.mode", NODE_MODE); builder.put("http.pipelining", enableHttpPipelining); builder.put("plugins." + PluginsService.LOAD_PLUGIN_FROM_CLASSPATH, false); @@ -874,7 +875,7 @@ public Client client(Node node, String clusterName) { .put("node.local", nodeSettings.get("node.local", "")) .put("logger.prefix", nodeSettings.get("logger.prefix", "")) .put("logger.level", nodeSettings.get("logger.level", "INFO")) - .put("config.ignore_system_properties", true) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) .put(settings); TransportClient client = TransportClient.builder().settings(builder.build()).build(); diff --git a/src/test/java/org/elasticsearch/tribe/TribeUnitTests.java b/src/test/java/org/elasticsearch/tribe/TribeUnitTests.java index 5959ed3a6c450..1eb962bb86f4b 100644 --- a/src/test/java/org/elasticsearch/tribe/TribeUnitTests.java +++ b/src/test/java/org/elasticsearch/tribe/TribeUnitTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeBuilder; +import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.test.InternalTestCluster; import org.junit.AfterClass; @@ -51,7 +52,7 @@ public class TribeUnitTests extends ElasticsearchTestCase { @BeforeClass public static void createTribes() { Settings baseSettings = Settings.builder() - .put("config.ignore_system_properties", true) + .put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true) .put("http.enabled", false) .put("node.mode", NODE_MODE) .put("path.home", createTempDir()).build(); @@ -86,7 +87,7 @@ public void testThatTribeClientsIgnoreGlobalSysProps() throws Exception { @Test public void testThatTribeClientsIgnoreGlobalConfig() throws Exception { Path pathConf = getDataPath("elasticsearch.yml").getParent(); - Settings settings = Settings.builder().put("config.ignore_system_properties", true).put("path.conf", pathConf).build(); + Settings settings = Settings.builder().put(InternalSettingsPreparer.IGNORE_SYSTEM_PROPERTIES_SETTING, true).put("path.conf", pathConf).build(); assertTribeNodeSuccesfullyCreated(settings); }