]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9590 add EsFileSystem class
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 22 Aug 2017 09:03:54 +0000 (11:03 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 5 Sep 2017 12:24:12 +0000 (14:24 +0200)
server/sonar-main/src/main/java/org/sonar/application/process/ProcessLauncherImpl.java
server/sonar-process/src/main/java/org/sonar/process/command/CommandFactoryImpl.java
server/sonar-process/src/main/java/org/sonar/process/command/EsCommand.java
server/sonar-process/src/main/java/org/sonar/process/es/EsFileSystem.java [new file with mode: 0644]
server/sonar-process/src/main/java/org/sonar/process/es/EsSettings.java
server/sonar-process/src/test/java/org/sonar/process/es/EsFileSystemTest.java [new file with mode: 0644]
server/sonar-process/src/test/java/org/sonar/process/es/EsSettingsTest.java

index 549e4ddfe4eda9e18fe168248d8e47c7232788b3..76576b6d235d8a0d27c971bd5726f134790e06bd 100644 (file)
@@ -36,6 +36,7 @@ import org.sonar.process.ProcessId;
 import org.sonar.process.command.AbstractCommand;
 import org.sonar.process.command.EsCommand;
 import org.sonar.process.command.JavaCommand;
+import org.sonar.process.es.EsFileSystem;
 import org.sonar.process.jmvoptions.JvmOptions;
 import org.sonar.process.sharedmemoryfile.AllProcessesCommands;
 import org.sonar.process.sharedmemoryfile.ProcessCommands;
@@ -90,7 +91,8 @@ public class ProcessLauncherImpl implements ProcessLauncher {
   }
 
   private void writeConfFiles(EsCommand esCommand) {
-    File confDir = esCommand.getConfDir();
+    EsFileSystem esFileSystem = esCommand.getFileSystem();
+    File confDir = esFileSystem.getConfDirectory();
     if (!confDir.exists() && !confDir.mkdirs()) {
       String error = format("Failed to create temporary configuration directory [%s]", confDir.getAbsolutePath());
       LOG.error(error);
@@ -98,9 +100,9 @@ public class ProcessLauncherImpl implements ProcessLauncher {
     }
 
     try {
-      IOUtils.copy(getClass().getResourceAsStream("elasticsearch.yml"), new FileOutputStream(new File(confDir, "elasticsearch.yml")));
-      esCommand.getEsJvmOptions().writeToJvmOptionFile(new File(confDir, "jvm.options"));
-      esCommand.getLog4j2Properties().store(new FileOutputStream(new File(confDir, "log4j2.properties")), "log42 properties file for ES bundled in SonarQube");
+      IOUtils.copy(getClass().getResourceAsStream("elasticsearch.yml"), new FileOutputStream(esFileSystem.getElasticsearchYml()));
+      esCommand.getEsJvmOptions().writeToJvmOptionFile(esFileSystem.getJvmOptions());
+      esCommand.getLog4j2Properties().store(new FileOutputStream(esFileSystem.getLog4j2Properties()), "log4j2 properties file for ES bundled in SonarQube");
     } catch (IOException e) {
       throw new IllegalStateException("Failed to write ES configuration files", e);
     }
@@ -137,7 +139,7 @@ public class ProcessLauncherImpl implements ProcessLauncher {
 
   private ProcessBuilder create(EsCommand esCommand) {
     List<String> commands = new ArrayList<>();
-    commands.add(esCommand.getExecutable().getAbsolutePath());
+    commands.add(esCommand.getFileSystem().getExecutable().getAbsolutePath());
     commands.addAll(esCommand.getEsOptions());
 
     return create(esCommand, commands);
index 987ea7cb23245c49e791aa8c399b017f0ec00923..7b96a5972bd6e3c103e291380ce479e6df314930 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Optional;
 import org.sonar.process.ProcessId;
 import org.sonar.process.ProcessProperties;
 import org.sonar.process.Props;
+import org.sonar.process.es.EsFileSystem;
 import org.sonar.process.es.EsLogging;
 import org.sonar.process.es.EsSettings;
 import org.sonar.process.jmvoptions.CeJvmOptions;
@@ -61,20 +62,15 @@ public class CommandFactoryImpl implements CommandFactory {
 
   @Override
   public EsCommand createEsCommand() {
-    File homeDir = props.nonNullValueAsFile(ProcessProperties.PATH_HOME);
-    File executable = new File(homeDir, getExecutable());
-    if (!executable.exists()) {
+    EsFileSystem esFileSystem = new EsFileSystem(props);
+    if (!esFileSystem.getExecutable().exists()) {
       throw new IllegalStateException("Cannot find elasticsearch binary");
     }
+    Map<String, String> settingsMap = new EsSettings(props, esFileSystem).build();
 
-    Map<String, String> settingsMap = new EsSettings(props).build();
-
-    File logDir = new File(settingsMap.get("path.logs"));
-    File confDir = new File(settingsMap.get("path.conf"));
-    EsCommand res = new EsCommand(ProcessId.ELASTICSEARCH, executable.getParentFile().getParentFile())
-      .setExecutable(executable)
-      .setConfDir(confDir)
-      .setLog4j2Properties(new EsLogging().createProperties(props, logDir))
+    EsCommand res = new EsCommand(ProcessId.ELASTICSEARCH, esFileSystem.getHomeDirectory())
+      .setFileSystem(esFileSystem)
+      .setLog4j2Properties(new EsLogging().createProperties(props, esFileSystem.getLogDirectory()))
       .setArguments(props.rawProperties())
       .setClusterName(settingsMap.get("cluster.name"))
       .setHost(settingsMap.get("network.host"))
@@ -89,13 +85,6 @@ public class CommandFactoryImpl implements CommandFactory {
     return res;
   }
 
-  private static String getExecutable() {
-    if (System.getProperty("os.name").startsWith("Windows")) {
-      return "elasticsearch/bin/elasticsearch.bat";
-    }
-    return "elasticsearch/bin/elasticsearch";
-  }
-
   @Override
   public JavaCommand createWebCommand(boolean leader) {
     File homeDir = props.nonNullValueAsFile(ProcessProperties.PATH_HOME);
index 6f1d374d77011d03c658101548ec7fff0d151f8d..7b2efefcb2661b3667ba779dcf0d3bb16ec956ba 100644 (file)
@@ -24,11 +24,11 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 import org.sonar.process.ProcessId;
+import org.sonar.process.es.EsFileSystem;
 import org.sonar.process.jmvoptions.EsJvmOptions;
 
 public class EsCommand extends AbstractCommand<EsCommand> {
-  private File executable;
-  private File confDir;
+  private EsFileSystem fileSystem;
   private String clusterName;
   private String host;
   private int port;
@@ -40,21 +40,12 @@ public class EsCommand extends AbstractCommand<EsCommand> {
     super(id, workDir);
   }
 
-  public File getExecutable() {
-    return executable;
+  public EsFileSystem getFileSystem() {
+    return fileSystem;
   }
 
-  public EsCommand setExecutable(File executable) {
-    this.executable = executable;
-    return this;
-  }
-
-  public File getConfDir() {
-    return confDir;
-  }
-
-  public EsCommand setConfDir(File confDir) {
-    this.confDir = confDir;
+  public EsCommand setFileSystem(EsFileSystem fileSystem) {
+    this.fileSystem = fileSystem;
     return this;
   }
 
diff --git a/server/sonar-process/src/main/java/org/sonar/process/es/EsFileSystem.java b/server/sonar-process/src/main/java/org/sonar/process/es/EsFileSystem.java
new file mode 100644 (file)
index 0000000..d8fc7c0
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.process.es;
+
+import java.io.File;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.process.ProcessProperties;
+import org.sonar.process.Props;
+
+/**
+ * Holds {@link File} to the various directories of ElasticSearch distribution embedded in SonarQube and provides
+ * {@link File} objects to the various files of it SonarQube cares about.
+ *
+ * <p>
+ * This class does not ensure files nor directories actually exist.
+ * </p>
+ */
+public class EsFileSystem {
+  private final File homeDirectory;
+  private final File dataDirectory;
+  private final File confDirectory;
+  private final File logDirectory;
+
+  public EsFileSystem(Props props) {
+    File sqHomeDir = props.nonNullValueAsFile(ProcessProperties.PATH_HOME);
+
+    this.homeDirectory = new File(sqHomeDir, "elasticsearch");
+    this.dataDirectory = buildDataDir(props, sqHomeDir);
+    this.confDirectory = buildConfDir(props);
+    this.logDirectory = buildLogPath(props, sqHomeDir);
+  }
+
+  private static File buildDataDir(Props props, File sqHomeDir) {
+    String dataPath = props.value(ProcessProperties.PATH_DATA);
+    if (StringUtils.isNotEmpty(dataPath)) {
+      return new File(dataPath, "es");
+    }
+    return new File(sqHomeDir, "data/es");
+  }
+
+  private static File buildLogPath(Props props, File sqHomeDir) {
+    String logPath = props.value(ProcessProperties.PATH_LOGS);
+    if (StringUtils.isNotEmpty(logPath)) {
+      return new File(logPath);
+    }
+    return new File(sqHomeDir, "log");
+  }
+
+  private static File buildConfDir(Props props) {
+    File tempPath = props.nonNullValueAsFile(ProcessProperties.PATH_TEMP);
+    return new File(new File(tempPath, "conf"), "es");
+  }
+
+  public File getHomeDirectory() {
+    return homeDirectory;
+  }
+
+  public File getDataDirectory() {
+    return dataDirectory;
+  }
+
+  public File getConfDirectory() {
+    return confDirectory;
+  }
+
+  public File getLogDirectory() {
+    return logDirectory;
+  }
+
+  public File getExecutable() {
+    return new File(homeDirectory, "bin/" + getExecutableName());
+  }
+
+  private static String getExecutableName() {
+    if (System.getProperty("os.name").startsWith("Windows")) {
+      return "elasticsearch.bat";
+    }
+    return "elasticsearch";
+  }
+
+  public File getLog4j2Properties() {
+    return new File(confDirectory, "log4j2.properties");
+  }
+
+  public File getElasticsearchYml() {
+    return new File(confDirectory, "elasticsearch.yml");
+  }
+
+  public File getJvmOptions() {
+    return new File(confDirectory, "jvm.options");
+  }
+}
index ae58355415b541aec3238b33d76c27e144989ce4..4761bc306389b23d3b35c2feb7f9468fcb6e9d8c 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.process.es;
 
-import java.io.File;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
@@ -44,13 +43,15 @@ public class EsSettings {
   private static final String STANDALONE_NODE_NAME = "sonarqube";
 
   private final Props props;
+  private final EsFileSystem fileSystem;
 
   private final boolean clusterEnabled;
   private final String clusterName;
   private final String nodeName;
 
-  public EsSettings(Props props) {
+  public EsSettings(Props props, EsFileSystem fileSystem) {
     this.props = props;
+    this.fileSystem = fileSystem;
 
     this.clusterName = props.nonNullValue(ProcessProperties.CLUSTER_NAME);
     this.clusterEnabled = props.valueAsBoolean(ProcessProperties.CLUSTER_ENABLED);
@@ -72,32 +73,9 @@ public class EsSettings {
   }
 
   private void configureFileSystem(Map<String, String> builder) {
-    File homeDir = props.nonNullValueAsFile(ProcessProperties.PATH_HOME);
-
-    builder.put("path.data", buildDataPath(homeDir).getAbsolutePath());
-    builder.put("path.conf", buildConfDir().getAbsolutePath());
-    builder.put("path.logs", buildLogPath(homeDir).getAbsolutePath());
-  }
-
-  private File buildDataPath(File homeDir) {
-    String dataPath = props.value(ProcessProperties.PATH_DATA);
-    if (StringUtils.isNotEmpty(dataPath)) {
-      return new File(dataPath, "es");
-    }
-    return new File(homeDir, "data/es");
-  }
-
-  private File buildLogPath(File homeDir) {
-    String logPath = props.value(ProcessProperties.PATH_LOGS);
-    if (StringUtils.isNotEmpty(logPath)) {
-      return new File(logPath);
-    }
-    return new File(homeDir, "log");
-  }
-
-  private File buildConfDir() {
-    String tempPath = props.value(ProcessProperties.PATH_TEMP);
-    return new File(new File(tempPath, "conf"), "es");
+    builder.put("path.data", fileSystem.getDataDirectory().getAbsolutePath());
+    builder.put("path.conf", fileSystem.getConfDirectory().getAbsolutePath());
+    builder.put("path.logs", fileSystem.getLogDirectory().getAbsolutePath());
   }
 
   private void configureNetwork(Map<String, String> builder) {
diff --git a/server/sonar-process/src/test/java/org/sonar/process/es/EsFileSystemTest.java b/server/sonar-process/src/test/java/org/sonar/process/es/EsFileSystemTest.java
new file mode 100644 (file)
index 0000000..c2bf6e7
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.process.es;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.process.ProcessProperties;
+import org.sonar.process.Props;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EsFileSystemTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void constructor_fails_with_IAE_if_sq_home_property_is_not_defined() {
+    Props props = new Props(new Properties());
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Property sonar.path.home is not set");
+
+    new EsFileSystem(props);
+  }
+
+  @Test
+  public void constructor_fails_with_IAE_if_temp_dir_property_is_not_defined() throws IOException {
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, temp.newFolder().getAbsolutePath());
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Property sonar.path.temp is not set");
+
+    new EsFileSystem(props);
+  }
+
+  @Test
+  public void getHomeDirectory_is_elasticsearch_subdirectory_of_sq_home_directory() throws IOException {
+    File sqHomeDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, sqHomeDir.getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, temp.newFolder().getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getHomeDirectory()).isEqualTo(new File(sqHomeDir, "elasticsearch"));
+  }
+
+  @Test
+  public void getDataDirectory_is_data_es_subdirectory_of_sq_home_directory_by_default() throws IOException {
+    File sqHomeDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, sqHomeDir.getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, temp.newFolder().getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getDataDirectory()).isEqualTo(new File(sqHomeDir, "data/es"));
+  }
+
+  @Test
+  public void override_data_dir() throws Exception {
+    File sqHomeDir = temp.newFolder();
+    File tempDir = temp.newFolder();
+    File dataDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, sqHomeDir.getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, tempDir.getAbsolutePath());
+
+    props.set(ProcessProperties.PATH_DATA, dataDir.getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getDataDirectory()).isEqualTo(new File(dataDir, "es"));
+  }
+
+  @Test
+  public void getLogDirectory_is_log_subdirectory_of_sq_home_directory_by_default() throws IOException {
+    File sqHomeDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, sqHomeDir.getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, temp.newFolder().getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getLogDirectory()).isEqualTo(new File(sqHomeDir, "log"));
+  }
+
+  @Test
+  public void override_log_dir() throws Exception {
+    File sqHomeDir = temp.newFolder();
+    File tempDir = temp.newFolder();
+    File logDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, sqHomeDir.getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, tempDir.getAbsolutePath());
+
+    props.set(ProcessProperties.PATH_LOGS, logDir.getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getDataDirectory()).isEqualTo(new File(sqHomeDir, "data/es"));
+  }
+
+  @Test
+  public void conf_directory_is_conf_es_subdirectory_of_sq_temp_directory() throws IOException {
+    File tempDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, temp.newFolder().getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, tempDir.getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getConfDirectory()).isEqualTo(new File(tempDir, "conf/es"));
+  }
+
+  @Test
+  public void getExecutable_resolve_executable_for_platform() throws IOException {
+    File sqHomeDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, sqHomeDir.getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, temp.newFolder().getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    if (System.getProperty("os.name").startsWith("Windows")) {
+      assertThat(underTest.getExecutable()).isEqualTo(new File(sqHomeDir, "elasticsearch/bin/elasticsearch.bat"));
+    } else {
+      assertThat(underTest.getExecutable()).isEqualTo(new File(sqHomeDir, "elasticsearch/bin/elasticsearch"));
+    }
+  }
+
+  @Test
+  public void getLog4j2Properties_is_in_es_conf_directory() throws IOException {
+    File tempDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, temp.newFolder().getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, tempDir.getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getLog4j2Properties()).isEqualTo(new File(tempDir, "conf/es/log4j2.properties"));
+  }
+
+  @Test
+  public void getElasticsearchYml_is_in_es_conf_directory() throws IOException {
+    File tempDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, temp.newFolder().getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, tempDir.getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getElasticsearchYml()).isEqualTo(new File(tempDir, "conf/es/elasticsearch.yml"));
+  }
+
+  @Test
+  public void getJvmOptions_is_in_es_conf_directory() throws IOException {
+    File tempDir = temp.newFolder();
+    Props props = new Props(new Properties());
+    props.set(ProcessProperties.PATH_HOME, temp.newFolder().getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, tempDir.getAbsolutePath());
+
+    EsFileSystem underTest = new EsFileSystem(props);
+
+    assertThat(underTest.getJvmOptions()).isEqualTo(new File(tempDir, "conf/es/jvm.options"));
+  }
+}
index f58ce46b6e3444ab693dff4bd58f8c4c0b05dcf6..673a849ae5c5c3c97cd58d756c9079147439a2d3 100644 (file)
@@ -23,6 +23,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Random;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -31,12 +32,14 @@ import org.sonar.process.ProcessProperties;
 import org.sonar.process.Props;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class EsSettingsTest {
 
   private static final boolean CLUSTER_ENABLED = true;
   private static final boolean CLUSTER_DISABLED = false;
-  
+
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
@@ -50,9 +53,10 @@ public class EsSettingsTest {
     props.set(ProcessProperties.SEARCH_PORT, "1234");
     props.set(ProcessProperties.SEARCH_HOST, "127.0.0.1");
     props.set(ProcessProperties.PATH_HOME, homeDir.getAbsolutePath());
+    props.set(ProcessProperties.PATH_TEMP, temp.newFolder().getAbsolutePath());
     props.set(ProcessProperties.CLUSTER_NAME, "sonarqube");
 
-    EsSettings esSettings = new EsSettings(props);
+    EsSettings esSettings = new EsSettings(props, new EsFileSystem(props));
 
     Map<String, String> generated = esSettings.build();
     assertThat(generated.get("transport.tcp.port")).isEqualTo("1234");
@@ -78,28 +82,26 @@ public class EsSettingsTest {
   }
 
   @Test
-  public void override_dirs() throws Exception {
-    File dataDir = temp.newFolder();
-    File logDir = temp.newFolder();
-    File tempDir = temp.newFolder();
-    Props props = minProps(CLUSTER_DISABLED);
-    props.set(ProcessProperties.PATH_DATA, dataDir.getAbsolutePath());
-    props.set(ProcessProperties.PATH_LOGS, logDir.getAbsolutePath());
-    props.set(ProcessProperties.PATH_TEMP, tempDir.getAbsolutePath());
-
-    Map<String, String> settings = new EsSettings(props).build();
-
-    assertThat(settings.get("path.data")).isEqualTo(new File(dataDir, "es").getAbsolutePath());
-    assertThat(settings.get("path.logs")).isEqualTo(logDir.getAbsolutePath());
-    assertThat(settings.get("path.home")).isNull();
-    assertThat(settings.get("path.conf")).isEqualTo(new File(tempDir, "conf/es").getAbsolutePath());
+  public void path_properties_are_values_from_EsFileSystem_argument() throws IOException {
+    EsFileSystem mockedEsFileSystem = mock(EsFileSystem.class);
+    when(mockedEsFileSystem.getHomeDirectory()).thenReturn(new File("/foo/home"));
+    when(mockedEsFileSystem.getConfDirectory()).thenReturn(new File("/foo/conf"));
+    when(mockedEsFileSystem.getLogDirectory()).thenReturn(new File("/foo/log"));
+    when(mockedEsFileSystem.getDataDirectory()).thenReturn(new File("/foo/data"));
+
+    EsSettings underTest = new EsSettings(minProps(new Random().nextBoolean()), mockedEsFileSystem);
+
+    Map<String, String> generated = underTest.build();
+    assertThat(generated.get("path.data")).isEqualTo("/foo/data");
+    assertThat(generated.get("path.logs")).isEqualTo("/foo/log");
+    assertThat(generated.get("path.conf")).isEqualTo("/foo/conf");
   }
 
   @Test
   public void set_discovery_settings_if_cluster_is_enabled() throws Exception {
     Props props = minProps(CLUSTER_ENABLED);
     props.set(ProcessProperties.CLUSTER_SEARCH_HOSTS, "1.2.3.4:9000,1.2.3.5:8080");
-    Map<String, String> settings = new EsSettings(props).build();
+    Map<String, String> settings = new EsSettings(props, new EsFileSystem(props)).build();
 
     assertThat(settings.get("discovery.zen.ping.unicast.hosts")).isEqualTo("1.2.3.4:9000,1.2.3.5:8080");
     assertThat(settings.get("discovery.zen.minimum_master_nodes")).isEqualTo("2");
@@ -111,7 +113,7 @@ public class EsSettingsTest {
     Props props = minProps(CLUSTER_ENABLED);
     props.set(ProcessProperties.SEARCH_MINIMUM_MASTER_NODES, "ꝱꝲꝳପ");
 
-    EsSettings underTest = new EsSettings(props);
+    EsSettings underTest = new EsSettings(props, new EsFileSystem(props));
 
     expectedException.expect(IllegalStateException.class);
     expectedException.expectMessage("Value of property sonar.search.minimumMasterNodes is not an integer:");
@@ -122,7 +124,7 @@ public class EsSettingsTest {
   public void cluster_is_enabled_with_defined_minimum_master_nodes() throws Exception {
     Props props = minProps(CLUSTER_ENABLED);
     props.set(ProcessProperties.SEARCH_MINIMUM_MASTER_NODES, "5");
-    Map<String, String> settings = new EsSettings(props).build();
+    Map<String, String> settings = new EsSettings(props, new EsFileSystem(props)).build();
 
     assertThat(settings.get("discovery.zen.minimum_master_nodes")).isEqualTo("5");
   }
@@ -131,7 +133,7 @@ public class EsSettingsTest {
   public void cluster_is_enabled_with_defined_initialTimeout() throws Exception {
     Props props = minProps(CLUSTER_ENABLED);
     props.set(ProcessProperties.SEARCH_INITIAL_STATE_TIMEOUT, "10s");
-    Map<String, String> settings = new EsSettings(props).build();
+    Map<String, String> settings = new EsSettings(props, new EsFileSystem(props)).build();
 
     assertThat(settings.get("discovery.initial_state_timeout")).isEqualTo("10s");
   }
@@ -140,7 +142,7 @@ public class EsSettingsTest {
   public void in_standalone_initialTimeout_is_not_overridable() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
     props.set(ProcessProperties.SEARCH_INITIAL_STATE_TIMEOUT, "10s");
-    Map<String, String> settings = new EsSettings(props).build();
+    Map<String, String> settings = new EsSettings(props, new EsFileSystem(props)).build();
 
     assertThat(settings.get("discovery.initial_state_timeout")).isEqualTo("30s");
   }
@@ -149,18 +151,16 @@ public class EsSettingsTest {
   public void in_standalone_minimumMasterNodes_is_not_overridable() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
     props.set(ProcessProperties.SEARCH_MINIMUM_MASTER_NODES, "5");
-    Map<String, String> settings = new EsSettings(props).build();
+    Map<String, String> settings = new EsSettings(props, new EsFileSystem(props)).build();
 
     assertThat(settings.get("discovery.zen.minimum_master_nodes")).isEqualTo("1");
   }
 
-
-
   @Test
   public void enable_marvel() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
     props.set("sonar.search.marvelHosts", "127.0.0.2,127.0.0.3");
-    Map<String, String> settings = new EsSettings(props).build();
+    Map<String, String> settings = new EsSettings(props, new EsFileSystem(props)).build();
 
     assertThat(settings.get("marvel.agent.exporter.es.hosts")).isEqualTo("127.0.0.2,127.0.0.3");
   }
@@ -169,7 +169,7 @@ public class EsSettingsTest {
   public void enable_http_connector() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
     props.set(ProcessProperties.SEARCH_HTTP_PORT, "9010");
-    Map<String, String> settings = new EsSettings(props).build();
+    Map<String, String> settings = new EsSettings(props, new EsFileSystem(props)).build();
 
     assertThat(settings.get("http.port")).isEqualTo("9010");
     assertThat(settings.get("http.host")).isEqualTo("127.0.0.1");
@@ -181,7 +181,7 @@ public class EsSettingsTest {
     Props props = minProps(CLUSTER_DISABLED);
     props.set(ProcessProperties.SEARCH_HTTP_PORT, "9010");
     props.set(ProcessProperties.SEARCH_HOST, "127.0.0.2");
-    Map<String, String> settings = new EsSettings(props).build();
+    Map<String, String> settings = new EsSettings(props, new EsFileSystem(props)).build();
 
     assertThat(settings.get("http.port")).isEqualTo("9010");
     assertThat(settings.get("http.host")).isEqualTo("127.0.0.2");