]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11792 use dedicated temp directory for ES
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 14 Mar 2019 17:38:20 +0000 (18:38 +0100)
committerSonarTech <sonartech@sonarsource.com>
Tue, 19 Mar 2019 19:21:26 +0000 (20:21 +0100)
server/sonar-main/src/main/java/org/sonar/application/command/CommandFactoryImpl.java
server/sonar-main/src/main/java/org/sonar/application/command/EsJvmOptions.java
server/sonar-main/src/main/java/org/sonar/application/es/EsInstallation.java
server/sonar-main/src/main/java/org/sonar/application/es/EsInstallationImpl.java [new file with mode: 0644]
server/sonar-main/src/main/java/org/sonar/application/process/ProcessLauncherImpl.java
server/sonar-main/src/test/java/org/sonar/application/command/CommandFactoryImplTest.java
server/sonar-main/src/test/java/org/sonar/application/command/EsJvmOptionsTest.java
server/sonar-main/src/test/java/org/sonar/application/es/EsInstallationTest.java
server/sonar-main/src/test/java/org/sonar/application/es/EsSettingsTest.java
server/sonar-main/src/test/java/org/sonar/application/process/ProcessLauncherImplTest.java

index 2afbc0310c9f4562063489054ca16e2bf2947066..5c93d060cd4fed076318397617a6b6b453f56e2b 100644 (file)
@@ -24,6 +24,7 @@ import java.util.Map;
 import java.util.Optional;
 import org.slf4j.LoggerFactory;
 import org.sonar.application.es.EsInstallation;
+import org.sonar.application.es.EsInstallationImpl;
 import org.sonar.application.es.EsLogging;
 import org.sonar.application.es.EsSettings;
 import org.sonar.application.es.EsYmlSettings;
@@ -112,7 +113,7 @@ public class CommandFactoryImpl implements CommandFactory {
     return new JavaCommand<EsJvmOptions>(ProcessId.ELASTICSEARCH, esInstallation.getHomeDirectory())
       .setEsInstallation(esInstallation)
       .setReadsArgumentsFromFile(false)
-      .setJvmOptions(new EsJvmOptions(tempDir)
+      .setJvmOptions(new EsJvmOptions(esInstallation)
         .addFromMandatoryProperty(props, SEARCH_JAVA_OPTS.getKey())
         .addFromMandatoryProperty(props, SEARCH_JAVA_ADDITIONAL_OPTS.getKey())
         .add("-Delasticsearch")
@@ -127,7 +128,7 @@ public class CommandFactoryImpl implements CommandFactory {
   }
 
   private EsInstallation createEsInstallation() {
-    EsInstallation esInstallation = new EsInstallation(props);
+    EsInstallationImpl esInstallation = new EsInstallationImpl(props);
     if (!esInstallation.getExecutable().exists()) {
       throw new IllegalStateException("Cannot find elasticsearch binary");
     }
@@ -135,7 +136,7 @@ public class CommandFactoryImpl implements CommandFactory {
 
     esInstallation
       .setLog4j2Properties(new EsLogging().createProperties(props, esInstallation.getLogDirectory()))
-      .setEsJvmOptions(new EsJvmOptions(tempDir)
+      .setEsJvmOptions(new EsJvmOptions(esInstallation)
         .addFromMandatoryProperty(props, SEARCH_JAVA_OPTS.getKey())
         .addFromMandatoryProperty(props, SEARCH_JAVA_ADDITIONAL_OPTS.getKey()))
       .setEsYmlSettings(new EsYmlSettings(settingsMap))
index 0b24606e27aee5411d21ce2533547d253cd7a980..01cf7db57253e55b6d75b8d0ed4be56220f98a9a 100644 (file)
@@ -26,6 +26,7 @@ import java.nio.file.Files;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.stream.Collectors;
+import org.sonar.application.es.EsInstallation;
 import org.sonar.process.System2;
 
 public class EsJvmOptions extends JvmOptions<EsJvmOptions> {
@@ -35,17 +36,17 @@ public class EsJvmOptions extends JvmOptions<EsJvmOptions> {
     "# DO NOT EDIT THIS FILE\n" +
     "\n";
 
-  public EsJvmOptions(File tmpDir) {
-    this(System2.INSTANCE, tmpDir);
+  public EsJvmOptions(EsInstallation esInstallation) {
+    this(System2.INSTANCE, esInstallation);
   }
 
-  EsJvmOptions(System2 system2, File tmpDir) {
-    super(mandatoryOptions(system2, tmpDir));
+  EsJvmOptions(System2 system2, EsInstallation esInstallation) {
+    super(mandatoryOptions(system2, esInstallation));
   }
 
   // this basically writes down the content of jvm.options file distributed in vanilla Elasticsearch package
   // with some changes to fit running bundled in SQ
-  private static Map<String, String> mandatoryOptions(System2 system2, File tmpDir) {
+  private static Map<String, String> mandatoryOptions(System2 system2, EsInstallation esInstallation) {
     Map<String, String> res = new LinkedHashMap<>(16);
     // GC configuration
     res.put("-XX:+UseConcMarkSweepGC", "");
@@ -91,7 +92,7 @@ public class EsJvmOptions extends JvmOptions<EsJvmOptions> {
 
     // (by default ES 6.6.1 uses variable ${ES_TMPDIR} which is replaced by start scripts. Since we start JAR file
     // directly on windows, we specify absolute file as URL (to support space in path) instead
-    res.put("-Djava.io.tmpdir=", tmpDir.getAbsolutePath());
+    res.put("-Djava.io.tmpdir=", esInstallation.getTmpDirectory().getAbsolutePath());
 
     // heap dumps (enable by default in ES 6.6.1, we don't enable them, no one will analyze them anyway)
     // generate a heap dump when an allocation from the Java heap fails
@@ -101,7 +102,7 @@ public class EsJvmOptions extends JvmOptions<EsJvmOptions> {
     // has sufficient space
     // res.put("-XX:HeapDumpPath", "data");
     // specify an alternative path for JVM fatal error logs (ES 6.6.1 default is "logs/hs_err_pid%p.log")
-    res.put("-XX:ErrorFile=", "../logs/es_hs_err_pid%p.log");
+    res.put("-XX:ErrorFile=", new File(esInstallation.getLogDirectory(), "es_hs_err_pid%p.log").getAbsolutePath());
 
     // JDK 8 GC logging (by default ES 6.6.1 enables them, we don't want to do that in SQ, no one will analyze them anyway)
     // res.put("8:-XX:+PrintGCDetails", "");
index 8ec7f31c7afaddf9ab57e16f750872cfb07956fa..549ccf0089532fc844d425b6a942509c2241539a 100644 (file)
 package org.sonar.application.es;
 
 import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Properties;
 import org.sonar.application.command.EsJvmOptions;
-import org.sonar.process.Props;
 
-import static org.sonar.process.ProcessProperties.Property.PATH_DATA;
-import static org.sonar.process.ProcessProperties.Property.PATH_HOME;
-import static org.sonar.process.ProcessProperties.Property.PATH_LOGS;
-import static org.sonar.process.ProcessProperties.Property.PATH_TEMP;
+public interface EsInstallation {
+  File getHomeDirectory();
 
-/**
- * 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 EsInstallation {
-  private final File homeDirectory;
-  private final List<File> outdatedSearchDirectories;
-  private final File dataDirectory;
-  private final File confDirectory;
-  private final File logDirectory;
-  private EsJvmOptions esJvmOptions;
-  private EsYmlSettings esYmlSettings;
-  private Properties log4j2Properties;
-  private String clusterName;
-  private String host;
-  private int port;
-
-  public EsInstallation(Props props) {
-    File sqHomeDir = props.nonNullValueAsFile(PATH_HOME.getKey());
-
-    this.homeDirectory = new File(sqHomeDir, "elasticsearch");
-    this.outdatedSearchDirectories = buildOutdatedSearchDirs(props);
-    this.dataDirectory = buildDataDir(props);
-    this.confDirectory = buildConfDir(props);
-    this.logDirectory = buildLogPath(props);
-  }
-
-  private static List<File> buildOutdatedSearchDirs(Props props) {
-    String dataPath = props.nonNullValue(PATH_DATA.getKey());
-    return Arrays.asList(new File(dataPath, "es"), new File(dataPath, "es5"));
-  }
-
-  private static File buildDataDir(Props props) {
-    String dataPath = props.nonNullValue(PATH_DATA.getKey());
-    return new File(dataPath, "es6");
-  }
-
-  private static File buildLogPath(Props props) {
-    return props.nonNullValueAsFile(PATH_LOGS.getKey());
-  }
-
-  private static File buildConfDir(Props props) {
-    File tempPath = props.nonNullValueAsFile(PATH_TEMP.getKey());
-    return new File(new File(tempPath, "conf"), "es");
-  }
-
-  public File getHomeDirectory() {
-    return homeDirectory;
-  }
-
-  public List<File> getOutdatedSearchDirectories() {
-    return Collections.unmodifiableList(outdatedSearchDirectories);
-  }
-
-  public File getDataDirectory() {
-    return dataDirectory;
-  }
-
-  public File getConfDirectory() {
-    return confDirectory;
-  }
-
-  public File getLogDirectory() {
-    return logDirectory;
-  }
-
-  public File getExecutable() {
-    return new File(homeDirectory, "bin/elasticsearch");
-  }
-
-  public File getLog4j2PropertiesLocation() {
-    return new File(confDirectory, "log4j2.properties");
-  }
-
-  public File getElasticsearchYml() {
-    return new File(confDirectory, "elasticsearch.yml");
-  }
-
-  public File getJvmOptions() {
-    return new File(confDirectory, "jvm.options");
-  }
-
-  public File getLibDirectory() {
-    return new File(homeDirectory, "lib");
-  }
-
-  public EsJvmOptions getEsJvmOptions() {
-    return esJvmOptions;
-  }
-
-  public EsInstallation setEsJvmOptions(EsJvmOptions esJvmOptions) {
-    this.esJvmOptions = esJvmOptions;
-    return this;
-  }
-
-  public EsYmlSettings getEsYmlSettings() {
-    return esYmlSettings;
-  }
-
-  public EsInstallation setEsYmlSettings(EsYmlSettings esYmlSettings) {
-    this.esYmlSettings = esYmlSettings;
-    return this;
-  }
-
-  public Properties getLog4j2Properties() {
-    return log4j2Properties;
-  }
-
-  public EsInstallation setLog4j2Properties(Properties log4j2Properties) {
-    this.log4j2Properties = log4j2Properties;
-    return this;
-  }
-
-  public String getClusterName() {
-    return clusterName;
-  }
-
-  public EsInstallation setClusterName(String clusterName) {
-    this.clusterName = clusterName;
-    return this;
-  }
-
-  public String getHost() {
-    return host;
-  }
-
-  public EsInstallation setHost(String host) {
-    this.host = host;
-    return this;
-  }
-
-  public int getPort() {
-    return port;
-  }
-
-  public EsInstallation setPort(int port) {
-    this.port = port;
-    return this;
-  }
+  List<File> getOutdatedSearchDirectories();
+
+  File getDataDirectory();
+
+  File getConfDirectory();
+
+  File getLogDirectory();
+
+  File getTmpDirectory();
+
+  File getExecutable();
+
+  File getLog4j2PropertiesLocation();
+
+  File getElasticsearchYml();
+
+  File getJvmOptions();
+
+  File getLibDirectory();
+
+  EsJvmOptions getEsJvmOptions();
+
+  EsYmlSettings getEsYmlSettings();
+
+  Properties getLog4j2Properties();
+
+  String getClusterName();
+
+  String getHost();
+
+  int getPort();
 }
diff --git a/server/sonar-main/src/main/java/org/sonar/application/es/EsInstallationImpl.java b/server/sonar-main/src/main/java/org/sonar/application/es/EsInstallationImpl.java
new file mode 100644 (file)
index 0000000..272bb06
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.application.es;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import org.sonar.application.command.EsJvmOptions;
+import org.sonar.process.Props;
+
+import static org.sonar.process.ProcessProperties.Property.PATH_DATA;
+import static org.sonar.process.ProcessProperties.Property.PATH_HOME;
+import static org.sonar.process.ProcessProperties.Property.PATH_LOGS;
+import static org.sonar.process.ProcessProperties.Property.PATH_TEMP;
+
+/**
+ * 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 EsInstallationImpl implements EsInstallation {
+  private final File homeDirectory;
+  private final List<File> outdatedSearchDirectories;
+  private final File dataDirectory;
+  private final File confDirectory;
+  private final File logDirectory;
+  private final File tmpDirectory;
+  private EsJvmOptions esJvmOptions;
+  private EsYmlSettings esYmlSettings;
+  private Properties log4j2Properties;
+  private String clusterName;
+  private String host;
+  private int port;
+
+  public EsInstallationImpl(Props props) {
+    File sqHomeDir = props.nonNullValueAsFile(PATH_HOME.getKey());
+
+    this.homeDirectory = new File(sqHomeDir, "elasticsearch");
+    this.outdatedSearchDirectories = buildOutdatedSearchDirs(props);
+    this.dataDirectory = buildDataDir(props);
+    this.confDirectory = buildConfDir(props);
+    this.logDirectory = buildLogDir(props);
+    this.tmpDirectory = buildTmpDir(props);
+  }
+
+  private static List<File> buildOutdatedSearchDirs(Props props) {
+    String dataPath = props.nonNullValue(PATH_DATA.getKey());
+    return Arrays.asList(new File(dataPath, "es"), new File(dataPath, "es5"));
+  }
+
+  private static File buildDataDir(Props props) {
+    String dataPath = props.nonNullValue(PATH_DATA.getKey());
+    return new File(dataPath, "es6");
+  }
+
+  private static File buildConfDir(Props props) {
+    File tmpDir = props.nonNullValueAsFile(PATH_TEMP.getKey());
+    return new File(new File(tmpDir, "conf"), "es");
+  }
+
+  private static File buildLogDir(Props props) {
+    return props.nonNullValueAsFile(PATH_LOGS.getKey());
+  }
+
+  private static File buildTmpDir(Props props) {
+    File tmpDir = props.nonNullValueAsFile(PATH_TEMP.getKey());
+    return new File(tmpDir, "es6");
+  }
+
+  @Override
+  public File getHomeDirectory() {
+    return homeDirectory;
+  }
+
+  @Override
+  public List<File> getOutdatedSearchDirectories() {
+    return Collections.unmodifiableList(outdatedSearchDirectories);
+  }
+
+  @Override
+  public File getDataDirectory() {
+    return dataDirectory;
+  }
+
+  @Override
+  public File getConfDirectory() {
+    return confDirectory;
+  }
+
+  @Override
+  public File getLogDirectory() {
+    return logDirectory;
+  }
+
+  @Override
+  public File getTmpDirectory() {
+    return tmpDirectory;
+  }
+
+  @Override
+  public File getExecutable() {
+    return new File(homeDirectory, "bin/elasticsearch");
+  }
+
+  @Override
+  public File getLog4j2PropertiesLocation() {
+    return new File(confDirectory, "log4j2.properties");
+  }
+
+  @Override
+  public File getElasticsearchYml() {
+    return new File(confDirectory, "elasticsearch.yml");
+  }
+
+  @Override
+  public File getJvmOptions() {
+    return new File(confDirectory, "jvm.options");
+  }
+
+  @Override
+  public File getLibDirectory() {
+    return new File(homeDirectory, "lib");
+  }
+
+  @Override
+  public EsJvmOptions getEsJvmOptions() {
+    return esJvmOptions;
+  }
+
+  public EsInstallationImpl setEsJvmOptions(EsJvmOptions esJvmOptions) {
+    this.esJvmOptions = esJvmOptions;
+    return this;
+  }
+
+  @Override
+  public EsYmlSettings getEsYmlSettings() {
+    return esYmlSettings;
+  }
+
+  public EsInstallationImpl setEsYmlSettings(EsYmlSettings esYmlSettings) {
+    this.esYmlSettings = esYmlSettings;
+    return this;
+  }
+
+  @Override
+  public Properties getLog4j2Properties() {
+    return log4j2Properties;
+  }
+
+  public EsInstallationImpl setLog4j2Properties(Properties log4j2Properties) {
+    this.log4j2Properties = log4j2Properties;
+    return this;
+  }
+
+  @Override
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public EsInstallationImpl setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+    return this;
+  }
+
+  @Override
+  public String getHost() {
+    return host;
+  }
+
+  public EsInstallationImpl setHost(String host) {
+    this.host = host;
+    return this;
+  }
+
+  @Override
+  public int getPort() {
+    return port;
+  }
+
+  public EsInstallationImpl setPort(int port) {
+    this.port = port;
+    return this;
+  }
+}
index 8225f6f5bebcb3dcec105dc4bd752a698bc1a059..be4c02fe1226b6ac48ae259345446d409b8109d3 100644 (file)
@@ -79,6 +79,7 @@ public class ProcessLauncherImpl implements ProcessLauncher {
     if (esInstallation != null) {
       cleanupOutdatedEsData(esInstallation);
       writeConfFiles(esInstallation);
+      ensureTempDirExists(esInstallation);
     }
 
     Process process;
@@ -150,6 +151,15 @@ public class ProcessLauncherImpl implements ProcessLauncher {
     }
   }
 
+  private static void ensureTempDirExists(EsInstallation esInstallation) {
+    File tmpDirectory = esInstallation.getTmpDirectory();
+    if (!tmpDirectory.exists() && !tmpDirectory.mkdirs()) {
+      String error = format("Failed to create ES temporary directory [%s]", tmpDirectory.getAbsolutePath());
+      LOG.error(error);
+      throw new IllegalStateException(error);
+    }
+  }
+
   private <T extends JvmOptions> Process launchJava(JavaCommand<T> javaCommand) {
     ProcessId processId = javaCommand.getProcessId();
     try {
index 0868f4150a89709bbc20934119dcc70e285a3fbd..c53c5b7ce152378357199bbdbda273f7ea8616a2 100644 (file)
@@ -152,7 +152,7 @@ public class CommandFactoryImplTest {
     assertThat(esCommand.getSuppressedEnvVariables()).containsOnly("JAVA_TOOL_OPTIONS", "ES_JAVA_OPTS");
 
     assertThat(esConfig.getEsJvmOptions().getAll())
-      .contains("-Djava.io.tmpdir=" + tempDir.getAbsolutePath());
+      .contains("-Djava.io.tmpdir=" + new File(tempDir, "es6").getAbsolutePath());
   }
 
   @Test
@@ -190,7 +190,7 @@ public class CommandFactoryImplTest {
     assertThat(esCommand.getSuppressedEnvVariables()).containsOnly("JAVA_TOOL_OPTIONS", "ES_JAVA_OPTS");
 
     assertThat(esConfig.getEsJvmOptions().getAll())
-      .contains("-Djava.io.tmpdir=" + tempDir.getAbsolutePath());
+      .contains("-Djava.io.tmpdir=" + new File(tempDir, "es6").getAbsolutePath());
     assertThat(esCommand.getJvmOptions().getAll())
       .containsAll(esConfig.getEsJvmOptions().getAll())
       .contains("-Delasticsearch")
@@ -216,7 +216,7 @@ public class CommandFactoryImplTest {
     assertThat(esConfig.getEsJvmOptions().getAll())
       // enforced values
       .contains("-XX:+UseConcMarkSweepGC", "-Dfile.encoding=UTF-8")
-      .contains("-Djava.io.tmpdir=" + tempDir.getAbsolutePath())
+      .contains("-Djava.io.tmpdir=" + new File(tempDir, "es6").getAbsolutePath())
       // user settings
       .contains("-Xms10G", "-Xmx10G")
       // default values disabled
index a90973c8d34c553b33fa4c6d32e6f4f168731b9c..679b1a598af66c9caaaf329ad02f5cc04c90762c 100644 (file)
@@ -29,6 +29,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
+import org.sonar.application.es.EsInstallation;
 import org.sonar.process.System2;
 import org.sonar.test.ExceptionCauseMatcher;
 
@@ -47,7 +48,12 @@ public class EsJvmOptionsTest {
   @UseDataProvider("java8or11")
   public void constructor_sets_mandatory_JVM_options_on_Java_8_and_11(System2 system2) throws IOException {
     File tmpDir = temporaryFolder.newFolder();
-    EsJvmOptions underTest = new EsJvmOptions(system2, tmpDir);
+    File logDir = temporaryFolder.newFolder();
+    EsInstallation esInstallation = mock(EsInstallation.class);
+    when(esInstallation.getTmpDirectory()).thenReturn(tmpDir);
+    when(esInstallation.getLogDirectory()).thenReturn(logDir);
+
+    EsJvmOptions underTest = new EsJvmOptions(system2, esInstallation);
 
     assertThat(underTest.getAll())
       .containsExactly(
@@ -68,7 +74,7 @@ public class EsJvmOptionsTest {
         "-Dlog4j.shutdownHookEnabled=false",
         "-Dlog4j2.disable.jmx=true",
         "-Djava.io.tmpdir=" + tmpDir.getAbsolutePath(),
-        "-XX:ErrorFile=../logs/es_hs_err_pid%p.log");
+        "-XX:ErrorFile=" + new File(logDir, "es_hs_err_pid%p.log").getAbsolutePath());
   }
 
   @DataProvider
@@ -92,7 +98,12 @@ public class EsJvmOptionsTest {
     when(java9.isJava10()).thenReturn(false);
 
     File tmpDir = temporaryFolder.newFolder();
-    EsJvmOptions underTest = new EsJvmOptions(java9, tmpDir);
+    File logDir = temporaryFolder.newFolder();
+    EsInstallation esInstallation = mock(EsInstallation.class);
+    when(esInstallation.getTmpDirectory()).thenReturn(tmpDir);
+    when(esInstallation.getLogDirectory()).thenReturn(logDir);
+
+    EsJvmOptions underTest = new EsJvmOptions(java9, esInstallation);
 
     assertThat(underTest.getAll())
       .containsExactly(
@@ -113,7 +124,7 @@ public class EsJvmOptionsTest {
         "-Dlog4j.shutdownHookEnabled=false",
         "-Dlog4j2.disable.jmx=true",
         "-Djava.io.tmpdir=" + tmpDir.getAbsolutePath(),
-        "-XX:ErrorFile=../logs/es_hs_err_pid%p.log",
+        "-XX:ErrorFile=" + new File(logDir, "es_hs_err_pid%p.log").getAbsolutePath(),
         "-Djava.locale.providers=COMPAT");
   }
 
@@ -124,7 +135,12 @@ public class EsJvmOptionsTest {
     when(java10.isJava10()).thenReturn(true);
 
     File tmpDir = temporaryFolder.newFolder();
-    EsJvmOptions underTest = new EsJvmOptions(java10, tmpDir);
+    File logDir = temporaryFolder.newFolder();
+    EsInstallation esInstallation = mock(EsInstallation.class);
+    when(esInstallation.getTmpDirectory()).thenReturn(tmpDir);
+    when(esInstallation.getLogDirectory()).thenReturn(logDir);
+
+    EsJvmOptions underTest = new EsJvmOptions(java10, esInstallation);
 
     assertThat(underTest.getAll())
       .containsExactly(
@@ -145,7 +161,7 @@ public class EsJvmOptionsTest {
         "-Dlog4j.shutdownHookEnabled=false",
         "-Dlog4j2.disable.jmx=true",
         "-Djava.io.tmpdir=" + tmpDir.getAbsolutePath(),
-        "-XX:ErrorFile=../logs/es_hs_err_pid%p.log",
+        "-XX:ErrorFile=" + new File(logDir, "es_hs_err_pid%p.log").getAbsolutePath(),
         "-XX:UseAVX=2");
   }
 
@@ -155,8 +171,13 @@ public class EsJvmOptionsTest {
   @Test
   public void writeToJvmOptionFile_writes_all_JVM_options_to_file_with_warning_header() throws IOException {
     File tmpDir = temporaryFolder.newFolder("with space");
+    File logDir = temporaryFolder.newFolder();
+    EsInstallation esInstallation = mock(EsInstallation.class);
+    when(esInstallation.getTmpDirectory()).thenReturn(tmpDir);
+    when(esInstallation.getLogDirectory()).thenReturn(logDir);
     File file = temporaryFolder.newFile();
-    EsJvmOptions underTest = new EsJvmOptions(tmpDir)
+
+    EsJvmOptions underTest = new EsJvmOptions(esInstallation)
       .add("-foo")
       .add("-bar");
 
@@ -185,7 +206,7 @@ public class EsJvmOptionsTest {
         "-Dlog4j.shutdownHookEnabled=false\n" +
         "-Dlog4j2.disable.jmx=true\n" +
         "-Djava.io.tmpdir=" + tmpDir.getAbsolutePath() + "\n" +
-        "-XX:ErrorFile=../logs/es_hs_err_pid%p.log\n" +
+        "-XX:ErrorFile=" + new File(logDir, "es_hs_err_pid%p.log").getAbsolutePath() + "\n" +
         "-foo\n" +
         "-bar");
 
@@ -194,7 +215,13 @@ public class EsJvmOptionsTest {
   @Test
   public void writeToJvmOptionFile_throws_ISE_in_case_of_IOException() throws IOException {
     File notAFile = temporaryFolder.newFolder();
-    EsJvmOptions underTest = new EsJvmOptions(temporaryFolder.newFolder());
+    File tmpDir = temporaryFolder.newFolder();
+    File logDir = temporaryFolder.newFolder();
+    EsInstallation esInstallation = mock(EsInstallation.class);
+    when(esInstallation.getTmpDirectory()).thenReturn(tmpDir);
+    when(esInstallation.getLogDirectory()).thenReturn(logDir);
+
+    EsJvmOptions underTest = new EsJvmOptions(esInstallation);
 
     expectedException.expect(IllegalStateException.class);
     expectedException.expectMessage("Cannot write Elasticsearch jvm options file");
index 31cb90d41152727ff27a61fd648cfdca275b2c42..2916dad2077a6a8ebafaad15b69fef293f106e92 100644 (file)
@@ -48,7 +48,7 @@ public class EsInstallationTest {
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Property sonar.path.home is not set");
 
-    new EsInstallation(props);
+    new EsInstallationImpl(props);
   }
 
   @Test
@@ -60,7 +60,7 @@ public class EsInstallationTest {
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Property sonar.path.temp is not set");
 
-    new EsInstallation(props);
+    new EsInstallationImpl(props);
   }
 
   @Test
@@ -71,7 +71,7 @@ public class EsInstallationTest {
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Missing property: sonar.path.data");
 
-    new EsInstallation(props);
+    new EsInstallationImpl(props);
   }
 
   @Test
@@ -83,7 +83,7 @@ public class EsInstallationTest {
     props.set(PATH_TEMP.getKey(), temp.newFolder().getAbsolutePath());
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     assertThat(underTest.getHomeDirectory()).isEqualTo(new File(sqHomeDir, "elasticsearch"));
   }
@@ -100,7 +100,7 @@ public class EsInstallationTest {
 
     props.set(PATH_DATA.getKey(), dataDir.getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     assertThat(underTest.getDataDirectory()).isEqualTo(new File(dataDir, "es6"));
   }
@@ -115,7 +115,7 @@ public class EsInstallationTest {
     props.set(PATH_TEMP.getKey(), temp.newFolder().getAbsolutePath());
     props.set(PATH_LOGS.getKey(), logDir.getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     assertThat(underTest.getLogDirectory()).isEqualTo(logDir);
   }
@@ -130,7 +130,7 @@ public class EsInstallationTest {
     props.set(PATH_TEMP.getKey(), temp.newFolder().getAbsolutePath());
     props.set(PATH_LOGS.getKey(), logDir.getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     assertThat(underTest.getOutdatedSearchDirectories())
       .extracting(t -> t.getName())
@@ -146,7 +146,7 @@ public class EsInstallationTest {
     props.set(PATH_TEMP.getKey(), tempDir.getAbsolutePath());
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     assertThat(underTest.getConfDirectory()).isEqualTo(new File(tempDir, "conf/es"));
   }
@@ -160,7 +160,7 @@ public class EsInstallationTest {
     props.set(PATH_TEMP.getKey(), temp.newFolder().getAbsolutePath());
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     if (System.getProperty("os.name").startsWith("Windows")) {
       assertThat(underTest.getExecutable()).isEqualTo(new File(sqHomeDir, "elasticsearch/bin/elasticsearch.bat"));
@@ -178,7 +178,7 @@ public class EsInstallationTest {
     props.set(PATH_TEMP.getKey(), tempDir.getAbsolutePath());
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     assertThat(underTest.getLog4j2PropertiesLocation()).isEqualTo(new File(tempDir, "conf/es/log4j2.properties"));
   }
@@ -192,7 +192,7 @@ public class EsInstallationTest {
     props.set(PATH_TEMP.getKey(), tempDir.getAbsolutePath());
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     assertThat(underTest.getElasticsearchYml()).isEqualTo(new File(tempDir, "conf/es/elasticsearch.yml"));
   }
@@ -206,7 +206,7 @@ public class EsInstallationTest {
     props.set(PATH_TEMP.getKey(), tempDir.getAbsolutePath());
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
 
-    EsInstallation underTest = new EsInstallation(props);
+    EsInstallation underTest = new EsInstallationImpl(props);
 
     assertThat(underTest.getJvmOptions()).isEqualTo(new File(tempDir, "conf/es/jvm.options"));
   }
index 8d4a0ab1afc0b7fff8c9e22675928e80f540d97e..8dc3f8faec8ac374bcf877a6351734f93c8eb905 100644 (file)
@@ -76,7 +76,7 @@ public class EsSettingsTest {
     this.listAppender = ListAppender.attachMemoryAppenderToLoggerOf(EsSettings.class);
     Props props = minimalProps();
     System2 system2 = mock(System2.class);
-    new EsSettings(props, new EsInstallation(props), system2);
+    new EsSettings(props, new EsInstallationImpl(props), system2);
 
     assertThat(listAppender.getLogs()).isEmpty();
   }
@@ -87,7 +87,7 @@ public class EsSettingsTest {
     Props props = minimalProps();
     System2 system2 = mock(System2.class);
     when(system2.getenv("ES_JVM_OPTIONS")).thenReturn("  ");
-    new EsSettings(props, new EsInstallation(props), system2);
+    new EsSettings(props, new EsInstallationImpl(props), system2);
 
     assertThat(listAppender.getLogs()).isEmpty();
   }
@@ -98,7 +98,7 @@ public class EsSettingsTest {
     Props props = minimalProps();
     System2 system2 = mock(System2.class);
     when(system2.getenv("ES_JVM_OPTIONS")).thenReturn(randomAlphanumeric(2));
-    new EsSettings(props, new EsInstallation(props), system2);
+    new EsSettings(props, new EsInstallationImpl(props), system2);
 
     assertThat(listAppender.getLogs())
       .extracting(ILoggingEvent::getMessage)
@@ -128,7 +128,7 @@ public class EsSettingsTest {
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
     props.set(CLUSTER_NAME.getKey(), "sonarqube");
 
-    EsSettings esSettings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE);
+    EsSettings esSettings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE);
 
     Map<String, String> generated = esSettings.build();
     assertThat(generated.get("transport.tcp.port")).isEqualTo("1234");
@@ -167,7 +167,7 @@ public class EsSettingsTest {
     props.set(Property.CLUSTER_ENABLED.getKey(), "true");
     props.set(CLUSTER_NODE_NAME.getKey(), "node-1");
 
-    EsSettings esSettings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE);
+    EsSettings esSettings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE);
 
     Map<String, String> generated = esSettings.build();
     assertThat(generated.get("cluster.name")).isEqualTo("sonarqube-1");
@@ -186,7 +186,7 @@ public class EsSettingsTest {
     props.set(PATH_DATA.getKey(), temp.newFolder().getAbsolutePath());
     props.set(PATH_TEMP.getKey(), temp.newFolder().getAbsolutePath());
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
-    EsSettings esSettings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE);
+    EsSettings esSettings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE);
     Map<String, String> generated = esSettings.build();
     assertThat(generated.get("node.name")).startsWith("sonarqube-");
   }
@@ -203,7 +203,7 @@ public class EsSettingsTest {
     props.set(PATH_DATA.getKey(), temp.newFolder().getAbsolutePath());
     props.set(PATH_TEMP.getKey(), temp.newFolder().getAbsolutePath());
     props.set(PATH_LOGS.getKey(), temp.newFolder().getAbsolutePath());
-    EsSettings esSettings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE);
+    EsSettings esSettings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE);
     Map<String, String> generated = esSettings.build();
     assertThat(generated.get("node.name")).isEqualTo("sonarqube");
   }
@@ -211,7 +211,7 @@ public class EsSettingsTest {
   @Test
   public void path_properties_are_values_from_EsFileSystem_argument() throws IOException {
     File foo = temp.newFolder();
-    EsInstallation mockedEsInstallation = mock(EsInstallation.class);
+    EsInstallation mockedEsInstallation = mock(EsInstallationImpl.class);
     File home = new File(foo, "home");
     when(mockedEsInstallation.getHomeDirectory()).thenReturn(home);
     File conf = new File(foo, "conf");
@@ -233,7 +233,7 @@ public class EsSettingsTest {
   public void set_discovery_settings_if_cluster_is_enabled() throws Exception {
     Props props = minProps(CLUSTER_ENABLED);
     props.set(CLUSTER_SEARCH_HOSTS.getKey(), "1.2.3.4:9000,1.2.3.5:8080");
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).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");
@@ -245,7 +245,7 @@ public class EsSettingsTest {
     Props props = minProps(CLUSTER_ENABLED);
     props.set(SEARCH_MINIMUM_MASTER_NODES.getKey(), "ꝱꝲꝳପ");
 
-    EsSettings underTest = new EsSettings(props, new EsInstallation(props), System2.INSTANCE);
+    EsSettings underTest = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE);
 
     expectedException.expect(IllegalStateException.class);
     expectedException.expectMessage("Value of property sonar.search.minimumMasterNodes is not an integer:");
@@ -256,7 +256,7 @@ public class EsSettingsTest {
   public void cluster_is_enabled_with_defined_minimum_master_nodes() throws Exception {
     Props props = minProps(CLUSTER_ENABLED);
     props.set(SEARCH_MINIMUM_MASTER_NODES.getKey(), "5");
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).build();
 
     assertThat(settings.get("discovery.zen.minimum_master_nodes")).isEqualTo("5");
   }
@@ -265,7 +265,7 @@ public class EsSettingsTest {
   public void cluster_is_enabled_with_defined_initialTimeout() throws Exception {
     Props props = minProps(CLUSTER_ENABLED);
     props.set(SEARCH_INITIAL_STATE_TIMEOUT.getKey(), "10s");
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).build();
 
     assertThat(settings.get("discovery.initial_state_timeout")).isEqualTo("10s");
   }
@@ -274,7 +274,7 @@ public class EsSettingsTest {
   public void in_standalone_initialTimeout_is_not_overridable() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
     props.set(SEARCH_INITIAL_STATE_TIMEOUT.getKey(), "10s");
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).build();
 
     assertThat(settings.get("discovery.initial_state_timeout")).isEqualTo("30s");
   }
@@ -283,7 +283,7 @@ public class EsSettingsTest {
   public void in_standalone_minimumMasterNodes_is_not_overridable() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
     props.set(SEARCH_MINIMUM_MASTER_NODES.getKey(), "5");
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).build();
 
     assertThat(settings.get("discovery.zen.minimum_master_nodes")).isEqualTo("1");
   }
@@ -292,7 +292,7 @@ public class EsSettingsTest {
   public void enable_http_connector() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
     props.set(SEARCH_HTTP_PORT.getKey(), "9010");
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).build();
 
     assertThat(settings.get("http.port")).isEqualTo("9010");
     assertThat(settings.get("http.host")).isEqualTo("127.0.0.1");
@@ -304,7 +304,7 @@ public class EsSettingsTest {
     Props props = minProps(CLUSTER_DISABLED);
     props.set(SEARCH_HTTP_PORT.getKey(), "9010");
     props.set(SEARCH_HOST.getKey(), "127.0.0.2");
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).build();
 
     assertThat(settings.get("http.port")).isEqualTo("9010");
     assertThat(settings.get("http.host")).isEqualTo("127.0.0.2");
@@ -314,7 +314,7 @@ public class EsSettingsTest {
   @Test
   public void enable_seccomp_filter_by_default() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).build();
 
     assertThat(settings.get("bootstrap.system_call_filter")).isNull();
   }
@@ -323,7 +323,7 @@ public class EsSettingsTest {
   public void disable_seccomp_filter_if_configured_in_search_additional_props() throws Exception {
     Props props = minProps(CLUSTER_DISABLED);
     props.set("sonar.search.javaAdditionalOpts", "-Xmx1G -Dbootstrap.system_call_filter=false -Dfoo=bar");
-    Map<String, String> settings = new EsSettings(props, new EsInstallation(props), System2.INSTANCE).build();
+    Map<String, String> settings = new EsSettings(props, new EsInstallationImpl(props), System2.INSTANCE).build();
 
     assertThat(settings.get("bootstrap.system_call_filter")).isEqualTo("false");
   }
index 37d2d1df54f1feb64bf839e9eb3533495debeef0..253a5fc17df719b5c77d27726bf891b714c4fc8f 100644 (file)
@@ -35,6 +35,7 @@ import org.sonar.application.command.EsScriptCommand;
 import org.sonar.application.command.JavaCommand;
 import org.sonar.application.command.JvmOptions;
 import org.sonar.application.es.EsInstallation;
+import org.sonar.application.es.EsInstallationImpl;
 import org.sonar.application.es.EsYmlSettings;
 import org.sonar.process.ProcessId;
 import org.sonar.process.Props;
@@ -191,7 +192,7 @@ public class ProcessLauncherImplTest {
     props.set("sonar.path.home", homeDir.getAbsolutePath());
     props.set("sonar.path.data", dataDir.getAbsolutePath());
     props.set("sonar.path.logs", logDir.getAbsolutePath());
-    command.setEsInstallation(new EsInstallation(props)
+    command.setEsInstallation(new EsInstallationImpl(props)
       .setEsYmlSettings(mock(EsYmlSettings.class))
       .setEsJvmOptions(mock(EsJvmOptions.class))
       .setLog4j2Properties(new Properties())
@@ -203,7 +204,10 @@ public class ProcessLauncherImplTest {
 
   private EsInstallation createEsInstallation() throws IOException {
     File tempFolder = this.temp.newFolder("temp");
-    return new EsInstallation(new Props(new Properties())
+    EsInstallation esInstallation = mock(EsInstallation.class);
+    when(esInstallation.getTmpDirectory()).thenReturn(temp.newFolder());
+    when(esInstallation.getLogDirectory()).thenReturn(temp.newFolder());
+    return new EsInstallationImpl(new Props(new Properties())
       .set("sonar.path.home", this.temp.newFolder("home").getAbsolutePath())
       .set("sonar.path.data", this.temp.newFolder("data").getAbsolutePath())
       .set("sonar.path.temp", tempFolder.getAbsolutePath())
@@ -212,7 +216,7 @@ public class ProcessLauncherImplTest {
       .setPort(9001)
       .setHost("localhost")
       .setEsYmlSettings(new EsYmlSettings(new HashMap<>()))
-      .setEsJvmOptions(new EsJvmOptions(tempFolder))
+      .setEsJvmOptions(new EsJvmOptions(esInstallation))
       .setLog4j2Properties(new Properties());
   }