Refactor utility code in qa:os: tests (#49945) (#50000)

This refactor bridges some gaps between a long-running feature branch (#49268) and the master branch.

First of all, this PR gives our PackagingTestCase class some methods to start and stop Elasticsearch that will switch on packaging type and delegate to the appropriate utility class for deb/RPM packages, archive installations, and Docker. These methods should be very useful as we continue group tests by function rather than by package or platform type.

Second, the password-protected keystore tests have a particular need to read the output of Elasticsearch startup commands. In order to make this easer to do, some commands now return Shell.Result objects so that tests can check over output to the shell. To that end, there's also an assertElasticsearchFailure method that will handle checking for startup failures for the various distribution types.

There is an update to the Powershell startup script for archives that asynchronously redirects the output of the Powershell process to files that we can read for errors.

Finally, we use the ES_STARTUP_SLEEP_TIME environment variable to make sure that our startup commands wait long enough before exiting for errors to make it to the standard output and error streams.
This commit is contained in:
William Brafford 2019-12-10 15:00:05 -05:00 committed by GitHub
parent df558aa0ca
commit ba9526ec4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 240 additions and 150 deletions

View File

@ -138,7 +138,7 @@ public class ArchiveTests extends PackagingTestCase {
rm(installation.config("elasticsearch.keystore"));
try {
Archives.runElasticsearch(installation, sh);
startElasticsearch();
} catch (Exception e ){
if (Files.exists(installation.home.resolve("elasticsearch.pid"))) {
String pid = FileUtils.slurp(installation.home.resolve("elasticsearch.pid")).trim();
@ -155,7 +155,7 @@ public class ArchiveTests extends PackagingTestCase {
assertTrue("gc logs exist", Files.exists(installation.logs.resolve(gcLogName)));
ServerUtils.runElasticsearchTests();
Archives.stopElasticsearch(installation);
stopElasticsearch();
}
public void test51JavaHomeOverride() throws Exception {
@ -168,9 +168,9 @@ public class ArchiveTests extends PackagingTestCase {
sh.getEnv().put("JAVA_HOME", systemJavaHome1);
});
Archives.runElasticsearch(installation, sh);
startElasticsearch();
ServerUtils.runElasticsearchTests();
Archives.stopElasticsearch(installation);
stopElasticsearch();
String systemJavaHome1 = sh.getEnv().get("JAVA_HOME");
assertThat(FileUtils.slurpAllLogs(installation.logs, "elasticsearch.log", "*.log.gz"),
@ -192,9 +192,9 @@ public class ArchiveTests extends PackagingTestCase {
sh.getEnv().put("JAVA_HOME", systemJavaHome1);
});
Archives.runElasticsearch(installation, sh);
startElasticsearch();
ServerUtils.runElasticsearchTests();
Archives.stopElasticsearch(installation);
stopElasticsearch();
String systemJavaHome1 = sh.getEnv().get("JAVA_HOME");
assertThat(FileUtils.slurpAllLogs(installation.logs, "elasticsearch.log", "*.log.gz"),
@ -215,9 +215,9 @@ public class ArchiveTests extends PackagingTestCase {
sh.getEnv().put("JAVA_HOME", "C:\\Program Files (x86)\\java");
//verify ES can start, stop and run plugin list
Archives.runElasticsearch(installation, sh);
startElasticsearch();
Archives.stopElasticsearch(installation);
stopElasticsearch();
String pluginListCommand = installation.bin + "/elasticsearch-plugin list";
Result result = sh.run(pluginListCommand);
@ -241,9 +241,9 @@ public class ArchiveTests extends PackagingTestCase {
sh.getEnv().put("JAVA_HOME", testJavaHome);
//verify ES can start, stop and run plugin list
Archives.runElasticsearch(installation, sh);
startElasticsearch();
Archives.stopElasticsearch(installation);
stopElasticsearch();
String pluginListCommand = installation.bin + "/elasticsearch-plugin list";
Result result = sh.run(pluginListCommand);
@ -288,13 +288,12 @@ public class ArchiveTests extends PackagingTestCase {
"-Dlog4j2.disable.jmx=true\n";
append(tempConf.resolve("jvm.options"), jvmOptions);
final Shell sh = newShell();
sh.chown(tempConf);
sh.getEnv().put("ES_PATH_CONF", tempConf.toString());
sh.getEnv().put("ES_JAVA_OPTS", "-XX:-UseCompressedOops");
Archives.runElasticsearch(installation, sh);
startElasticsearch();
final String nodesResponse = makeRequest(Request.Get("http://localhost:9200/_nodes"));
assertThat(nodesResponse, containsString("\"heap_init_in_bytes\":536870912"));
@ -322,17 +321,16 @@ public class ArchiveTests extends PackagingTestCase {
append(tempConf.resolve("elasticsearch.yml"), "node.name: relative");
final Shell sh = newShell();
sh.chown(temp);
sh.setWorkingDirectory(temp);
sh.getEnv().put("ES_PATH_CONF", "config");
Archives.runElasticsearch(installation, sh);
startElasticsearch();
final String nodesResponse = makeRequest(Request.Get("http://localhost:9200/_nodes"));
assertThat(nodesResponse, containsString("\"name\":\"relative\""));
Archives.stopElasticsearch(installation);
stopElasticsearch();
} finally {
rm(tempConf);
@ -397,7 +395,7 @@ public class ArchiveTests extends PackagingTestCase {
sh.setWorkingDirectory(getTempDir());
Archives.runElasticsearch(installation, sh);
startElasticsearch();
Archives.stopElasticsearch(installation);
Result result = sh.run("echo y | " + installation.executables().elasticsearchNode + " unsafe-bootstrap");

View File

@ -50,9 +50,6 @@ import static org.elasticsearch.packaging.util.Packages.clearJournal;
import static org.elasticsearch.packaging.util.Packages.installPackage;
import static org.elasticsearch.packaging.util.Packages.remove;
import static org.elasticsearch.packaging.util.Packages.restartElasticsearch;
import static org.elasticsearch.packaging.util.Packages.startElasticsearch;
import static org.elasticsearch.packaging.util.Packages.startElasticsearchIgnoringFailure;
import static org.elasticsearch.packaging.util.Packages.stopElasticsearch;
import static org.elasticsearch.packaging.util.Packages.verifyPackageInstallation;
import static org.elasticsearch.packaging.util.Platforms.getOsRelease;
import static org.elasticsearch.packaging.util.Platforms.isSystemd;
@ -101,9 +98,9 @@ public class PackageTests extends PackagingTestCase {
try {
Files.write(installation.envFile, ("JAVA_HOME=" + systemJavaHome + "\n").getBytes(StandardCharsets.UTF_8),
StandardOpenOption.APPEND);
startElasticsearch(sh, installation);
startElasticsearch();
runElasticsearchTests();
stopElasticsearch(sh);
stopElasticsearch();
} finally {
Files.write(installation.envFile, originalEnvFile);
}
@ -129,9 +126,9 @@ public class PackageTests extends PackagingTestCase {
}
try {
startElasticsearch(sh, installation);
startElasticsearch();
runElasticsearchTests();
stopElasticsearch(sh);
stopElasticsearch();
} finally {
if (Files.exists(Paths.get(backupPath))) {
sh.run("sudo mv " + backupPath + " /usr/bin/java");
@ -153,7 +150,7 @@ public class PackageTests extends PackagingTestCase {
public void test40StartServer() throws Exception {
String start = sh.runIgnoreExitCode("date ").stdout.trim();
startElasticsearch(sh, installation);
startElasticsearch();
String journalEntries = sh.runIgnoreExitCode("journalctl _SYSTEMD_UNIT=elasticsearch.service " +
"--since \"" + start + "\" --output cat | grep -v \"future versions of Elasticsearch will require Java 11\" | wc -l")
@ -219,7 +216,7 @@ public class PackageTests extends PackagingTestCase {
}
public void test60Reinstall() throws Exception {
installation = installPackage(distribution());
install();
assertInstalled(distribution());
verifyPackageInstallation(installation, distribution(), sh);
@ -229,13 +226,13 @@ public class PackageTests extends PackagingTestCase {
public void test70RestartServer() throws Exception {
try {
installation = installPackage(distribution());
install();
assertInstalled(distribution());
startElasticsearch(sh, installation);
startElasticsearch();
restartElasticsearch(sh, installation);
runElasticsearchTests();
stopElasticsearch(sh);
stopElasticsearch();
} finally {
cleanup();
}
@ -244,22 +241,22 @@ public class PackageTests extends PackagingTestCase {
public void test72TestRuntimeDirectory() throws Exception {
try {
installation = installPackage(distribution());
install();
FileUtils.rm(installation.pidDir);
startElasticsearch(sh, installation);
startElasticsearch();
assertPathsExist(installation.pidDir);
stopElasticsearch(sh);
stopElasticsearch();
} finally {
cleanup();
}
}
public void test73gcLogsExist() throws Exception {
installation = installPackage(distribution());
startElasticsearch(sh, installation);
install();
startElasticsearch();
// it can be gc.log or gc.log.0.current
assertThat(installation.logs, fileWithGlobExist("gc.log*"));
stopElasticsearch(sh);
stopElasticsearch();
}
// TEST CASES FOR SYSTEMD ONLY
@ -278,26 +275,26 @@ public class PackageTests extends PackagingTestCase {
sh.run("systemd-tmpfiles --create");
startElasticsearch(sh, installation);
startElasticsearch();
final Path pidFile = installation.pidDir.resolve("elasticsearch.pid");
assertTrue(Files.exists(pidFile));
stopElasticsearch(sh);
stopElasticsearch();
}
public void test81CustomPathConfAndJvmOptions() throws Exception {
withCustomConfig(tempConf -> {
append(installation.envFile, "ES_JAVA_OPTS=-XX:-UseCompressedOops");
startElasticsearch(sh, installation);
startElasticsearch();
final String nodesResponse = makeRequest(Request.Get("http://localhost:9200/_nodes"));
assertThat(nodesResponse, containsString("\"heap_init_in_bytes\":536870912"));
assertThat(nodesResponse, containsString("\"using_compressed_ordinary_object_pointers\":\"false\""));
stopElasticsearch(sh);
stopElasticsearch();
});
}
@ -307,7 +304,7 @@ public class PackageTests extends PackagingTestCase {
sh.run("systemctl mask systemd-sysctl.service");
installation = installPackage(distribution());
install();
sh.run("systemctl unmask systemd-sysctl.service");
} finally {
@ -319,9 +316,9 @@ public class PackageTests extends PackagingTestCase {
// Limits are changed on systemd platforms only
assumeTrue(isSystemd());
installation = installPackage(distribution());
install();
startElasticsearch(sh, installation);
startElasticsearch();
final Path pidFile = installation.pidDir.resolve("elasticsearch.pid");
assertTrue(Files.exists(pidFile));
@ -338,7 +335,7 @@ public class PackageTests extends PackagingTestCase {
String maxAddressSpace = sh.run("cat /proc/%s/limits | grep \"Max address space\" | awk '{ print $4 }'", pid).stdout.trim();
assertThat(maxAddressSpace, equalTo("unlimited"));
stopElasticsearch(sh);
stopElasticsearch();
}
public void test90DoNotCloseStderrWhenQuiet() throws Exception {
@ -348,7 +345,7 @@ public class PackageTests extends PackagingTestCase {
// Make sure we don't pick up the journal entries for previous ES instances.
clearJournal(sh);
startElasticsearchIgnoringFailure(sh);
runElasticsearchStartCommand();
final Result logs = sh.run("journalctl -u elasticsearch.service");
@ -366,7 +363,7 @@ public class PackageTests extends PackagingTestCase {
assertPathsExist(installation.envFile);
stopElasticsearch(sh);
stopElasticsearch();
// The custom config directory is not under /tmp or /var/tmp because
// systemd's private temp directory functionally means different

View File

@ -48,6 +48,8 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import static org.elasticsearch.packaging.util.Cleanup.cleanEverything;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
@ -139,6 +141,9 @@ public abstract class PackagingTestCase extends Assert {
case DOCKER:
installation = Docker.runContainer(distribution);
Docker.verifyContainerInstallation(installation, distribution);
break;
default:
throw new IllegalStateException("Unknown Elasticsearch packaging type.");
}
}
@ -147,19 +152,7 @@ public abstract class PackagingTestCase extends Assert {
*/
protected void assertWhileRunning(Platforms.PlatformAction assertions) throws Exception {
try {
switch (distribution.packaging) {
case TAR:
case ZIP:
Archives.runElasticsearch(installation, sh);
break;
case DEB:
case RPM:
Packages.startElasticsearch(sh, installation);
break;
case DOCKER:
// nothing, "installing" docker image is running it
}
awaitElasticsearchStartup(runElasticsearchStartCommand());
} catch (Exception e ){
if (Files.exists(installation.home.resolve("elasticsearch.pid"))) {
String pid = FileUtils.slurp(installation.home.resolve("elasticsearch.pid")).trim();
@ -180,19 +173,7 @@ public abstract class PackagingTestCase extends Assert {
FileUtils.slurpAllLogs(installation.logs, "elasticsearch.log", "*.log.gz"));
throw e;
}
switch (distribution.packaging) {
case TAR:
case ZIP:
Archives.stopElasticsearch(installation);
break;
case DEB:
case RPM:
Packages.stopElasticsearch(sh);
break;
case DOCKER:
// nothing, removing container is handled externally
}
stopElasticsearch();
}
protected static Shell newShell() throws Exception {
@ -207,4 +188,109 @@ public abstract class PackagingTestCase extends Assert {
}
return sh;
}
/**
* Run the command to start Elasticsearch, but don't wait or test for success.
* This method is useful for testing failure conditions in startup. To await success,
* use {@link #startElasticsearch()}.
* @return Shell results of the startup command.
* @throws Exception when command fails immediately.
*/
public Shell.Result runElasticsearchStartCommand() throws Exception {
switch (distribution.packaging) {
case TAR:
case ZIP:
return Archives.runElasticsearchStartCommand(installation, sh);
case DEB:
case RPM:
return Packages.runElasticsearchStartCommand(sh);
case DOCKER:
// nothing, "installing" docker image is running it
return Shell.NO_OP;
default:
throw new IllegalStateException("Unknown Elasticsearch packaging type.");
}
}
public void stopElasticsearch() throws Exception {
switch (distribution.packaging) {
case TAR:
case ZIP:
Archives.stopElasticsearch(installation);
break;
case DEB:
case RPM:
Packages.stopElasticsearch(sh);
break;
case DOCKER:
// nothing, "installing" docker image is running it
break;
default:
throw new IllegalStateException("Unknown Elasticsearch packaging type.");
}
}
public void awaitElasticsearchStartup(Shell.Result result) throws Exception {
assertThat("Startup command should succeed", result.exitCode, equalTo(0));
switch (distribution.packaging) {
case TAR:
case ZIP:
Archives.assertElasticsearchStarted(installation);
break;
case DEB:
case RPM:
Packages.assertElasticsearchStarted(sh, installation);
break;
case DOCKER:
Docker.waitForElasticsearchToStart();
break;
default:
throw new IllegalStateException("Unknown Elasticsearch packaging type.");
}
}
/**
* Start Elasticsearch and wait until it's up and running. If you just want to run
* the start command, use {@link #runElasticsearchStartCommand()}.
* @throws Exception if Elasticsearch can't start
*/
public void startElasticsearch() throws Exception {
awaitElasticsearchStartup(runElasticsearchStartCommand());
}
public void assertElasticsearchFailure(Shell.Result result, String expectedMessage) {
if (Files.exists(installation.logs.resolve("elasticsearch.log"))) {
// If log file exists, then we have bootstrapped our logging and the
// error should be in the logs
assertTrue("log file exists", Files.exists(installation.logs.resolve("elasticsearch.log")));
String logfile = FileUtils.slurp(installation.logs.resolve("elasticsearch.log"));
assertThat(logfile, containsString(expectedMessage));
} else if (distribution().isPackage() && Platforms.isSystemd()) {
// For systemd, retrieve the error from journalctl
assertThat(result.stderr, containsString("Job for elasticsearch.service failed"));
Shell.Result error = sh.run("journalctl --boot --unit elasticsearch.service");
assertThat(error.stdout, containsString(expectedMessage));
} else if (Platforms.WINDOWS == true) {
// In Windows, we have written our stdout and stderr to files in order to run
// in the background
String wrapperPid = result.stdout.trim();
sh.runIgnoreExitCode("Wait-Process -Timeout " + Archives.ES_STARTUP_SLEEP_TIME_SECONDS + " -Id " + wrapperPid);
sh.runIgnoreExitCode("Get-EventSubscriber | " +
"where {($_.EventName -eq 'OutputDataReceived' -Or $_.EventName -eq 'ErrorDataReceived' |" +
"Unregister-EventSubscriber -Force");
assertThat(FileUtils.slurp(Archives.getPowershellErrorPath(installation)), containsString(expectedMessage));
} else {
// Otherwise, error should be on shell stderr
assertThat(result.stderr, containsString(expectedMessage));
}
}
}

View File

@ -43,7 +43,7 @@ import static org.elasticsearch.packaging.util.FileUtils.mv;
import static org.elasticsearch.packaging.util.FileUtils.slurp;
import static org.elasticsearch.packaging.util.Platforms.isDPKG;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.emptyOrNullString;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.hamcrest.core.Is.is;
@ -63,6 +63,10 @@ public class Archives {
? System.getenv("username")
: "elasticsearch";
/** This is an arbitrarily chosen value that gives Elasticsearch time to log Bootstrap
* errors to the console if they occur before the logging framework is initialized. */
public static final String ES_STARTUP_SLEEP_TIME_SECONDS = "10";
public static Installation installArchive(Distribution distribution) throws Exception {
return installArchive(distribution, getDefaultArchiveInstallPath(), getCurrentVersion());
}
@ -243,89 +247,109 @@ public class Archives {
).forEach(configFile -> assertThat(es.config(configFile), file(File, owner, owner, p660)));
}
public static void runElasticsearch(Installation installation, Shell sh) throws Exception {
public static Shell.Result runElasticsearchStartCommand(Installation installation, Shell sh) {
final Path pidFile = installation.home.resolve("elasticsearch.pid");
assertFalse("Pid file doesn't exist when starting Elasticsearch", Files.exists(pidFile));
final Installation.Executables bin = installation.executables();
Platforms.onLinux(() -> {
if (Platforms.WINDOWS == false) {
// If jayatana is installed then we try to use it. Elasticsearch should ignore it even when we try.
// If it doesn't ignore it then Elasticsearch will fail to start because of security errors.
// This line is attempting to emulate the on login behavior of /usr/share/upstart/sessions/jayatana.conf
if (Files.exists(Paths.get("/usr/share/java/jayatanaag.jar"))) {
sh.getEnv().put("JAVA_TOOL_OPTIONS", "-javaagent:/usr/share/java/jayatanaag.jar");
}
sh.run("sudo -E -u " + ARCHIVE_OWNER + " " +
bin.elasticsearch + " -d -p " + installation.home.resolve("elasticsearch.pid"));
});
Platforms.onWindows(() -> {
// this starts the server in the background. the -d flag is unsupported on windows
if (System.getenv("username").equals("vagrant")) {
// these tests run as Administrator in vagrant.
// we don't want to run the server as Administrator, so we provide the current user's
// username and password to the process which has the effect of starting it not as Administrator.
sh.run(
"$password = ConvertTo-SecureString 'vagrant' -AsPlainText -Force; " +
"$processInfo = New-Object System.Diagnostics.ProcessStartInfo; " +
"$processInfo.FileName = '" + bin.elasticsearch + "'; " +
"$processInfo.Arguments = '-p " + installation.home.resolve("elasticsearch.pid") + "'; " +
"$processInfo.Username = 'vagrant'; " +
"$processInfo.Password = $password; " +
"$processInfo.RedirectStandardOutput = $true; " +
"$processInfo.RedirectStandardError = $true; " +
sh.env.entrySet().stream()
.map(entry -> "$processInfo.Environment.Add('" + entry.getKey() + "', '" + entry.getValue() + "'); ")
.collect(joining()) +
"$processInfo.UseShellExecute = $false; " +
"$process = New-Object System.Diagnostics.Process; " +
"$process.StartInfo = $processInfo; " +
"$process.Start() | Out-Null; " +
"$process.Id;"
);
} else {
sh.run(
"$processInfo = New-Object System.Diagnostics.ProcessStartInfo; " +
"$processInfo.FileName = '" + bin.elasticsearch + "'; " +
"$processInfo.Arguments = '-p " + installation.home.resolve("elasticsearch.pid") + "'; " +
"$processInfo.RedirectStandardOutput = $true; " +
"$processInfo.RedirectStandardError = $true; " +
sh.env.entrySet().stream()
.map(entry -> "$processInfo.Environment.Add('" + entry.getKey() + "', '" + entry.getValue() + "'); ")
.collect(joining()) +
"$processInfo.UseShellExecute = $false; " +
"$process = New-Object System.Diagnostics.Process; " +
"$process.StartInfo = $processInfo; " +
"$process.Start() | Out-Null; " +
"$process.Id;"
);
}
});
// We need to give Elasticsearch enough time to print failures to stderr before exiting
sh.getEnv().put("ES_STARTUP_SLEEP_TIME", ES_STARTUP_SLEEP_TIME_SECONDS);
return sh.runIgnoreExitCode("sudo -E -u " + ARCHIVE_OWNER + " " + bin.elasticsearch + " -d -p " + pidFile);
}
final Path stdout = getPowershellOutputPath(installation);
final Path stderr = getPowershellErrorPath(installation);
String powerShellProcessUserSetup;
if (System.getenv("username").equals("vagrant")) {
// the tests will run as Administrator in vagrant.
// we don't want to run the server as Administrator, so we provide the current user's
// username and password to the process which has the effect of starting it not as Administrator.
powerShellProcessUserSetup =
"$password = ConvertTo-SecureString 'vagrant' -AsPlainText -Force; " +
"$processInfo.Username = 'vagrant'; " +
"$processInfo.Password = $password; ";
} else {
powerShellProcessUserSetup = "";
}
// this starts the server in the background. the -d flag is unsupported on windows
return sh.run(
"$processInfo = New-Object System.Diagnostics.ProcessStartInfo; " +
"$processInfo.FileName = '" + bin.elasticsearch + "'; " +
"$processInfo.Arguments = '-p " + installation.home.resolve("elasticsearch.pid") + "'; " +
powerShellProcessUserSetup +
"$processInfo.RedirectStandardOutput = $true; " +
"$processInfo.RedirectStandardError = $true; " +
"$processInfo.RedirectStandardInput = $true; " +
sh.env.entrySet().stream()
.map(entry -> "$processInfo.Environment.Add('" + entry.getKey() + "', '" + entry.getValue() + "'); ")
.collect(joining()) +
"$processInfo.UseShellExecute = $false; " +
"$process = New-Object System.Diagnostics.Process; " +
"$process.StartInfo = $processInfo; " +
// set up some asynchronous output handlers
"$outScript = { $EventArgs.Data | Out-File -Encoding UTF8 -Append '" + stdout + "' }; " +
"$errScript = { $EventArgs.Data | Out-File -Encoding UTF8 -Append '" + stderr + "' }; " +
"$stdOutEvent = Register-ObjectEvent -InputObject $process " +
"-Action $outScript -EventName 'OutputDataReceived'; " +
"$stdErrEvent = Register-ObjectEvent -InputObject $process " +
"-Action $errScript -EventName 'ErrorDataReceived'; " +
"$process.Start() | Out-Null; " +
"$process.BeginOutputReadLine(); " +
"$process.BeginErrorReadLine(); " +
"Wait-Process -Timeout " + ES_STARTUP_SLEEP_TIME_SECONDS + " -Id $process.Id; " +
"$process.Id;"
);
}
public static void assertElasticsearchStarted(Installation installation) throws Exception {
final Path pidFile = installation.home.resolve("elasticsearch.pid");
ServerUtils.waitForElasticsearch(installation);
assertTrue("Starting Elasticsearch produced a pid file at " + pidFile, Files.exists(pidFile));
String pid = slurp(pidFile).trim();
assertThat(pid, not(isEmptyOrNullString()));
Platforms.onLinux(() -> sh.run("ps " + pid));
Platforms.onWindows(() -> sh.run("Get-Process -Id " + pid));
assertThat(pid, is(not(emptyOrNullString())));
}
public static void stopElasticsearch(Installation installation) throws Exception {
Path pidFile = installation.home.resolve("elasticsearch.pid");
assertTrue(Files.exists(pidFile));
assertTrue("pid file should exist", Files.exists(pidFile));
String pid = slurp(pidFile).trim();
assertThat(pid, not(isEmptyOrNullString()));
assertThat(pid, is(not(emptyOrNullString())));
final Shell sh = new Shell();
Platforms.onLinux(() -> sh.run("kill -SIGTERM " + pid + "; tail --pid=" + pid + " -f /dev/null"));
Platforms.onWindows(() -> sh.run("Get-Process -Id " + pid + " | Stop-Process -Force; Wait-Process -Id " + pid));
Platforms.onWindows(() -> {
sh.run("Get-Process -Id " + pid + " | Stop-Process -Force; Wait-Process -Id " + pid);
// Clear the asynchronous event handlers
sh.runIgnoreExitCode("Get-EventSubscriber | " +
"where {($_.EventName -eq 'OutputDataReceived' -Or $_.EventName -eq 'ErrorDataReceived' |" +
"Unregister-EventSubscriber -Force");
});
if (Files.exists(pidFile)) {
Files.delete(pidFile);
}
}
public static Path getPowershellErrorPath(Installation installation) {
return installation.logs.resolve("output.err");
}
private static Path getPowershellOutputPath(Installation installation) {
return installation.logs.resolve("output.out");
}
}

View File

@ -166,7 +166,7 @@ public class Docker {
* Waits for the Elasticsearch process to start executing in the container.
* This is called every time a container is started.
*/
private static void waitForElasticsearchToStart() {
public static void waitForElasticsearchToStart() {
boolean isElasticsearchRunning = false;
int attempt = 0;

View File

@ -268,32 +268,17 @@ public class Packages {
).forEach(configFile -> assertThat(es.config(configFile), file(File, "root", "elasticsearch", p660)));
}
public static void startElasticsearch(Shell sh, Installation installation) throws IOException {
/**
* Starts Elasticsearch, without checking that startup is successful.
*/
public static Shell.Result runElasticsearchStartCommand(Shell sh) throws IOException {
if (isSystemd()) {
sh.run("systemctl daemon-reload");
sh.run("systemctl enable elasticsearch.service");
sh.run("systemctl is-enabled elasticsearch.service");
sh.run("systemctl start elasticsearch.service");
} else {
sh.run("service elasticsearch start");
}
assertElasticsearchStarted(sh, installation);
}
/**
* Starts Elasticsearch, without checking that startup is successful. To also check
* that Elasticsearch has started, call {@link #startElasticsearch(Shell, Installation)}.
*/
public static void startElasticsearchIgnoringFailure(Shell sh) {
if (isSystemd()) {
sh.runIgnoreExitCode("systemctl daemon-reload");
sh.runIgnoreExitCode("systemctl enable elasticsearch.service");
sh.runIgnoreExitCode("systemctl is-enabled elasticsearch.service");
sh.runIgnoreExitCode("systemctl start elasticsearch.service");
} else {
sh.runIgnoreExitCode("service elasticsearch start");
return sh.runIgnoreExitCode("systemctl start elasticsearch.service");
}
return sh.runIgnoreExitCode("service elasticsearch start");
}
/**
@ -307,7 +292,7 @@ public class Packages {
}
}
private static void assertElasticsearchStarted(Shell sh, Installation installation) throws IOException {
public static void assertElasticsearchStarted(Shell sh, Installation installation) throws IOException {
waitForElasticsearch(installation);
if (isSystemd()) {
@ -332,7 +317,6 @@ public class Packages {
} else {
sh.run("service elasticsearch restart");
}
waitForElasticsearch(installation);
assertElasticsearchStarted(sh, installation);
}
}

View File

@ -43,6 +43,7 @@ import java.util.stream.Stream;
public class Shell {
public static final int TAIL_WHEN_TOO_MUCH_OUTPUT = 1000;
public static final Result NO_OP = new Shell.Result(0, "","");
protected final Logger logger = LogManager.getLogger(getClass());
final Map<String, String> env = new HashMap<>();