Merge pull request #17088 from jasontedor/simplify-bootstrap-settings

Bootstrap does not set system properties
This commit is contained in:
Jason Tedor 2016-03-15 19:25:16 -04:00
commit 618441aea3
39 changed files with 367 additions and 426 deletions

View File

@ -413,6 +413,7 @@ class BuildPlugin implements Plugin<Project> {
systemProperty 'jna.nosys', 'true'
// default test sysprop values
systemProperty 'tests.ifNoTests', 'fail'
// TODO: remove setting logging level via system property
systemProperty 'es.logger.level', 'WARN'
for (Map.Entry<String, String> property : System.properties.entrySet()) {
if (property.getKey().startsWith('tests.') ||

View File

@ -133,14 +133,15 @@ class NodeInfo {
'JAVA_HOME' : project.javaHome,
'ES_GC_OPTS': config.jvmArgs // we pass these with the undocumented gc opts so the argline can set gc, etc
]
args.add("-Des.node.portsfile=true")
args.addAll(config.systemProperties.collect { key, value -> "-D${key}=${value}" })
args.addAll("-E", "es.node.portsfile=true")
env.put('ES_JAVA_OPTS', config.systemProperties.collect { key, value -> "-D${key}=${value}" }.join(" "))
for (Map.Entry<String, String> property : System.properties.entrySet()) {
if (property.getKey().startsWith('es.')) {
args.add("-D${property.getKey()}=${property.getValue()}")
args.add("-E")
args.add("${property.getKey()}=${property.getValue()}")
}
}
args.add("-Des.path.conf=${confDir}")
args.addAll("-E", "es.path.conf=${confDir}")
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
args.add('"') // end the entire command, quoted
}

View File

@ -259,7 +259,6 @@
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]update[/\\]UpdateRequest.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]update[/\\]UpdateRequestBuilder.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]Bootstrap.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]BootstrapCLIParser.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]JNAKernel32Library.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]JNANatives.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]JVMCheck.java" checks="LineLength" />
@ -1597,7 +1596,6 @@
<suppress files="plugins[/\\]repository-s3[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]cloud[/\\]aws[/\\]blobstore[/\\]MockDefaultS3OutputStream.java" checks="LineLength" />
<suppress files="plugins[/\\]repository-s3[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]repositories[/\\]s3[/\\]AbstractS3SnapshotRestoreTest.java" checks="LineLength" />
<suppress files="plugins[/\\]store-smb[/\\]src[/\\]main[/\\]java[/\\]org[/\\]apache[/\\]lucene[/\\]store[/\\]SmbDirectoryWrapper.java" checks="LineLength" />
<suppress files="qa[/\\]evil-tests[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]BootstrapCliParserTests.java" checks="LineLength" />
<suppress files="qa[/\\]evil-tests[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]ESPolicyUnitTests.java" checks="LineLength" />
<suppress files="qa[/\\]evil-tests[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]EvilSecurityTests.java" checks="LineLength" />
<suppress files="qa[/\\]evil-tests[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]common[/\\]cli[/\\]CheckFileCommandTests.java" checks="LineLength" />

View File

@ -19,21 +19,14 @@
package org.elasticsearch.bootstrap;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import org.apache.lucene.util.Constants;
import org.apache.lucene.util.IOUtils;
import org.apache.lucene.util.StringHelper;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.Version;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.common.PidFile;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.inject.CreationException;
import org.elasticsearch.common.logging.ESLogger;
@ -47,7 +40,13 @@ import org.elasticsearch.monitor.process.ProcessProbe;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.internal.InternalSettingsPreparer;
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
/**
* Internal startup code.
@ -189,9 +188,13 @@ final class Bootstrap {
node = new Node(nodeSettings);
}
private static Environment initialSettings(boolean foreground) {
private static Environment initialSettings(boolean foreground, String pidFile) {
Terminal terminal = foreground ? Terminal.DEFAULT : null;
return InternalSettingsPreparer.prepareEnvironment(EMPTY_SETTINGS, terminal);
Settings.Builder builder = Settings.builder();
if (Strings.hasLength(pidFile)) {
builder.put(Environment.PIDFILE_SETTING.getKey(), pidFile);
}
return InternalSettingsPreparer.prepareEnvironment(builder.build(), terminal);
}
private void start() {
@ -218,22 +221,18 @@ final class Bootstrap {
* This method is invoked by {@link Elasticsearch#main(String[])}
* to startup elasticsearch.
*/
static void init(String[] args) throws Throwable {
static void init(
final boolean foreground,
final String pidFile,
final Map<String, String> esSettings) throws Throwable {
// Set the system property before anything has a chance to trigger its use
initLoggerPrefix();
BootstrapCliParser parser = new BootstrapCliParser();
int status = parser.main(args, Terminal.DEFAULT);
if (parser.shouldRun() == false || status != ExitCodes.OK) {
exit(status);
}
elasticsearchSettings(esSettings);
INSTANCE = new Bootstrap();
boolean foreground = !"false".equals(System.getProperty("es.foreground", System.getProperty("es-foreground")));
Environment environment = initialSettings(foreground);
Environment environment = initialSettings(foreground, pidFile);
Settings settings = environment.settings();
LogConfigurator.configure(settings, true);
checkForCustomConfFile();
@ -297,6 +296,13 @@ final class Bootstrap {
}
}
@SuppressForbidden(reason = "Sets system properties passed as CLI parameters")
private static void elasticsearchSettings(Map<String, String> esSettings) {
for (Map.Entry<String, String> esSetting : esSettings.entrySet()) {
System.setProperty(esSetting.getKey(), esSetting.getValue());
}
}
@SuppressForbidden(reason = "System#out")
private static void closeSystOut() {
System.out.close();

View File

@ -1,95 +0,0 @@
/*
* 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.bootstrap;
import java.util.Arrays;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.elasticsearch.Build;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.Strings;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.monitor.jvm.JvmInfo;
final class BootstrapCliParser extends Command {
private final OptionSpec<Void> versionOption;
private final OptionSpec<Void> daemonizeOption;
private final OptionSpec<String> pidfileOption;
private final OptionSpec<String> propertyOption;
private boolean shouldRun = false;
BootstrapCliParser() {
super("Starts elasticsearch");
// TODO: in jopt-simple 5.0, make this mutually exclusive with all other options
versionOption = parser.acceptsAll(Arrays.asList("V", "version"),
"Prints elasticsearch version information and exits");
daemonizeOption = parser.acceptsAll(Arrays.asList("d", "daemonize"),
"Starts Elasticsearch in the background");
// TODO: in jopt-simple 5.0 this option type can be a Path
pidfileOption = parser.acceptsAll(Arrays.asList("p", "pidfile"),
"Creates a pid file in the specified path on start")
.withRequiredArg();
propertyOption = parser.accepts("D", "Configures an Elasticsearch setting")
.withRequiredArg();
}
// TODO: don't use system properties as a way to do this, its horrible...
@SuppressForbidden(reason = "Sets system properties passed as CLI parameters")
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
if (options.has(versionOption)) {
terminal.println("Version: " + org.elasticsearch.Version.CURRENT
+ ", Build: " + Build.CURRENT.shortHash() + "/" + Build.CURRENT.date()
+ ", JVM: " + JvmInfo.jvmInfo().version());
return;
}
// TODO: don't use sysprops for any of these! pass the args through to bootstrap...
if (options.has(daemonizeOption)) {
System.setProperty("es.foreground", "false");
}
String pidFile = pidfileOption.value(options);
if (Strings.isNullOrEmpty(pidFile) == false) {
System.setProperty("es.pidfile", pidFile);
}
for (String property : propertyOption.values(options)) {
String[] keyValue = property.split("=", 2);
if (keyValue.length != 2) {
throw new UserError(ExitCodes.USAGE, "Malformed elasticsearch setting, must be of the form key=value");
}
String key = keyValue[0];
if (key.startsWith("es.") == false) {
key = "es." + key;
}
System.setProperty(key, keyValue[1]);
}
shouldRun = true;
}
boolean shouldRun() {
return shouldRun;
}
}

View File

@ -19,23 +19,94 @@
package org.elasticsearch.bootstrap;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import joptsimple.util.KeyValuePair;
import org.elasticsearch.Build;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.monitor.jvm.JvmInfo;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* This class starts elasticsearch.
*/
public final class Elasticsearch {
class Elasticsearch extends Command {
/** no instantiation */
private Elasticsearch() {}
private final OptionSpec<Void> versionOption;
private final OptionSpec<Void> daemonizeOption;
private final OptionSpec<String> pidfileOption;
private final OptionSpec<KeyValuePair> propertyOption;
// visible for testing
Elasticsearch() {
super("starts elasticsearch");
// TODO: in jopt-simple 5.0, make this mutually exclusive with all other options
versionOption = parser.acceptsAll(Arrays.asList("V", "version"),
"Prints elasticsearch version information and exits");
daemonizeOption = parser.acceptsAll(Arrays.asList("d", "daemonize"),
"Starts Elasticsearch in the background");
// TODO: in jopt-simple 5.0 this option type can be a Path
pidfileOption = parser.acceptsAll(Arrays.asList("p", "pidfile"),
"Creates a pid file in the specified path on start")
.withRequiredArg();
propertyOption = parser.accepts("E", "Configure an Elasticsearch setting").withRequiredArg().ofType(KeyValuePair.class);
}
/**
* Main entry point for starting elasticsearch
*/
public static void main(String[] args) throws Exception {
public static void main(final String[] args) throws Exception {
final Elasticsearch elasticsearch = new Elasticsearch();
int status = main(args, elasticsearch, Terminal.DEFAULT);
if (status != ExitCodes.OK) {
exit(status);
}
}
static int main(final String[] args, final Elasticsearch elasticsearch, final Terminal terminal) throws Exception {
return elasticsearch.main(args, terminal);
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
if (options.has(versionOption)) {
if (options.has(daemonizeOption) || options.has(pidfileOption)) {
throw new UserError(ExitCodes.USAGE, "Elasticsearch version option is mutually exclusive with any other option");
}
terminal.println("Version: " + org.elasticsearch.Version.CURRENT
+ ", Build: " + Build.CURRENT.shortHash() + "/" + Build.CURRENT.date()
+ ", JVM: " + JvmInfo.jvmInfo().version());
return;
}
final boolean daemonize = options.has(daemonizeOption);
final String pidFile = pidfileOption.value(options);
final Map<String, String> esSettings = new HashMap<>();
for (final KeyValuePair kvp : propertyOption.values(options)) {
if (!kvp.key.startsWith("es.")) {
throw new UserError(ExitCodes.USAGE, "Elasticsearch settings must be prefixed with [es.] but was [" + kvp.key + "]");
}
if (kvp.value.isEmpty()) {
throw new UserError(ExitCodes.USAGE, "Elasticsearch setting [" + kvp.key + "] must not be empty");
}
esSettings.put(kvp.key, kvp.value);
}
init(daemonize, pidFile, esSettings);
}
void init(final boolean daemonize, final String pidFile, final Map<String, String> esSettings) {
try {
Bootstrap.init(args);
} catch (Throwable t) {
Bootstrap.init(!daemonize, pidFile, esSettings);
} catch (final Throwable t) {
// format exceptions to the console in a special way
// to avoid 2MB stacktraces from guice, etc.
throw new StartupError(t);

View File

@ -110,9 +110,7 @@ public class LogConfigurator {
if (resolveConfig) {
resolveConfig(environment, settingsBuilder);
}
settingsBuilder
.putProperties("elasticsearch.", BootstrapInfo.getSystemProperties())
.putProperties("es.", BootstrapInfo.getSystemProperties());
settingsBuilder.putProperties("es.", BootstrapInfo.getSystemProperties());
// add custom settings after config was added so that they are not overwritten by config
settingsBuilder.put(settings);
settingsBuilder.replacePropertyPlaceholders();

View File

@ -1136,10 +1136,10 @@ public final class Settings implements ToXContent {
* @param properties The properties to put
* @return The builder
*/
public Builder putProperties(String prefix, Dictionary<Object,Object> properties) {
for (Object key1 : Collections.list(properties.keys())) {
String key = Objects.toString(key1);
String value = Objects.toString(properties.get(key));
public Builder putProperties(String prefix, Dictionary<Object, Object> properties) {
for (Object property : Collections.list(properties.keys())) {
String key = Objects.toString(property);
String value = Objects.toString(properties.get(property));
if (key.startsWith(prefix)) {
map.put(key.substring(prefix.length()), value);
}
@ -1154,19 +1154,12 @@ public final class Settings implements ToXContent {
* @param properties The properties to put
* @return The builder
*/
public Builder putProperties(String prefix, Dictionary<Object,Object> properties, String[] ignorePrefixes) {
for (Object key1 : Collections.list(properties.keys())) {
String key = Objects.toString(key1);
String value = Objects.toString(properties.get(key));
public Builder putProperties(String prefix, Dictionary<Object, Object> properties, String ignorePrefix) {
for (Object property : Collections.list(properties.keys())) {
String key = Objects.toString(property);
String value = Objects.toString(properties.get(property));
if (key.startsWith(prefix)) {
boolean ignore = false;
for (String ignorePrefix : ignorePrefixes) {
if (key.startsWith(ignorePrefix)) {
ignore = true;
break;
}
}
if (!ignore) {
if (!key.startsWith(ignorePrefix)) {
map.put(key.substring(prefix.length()), value);
}
}

View File

@ -53,8 +53,8 @@ import static org.elasticsearch.common.settings.Settings.settingsBuilder;
public class InternalSettingsPreparer {
private static final String[] ALLOWED_SUFFIXES = {".yml", ".yaml", ".json", ".properties"};
static final String[] PROPERTY_PREFIXES = {"es.", "elasticsearch."};
static final String[] PROPERTY_DEFAULTS_PREFIXES = {"es.default.", "elasticsearch.default."};
static final String PROPERTY_PREFIX = "es.";
static final String PROPERTY_DEFAULTS_PREFIX = "es.default.";
public static final String SECRET_PROMPT_VALUE = "${prompt.secret}";
public static final String TEXT_PROMPT_VALUE = "${prompt.text}";
@ -126,13 +126,9 @@ public class InternalSettingsPreparer {
output.put(input);
if (useSystemProperties(input)) {
if (loadDefaults) {
for (String prefix : PROPERTY_DEFAULTS_PREFIXES) {
output.putProperties(prefix, BootstrapInfo.getSystemProperties());
}
}
for (String prefix : PROPERTY_PREFIXES) {
output.putProperties(prefix, BootstrapInfo.getSystemProperties(), PROPERTY_DEFAULTS_PREFIXES);
output.putProperties(PROPERTY_DEFAULTS_PREFIX, BootstrapInfo.getSystemProperties());
}
output.putProperties(PROPERTY_PREFIX, BootstrapInfo.getSystemProperties(), PROPERTY_DEFAULTS_PREFIX);
}
output.replacePropertyPlaceholders();
}

View File

@ -72,9 +72,6 @@ grant {
// set by ESTestCase to improve test reproducibility
// TODO: set this with gradle or some other way that repros with seed?
permission java.util.PropertyPermission "es.processors.override", "write";
// set by CLIToolTestCase
// TODO: do this differently? or test commandline tools differently?
permission java.util.PropertyPermission "es.default.path.home", "write";
// TODO: these simply trigger a noisy warning if its unable to clear the properties
// fix that in randomizedtesting

View File

@ -0,0 +1,191 @@
/*
* 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.bootstrap;
import org.elasticsearch.Build;
import org.elasticsearch.Version;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.MockTerminal;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.monitor.jvm.JvmInfo;
import org.elasticsearch.test.ESTestCase;
import org.junit.After;
import org.junit.Before;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
public class ElasticsearchCliTests extends ESTestCase {
public void testVersion() throws Exception {
runTestThatVersionIsMutuallyExclusiveToOtherOptions("-V", "-d");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("-V", "--daemonize");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("-V", "-p", "/tmp/pid");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("-V", "--pidfile", "/tmp/pid");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "-d");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "--daemonize");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "-p", "/tmp/pid");
runTestThatVersionIsMutuallyExclusiveToOtherOptions("--version", "--pidfile", "/tmp/pid");
runTestThatVersionIsReturned("-V");
runTestThatVersionIsReturned("--version");
}
private void runTestThatVersionIsMutuallyExclusiveToOtherOptions(String... args) throws Exception {
runTestVersion(
ExitCodes.USAGE,
output -> assertThat(
output,
containsString("ERROR: Elasticsearch version option is mutually exclusive with any other option")),
args);
}
private void runTestThatVersionIsReturned(String... args) throws Exception {
runTestVersion(ExitCodes.OK, output -> {
assertThat(output, containsString("Version: " + Version.CURRENT.toString()));
assertThat(output, containsString("Build: " + Build.CURRENT.shortHash() + "/" + Build.CURRENT.date()));
assertThat(output, containsString("JVM: " + JvmInfo.jvmInfo().version()));
}, args);
}
private void runTestVersion(int expectedStatus, Consumer<String> outputConsumer, String... args) throws Exception {
runTest(expectedStatus, false, outputConsumer, (foreground, pidFile, esSettings) -> {}, args);
}
public void testThatPidFileCanBeConfigured() throws Exception {
runPidFileTest(ExitCodes.USAGE, false, output -> assertThat(output, containsString("Option p/pidfile requires an argument")), "-p");
runPidFileTest(ExitCodes.OK, true, output -> {}, "-p", "/tmp/pid");
runPidFileTest(ExitCodes.OK, true, output -> {}, "--pidfile", "/tmp/pid");
}
private void runPidFileTest(final int expectedStatus, final boolean expectedInit, Consumer<String> outputConsumer, final String... args)
throws Exception {
runTest(
expectedStatus,
expectedInit,
outputConsumer,
(foreground, pidFile, esSettings) -> assertThat(pidFile, equalTo("/tmp/pid")),
args);
}
public void testThatParsingDaemonizeWorks() throws Exception {
runDaemonizeTest(true, "-d");
runDaemonizeTest(true, "--daemonize");
runDaemonizeTest(false);
}
private void runDaemonizeTest(final boolean expectedDaemonize, final String... args) throws Exception {
runTest(
ExitCodes.OK,
true,
output -> {},
(foreground, pidFile, esSettings) -> assertThat(foreground, equalTo(!expectedDaemonize)),
args);
}
public void testElasticsearchSettings() throws Exception {
runTest(
ExitCodes.OK,
true,
output -> {},
(foreground, pidFile, esSettings) -> {
assertThat(esSettings.size(), equalTo(2));
assertThat(esSettings, hasEntry("es.foo", "bar"));
assertThat(esSettings, hasEntry("es.baz", "qux"));
},
"-Ees.foo=bar", "-E", "es.baz=qux"
);
}
public void testElasticsearchSettingPrefix() throws Exception {
runElasticsearchSettingPrefixTest("-E", "foo");
runElasticsearchSettingPrefixTest("-E", "foo=bar");
runElasticsearchSettingPrefixTest("-E", "=bar");
}
private void runElasticsearchSettingPrefixTest(String... args) throws Exception {
runTest(
ExitCodes.USAGE,
false,
output -> assertThat(output, containsString("Elasticsearch settings must be prefixed with [es.] but was [")),
(foreground, pidFile, esSettings) -> {},
args
);
}
public void testElasticsearchSettingCanNotBeEmpty() throws Exception {
runTest(
ExitCodes.USAGE,
false,
output -> assertThat(output, containsString("Elasticsearch setting [es.foo] must not be empty")),
(foreground, pidFile, esSettings) -> {},
"-E", "es.foo="
);
}
public void testUnknownOption() throws Exception {
runTest(
ExitCodes.USAGE,
false,
output -> assertThat(output, containsString("network.host is not a recognized option")),
(foreground, pidFile, esSettings) -> {},
"--network.host");
}
private interface InitConsumer {
void accept(final boolean foreground, final String pidFile, final Map<String, String> esSettings);
}
private void runTest(
final int expectedStatus,
final boolean expectedInit,
final Consumer<String> outputConsumer,
final InitConsumer initConsumer,
String... args) throws Exception {
final MockTerminal terminal = new MockTerminal();
try {
final AtomicBoolean init = new AtomicBoolean();
final int status = Elasticsearch.main(args, new Elasticsearch() {
@Override
void init(final boolean daemonize, final String pidFile, final Map<String, String> esSettings) {
init.set(true);
initConsumer.accept(!daemonize, pidFile, esSettings);
}
}, terminal);
assertThat(status, equalTo(expectedStatus));
assertThat(init.get(), equalTo(expectedInit));
outputConsumer.accept(terminal.getOutput());
} catch (Throwable t) {
// if an unexpected exception is thrown, we log
// terminal output to aid debugging
logger.info(terminal.getOutput());
// rethrow so the test fails
throw t;
}
}
}

View File

@ -1,4 +1,4 @@
# you can override this using by setting a system property, for example -Des.logger.level=DEBUG
# you can override this using by setting a system property, for example -Ees.logger.level=DEBUG
es.logger.level: INFO
rootLogger: ${es.logger.level}, console
logger:

View File

@ -99,7 +99,7 @@ fi
# Define other required variables
PID_FILE="$PID_DIR/$NAME.pid"
DAEMON=$ES_HOME/bin/elasticsearch
DAEMON_OPTS="-d -p $PID_FILE -D es.default.path.home=$ES_HOME -D es.default.path.logs=$LOG_DIR -D es.default.path.data=$DATA_DIR -D es.default.path.conf=$CONF_DIR"
DAEMON_OPTS="-d -p $PID_FILE -Ees.default.path.logs=$LOG_DIR -Ees.default.path.data=$DATA_DIR -Ees.default.path.conf=$CONF_DIR"
export ES_HEAP_SIZE
export ES_HEAP_NEWSIZE

View File

@ -117,7 +117,7 @@ start() {
cd $ES_HOME
echo -n $"Starting $prog: "
# if not running, start it up here, usually something like "daemon $exec"
daemon --user $ES_USER --pidfile $pidfile $exec -p $pidfile -d -D es.default.path.home=$ES_HOME -D es.default.path.logs=$LOG_DIR -D es.default.path.data=$DATA_DIR -D es.default.path.conf=$CONF_DIR
daemon --user $ES_USER --pidfile $pidfile $exec -p $pidfile -d -Ees.default.path.home=$ES_HOME -Ees.default.path.logs=$LOG_DIR -Ees.default.path.data=$DATA_DIR -Ees.default.path.conf=$CONF_DIR
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile

View File

@ -20,11 +20,10 @@ Group=elasticsearch
ExecStartPre=/usr/share/elasticsearch/bin/elasticsearch-systemd-pre-exec
ExecStart=/usr/share/elasticsearch/bin/elasticsearch \
-Des.pidfile=${PID_DIR}/elasticsearch.pid \
-Des.default.path.home=${ES_HOME} \
-Des.default.path.logs=${LOG_DIR} \
-Des.default.path.data=${DATA_DIR} \
-Des.default.path.conf=${CONF_DIR}
-p ${PID_DIR}/elasticsearch.pid \
-Ees.default.path.logs=${LOG_DIR} \
-Ees.default.path.data=${DATA_DIR} \
-Ees.default.path.conf=${CONF_DIR}
StandardOutput=journal
StandardError=inherit

View File

@ -127,10 +127,10 @@ export HOSTNAME
daemonized=`echo $* | egrep -- '(^-d |-d$| -d |--daemonize$|--daemonize )'`
if [ -z "$daemonized" ] ; then
exec "$JAVA" $JAVA_OPTS $ES_JAVA_OPTS -Des.path.home="$ES_HOME" -cp "$ES_CLASSPATH" \
org.elasticsearch.bootstrap.Elasticsearch start "$@"
org.elasticsearch.bootstrap.Elasticsearch "$@"
else
exec "$JAVA" $JAVA_OPTS $ES_JAVA_OPTS -Des.path.home="$ES_HOME" -cp "$ES_CLASSPATH" \
org.elasticsearch.bootstrap.Elasticsearch start "$@" <&- &
org.elasticsearch.bootstrap.Elasticsearch "$@" <&- &
retval=$?
pid=$!
[ $retval -eq 0 ] || exit $retval

View File

@ -48,7 +48,7 @@ GOTO loop
SET HOSTNAME=%COMPUTERNAME%
"%JAVA_HOME%\bin\java" -client -Des.path.home="%ES_HOME%" !properties! -cp "%ES_HOME%/lib/*;" "org.elasticsearch.plugins.PluginCli" !args!
"%JAVA_HOME%\bin\java" -client -Ees.path.home="%ES_HOME%" !properties! -cp "%ES_HOME%/lib/*;" "org.elasticsearch.plugins.PluginCli" !args!
goto finally

View File

@ -104,4 +104,4 @@ ECHO additional elements via the plugin mechanism, or if code must really be 1>&
ECHO added to the main classpath, add jars to lib\, unsupported 1>&2
EXIT /B 1
)
set ES_PARAMS=-Delasticsearch -Des-foreground=yes -Des.path.home="%ES_HOME%"
set ES_PARAMS=-Delasticsearch -Ees.path.home="%ES_HOME%"

View File

@ -152,7 +152,7 @@ if "%DATA_DIR%" == "" set DATA_DIR=%ES_HOME%\data
if "%CONF_DIR%" == "" set CONF_DIR=%ES_HOME%\config
set ES_PARAMS=-Delasticsearch;-Des.path.home="%ES_HOME%";-Des.default.path.home="%ES_HOME%";-Des.default.path.logs="%LOG_DIR%";-Des.default.path.data="%DATA_DIR%";-Des.default.path.conf="%CONF_DIR%"
set ES_PARAMS=-Delasticsearch;-Des.path.home="%ES_HOME%";-Des.default.path.logs="%LOG_DIR%";-Des.default.path.data="%DATA_DIR%";-Des.default.path.conf="%CONF_DIR%"
set JVM_OPTS=%JAVA_OPTS: =;%

View File

@ -1,4 +1,4 @@
# you can override this using by setting a system property, for example -Des.logger.level=DEBUG
# you can override this using by setting a system property, for example -Ees.logger.level=DEBUG
es.logger.level: INFO
rootLogger: ${es.logger.level}, console, file
logger:

View File

@ -167,7 +167,7 @@ can do this as follows:
[source,sh]
---------------------
sudo bin/elasticsearch-plugin -Des.path.conf=/path/to/custom/config/dir install <plugin name>
sudo bin/elasticsearch-plugin -Ees.path.conf=/path/to/custom/config/dir install <plugin name>
---------------------
You can also set the `CONF_DIR` environment variable to the custom config

View File

@ -163,7 +163,7 @@ As mentioned previously, we can override either the cluster or node name. This c
[source,sh]
--------------------------------------------------
./elasticsearch --cluster.name my_cluster_name --node.name my_node_name
./elasticsearch -Ees.cluster.name=my_cluster_name -Ees.node.name=my_node_name
--------------------------------------------------
Also note the line marked http with information about the HTTP address (`192.168.8.112`) and port (`9200`) that our node is reachable from. By default, Elasticsearch uses port `9200` to provide access to its REST API. This port is configurable if necessary.

View File

@ -14,7 +14,7 @@ attribute as follows:
[source,sh]
------------------------
bin/elasticsearch --node.rack rack1 --node.size big <1>
bin/elasticsearch -Ees.node.rack=rack1 -Ees.node.size=big <1>
------------------------
<1> These attribute settings can also be specified in the `elasticsearch.yml` config file.

View File

@ -172,3 +172,18 @@ Two cache concurrency level settings
`indices.fielddata.cache.concurrency_level` because they no longer apply to
the cache implementation used for the request cache and the field data cache.
==== Using system properties to configure Elasticsearch
Elasticsearch can be configured by setting system properties on the
command line via `-Des.name.of.property=value.of.property`. This will be
removed in a future version of Elasticsearch. Instead, use
`-E es.name.of.setting=value.of.setting`. Note that in all cases the
name of the setting must be prefixed with `es.`.
==== Removed using double-dashes to configure Elasticsearch
Elasticsearch could previously be configured on the command line by
setting settings via `--name.of.setting value.of.setting`. This feature
has been removed. Instead, use
`-Ees.name.of.setting=value.of.setting`. Note that in all cases the
name of the setting must be prefixed with `es.`.

View File

@ -21,7 +21,7 @@ attribute called `rack_id` -- we could use any attribute name. For example:
[source,sh]
----------------------
./bin/elasticsearch --node.rack_id rack_one <1>
./bin/elasticsearch -Ees.node.rack_id=rack_one <1>
----------------------
<1> This setting could also be specified in the `elasticsearch.yml` config file.

View File

@ -242,7 +242,7 @@ Like all node settings, it can also be specified on the command line as:
[source,sh]
-----------------------
./bin/elasticsearch --path.data /var/elasticsearch/data
./bin/elasticsearch -Ees.path.data=/var/elasticsearch/data
-----------------------
TIP: When using the `.zip` or `.tar.gz` distributions, the `path.data` setting

View File

@ -67,13 +67,12 @@ There are added features when using the `elasticsearch` shell script.
The first, which was explained earlier, is the ability to easily run the
process either in the foreground or the background.
Another feature is the ability to pass `-D` or getopt long style
configuration parameters directly to the script. When set, all override
anything set using either `JAVA_OPTS` or `ES_JAVA_OPTS`. For example:
Another feature is the ability to pass `-E` configuration parameters
directly to the script. For example:
[source,sh]
--------------------------------------------------
$ bin/elasticsearch -Des.index.refresh_interval=5s --node.name=my-node
$ bin/elasticsearch -Ees.index.refresh_interval=5s -Ees.node.name=my-node
--------------------------------------------------
*************************************************************************

View File

@ -259,7 +259,7 @@ command, for example:
[source,sh]
--------------------------------------------------
$ elasticsearch -Des.network.host=10.0.0.4
$ elasticsearch -Ees.network.host=10.0.0.4
--------------------------------------------------
Another option is to set `es.default.` prefix instead of `es.` prefix,
@ -336,7 +336,7 @@ course, the above can also be set as a "collapsed" setting, for example:
[source,sh]
--------------------------------------------------
$ elasticsearch -Des.index.refresh_interval=5s
$ elasticsearch -Ees.index.refresh_interval=5s
--------------------------------------------------
All of the index level configuration can be found within each

View File

@ -80,7 +80,7 @@ To upgrade using a zip or compressed tarball:
overwrite the `config` or `data` directories.
* Either copy the files in the `config` directory from your old installation
to your new installation, or use the `--path.conf` option on the command
to your new installation, or use the `-E path.conf=` option on the command
line to point to an external config directory.
* Either copy the files in the `data` directory from your old installation

View File

@ -28,8 +28,8 @@ dependencies {
integTest {
cluster {
systemProperty 'es.script.inline', 'true'
systemProperty 'es.script.indexed', 'true'
setting 'script.inline', 'true'
setting 'script.indexed', 'true'
}
}

View File

@ -28,7 +28,7 @@ dependencies {
integTest {
cluster {
systemProperty 'es.script.inline', 'true'
systemProperty 'es.script.indexed', 'true'
setting 'script.inline', 'true'
setting 'script.indexed', 'true'
}
}

View File

@ -28,7 +28,7 @@ dependencies {
integTest {
cluster {
systemProperty 'es.script.inline', 'true'
systemProperty 'es.script.indexed', 'true'
setting 'script.inline', 'true'
setting 'script.indexed', 'true'
}
}

View File

@ -28,8 +28,8 @@ dependencies {
integTest {
cluster {
systemProperty 'es.script.inline', 'true'
systemProperty 'es.script.indexed', 'true'
setting 'script.inline', 'true'
setting 'script.indexed', 'true'
}
}

View File

@ -1,164 +0,0 @@
/*
* 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.bootstrap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import joptsimple.OptionException;
import org.elasticsearch.Build;
import org.elasticsearch.Version;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.CommandTestCase;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.monitor.jvm.JvmInfo;
import org.junit.After;
import org.junit.Before;
import static org.hamcrest.Matchers.is;
@SuppressForbidden(reason = "modifies system properties intentionally")
public class BootstrapCliParserTests extends CommandTestCase {
@Override
protected Command newCommand() {
return new BootstrapCliParser();
}
private List<String> propertiesToClear = new ArrayList<>();
private Map<Object, Object> properties;
@Before
public void before() {
this.properties = new HashMap<>(System.getProperties());
}
@After
public void clearProperties() {
for (String property : propertiesToClear) {
System.clearProperty(property);
}
propertiesToClear.clear();
assertEquals("properties leaked", properties, new HashMap<>(System.getProperties()));
}
void assertShouldRun(boolean shouldRun) {
BootstrapCliParser parser = (BootstrapCliParser)command;
assertEquals(shouldRun, parser.shouldRun());
}
public void testVersion() throws Exception {
String output = execute("-V");
assertTrue(output, output.contains(Version.CURRENT.toString()));
assertTrue(output, output.contains(Build.CURRENT.shortHash()));
assertTrue(output, output.contains(Build.CURRENT.date()));
assertTrue(output, output.contains(JvmInfo.jvmInfo().version()));
assertShouldRun(false);
terminal.reset();
output = execute("--version");
assertTrue(output, output.contains(Version.CURRENT.toString()));
assertTrue(output, output.contains(Build.CURRENT.shortHash()));
assertTrue(output, output.contains(Build.CURRENT.date()));
assertTrue(output, output.contains(JvmInfo.jvmInfo().version()));
assertShouldRun(false);
}
public void testPidfile() throws Exception {
registerProperties("es.pidfile");
// missing argument
OptionException e = expectThrows(OptionException.class, () -> {
execute("-p");
});
assertEquals("Option p/pidfile requires an argument", e.getMessage());
assertShouldRun(false);
// good cases
terminal.reset();
execute("--pidfile", "/tmp/pid");
assertSystemProperty("es.pidfile", "/tmp/pid");
assertShouldRun(true);
System.clearProperty("es.pidfile");
terminal.reset();
execute("-p", "/tmp/pid");
assertSystemProperty("es.pidfile", "/tmp/pid");
assertShouldRun(true);
}
public void testNoDaemonize() throws Exception {
registerProperties("es.foreground");
execute();
assertSystemProperty("es.foreground", null);
assertShouldRun(true);
}
public void testDaemonize() throws Exception {
registerProperties("es.foreground");
execute("-d");
assertSystemProperty("es.foreground", "false");
assertShouldRun(true);
System.clearProperty("es.foreground");
execute("--daemonize");
assertSystemProperty("es.foreground", "false");
assertShouldRun(true);
}
public void testConfig() throws Exception {
registerProperties("es.foo", "es.spam");
execute("-Dfoo=bar", "-Dspam=eggs");
assertSystemProperty("es.foo", "bar");
assertSystemProperty("es.spam", "eggs");
assertShouldRun(true);
}
public void testConfigMalformed() throws Exception {
UserError e = expectThrows(UserError.class, () -> {
execute("-Dfoo");
});
assertTrue(e.getMessage(), e.getMessage().contains("Malformed elasticsearch setting"));
}
public void testUnknownOption() throws Exception {
OptionException e = expectThrows(OptionException.class, () -> {
execute("--network.host");
});
assertTrue(e.getMessage(), e.getMessage().contains("network.host is not a recognized option"));
}
private void registerProperties(String ... systemProperties) {
propertiesToClear.addAll(Arrays.asList(systemProperties));
}
private void assertSystemProperty(String name, String expectedValue) throws Exception {
String msg = String.format(Locale.ROOT, "Expected property %s to be %s, terminal output was %s", name, expectedValue, terminal.getOutput());
assertThat(msg, System.getProperty(name), is(expectedValue));
}
}

View File

@ -21,6 +21,6 @@ apply plugin: 'elasticsearch.rest-test'
integTest {
cluster {
systemProperty 'es.node.ingest', 'false'
setting 'node.ingest', 'false'
}
}

View File

@ -21,6 +21,6 @@ apply plugin: 'elasticsearch.rest-test'
integTest {
cluster {
systemProperty 'es.script.inline', 'true'
setting 'script.inline', 'true'
}
}

View File

@ -303,7 +303,7 @@ run_elasticsearch_service() {
# This line is attempting to emulate the on login behavior of /usr/share/upstart/sessions/jayatana.conf
[ -f /usr/share/java/jayatanaag.jar ] && export JAVA_TOOL_OPTIONS="-javaagent:/usr/share/java/jayatanaag.jar"
# And now we can start Elasticsearch normally, in the background (-d) and with a pidfile (-p).
$timeoutCommand/tmp/elasticsearch/bin/elasticsearch $background -p /tmp/elasticsearch/elasticsearch.pid -Des.path.conf=$CONF_DIR $commandLineArgs
$timeoutCommand/tmp/elasticsearch/bin/elasticsearch $background -p /tmp/elasticsearch/elasticsearch.pid -Ees.path.conf=$CONF_DIR $commandLineArgs
BASH
[ "$status" -eq "$expectedStatus" ]
elif is_systemd; then

View File

@ -102,7 +102,7 @@ fi
echo "CONF_FILE=$CONF_FILE" >> /etc/sysconfig/elasticsearch;
fi
run_elasticsearch_service 1 -Des.default.config="$CONF_FILE"
run_elasticsearch_service 1 -Ees.default.config="$CONF_FILE"
# remove settings again otherwise cleaning up before next testrun will fail
if is_dpkg ; then
@ -408,7 +408,7 @@ fi
remove_jvm_example
local relativePath=${1:-$(readlink -m jvm-example-*.zip)}
sudo -E -u $ESPLUGIN_COMMAND_USER "$ESHOME/bin/elasticsearch-plugin" install "file://$relativePath" -Des.logger.level=DEBUG > /tmp/plugin-cli-output
sudo -E -u $ESPLUGIN_COMMAND_USER "$ESHOME/bin/elasticsearch-plugin" install "file://$relativePath" -Ees.logger.level=DEBUG > /tmp/plugin-cli-output
local loglines=$(cat /tmp/plugin-cli-output | wc -l)
if [ "$GROUP" == "TAR PLUGINS" ]; then
[ "$loglines" -gt "7" ] || {

View File

@ -1,65 +0,0 @@
/*
* 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.common.cli;
import java.io.IOException;
import org.elasticsearch.cli.MockTerminal;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.StreamsUtils;
import org.junit.After;
import org.junit.Before;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.isEmptyString;
import static org.hamcrest.Matchers.not;
public abstract class CliToolTestCase extends ESTestCase {
@Before
@SuppressForbidden(reason = "sets es.default.path.home during tests")
public void setPathHome() {
System.setProperty("es.default.path.home", createTempDir().toString());
}
@After
@SuppressForbidden(reason = "clears es.default.path.home during tests")
public void clearPathHome() {
System.clearProperty("es.default.path.home");
}
public static String[] args(String command) {
if (!Strings.hasLength(command)) {
return Strings.EMPTY_ARRAY;
}
return command.split("\\s+");
}
public static void assertTerminalOutputContainsHelpFile(MockTerminal terminal, String classPath) throws IOException {
String output = terminal.getOutput();
assertThat(output, not(isEmptyString()));
String expectedDocs = StreamsUtils.copyToStringFromClasspath(classPath);
// convert to *nix newlines as MockTerminal used for tests also uses *nix newlines
expectedDocs = expectedDocs.replace("\r\n", "\n");
assertThat(output, containsString(expectedDocs));
}
}