浏览代码

Remove path.conf setting

This commit removes path.conf as a valid setting and replaces it with a
command-line flag for specifying a non-default path for configuration.

Relates #25392
Jason Tedor 8 年之前
父节点
当前提交
5a9fc8aa2a
共有 54 个文件被更改,包括 290 次插入199 次删除
  1. 6 2
      buildSrc/src/main/groovy/org/elasticsearch/gradle/test/NodeInfo.groovy
  2. 8 5
      core/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java
  3. 1 1
      core/src/main/java/org/elasticsearch/bootstrap/Security.java
  4. 16 4
      core/src/main/java/org/elasticsearch/cli/EnvironmentAwareCommand.java
  5. 1 1
      core/src/main/java/org/elasticsearch/client/transport/TransportClient.java
  6. 0 2
      core/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java
  7. 6 7
      core/src/main/java/org/elasticsearch/env/Environment.java
  8. 10 8
      core/src/main/java/org/elasticsearch/node/InternalSettingsPreparer.java
  9. 12 7
      core/src/main/java/org/elasticsearch/node/Node.java
  10. 17 10
      core/src/main/java/org/elasticsearch/plugins/PluginsService.java
  11. 5 6
      core/src/main/java/org/elasticsearch/tribe/TribeService.java
  12. 0 2
      core/src/test/java/org/elasticsearch/action/update/UpdateRequestTests.java
  13. 1 1
      core/src/test/java/org/elasticsearch/common/settings/AddFileKeyStoreCommandTests.java
  14. 2 1
      core/src/test/java/org/elasticsearch/common/settings/AddStringKeyStoreCommandTests.java
  15. 1 1
      core/src/test/java/org/elasticsearch/common/settings/CreateKeyStoreCommandTests.java
  16. 2 1
      core/src/test/java/org/elasticsearch/common/settings/ListKeyStoreCommandTests.java
  17. 5 7
      core/src/test/java/org/elasticsearch/common/settings/RemoveSettingKeyStoreCommandTests.java
  18. 6 1
      core/src/test/java/org/elasticsearch/discovery/single/SingleNodeDiscoveryIT.java
  19. 11 19
      core/src/test/java/org/elasticsearch/env/EnvironmentTests.java
  20. 3 4
      core/src/test/java/org/elasticsearch/index/analysis/HunspellTokenFilterFactoryTests.java
  21. 16 9
      core/src/test/java/org/elasticsearch/indices/analyze/HunspellServiceTests.java
  22. 1 1
      core/src/test/java/org/elasticsearch/node/InternalSettingsPreparerTests.java
  23. 1 1
      core/src/test/java/org/elasticsearch/plugins/PluginsServiceTests.java
  24. 0 2
      core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java
  25. 12 10
      core/src/test/java/org/elasticsearch/search/aggregations/metrics/ScriptedMetricIT.java
  26. 0 2
      core/src/test/java/org/elasticsearch/search/sort/AbstractSortTestCase.java
  27. 0 2
      core/src/test/java/org/elasticsearch/tribe/TribeServiceTests.java
  28. 1 1
      distribution/deb/src/main/packaging/init.d/elasticsearch
  29. 1 1
      distribution/rpm/src/main/packaging/init.d/elasticsearch
  30. 1 1
      distribution/src/main/packaging/systemd/elasticsearch.service
  31. 1 1
      distribution/src/main/resources/bin/elasticsearch-plugin
  32. 2 2
      distribution/src/main/resources/bin/elasticsearch-service.bat
  33. 1 1
      distribution/src/main/resources/bin/elasticsearch-translog
  34. 10 0
      docs/reference/migration/migrate_6_0/packaging.asciidoc
  35. 10 0
      docs/reference/migration/migrate_6_0/plugins.asciidoc
  36. 0 1
      docs/reference/modules/tribe.asciidoc
  37. 2 2
      docs/reference/setup/configuration.asciidoc
  38. 5 1
      plugins/discovery-azure-classic/src/test/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java
  39. 3 3
      plugins/jvm-example/src/main/java/org/elasticsearch/plugin/example/JvmExamplePlugin.java
  40. 1 2
      qa/evil-tests/src/test/java/org/elasticsearch/bootstrap/EvilSecurityTests.java
  41. 6 12
      qa/evil-tests/src/test/java/org/elasticsearch/common/logging/EvilLoggerConfigurationTests.java
  42. 2 4
      qa/evil-tests/src/test/java/org/elasticsearch/common/logging/EvilLoggerTests.java
  43. 8 11
      qa/evil-tests/src/test/java/org/elasticsearch/tribe/TribeUnitTests.java
  44. 1 1
      qa/vagrant/src/test/resources/packaging/utils/utils.bash
  45. 3 5
      test/framework/src/main/java/org/elasticsearch/bootstrap/ESElasticsearchCliTestCase.java
  46. 21 13
      test/framework/src/main/java/org/elasticsearch/index/analysis/AnalysisTestsHelper.java
  47. 10 3
      test/framework/src/main/java/org/elasticsearch/node/MockNode.java
  48. 1 1
      test/framework/src/main/java/org/elasticsearch/search/aggregations/BaseAggregationTestCase.java
  49. 2 1
      test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java
  50. 9 4
      test/framework/src/main/java/org/elasticsearch/test/ESIntegTestCase.java
  51. 1 1
      test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java
  52. 8 0
      test/framework/src/main/java/org/elasticsearch/test/NodeConfigurationSource.java
  53. 6 0
      test/framework/src/main/java/org/elasticsearch/test/discovery/ClusterDiscoveryConfiguration.java
  54. 31 10
      test/framework/src/test/java/org/elasticsearch/test/test/InternalTestClusterTests.java

+ 6 - 2
buildSrc/src/main/groovy/org/elasticsearch/gradle/test/NodeInfo.groovy

@@ -143,7 +143,7 @@ class NodeInfo {
             args.add("${esScript}")
         }
 
-        env = [ 'JAVA_HOME' : project.javaHome ]
+        env = ['JAVA_HOME': project.javaHome]
         args.addAll("-E", "node.portsfile=true")
         String collectedSystemProperties = config.systemProperties.collect { key, value -> "-D${key}=${value}" }.join(" ")
         String esJavaOpts = config.jvmArgs.isEmpty() ? collectedSystemProperties : collectedSystemProperties + " " + config.jvmArgs
@@ -158,7 +158,11 @@ class NodeInfo {
             }
         }
         env.put('ES_JVM_OPTIONS', new File(confDir, 'jvm.options'))
-        args.addAll("-E", "path.conf=${confDir}")
+        if (nodeVersion.startsWith("5.")) {
+            args.addAll("-E", "path.conf=${confDir}")
+        } else {
+            args.addAll("--path.conf", "${confDir}")
+        }
         if (!System.properties.containsKey("tests.es.path.data")) {
             args.addAll("-E", "path.data=${-> dataDir.toString()}")
         }

+ 8 - 5
core/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java

@@ -238,9 +238,12 @@ final class Bootstrap {
         return keystore;
     }
 
-
-    private static Environment createEnvironment(boolean foreground, Path pidFile,
-                                                 SecureSettings secureSettings, Settings initialSettings) {
+    private static Environment createEnvironment(
+            final boolean foreground,
+            final Path pidFile,
+            final SecureSettings secureSettings,
+            final Settings initialSettings,
+            final Path configPath) {
         Terminal terminal = foreground ? Terminal.DEFAULT : null;
         Settings.Builder builder = Settings.builder();
         if (pidFile != null) {
@@ -250,7 +253,7 @@ final class Bootstrap {
         if (secureSettings != null) {
             builder.setSecureSettings(secureSettings);
         }
-        return InternalSettingsPreparer.prepareEnvironment(builder.build(), terminal, Collections.emptyMap());
+        return InternalSettingsPreparer.prepareEnvironment(builder.build(), terminal, Collections.emptyMap(), configPath);
     }
 
     private void start() throws NodeValidationException {
@@ -281,7 +284,7 @@ final class Bootstrap {
         INSTANCE = new Bootstrap();
 
         final SecureSettings keystore = loadSecureSettings(initialEnv);
-        Environment environment = createEnvironment(foreground, pidFile, keystore, initialEnv.settings());
+        final Environment environment = createEnvironment(foreground, pidFile, keystore, initialEnv.settings(), initialEnv.configFile());
         try {
             LogConfigurator.configure(environment);
         } catch (IOException e) {

+ 1 - 1
core/src/main/java/org/elasticsearch/bootstrap/Security.java

@@ -256,7 +256,7 @@ final class Security {
         addPath(policy, Environment.PATH_HOME_SETTING.getKey(), environment.libFile(), "read,readlink");
         addPath(policy, Environment.PATH_HOME_SETTING.getKey(), environment.modulesFile(), "read,readlink");
         addPath(policy, Environment.PATH_HOME_SETTING.getKey(), environment.pluginsFile(), "read,readlink");
-        addPath(policy, Environment.PATH_CONF_SETTING.getKey(), environment.configFile(), "read,readlink");
+        addPath(policy, "path.conf'", environment.configFile(), "read,readlink");
         // read-write dirs
         addPath(policy, "java.io.tmpdir", environment.tmpFile(), "read,readlink,write,delete");
         addPath(policy, Environment.PATH_LOGS_SETTING.getKey(), environment.logsFile(), "read,readlink,write,delete");

+ 16 - 4
core/src/main/java/org/elasticsearch/cli/EnvironmentAwareCommand.java

@@ -22,10 +22,14 @@ package org.elasticsearch.cli;
 import joptsimple.OptionSet;
 import joptsimple.OptionSpec;
 import joptsimple.util.KeyValuePair;
+import org.elasticsearch.common.SuppressForbidden;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.env.Environment;
 import org.elasticsearch.node.InternalSettingsPreparer;
 
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -34,10 +38,13 @@ import java.util.Map;
 public abstract class EnvironmentAwareCommand extends Command {
 
     private final OptionSpec<KeyValuePair> settingOption;
+    private final OptionSpec<String> pathConfOption;
 
     public EnvironmentAwareCommand(String description) {
         super(description);
         this.settingOption = parser.accepts("E", "Configure a setting").withRequiredArg().ofType(KeyValuePair.class);
+        this.pathConfOption =
+                parser.acceptsAll(Arrays.asList("c", "path.conf"), "Configure config path").withRequiredArg().ofType(String.class);
     }
 
     @Override
@@ -59,17 +66,22 @@ public abstract class EnvironmentAwareCommand extends Command {
             settings.put(kvp.key, kvp.value);
         }
 
-        putSystemPropertyIfSettingIsMissing(settings, "path.conf", "es.path.conf");
         putSystemPropertyIfSettingIsMissing(settings, "path.data", "es.path.data");
         putSystemPropertyIfSettingIsMissing(settings, "path.home", "es.path.home");
         putSystemPropertyIfSettingIsMissing(settings, "path.logs", "es.path.logs");
 
-        execute(terminal, options, createEnv(terminal, settings));
+        final String pathConf = pathConfOption.value(options);
+        execute(terminal, options, createEnv(terminal, settings, getConfigPath(pathConf)));
+    }
+
+    @SuppressForbidden(reason = "need path to construct environment")
+    private static Path getConfigPath(final String pathConf) {
+        return pathConf == null ? null : Paths.get(pathConf);
     }
 
     /** Create an {@link Environment} for the command to use. Overrideable for tests. */
-    protected Environment createEnv(Terminal terminal, Map<String, String> settings) {
-        return InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
+    protected Environment createEnv(Terminal terminal, Map<String, String> settings, Path configPath) {
+        return InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings, configPath);
     }
 
     /** Ensure the given setting exists, reading it from system properties if not already set. */

+ 1 - 1
core/src/main/java/org/elasticsearch/client/transport/TransportClient.java

@@ -97,7 +97,7 @@ public abstract class TransportClient extends AbstractClient {
                 .put(InternalSettingsPreparer.prepareSettings(settings))
                 .put(NetworkService.NETWORK_SERVER.getKey(), false)
                 .put(CLIENT_TYPE_SETTING_S.getKey(), CLIENT_TYPE);
-        return new PluginsService(settingsBuilder.build(), null, null, plugins);
+        return new PluginsService(settingsBuilder.build(), null, null, null, plugins);
     }
 
     protected static Collection<Class<? extends Plugin>> addPlugins(Collection<Class<? extends Plugin>> collection,

+ 0 - 2
core/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java

@@ -314,8 +314,6 @@ public final class ClusterSettings extends AbstractScopedSettings {
                     HunspellService.HUNSPELL_IGNORE_CASE,
                     HunspellService.HUNSPELL_DICTIONARY_OPTIONS,
                     IndicesStore.INDICES_STORE_DELETE_SHARD_TIMEOUT,
-                    Environment.DEFAULT_PATH_CONF_SETTING,
-                    Environment.PATH_CONF_SETTING,
                     Environment.DEFAULT_PATH_DATA_SETTING,
                     Environment.PATH_DATA_SETTING,
                     Environment.PATH_HOME_SETTING,

+ 6 - 7
core/src/main/java/org/elasticsearch/env/Environment.java

@@ -46,9 +46,6 @@ import java.util.function.Function;
 // public+forbidden api!
 public class Environment {
     public static final Setting<String> PATH_HOME_SETTING = Setting.simpleString("path.home", Property.NodeScope);
-    public static final Setting<String> DEFAULT_PATH_CONF_SETTING = Setting.simpleString("default.path.conf", Property.NodeScope);
-    public static final Setting<String> PATH_CONF_SETTING =
-            new Setting<>("path.conf", DEFAULT_PATH_CONF_SETTING, Function.identity(), Property.NodeScope);
     public static final Setting<List<String>> DEFAULT_PATH_DATA_SETTING =
             Setting.listSetting("default.path.data", Collections.emptyList(), Function.identity(), Property.NodeScope);
     public static final Setting<List<String>> PATH_DATA_SETTING =
@@ -92,6 +89,10 @@ public class Environment {
     private final Path tmpFile = PathUtils.get(System.getProperty("java.io.tmpdir"));
 
     public Environment(Settings settings) {
+        this(settings, null);
+    }
+
+    public Environment(final Settings settings, final Path configPath) {
         final Path homeFile;
         if (PATH_HOME_SETTING.exists(settings)) {
             homeFile = PathUtils.get(PATH_HOME_SETTING.get(settings)).normalize();
@@ -99,9 +100,8 @@ public class Environment {
             throw new IllegalStateException(PATH_HOME_SETTING.getKey() + " is not configured");
         }
 
-        // this is trappy, Setting#get(Settings) will get a fallback setting yet return false for Settings#exists(Settings)
-        if (PATH_CONF_SETTING.exists(settings) || DEFAULT_PATH_CONF_SETTING.exists(settings)) {
-            configFile = PathUtils.get(PATH_CONF_SETTING.get(settings)).normalize();
+        if (configPath != null) {
+            configFile = configPath.normalize();
         } else {
             configFile = homeFile.resolve("config");
         }
@@ -160,7 +160,6 @@ public class Environment {
         }
         finalSettings.put(PATH_LOGS_SETTING.getKey(), logsFile);
         this.settings = finalSettings.build();
-
     }
 
     /**

+ 10 - 8
core/src/main/java/org/elasticsearch/node/InternalSettingsPreparer.java

@@ -63,7 +63,7 @@ public class InternalSettingsPreparer {
      * @return the {@link Settings} and {@link Environment} as a {@link Tuple}
      */
     public static Environment prepareEnvironment(Settings input, Terminal terminal) {
-        return prepareEnvironment(input, terminal, Collections.emptyMap());
+        return prepareEnvironment(input, terminal, Collections.emptyMap(), null);
     }
 
     /**
@@ -71,16 +71,18 @@ public class InternalSettingsPreparer {
      * and then replacing all property placeholders. If a {@link Terminal} is provided and configuration settings are loaded,
      * settings with a value of <code>${prompt.text}</code> or <code>${prompt.secret}</code> will result in a prompt for
      * the setting to the user.
-     * @param input The custom settings to use. These are not overwritten by settings in the configuration file.
-     * @param terminal the Terminal to use for input/output
-     * @param properties Map of properties key/value pairs (usually from the command-line)
+     *
+     * @param input      the custom settings to use; these are not overwritten by settings in the configuration file
+     * @param terminal   the Terminal to use for input/output
+     * @param properties map of properties key/value pairs (usually from the command-line)
+     * @param configPath path to config directory; (use null to indicate the default)
      * @return the {@link Settings} and {@link Environment} as a {@link Tuple}
      */
-    public static Environment prepareEnvironment(Settings input, Terminal terminal, Map<String, String> properties) {
+    public static Environment prepareEnvironment(Settings input, Terminal terminal, Map<String, String> properties, Path configPath) {
         // just create enough settings to build the environment, to get the config dir
         Settings.Builder output = Settings.builder();
         initializeSettings(output, input, properties);
-        Environment environment = new Environment(output.build());
+        Environment environment = new Environment(output.build(), configPath);
 
         if (Files.exists(environment.configFile().resolve("elasticsearch.yaml"))) {
             throw new SettingsException("elasticsearch.yaml was deprecated in 5.5.0 and must be renamed to elasticsearch.yml");
@@ -104,11 +106,11 @@ public class InternalSettingsPreparer {
         initializeSettings(output, input, properties);
         finalizeSettings(output, terminal);
 
-        environment = new Environment(output.build());
+        environment = new Environment(output.build(), configPath);
 
         // we put back the path.logs so we can use it in the logging configuration file
         output.put(Environment.PATH_LOGS_SETTING.getKey(), environment.logsFile().toAbsolutePath().normalize().toString());
-        return new Environment(output.build());
+        return new Environment(output.build(), configPath);
     }
 
     /**

+ 12 - 7
core/src/main/java/org/elasticsearch/node/Node.java

@@ -302,16 +302,15 @@ public class Node implements Closeable {
                     environment.configFile(), Arrays.toString(environment.dataFiles()), environment.logsFile(), environment.pluginsFile());
             }
 
-            this.pluginsService = new PluginsService(tmpSettings, environment.modulesFile(), environment.pluginsFile(), classpathPlugins);
+            this.pluginsService = new PluginsService(tmpSettings, environment.configFile(), environment.modulesFile(), environment.pluginsFile(), classpathPlugins);
             this.settings = pluginsService.updatedSettings();
             localNodeFactory = new LocalNodeFactory(settings, nodeEnvironment.nodeId());
 
             // create the environment based on the finalized (processed) view of the settings
             // this is just to makes sure that people get the same settings, no matter where they ask them from
-            this.environment = new Environment(this.settings);
+            this.environment = new Environment(this.settings, environment.configFile());
             Environment.assertEquivalent(environment, this.environment);
 
-
             final List<ExecutorBuilder<?>> executorBuilders = pluginsService.getExecutorBuilders(settings);
 
             final ThreadPool threadPool = new ThreadPool(settings, executorBuilders.toArray(new ExecutorBuilder[0]));
@@ -387,8 +386,14 @@ public class Node implements Closeable {
                     .flatMap(p -> p.getNamedXContent().stream()),
                 ClusterModule.getNamedXWriteables().stream())
                 .flatMap(Function.identity()).collect(toList()));
-            final TribeService tribeService = new TribeService(settings, clusterService, nodeId, namedWriteableRegistry,
-                s -> newTribeClientNode(s, classpathPlugins));
+            final TribeService tribeService =
+                    new TribeService(
+                            settings,
+                            environment.configFile(),
+                            clusterService,
+                            nodeId,
+                            namedWriteableRegistry,
+                            (s, p) -> newTribeClientNode(s, classpathPlugins, p));
             resourcesToClose.add(tribeService);
             modules.add(new RepositoriesModule(this.environment, pluginsService.filterPlugins(RepositoryPlugin.class), xContentRegistry));
             final MetaStateService metaStateService = new MetaStateService(settings, nodeEnvironment, xContentRegistry);
@@ -980,8 +985,8 @@ public class Node implements Closeable {
     }
 
     /** Constructs an internal node used as a client into a cluster fronted by this tribe node. */
-    protected Node newTribeClientNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
-        return new Node(new Environment(settings), classpathPlugins);
+    protected Node newTribeClientNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins, Path configPath) {
+        return new Node(new Environment(settings, configPath), classpathPlugins);
     }
 
     /** Constructs a ClusterInfoService which may be mocked for tests. */

+ 17 - 10
core/src/main/java/org/elasticsearch/plugins/PluginsService.java

@@ -61,12 +61,13 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import static org.elasticsearch.common.io.FileSystemUtils.isAccessibleDirectory;
 
 public class PluginsService extends AbstractComponent {
 
+    private final Path configPath;
+
     /**
      * We keep around a list of plugins and modules
      */
@@ -90,14 +91,16 @@ public class PluginsService extends AbstractComponent {
      * @param pluginsDirectory The directory plugins exist in, or null if plugins should not be loaded from the filesystem
      * @param classpathPlugins Plugins that exist in the classpath which should be loaded
      */
-    public PluginsService(Settings settings, Path modulesDirectory, Path pluginsDirectory, Collection<Class<? extends Plugin>> classpathPlugins) {
+    public PluginsService(Settings settings, Path configPath, Path modulesDirectory, Path pluginsDirectory, Collection<Class<? extends Plugin>> classpathPlugins) {
         super(settings);
 
+        this.configPath = configPath;
+
         List<Tuple<PluginInfo, Plugin>> pluginsLoaded = new ArrayList<>();
         List<PluginInfo> pluginsList = new ArrayList<>();
         // first we load plugins that are on the classpath. this is for tests and transport clients
         for (Class<? extends Plugin> pluginClass : classpathPlugins) {
-            Plugin plugin = loadPlugin(pluginClass, settings);
+            Plugin plugin = loadPlugin(pluginClass, settings, configPath);
             PluginInfo pluginInfo = new PluginInfo(pluginClass.getName(), "classpath plugin", "NA", pluginClass.getName(), false);
             if (logger.isTraceEnabled()) {
                 logger.trace("plugin loaded from classpath [{}]", pluginInfo);
@@ -381,7 +384,7 @@ public class PluginsService extends AbstractComponent {
             reloadLuceneSPI(loader);
             final Class<? extends Plugin> pluginClass =
                 loadPluginClass(bundle.plugin.getClassname(), loader);
-            final Plugin plugin = loadPlugin(pluginClass, settings);
+            final Plugin plugin = loadPlugin(pluginClass, settings, configPath);
             plugins.add(new Tuple<>(bundle.plugin, plugin));
         }
 
@@ -414,17 +417,21 @@ public class PluginsService extends AbstractComponent {
         }
     }
 
-    private Plugin loadPlugin(Class<? extends Plugin> pluginClass, Settings settings) {
+    private Plugin loadPlugin(Class<? extends Plugin> pluginClass, Settings settings, Path configPath) {
         try {
             try {
-                return pluginClass.getConstructor(Settings.class).newInstance(settings);
+                return pluginClass.getConstructor(Settings.class, Path.class).newInstance(settings, configPath);
             } catch (NoSuchMethodException e) {
                 try {
-                    return pluginClass.getConstructor().newInstance();
+                    return pluginClass.getConstructor(Settings.class).newInstance(settings);
                 } catch (NoSuchMethodException e1) {
-                    throw new ElasticsearchException("No constructor for [" + pluginClass + "]. A plugin class must " +
-                        "have either an empty default constructor or a single argument constructor accepting a " +
-                        "Settings instance");
+                    try {
+                        return pluginClass.getConstructor().newInstance();
+                    } catch (NoSuchMethodException e2) {
+                        throw new ElasticsearchException("No constructor for [" + pluginClass + "]. A plugin class must " +
+                                "have either an empty default constructor, a single argument constructor accepting a " +
+                                "Settings instance, or a single argument constructor accepting a pair of Settings, Path instances");
+                    }
                 }
             }
         } catch (Exception e) {

+ 5 - 6
core/src/main/java/org/elasticsearch/tribe/TribeService.java

@@ -68,6 +68,7 @@ import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.transport.TransportSettings;
 
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -77,6 +78,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.BiFunction;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -216,8 +218,8 @@ public class TribeService extends AbstractLifecycleComponent {
 
     private final NamedWriteableRegistry namedWriteableRegistry;
 
-    public TribeService(Settings settings, ClusterService clusterService, final String tribeNodeId,
-                        NamedWriteableRegistry namedWriteableRegistry, Function<Settings, Node> clientNodeBuilder) {
+    public TribeService(Settings settings, Path configPath, ClusterService clusterService, final String tribeNodeId,
+                        NamedWriteableRegistry namedWriteableRegistry, BiFunction<Settings, Path, Node> clientNodeBuilder) {
         super(settings);
         this.clusterService = clusterService;
         this.namedWriteableRegistry = namedWriteableRegistry;
@@ -226,7 +228,7 @@ public class TribeService extends AbstractLifecycleComponent {
         nodesSettings.remove("on_conflict"); // remove prefix settings that don't indicate a client
         for (Map.Entry<String, Settings> entry : nodesSettings.entrySet()) {
             Settings clientSettings = buildClientSettings(entry.getKey(), tribeNodeId, settings, entry.getValue());
-            nodes.add(clientNodeBuilder.apply(clientSettings));
+            nodes.add(clientNodeBuilder.apply(clientSettings, configPath));
         }
 
         this.blockIndicesMetadata = BLOCKS_METADATA_INDICES_SETTING.get(settings).toArray(Strings.EMPTY_ARRAY);
@@ -253,9 +255,6 @@ public class TribeService extends AbstractLifecycleComponent {
         Settings.Builder sb = Settings.builder().put(tribeSettings);
         sb.put(Node.NODE_NAME_SETTING.getKey(), Node.NODE_NAME_SETTING.get(globalSettings) + "/" + tribeName);
         sb.put(Environment.PATH_HOME_SETTING.getKey(), Environment.PATH_HOME_SETTING.get(globalSettings)); // pass through ES home dir
-        if (Environment.PATH_CONF_SETTING.exists(globalSettings)) {
-            sb.put(Environment.PATH_CONF_SETTING.getKey(), Environment.PATH_CONF_SETTING.get(globalSettings));
-        }
         if (Environment.PATH_LOGS_SETTING.exists(globalSettings)) {
             sb.put(Environment.PATH_LOGS_SETTING.getKey(), Environment.PATH_LOGS_SETTING.get(globalSettings));
         }

+ 0 - 2
core/src/test/java/org/elasticsearch/action/update/UpdateRequestTests.java

@@ -75,10 +75,8 @@ public class UpdateRequestTests extends ESTestCase {
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        final Path genericConfigFolder = createTempDir();
         final Settings baseSettings = Settings.builder()
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
-                .put(Environment.PATH_CONF_SETTING.getKey(), genericConfigFolder)
                 .build();
         final Map<String, Function<Map<String, Object>, Object>> scripts =  new HashMap<>();
         scripts.put(

+ 1 - 1
core/src/test/java/org/elasticsearch/common/settings/AddFileKeyStoreCommandTests.java

@@ -37,7 +37,7 @@ public class AddFileKeyStoreCommandTests extends KeyStoreCommandTestCase {
     protected Command newCommand() {
         return new AddFileKeyStoreCommand() {
             @Override
-            protected Environment createEnv(Terminal terminal, Map<String, String> settings) {
+            protected Environment createEnv(Terminal terminal, Map<String, String> settings, Path configPath) {
                 return env;
             }
         };

+ 2 - 1
core/src/test/java/org/elasticsearch/common/settings/AddStringKeyStoreCommandTests.java

@@ -22,6 +22,7 @@ package org.elasticsearch.common.settings;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
 import java.util.Map;
 
 import org.elasticsearch.cli.Command;
@@ -39,7 +40,7 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase {
     protected Command newCommand() {
         return new AddStringKeyStoreCommand() {
             @Override
-            protected Environment createEnv(Terminal terminal, Map<String, String> settings) {
+            protected Environment createEnv(Terminal terminal, Map<String, String> settings, Path configPath) {
                 return env;
             }
             @Override

+ 1 - 1
core/src/test/java/org/elasticsearch/common/settings/CreateKeyStoreCommandTests.java

@@ -34,7 +34,7 @@ public class CreateKeyStoreCommandTests extends KeyStoreCommandTestCase {
     protected Command newCommand() {
         return new CreateKeyStoreCommand() {
             @Override
-            protected Environment createEnv(Terminal terminal, Map<String, String> settings) {
+            protected Environment createEnv(Terminal terminal, Map<String, String> settings, Path configPath) {
                 return env;
             }
         };

+ 2 - 1
core/src/test/java/org/elasticsearch/common/settings/ListKeyStoreCommandTests.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.common.settings;
 
+import java.nio.file.Path;
 import java.util.Map;
 
 import org.elasticsearch.cli.Command;
@@ -35,7 +36,7 @@ public class ListKeyStoreCommandTests extends KeyStoreCommandTestCase {
     protected Command newCommand() {
         return new ListKeyStoreCommand() {
             @Override
-            protected Environment createEnv(Terminal terminal, Map<String, String> settings) {
+            protected Environment createEnv(Terminal terminal, Map<String, String> settings, Path configPath) {
                 return env;
             }
         };

+ 5 - 7
core/src/test/java/org/elasticsearch/common/settings/RemoveSettingKeyStoreCommandTests.java

@@ -19,18 +19,16 @@
 
 package org.elasticsearch.common.settings;
 
-import javax.crypto.SecretKeyFactory;
-import java.security.Provider;
-import java.security.Security;
-import java.util.Map;
-import java.util.Set;
-
 import org.elasticsearch.cli.Command;
 import org.elasticsearch.cli.ExitCodes;
 import org.elasticsearch.cli.Terminal;
 import org.elasticsearch.cli.UserException;
 import org.elasticsearch.env.Environment;
 
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Set;
+
 import static org.hamcrest.Matchers.containsString;
 
 public class RemoveSettingKeyStoreCommandTests extends KeyStoreCommandTestCase {
@@ -39,7 +37,7 @@ public class RemoveSettingKeyStoreCommandTests extends KeyStoreCommandTestCase {
     protected Command newCommand() {
         return new RemoveSettingKeyStoreCommand() {
             @Override
-            protected Environment createEnv(Terminal terminal, Map<String, String> settings) {
+            protected Environment createEnv(Terminal terminal, Map<String, String> settings, Path configPath) {
                 return env;
             }
         };

+ 6 - 1
core/src/test/java/org/elasticsearch/discovery/single/SingleNodeDiscoveryIT.java

@@ -27,7 +27,6 @@ import org.elasticsearch.cluster.node.DiscoveryNodes;
 import org.elasticsearch.cluster.service.ClusterService;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.discovery.zen.PingContextProvider;
 import org.elasticsearch.discovery.zen.UnicastHostsProvider;
 import org.elasticsearch.discovery.zen.UnicastZenPing;
 import org.elasticsearch.discovery.zen.ZenPing;
@@ -41,6 +40,7 @@ import org.elasticsearch.transport.TransportService;
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.Collections;
 import java.util.Stack;
 import java.util.concurrent.CompletableFuture;
@@ -133,6 +133,11 @@ public class SingleNodeDiscoveryIT extends ESIntegTestCase {
                         .put("transport.tcp.port", port + "-" + (port + 5 - 1))
                         .build();
             }
+
+            @Override
+            public Path nodeConfigPath(int nodeOrdinal) {
+                return null;
+            }
         };
         try (InternalTestCluster other =
                 new InternalTestCluster(

+ 11 - 19
core/src/test/java/org/elasticsearch/env/EnvironmentTests.java

@@ -144,29 +144,21 @@ public class EnvironmentTests extends ESTestCase {
         assertThat(environment.logsFile(), equalTo(pathHome.resolve("logs")));
     }
 
-    public void testDefaultPathConf() {
-        final Path defaultPathConf = createTempDir().toAbsolutePath();
-        final Settings settings = Settings.builder()
-                .put("path.home", createTempDir().toAbsolutePath())
-                .put("default.path.conf", defaultPathConf)
-                .build();
-        final Environment environment = new Environment(settings);
-        assertThat(environment.configFile(), equalTo(defaultPathConf));
+    public void testDefaultConfigPath() {
+        final Path path = createTempDir().toAbsolutePath();
+        final Settings settings = Settings.builder().put("path.home", path).build();
+        final Environment environment = new Environment(settings, null);
+        assertThat(environment.configFile(), equalTo(path.resolve("config")));
     }
 
-    public void testPathConfOverrideDefaultPathConf() {
-        final Path pathConf = createTempDir().toAbsolutePath();
-        final Path defaultPathConf = createTempDir().toAbsolutePath();
-        final Settings settings = Settings.builder()
-                .put("path.home", createTempDir().toAbsolutePath())
-                .put("path.conf", pathConf)
-                .put("default.path.conf", defaultPathConf)
-                .build();
-        final Environment environment = new Environment(settings);
-        assertThat(environment.configFile(), equalTo(pathConf));
+    public void testConfigPath() {
+        final Path configPath = createTempDir().toAbsolutePath();
+        final Settings settings = Settings.builder().put("path.home", createTempDir().toAbsolutePath()).build();
+        final Environment environment = new Environment(settings, configPath);
+        assertThat(environment.configFile(), equalTo(configPath));
     }
 
-    public void testPathConfWhenNotSet() {
+    public void testConfigPathWhenNotSet() {
         final Path pathHome = createTempDir().toAbsolutePath();
         final Settings settings = Settings.builder().put("path.home", pathHome).build();
         final Environment environment = new Environment(settings);

+ 3 - 4
core/src/test/java/org/elasticsearch/index/analysis/HunspellTokenFilterFactoryTests.java

@@ -31,12 +31,12 @@ public class HunspellTokenFilterFactoryTests extends ESTestCase {
     public void testDedup() throws IOException {
         Settings settings = Settings.builder()
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
-                .put(Environment.PATH_CONF_SETTING.getKey(), getDataPath("/indices/analyze/conf_dir"))
                 .put("index.analysis.filter.en_US.type", "hunspell")
                 .put("index.analysis.filter.en_US.locale", "en_US")
                 .build();
 
-        TestAnalysis analysis = AnalysisTestsHelper.createTestAnalysisFromSettings(settings);
+        TestAnalysis analysis =
+                AnalysisTestsHelper.createTestAnalysisFromSettings(settings, getDataPath("/indices/analyze/conf_dir"));
         TokenFilterFactory tokenFilter = analysis.tokenFilter.get("en_US");
         assertThat(tokenFilter, instanceOf(HunspellTokenFilterFactory.class));
         HunspellTokenFilterFactory hunspellTokenFilter = (HunspellTokenFilterFactory) tokenFilter;
@@ -44,13 +44,12 @@ public class HunspellTokenFilterFactoryTests extends ESTestCase {
 
         settings = Settings.builder()
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
-                .put(Environment.PATH_CONF_SETTING.getKey(), getDataPath("/indices/analyze/conf_dir"))
                 .put("index.analysis.filter.en_US.type", "hunspell")
                 .put("index.analysis.filter.en_US.dedup", false)
                 .put("index.analysis.filter.en_US.locale", "en_US")
                 .build();
 
-        analysis = AnalysisTestsHelper.createTestAnalysisFromSettings(settings);
+        analysis = AnalysisTestsHelper.createTestAnalysisFromSettings(settings, getDataPath("/indices/analyze/conf_dir"));
         tokenFilter = analysis.tokenFilter.get("en_US");
         assertThat(tokenFilter, instanceOf(HunspellTokenFilterFactory.class));
         hunspellTokenFilter = (HunspellTokenFilterFactory) tokenFilter;

+ 16 - 9
core/src/test/java/org/elasticsearch/indices/analyze/HunspellServiceTests.java

@@ -24,6 +24,8 @@ import org.elasticsearch.env.Environment;
 import org.elasticsearch.indices.analysis.HunspellService;
 import org.elasticsearch.test.ESTestCase;
 
+import java.nio.file.Path;
+
 import static java.util.Collections.emptyMap;
 import static org.elasticsearch.indices.analysis.HunspellService.HUNSPELL_IGNORE_CASE;
 import static org.elasticsearch.indices.analysis.HunspellService.HUNSPELL_LAZY_LOAD;
@@ -34,20 +36,19 @@ import static org.hamcrest.Matchers.notNullValue;
 public class HunspellServiceTests extends ESTestCase {
     public void testLocaleDirectoryWithNodeLevelConfig() throws Exception {
         Settings settings = Settings.builder()
-                .put(Environment.PATH_CONF_SETTING.getKey(), getDataPath("/indices/analyze/conf_dir"))
                 .put(HUNSPELL_LAZY_LOAD.getKey(), randomBoolean())
                 .put(HUNSPELL_IGNORE_CASE.getKey(), true)
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
                 .build();
 
-        Dictionary dictionary = new HunspellService(settings, new Environment(settings), emptyMap()).getDictionary("en_US");
+        final Environment environment = new Environment(settings, getDataPath("/indices/analyze/conf_dir"));
+        Dictionary dictionary = new HunspellService(settings, environment, emptyMap()).getDictionary("en_US");
         assertThat(dictionary, notNullValue());
         assertTrue(dictionary.getIgnoreCase());
     }
 
     public void testLocaleDirectoryWithLocaleSpecificConfig() throws Exception {
         Settings settings = Settings.builder()
-                .put(Environment.PATH_CONF_SETTING.getKey(), getDataPath("/indices/analyze/conf_dir"))
                 .put(HUNSPELL_LAZY_LOAD.getKey(), randomBoolean())
                 .put(HUNSPELL_IGNORE_CASE.getKey(), true)
                 .put("indices.analysis.hunspell.dictionary.en_US.strict_affix_parsing", false)
@@ -55,38 +56,44 @@ public class HunspellServiceTests extends ESTestCase {
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
                 .build();
 
-        Dictionary dictionary = new HunspellService(settings, new Environment(settings), emptyMap()).getDictionary("en_US");
+        final Path configPath = getDataPath("/indices/analyze/conf_dir");
+        final Environment environment = new Environment(settings, configPath);
+        Dictionary dictionary = new HunspellService(settings, environment, emptyMap()).getDictionary("en_US");
         assertThat(dictionary, notNullValue());
         assertFalse(dictionary.getIgnoreCase());
 
         // testing that dictionary specific settings override node level settings
-        dictionary = new HunspellService(settings, new Environment(settings), emptyMap()).getDictionary("en_US_custom");
+        dictionary = new HunspellService(settings, new Environment(settings, configPath), emptyMap()).getDictionary("en_US_custom");
         assertThat(dictionary, notNullValue());
         assertTrue(dictionary.getIgnoreCase());
     }
 
     public void testDicWithNoAff() throws Exception {
         Settings settings = Settings.builder()
-                .put(Environment.PATH_CONF_SETTING.getKey(), getDataPath("/indices/analyze/no_aff_conf_dir"))
                 .put(HUNSPELL_LAZY_LOAD.getKey(), randomBoolean())
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
                 .build();
 
         IllegalStateException e = expectThrows(IllegalStateException.class,
-                () -> new HunspellService(settings, new Environment(settings), emptyMap()).getDictionary("en_US"));
+                () -> {
+                    final Environment environment = new Environment(settings, getDataPath("/indices/analyze/no_aff_conf_dir"));
+                    new HunspellService(settings, environment, emptyMap()).getDictionary("en_US");
+                });
         assertEquals("failed to load hunspell dictionary for locale: en_US", e.getMessage());
         assertThat(e.getCause(), hasToString(containsString("Missing affix file")));
     }
 
     public void testDicWithTwoAffs() throws Exception {
         Settings settings = Settings.builder()
-                .put(Environment.PATH_CONF_SETTING.getKey(), getDataPath("/indices/analyze/two_aff_conf_dir"))
                 .put(HUNSPELL_LAZY_LOAD.getKey(), randomBoolean())
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
                 .build();
 
         IllegalStateException e = expectThrows(IllegalStateException.class,
-                () -> new HunspellService(settings, new Environment(settings), emptyMap()).getDictionary("en_US"));
+                () -> {
+                    final Environment environment = new Environment(settings, getDataPath("/indices/analyze/two_aff_conf_dir"));
+                    new HunspellService(settings, environment, emptyMap()).getDictionary("en_US");
+                });
         assertEquals("failed to load hunspell dictionary for locale: en_US", e.getMessage());
         assertThat(e.getCause(), hasToString(containsString("Too many affix files")));
     }

+ 1 - 1
core/src/test/java/org/elasticsearch/node/InternalSettingsPreparerTests.java

@@ -181,7 +181,7 @@ public class InternalSettingsPreparerTests extends ESTestCase {
 
     public void testDefaultPropertiesDoNothing() throws Exception {
         Map<String, String> props = Collections.singletonMap("default.setting", "foo");
-        Environment env = InternalSettingsPreparer.prepareEnvironment(baseEnvSettings, null, props);
+        Environment env = InternalSettingsPreparer.prepareEnvironment(baseEnvSettings, null, props, null);
         assertEquals("foo", env.settings().get("default.setting"));
         assertNull(env.settings().get("setting"));
     }

+ 1 - 1
core/src/test/java/org/elasticsearch/plugins/PluginsServiceTests.java

@@ -54,7 +54,7 @@ public class PluginsServiceTests extends ESTestCase {
     public static class FilterablePlugin extends Plugin implements ScriptPlugin {}
 
     static PluginsService newPluginsService(Settings settings, Class<? extends Plugin>... classpathPlugins) {
-        return new PluginsService(settings, null, new Environment(settings).pluginsFile(), Arrays.asList(classpathPlugins));
+        return new PluginsService(settings, null, null, new Environment(settings).pluginsFile(), Arrays.asList(classpathPlugins));
     }
 
     public void testAdditionalSettings() {

+ 0 - 2
core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java

@@ -54,10 +54,8 @@ public class ScriptServiceTests extends ESTestCase {
 
     @Before
     public void setup() throws IOException {
-        Path genericConfigFolder = createTempDir();
         baseSettings = Settings.builder()
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
-                .put(Environment.PATH_CONF_SETTING.getKey(), genericConfigFolder)
                 .put(ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE.getKey(), 10000)
                 .build();
         Map<String, Function<Map<String, Object>, Object>> scripts = new HashMap<>();

+ 12 - 10
core/src/test/java/org/elasticsearch/search/aggregations/metrics/ScriptedMetricIT.java

@@ -25,7 +25,6 @@ import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.common.xcontent.support.XContentMapValues;
-import org.elasticsearch.env.Environment;
 import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.script.MockScriptPlugin;
 import org.elasticsearch.script.Script;
@@ -40,6 +39,7 @@ import org.elasticsearch.search.aggregations.metrics.scripted.ScriptedMetric;
 import org.elasticsearch.test.ESIntegTestCase;
 import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
 import org.elasticsearch.test.ESIntegTestCase.Scope;
+import org.junit.Before;
 
 import java.io.IOException;
 import java.nio.file.Files;
@@ -253,14 +253,16 @@ public class ScriptedMetricIT extends ESIntegTestCase {
         ensureSearchable();
     }
 
-    @Override
-    protected Settings nodeSettings(int nodeOrdinal) {
-        Path config = createTempDir().resolve("config");
-        Path scripts = config.resolve("scripts");
+    private Path config;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        config = createTempDir().resolve("config");
+        final Path scripts = config.resolve("scripts");
 
         try {
             Files.createDirectories(scripts);
-
             // When using the MockScriptPlugin we can map File scripts to inline scripts:
             // the name of the file script is used in test method while the source of the file script
             // must match a predefined script from CustomScriptPlugin.pluginScripts() method
@@ -271,11 +273,11 @@ public class ScriptedMetricIT extends ESIntegTestCase {
         } catch (IOException e) {
             throw new RuntimeException("failed to create scripts");
         }
+    }
 
-        return Settings.builder()
-                .put(super.nodeSettings(nodeOrdinal))
-                .put(Environment.PATH_CONF_SETTING.getKey(), config)
-                .build();
+    @Override
+    protected Path nodeConfigPath(int nodeOrdinal) {
+        return config;
     }
 
     public void testMap() {

+ 0 - 2
core/src/test/java/org/elasticsearch/search/sort/AbstractSortTestCase.java

@@ -81,10 +81,8 @@ public abstract class AbstractSortTestCase<T extends SortBuilder<T>> extends EST
 
     @BeforeClass
     public static void init() throws IOException {
-        Path genericConfigFolder = createTempDir();
         Settings baseSettings = Settings.builder()
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
-                .put(Environment.PATH_CONF_SETTING.getKey(), genericConfigFolder)
                 .build();
         Map<String, Function<Map<String, Object>, Object>> scripts = Collections.singletonMap("dummy", p -> null);
         ScriptEngine engine = new MockScriptEngine(MockScriptEngine.NAME, scripts);

+ 0 - 2
core/src/test/java/org/elasticsearch/tribe/TribeServiceTests.java

@@ -68,11 +68,9 @@ public class TribeServiceTests extends ESTestCase {
         Settings globalSettings = Settings.builder()
             .put("node.name", "nodename")
             .put("path.home", "some/path")
-            .put("path.conf", "conf/path")
             .put("path.logs", "logs/path").build();
         Settings clientSettings = TribeService.buildClientSettings("tribe1", "parent_id", globalSettings, Settings.EMPTY);
         assertEquals("some/path", clientSettings.get("path.home"));
-        assertEquals("conf/path", clientSettings.get("path.conf"));
         assertEquals("logs/path", clientSettings.get("path.logs"));
 
         Settings tribeSettings = Settings.builder()

+ 1 - 1
distribution/deb/src/main/packaging/init.d/elasticsearch

@@ -81,7 +81,7 @@ fi
 # Define other required variables
 PID_FILE="$PID_DIR/$NAME.pid"
 DAEMON=$ES_HOME/bin/elasticsearch
-DAEMON_OPTS="-d -p $PID_FILE -Edefault.path.logs=$LOG_DIR -Edefault.path.data=$DATA_DIR -Edefault.path.conf=$CONF_DIR"
+DAEMON_OPTS="-d -p $PID_FILE -Edefault.path.logs=$LOG_DIR -Edefault.path.data=$DATA_DIR --path.conf $CONF_DIR"
 
 export ES_JAVA_OPTS
 export JAVA_HOME

+ 1 - 1
distribution/rpm/src/main/packaging/init.d/elasticsearch

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

+ 1 - 1
distribution/src/main/packaging/systemd/elasticsearch.service

@@ -24,7 +24,7 @@ ExecStart=/usr/share/elasticsearch/bin/elasticsearch \
                                                 --quiet \
                                                 -Edefault.path.logs=${LOG_DIR} \
                                                 -Edefault.path.data=${DATA_DIR} \
-                                                -Edefault.path.conf=${CONF_DIR}
+                                                --path.conf ${CONF_DIR}
 
 # StandardOutput is configured to redirect to journalctl since
 # some error messages may be logged in standard output before

+ 1 - 1
distribution/src/main/resources/bin/elasticsearch-plugin

@@ -85,7 +85,7 @@ declare -a args=("$@")
 path_props=(-Des.path.home="$ES_HOME")
 
 if [ -e "$CONF_DIR" ]; then
-  path_props=("${path_props[@]}" -Des.path.conf="$CONF_DIR")
+  args=("${args[@]}" --path.conf "$CONF_DIR")
 fi
 
 exec "$JAVA" $ES_JAVA_OPTS -Delasticsearch "${path_props[@]}" -cp "$ES_HOME/lib/*" org.elasticsearch.plugins.PluginCli "${args[@]}"

+ 2 - 2
distribution/src/main/resources/bin/elasticsearch-service.bat

@@ -226,7 +226,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.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%"
 
 if "%ES_START_TYPE%" == "" set ES_START_TYPE=manual
 if "%ES_STOP_TIMEOUT%" == "" set ES_STOP_TIMEOUT=0
@@ -240,7 +240,7 @@ if not "%SERVICE_USERNAME%" == "" (
 	)
 )
 
-"%EXECUTABLE%" //IS//%SERVICE_ID% --Startup %ES_START_TYPE% --StopTimeout %ES_STOP_TIMEOUT% --StartClass org.elasticsearch.bootstrap.Elasticsearch --StopClass org.elasticsearch.bootstrap.Elasticsearch --StartMethod main --StopMethod close --Classpath "%ES_CLASSPATH%" --JvmMs %JVM_MS% --JvmMx %JVM_MX% --JvmSs %JVM_SS% --JvmOptions %ES_JAVA_OPTS% ++JvmOptions %ES_PARAMS% %LOG_OPTS% --PidFile "%SERVICE_ID%.pid" --DisplayName "%SERVICE_DISPLAY_NAME%" --Description "%SERVICE_DESCRIPTION%" --Jvm "%%JAVA_HOME%%%JVM_DLL%" --StartMode jvm --StopMode jvm --StartPath "%ES_HOME%" %SERVICE_PARAMS%
+"%EXECUTABLE%" //IS//%SERVICE_ID% --Startup %ES_START_TYPE% --StopTimeout %ES_STOP_TIMEOUT% --StartClass org.elasticsearch.bootstrap.Elasticsearch --StopClass org.elasticsearch.bootstrap.Elasticsearch --StartMethod main --StopMethod close --Classpath "%ES_CLASSPATH%" --JvmMs %JVM_MS% --JvmMx %JVM_MX% --JvmSs %JVM_SS% --JvmOptions %ES_JAVA_OPTS% ++JvmOptions %ES_PARAMS% %LOG_OPTS% --PidFile "%SERVICE_ID%.pid" --DisplayName "%SERVICE_DISPLAY_NAME%" --Description "%SERVICE_DESCRIPTION%" --Jvm "%%JAVA_HOME%%%JVM_DLL%" --StartMode jvm --StopMode jvm --StartPath "%ES_HOME%" --StartParams --path.conf ++StartParams "%CONF_DIR%" %SERVICE_PARAMS%
 
 if not errorlevel 1 goto installed
 echo Failed installing '%SERVICE_ID%' service

+ 1 - 1
distribution/src/main/resources/bin/elasticsearch-translog

@@ -84,7 +84,7 @@ export HOSTNAME
 declare -a args=("$@")
 
 if [ -e "$CONF_DIR" ]; then
-  args=("${args[@]}" -Edefault.path.conf="$CONF_DIR")
+  args=("${args[@]}" --path.conf "$CONF_DIR")
 fi
 
 exec "$JAVA" $ES_JAVA_OPTS -Delasticsearch -Des.path.home="$ES_HOME" -cp "$ES_HOME/lib/*" org.elasticsearch.index.translog.TranslogToolCli "${args[@]}"

+ 10 - 0
docs/reference/migration/migrate_6_0/packaging.asciidoc

@@ -9,3 +9,13 @@ possible, the DEB and RPM packages now exclusively use the user and group
 `elasticsearch`. If a custom user or group is needed then a provisioning system
 should use the tarball distribution instead of the provided RPM and DEB
 packages.
+
+==== `path.conf` is no longer a configurable setting
+
+Previous versions of Elasticsearch enabled setting `path.conf` as a
+setting. This was rather convoluted as it meant that you could start
+Elasticsearch with a config file that specified via `path.conf` that
+Elasticsearch should use another config file. Instead, `path.conf` is now a
+command-line flag. To start Elasticsearch with a custom config file, use `-c
+/path/to/config` or `--path.conf /path/to/config`. Here, `/path/to/config` is
+the *directory* containing the config file.

+ 10 - 0
docs/reference/migration/migrate_6_0/plugins.asciidoc

@@ -80,3 +80,13 @@ The icu4j library has been upgraded to 59.1,
 Indices created in the previous major version will need to be reindexed
 in order to return correct (and correctly ordered) results,
 and to take advantage of new characters.
+
+==== Plugins should not construct `Environment` instances from `Settings`
+
+Previously, plugins could construct an `Environment` instance from `Settings` to
+discover the path to plugin-specific config files. This will no longer work in
+all situations as the `Settings` object does not carry the necessary information
+for the config path to be set correctly. Instead, plugins that need to know the
+config path should have a single constructor that accepts a pair of `Settings`
+and `Path` instances, and construct an `Environment` using the corresponding
+constructor on `Environment`.

+ 0 - 1
docs/reference/modules/tribe.asciidoc

@@ -88,7 +88,6 @@ configuration options are passed down from the tribe node to each node client:
 * `transport.bind_host`
 * `transport.publish_host`
 * `path.home`
-* `path.conf`
 * `path.logs`
 * `shield.*`
 

+ 2 - 2
docs/reference/setup/configuration.asciidoc

@@ -22,11 +22,11 @@ These files are located in the config directory, whose location defaults to
 location to `/etc/elasticsearch/`.
 
 The location of the config directory can be changed with the `path.conf`
-setting, as follows:
+flag, as follows:
 
 [source,sh]
 -------------------------------
-./bin/elasticsearch -Epath.conf=/path/to/my/config/
+./bin/elasticsearch --path.conf /path/to/my/config/
 -------------------------------
 
 [float]

+ 5 - 1
plugins/discovery-azure-classic/src/test/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java

@@ -112,7 +112,6 @@ public class AzureDiscoveryClusterFormationTests extends ESIntegTestCase {
             .put(Node.WRITE_PORTS_FILE_SETTING.getKey(), "true")
             .put(AzureComputeService.Management.ENDPOINT_SETTING.getKey(), "https://" + InetAddress.getLoopbackAddress().getHostAddress() +
                 ":" + httpsServer.getAddress().getPort())
-            .put(Environment.PATH_CONF_SETTING.getKey(), keyStoreFile.getParent().toAbsolutePath())
             .put(AzureComputeService.Management.KEYSTORE_PATH_SETTING.getKey(), keyStoreFile.toAbsolutePath())
             .put(AzureComputeService.Discovery.HOST_TYPE_SETTING.getKey(), AzureUnicastHostsProvider.HostType.PUBLIC_IP.name())
             .put(AzureComputeService.Management.KEYSTORE_PASSWORD_SETTING.getKey(), "keypass")
@@ -125,6 +124,11 @@ public class AzureDiscoveryClusterFormationTests extends ESIntegTestCase {
             .build();
     }
 
+    @Override
+    protected Path nodeConfigPath(int nodeOrdinal) {
+        return keyStoreFile.getParent();
+    }
+
     /**
      * Creates mock EC2 endpoint providing the list of started nodes to the DescribeInstances API call
      */

+ 3 - 3
plugins/jvm-example/src/main/java/org/elasticsearch/plugin/example/JvmExamplePlugin.java

@@ -31,6 +31,7 @@ import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.rest.RestController;
 import org.elasticsearch.rest.RestHandler;
 
+import java.nio.file.Path;
 import java.util.List;
 import java.util.function.Supplier;
 
@@ -42,9 +43,8 @@ import static java.util.Collections.singletonList;
 public class JvmExamplePlugin extends Plugin implements ActionPlugin {
     private final ExamplePluginConfiguration config;
 
-    public JvmExamplePlugin(Settings settings) {
-        Environment environment = new Environment(settings);
-        config = new ExamplePluginConfiguration(environment);
+    public JvmExamplePlugin(Settings settings, Path configPath) {
+        config = new ExamplePluginConfiguration(new Environment(settings, configPath));
     }
 
     @Override

+ 1 - 2
qa/evil-tests/src/test/java/org/elasticsearch/bootstrap/EvilSecurityTests.java

@@ -80,7 +80,6 @@ public class EvilSecurityTests extends ESTestCase {
 
         Settings.Builder settingsBuilder = Settings.builder();
         settingsBuilder.put(Environment.PATH_HOME_SETTING.getKey(), esHome.resolve("home").toString());
-        settingsBuilder.put(Environment.PATH_CONF_SETTING.getKey(), esHome.resolve("conf").toString());
         settingsBuilder.putArray(Environment.PATH_DATA_SETTING.getKey(), esHome.resolve("data1").toString(),
                 esHome.resolve("data2").toString());
         settingsBuilder.put(Environment.PATH_SHARED_DATA_SETTING.getKey(), esHome.resolve("custom").toString());
@@ -94,7 +93,7 @@ public class EvilSecurityTests extends ESTestCase {
         Environment environment;
         try {
             System.setProperty("java.io.tmpdir", fakeTmpDir.toString());
-            environment = new Environment(settings);
+            environment = new Environment(settings, esHome.resolve("conf"));
             permissions = Security.createPermissions(environment);
         } finally {
             System.setProperty("java.io.tmpdir", realTmpDir);

+ 6 - 12
qa/evil-tests/src/test/java/org/elasticsearch/common/logging/EvilLoggerConfigurationTests.java

@@ -62,10 +62,9 @@ public class EvilLoggerConfigurationTests extends ESTestCase {
         try {
             final Path configDir = getDataPath("config");
             final Settings settings = Settings.builder()
-                .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath())
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
                 .build();
-            final Environment environment = new Environment(settings);
+            final Environment environment = new Environment(settings, configDir);
             LogConfigurator.configure(environment);
 
             {
@@ -100,11 +99,10 @@ public class EvilLoggerConfigurationTests extends ESTestCase {
         final Path configDir = getDataPath("config");
         final String level = randomFrom(Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR).toString();
         final Settings settings = Settings.builder()
-            .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath())
             .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
             .put("logger.level", level)
             .build();
-        final Environment environment = new Environment(settings);
+        final Environment environment = new Environment(settings, configDir);
         LogConfigurator.configure(environment);
 
         final String loggerName = "test";
@@ -116,11 +114,10 @@ public class EvilLoggerConfigurationTests extends ESTestCase {
     public void testResolveOrder() throws Exception {
         final Path configDir = getDataPath("config");
         final Settings settings = Settings.builder()
-            .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath())
             .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
             .put("logger.test_resolve_order", "TRACE")
             .build();
-        final Environment environment = new Environment(settings);
+        final Environment environment = new Environment(settings, configDir);
         LogConfigurator.configure(environment);
 
         // args should overwrite whatever is in the config
@@ -132,10 +129,9 @@ public class EvilLoggerConfigurationTests extends ESTestCase {
     public void testHierarchy() throws Exception {
         final Path configDir = getDataPath("hierarchy");
         final Settings settings = Settings.builder()
-                .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath())
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
                 .build();
-        final Environment environment = new Environment(settings);
+        final Environment environment = new Environment(settings, configDir);
         LogConfigurator.configure(environment);
 
         assertThat(ESLoggerFactory.getLogger("x").getLevel(), equalTo(Level.TRACE));
@@ -151,10 +147,9 @@ public class EvilLoggerConfigurationTests extends ESTestCase {
     public void testMissingConfigFile() {
         final Path configDir = getDataPath("does_not_exist");
         final Settings settings = Settings.builder()
-            .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath())
             .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
             .build();
-        final Environment environment = new Environment(settings);
+        final Environment environment = new Environment(settings, configDir);
         UserException e = expectThrows(UserException.class, () -> LogConfigurator.configure(environment));
         assertThat(e, hasToString(containsString("no log4j2.properties found; tried")));
     }
@@ -165,13 +160,12 @@ public class EvilLoggerConfigurationTests extends ESTestCase {
         final Level barLevel = randomFrom(Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR);
         final Path configDir = getDataPath("minimal");
         final Settings settings = Settings.builder()
-            .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath())
             .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
             .put("logger.level", rootLevel.name())
             .put("logger.foo", fooLevel.name())
             .put("logger.bar", barLevel.name())
             .build();
-        final Environment environment = new Environment(settings);
+        final Environment environment = new Environment(settings, configDir);
         LogConfigurator.configure(environment);
 
         final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);

+ 2 - 4
qa/evil-tests/src/test/java/org/elasticsearch/common/logging/EvilLoggerTests.java

@@ -194,16 +194,14 @@ public class EvilLoggerTests extends ESTestCase {
     }
 
     private void setupLogging(final String config, final Settings settings) throws IOException, UserException {
-        assert !Environment.PATH_CONF_SETTING.exists(settings);
         assert !Environment.PATH_HOME_SETTING.exists(settings);
         final Path configDir = getDataPath(config);
-        // need to set custom path.conf so we can use a custom log4j2.properties file for the test
         final Settings mergedSettings = Settings.builder()
             .put(settings)
-            .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath())
             .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
             .build();
-        final Environment environment = new Environment(mergedSettings);
+        // need to use custom config path so we can use a custom log4j2.properties file for the test
+        final Environment environment = new Environment(mergedSettings, configDir);
         LogConfigurator.configure(environment);
     }
 

+ 8 - 11
qa/evil-tests/src/test/java/org/elasticsearch/tribe/TribeUnitTests.java

@@ -58,7 +58,6 @@ public class TribeUnitTests extends ESTestCase {
     private static Node tribe1;
     private static Node tribe2;
 
-
     @BeforeClass
     public static void createTribes() throws NodeValidationException {
         Settings baseSettings = Settings.builder()
@@ -93,25 +92,22 @@ public class TribeUnitTests extends ESTestCase {
     }
 
     public void testThatTribeClientsIgnoreGlobalConfig() throws Exception {
-        Path pathConf = getDataPath("elasticsearch.yml").getParent();
-        Settings settings = Settings
-            .builder()
-            .put(Environment.PATH_CONF_SETTING.getKey(), pathConf)
-            .build();
-        assertTribeNodeSuccessfullyCreated(settings);
+        assertTribeNodeSuccessfullyCreated(getDataPath("elasticsearch.yml").getParent());
         assertWarnings("tribe nodes are deprecated in favor of cross-cluster search and will be removed in Elasticsearch 7.0.0");
     }
 
-    private static void assertTribeNodeSuccessfullyCreated(Settings extraSettings) throws Exception {
-        //The tribe clients do need it to make sure they can find their corresponding tribes using the proper transport
+    private static void assertTribeNodeSuccessfullyCreated(Path configPath) throws Exception {
+        // the tribe clients do need it to make sure they can find their corresponding tribes using the proper transport
         Settings settings = Settings.builder().put(NetworkModule.HTTP_ENABLED.getKey(), false).put("node.name", "tribe_node")
                 .put("transport.type", MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME).put("discovery.type", "local")
                 .put("tribe.t1.transport.type", MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME)
                 .put("tribe.t2.transport.type",MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME)
                 .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
-                .put(extraSettings).build();
+                .build();
 
-        try (Node node = new MockNode(settings, Arrays.asList(MockTcpTransportPlugin.class, TestZenDiscovery.TestPlugin.class)).start()) {
+        final List<Class<? extends Plugin>> classpathPlugins =
+                Arrays.asList(MockTcpTransportPlugin.class, TestZenDiscovery.TestPlugin.class);
+        try (Node node = new MockNode(settings, classpathPlugins, configPath).start()) {
             try (Client client = node.client()) {
                 assertBusy(() -> {
                     ClusterState state = client.admin().cluster().prepareState().clear().setNodes(true).get().getState();
@@ -125,4 +121,5 @@ public class TribeUnitTests extends ESTestCase {
             }
         }
     }
+
 }

+ 1 - 1
qa/vagrant/src/test/resources/packaging/utils/utils.bash

@@ -348,7 +348,7 @@ run_elasticsearch_service() {
             local CONF_DIR=""
             local ES_PATH_CONF=""
         else
-            local ES_PATH_CONF="-Epath.conf=$CONF_DIR"
+            local ES_PATH_CONF="--path.conf $CONF_DIR"
         fi
         # we must capture the exit code to compare so we don't want to start as background process in case we expect something other than 0
         local background=""

+ 3 - 5
test/framework/src/main/java/org/elasticsearch/bootstrap/ESElasticsearchCliTestCase.java

@@ -50,11 +50,9 @@ abstract class ESElasticsearchCliTestCase extends ESTestCase {
             final AtomicBoolean init = new AtomicBoolean();
             final int status = Elasticsearch.main(args, new Elasticsearch() {
                 @Override
-                protected Environment createEnv(Terminal terminal, Map<String, String> settings) {
-                    Settings realSettings = Settings.builder()
-                        .put("path.home", home)
-                        .put(settings).build();
-                    return new Environment(realSettings);
+                protected Environment createEnv(Terminal terminal, Map<String, String> settings, Path configPath) {
+                    final Settings realSettings = Settings.builder().put("path.home", home).put(settings).build();
+                    return new Environment(realSettings, configPath);
                 }
                 @Override
                 void init(final boolean daemonize, final Path pidFile, final boolean quiet, Environment initialEnv) {

+ 21 - 13
test/framework/src/main/java/org/elasticsearch/index/analysis/AnalysisTestsHelper.java

@@ -35,9 +35,8 @@ import java.util.Arrays;
 
 public class AnalysisTestsHelper {
 
-    public static ESTestCase.TestAnalysis createTestAnalysisFromClassPath(Path baseDir,
-            String resource) throws IOException {
-        Settings settings = Settings.builder()
+    public static ESTestCase.TestAnalysis createTestAnalysisFromClassPath(final Path baseDir, final String resource) throws IOException {
+        final Settings settings = Settings.builder()
                 .loadFromStream(resource, AnalysisTestsHelper.class.getResourceAsStream(resource))
                 .put(Environment.PATH_HOME_SETTING.getKey(), baseDir.toString())
                 .build();
@@ -46,18 +45,27 @@ public class AnalysisTestsHelper {
     }
 
     public static ESTestCase.TestAnalysis createTestAnalysisFromSettings(
-            Settings settings, AnalysisPlugin... plugins) throws IOException {
+            final Settings settings, final AnalysisPlugin... plugins) throws IOException {
+        return createTestAnalysisFromSettings(settings, null, plugins);
+    }
+
+    public static ESTestCase.TestAnalysis createTestAnalysisFromSettings(
+            final Settings settings,
+            final Path configPath,
+            final AnalysisPlugin... plugins) throws IOException {
+        final Settings actualSettings;
         if (settings.get(IndexMetaData.SETTING_VERSION_CREATED) == null) {
-            settings = Settings.builder().put(settings)
-                    .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
+            actualSettings = Settings.builder().put(settings).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
+        } else {
+            actualSettings = settings;
         }
-        IndexSettings indexSettings = IndexSettingsModule.newIndexSettings("test", settings);
-        AnalysisRegistry analysisRegistry =
-                new AnalysisModule(new Environment(settings), Arrays.asList(plugins))
-                .getAnalysisRegistry();
+        final IndexSettings indexSettings = IndexSettingsModule.newIndexSettings("test", actualSettings);
+        final AnalysisRegistry analysisRegistry =
+                new AnalysisModule(new Environment(actualSettings, configPath), Arrays.asList(plugins)).getAnalysisRegistry();
         return new ESTestCase.TestAnalysis(analysisRegistry.build(indexSettings),
-            analysisRegistry.buildTokenFilterFactories(indexSettings),
-            analysisRegistry.buildTokenizerFactories(indexSettings),
-            analysisRegistry.buildCharFilterFactories(indexSettings));
+                analysisRegistry.buildTokenFilterFactories(indexSettings),
+                analysisRegistry.buildTokenizerFactories(indexSettings),
+                analysisRegistry.buildCharFilterFactories(indexSettings));
     }
+
 }

+ 10 - 3
test/framework/src/main/java/org/elasticsearch/node/MockNode.java

@@ -37,13 +37,16 @@ import org.elasticsearch.script.ScriptService;
 import org.elasticsearch.search.MockSearchService;
 import org.elasticsearch.search.SearchService;
 import org.elasticsearch.search.fetch.FetchPhase;
+import org.elasticsearch.test.InternalSettingsPlugin;
 import org.elasticsearch.test.transport.MockTransportService;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.Transport;
 import org.elasticsearch.transport.TransportInterceptor;
 import org.elasticsearch.transport.TransportService;
 
+import java.nio.file.Path;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.function.Function;
 
 /**
@@ -57,7 +60,11 @@ public class MockNode extends Node {
     private final Collection<Class<? extends Plugin>> classpathPlugins;
 
     public MockNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
-        super(InternalSettingsPreparer.prepareEnvironment(settings, null), classpathPlugins);
+        this(settings, classpathPlugins, null);
+    }
+
+    public MockNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins, Path configPath) {
+        super(InternalSettingsPreparer.prepareEnvironment(settings, null, Collections.emptyMap(), configPath), classpathPlugins);
         this.classpathPlugins = classpathPlugins;
     }
 
@@ -104,8 +111,8 @@ public class MockNode extends Node {
     }
 
     @Override
-    protected Node newTribeClientNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
-        return new MockNode(settings, classpathPlugins);
+    protected Node newTribeClientNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins, Path configPath) {
+        return new MockNode(settings, classpathPlugins, configPath);
     }
 
     @Override

+ 1 - 1
test/framework/src/main/java/org/elasticsearch/search/aggregations/BaseAggregationTestCase.java

@@ -85,7 +85,7 @@ public abstract class BaseAggregationTestCase<AB extends AbstractAggregationBuil
             .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
             .build();
         IndicesModule indicesModule = new IndicesModule(Collections.emptyList());
-        PluginsService pluginsService = new PluginsService(settings, null, null, getPlugins());
+        PluginsService pluginsService = new PluginsService(settings, null, null, null, getPlugins());
         SearchModule searchModule = new SearchModule(settings, false, pluginsService.filterPlugins(SearchPlugin.class));
         List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
         entries.addAll(indicesModule.getNamedWriteables());

+ 2 - 1
test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java

@@ -1007,7 +1007,8 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
         ServiceHolder(Settings nodeSettings, Settings indexSettings,
                       Collection<Class<? extends Plugin>> plugins, AbstractQueryTestCase<?> testCase) throws IOException {
             Environment env = InternalSettingsPreparer.prepareEnvironment(nodeSettings, null);
-            PluginsService pluginsService = new PluginsService(nodeSettings, env.modulesFile(), env.pluginsFile(), plugins);
+            PluginsService pluginsService;
+            pluginsService = new PluginsService(nodeSettings, null, env.modulesFile(), env.pluginsFile(), plugins);
 
             client = (Client) Proxy.newProxyInstance(
                     Client.class.getClassLoader(),

+ 9 - 4
test/framework/src/main/java/org/elasticsearch/test/ESIntegTestCase.java

@@ -1731,6 +1731,10 @@ public abstract class ESIntegTestCase extends ESTestCase {
         return builder.build();
     }
 
+    protected Path nodeConfigPath(int nodeOrdinal) {
+        return null;
+    }
+
     /**
      * Returns a collection of plugins that should be loaded on each node.
      */
@@ -1839,6 +1843,11 @@ public abstract class ESIntegTestCase extends ESTestCase {
                         put(ESIntegTestCase.this.nodeSettings(nodeOrdinal)).build();
             }
 
+            @Override
+            public Path nodeConfigPath(int nodeOrdinal) {
+                return ESIntegTestCase.this.nodeConfigPath(nodeOrdinal);
+            }
+
             @Override
             public Collection<Class<? extends Plugin>> nodePlugins() {
                 return ESIntegTestCase.this.nodePlugins();
@@ -2153,10 +2162,6 @@ public abstract class ESIntegTestCase extends ESTestCase {
             .put(settings)
             .put(Environment.PATH_DATA_SETTING.getKey(), dataDir.toAbsolutePath());
 
-        Path configDir = indexDir.resolve("config");
-        if (Files.exists(configDir)) {
-            builder.put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath());
-        }
         return builder.build();
     }
 

+ 1 - 1
test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java

@@ -608,7 +608,7 @@ public final class InternalTestCluster extends TestCluster {
             throw new IllegalArgumentException(DISCOVERY_ZEN_MINIMUM_MASTER_NODES_SETTING.getKey() + " must be configured");
         }
         SecureSettings secureSettings = finalSettings.getSecureSettings();
-        MockNode node = new MockNode(finalSettings.build(), plugins);
+        MockNode node = new MockNode(finalSettings.build(), plugins, nodeConfigurationSource.nodeConfigPath(nodeId));
         try {
             IOUtils.close(secureSettings);
         } catch (IOException e) {

+ 8 - 0
test/framework/src/main/java/org/elasticsearch/test/NodeConfigurationSource.java

@@ -21,6 +21,7 @@ package org.elasticsearch.test;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.plugins.Plugin;
 
+import java.nio.file.Path;
 import java.util.Collection;
 import java.util.Collections;
 
@@ -32,6 +33,11 @@ public abstract class NodeConfigurationSource {
             return Settings.EMPTY;
         }
 
+        @Override
+        public Path nodeConfigPath(int nodeOrdinal) {
+            return null;
+        }
+
         @Override
         public Settings transportClientSettings() {
             return Settings.EMPTY;
@@ -43,6 +49,8 @@ public abstract class NodeConfigurationSource {
      */
     public abstract Settings nodeSettings(int nodeOrdinal);
 
+    public abstract Path nodeConfigPath(int nodeOrdinal);
+
     /** Returns plugins that should be loaded on the node */
     public Collection<Class<? extends Plugin>> nodePlugins() {
         return Collections.emptyList();

+ 6 - 0
test/framework/src/main/java/org/elasticsearch/test/discovery/ClusterDiscoveryConfiguration.java

@@ -34,6 +34,7 @@ import org.elasticsearch.transport.TransportSettings;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
+import java.nio.file.Path;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -57,6 +58,11 @@ public class ClusterDiscoveryConfiguration extends NodeConfigurationSource {
         return nodeSettings;
     }
 
+    @Override
+    public Path nodeConfigPath(int nodeOrdinal) {
+        return null;
+    }
+
     @Override
     public Settings transportClientSettings() {
         return transportClientSettings;

+ 31 - 10
test/framework/src/test/java/org/elasticsearch/test/test/InternalTestClusterTests.java

@@ -193,6 +193,11 @@ public class InternalTestClusterTests extends ESTestCase {
                 return settings.build();
             }
 
+            @Override
+            public Path nodeConfigPath(int nodeOrdinal) {
+                return null;
+            }
+
             @Override
             public Settings transportClientSettings() {
                 return Settings.builder()
@@ -258,6 +263,12 @@ public class InternalTestClusterTests extends ESTestCase {
                     .put(NetworkModule.TRANSPORT_TYPE_KEY, MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME)
                     .build();
             }
+
+            @Override
+            public Path nodeConfigPath(int nodeOrdinal) {
+                return null;
+            }
+
             @Override
             public Settings transportClientSettings() {
                 return Settings.builder()
@@ -350,10 +361,10 @@ public class InternalTestClusterTests extends ESTestCase {
         final Path baseDir = createTempDir();
         final int numNodes = 5;
         InternalTestCluster cluster = new InternalTestCluster(randomLong(), baseDir, false,
-            false, 0, 0, "test", new NodeConfigurationSource() {
-                @Override
-                public Settings nodeSettings(int nodeOrdinal) {
-                    return Settings.builder()
+                false, 0, 0, "test", new NodeConfigurationSource() {
+            @Override
+            public Settings nodeSettings(int nodeOrdinal) {
+                return Settings.builder()
                         .put(NodeEnvironment.MAX_LOCAL_STORAGE_NODES_SETTING.getKey(), numNodes)
                         .put(NetworkModule.HTTP_ENABLED.getKey(), false)
                         .put(NetworkModule.TRANSPORT_TYPE_KEY, MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME)
@@ -362,14 +373,19 @@ public class InternalTestClusterTests extends ESTestCase {
                         // elections more likely
                         .put(ZenDiscovery.JOIN_TIMEOUT_SETTING.getKey(), "3s")
                         .build();
-                }
+            }
 
-                @Override
-                public Settings transportClientSettings() {
-                    return Settings.builder()
+            @Override
+            public Path nodeConfigPath(int nodeOrdinal) {
+                return null;
+            }
+
+            @Override
+            public Settings transportClientSettings() {
+                return Settings.builder()
                         .put(NetworkModule.TRANSPORT_TYPE_KEY, MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME).build();
-                }
-            }, 0, randomBoolean(), "", Arrays.asList(MockTcpTransportPlugin.class, TestZenDiscovery.TestPlugin.class), Function.identity());
+            }
+        }, 0, randomBoolean(), "", Arrays.asList(MockTcpTransportPlugin.class, TestZenDiscovery.TestPlugin.class), Function.identity());
         cluster.beforeTest(random(), 0.0);
         List<DiscoveryNode.Role> roles = new ArrayList<>();
         for (int i = 0; i < numNodes; i++) {
@@ -440,6 +456,11 @@ public class InternalTestClusterTests extends ESTestCase {
                     .build();
             }
 
+            @Override
+            public Path nodeConfigPath(int nodeOrdinal) {
+                return null;
+            }
+
             @Override
             public Settings transportClientSettings() {
                 return Settings.builder()