mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-24 17:09:48 +00:00
[test] port archive distribution packaging tests (#31314)
Recreates the rest of the bats packaging tests for the tar distribution in the java packaging test project, with support for both tar and zip packaging, both oss and default flavors, and on Linux and Windows. Most tests are followed fairly closely, some have either been dropped if unnecessary or folded into others if convenient.
This commit is contained in:
parent
8ec33b742d
commit
006c2c9ab0
@ -546,9 +546,15 @@ class VagrantTestPlugin implements Plugin<Project> {
|
||||
javaPackagingTest.command = 'ssh'
|
||||
javaPackagingTest.args = ['--command', 'sudo bash "$PACKAGING_TESTS/run-tests.sh"']
|
||||
} else {
|
||||
// powershell sessions run over winrm always run as administrator, whether --elevated is passed or not. however
|
||||
// remote sessions have some restrictions on what they can do, such as impersonating another user (or the same user
|
||||
// without administrator elevation), which we need to do for these tests. passing --elevated runs the session
|
||||
// as a scheduled job locally on the vm as a true administrator to get around this limitation
|
||||
//
|
||||
// https://github.com/hashicorp/vagrant/blob/9c299a2a357fcf87f356bb9d56e18a037a53d138/plugins/communicators/winrm/communicator.rb#L195-L225
|
||||
// https://devops-collective-inc.gitbooks.io/secrets-of-powershell-remoting/content/manuscript/accessing-remote-computers.html
|
||||
javaPackagingTest.command = 'winrm'
|
||||
// winrm commands run as administrator
|
||||
javaPackagingTest.args = ['--command', 'powershell -File "$Env:PACKAGING_TESTS/run-tests.ps1"']
|
||||
javaPackagingTest.args = ['--elevated', '--command', 'powershell -File "$Env:PACKAGING_TESTS/run-tests.ps1"']
|
||||
}
|
||||
|
||||
TaskExecutionAdapter javaPackagingReproListener = createReproListener(project, javaPackagingTest.path)
|
||||
|
@ -31,6 +31,12 @@ dependencies {
|
||||
compile "org.hamcrest:hamcrest-core:${versions.hamcrest}"
|
||||
compile "org.hamcrest:hamcrest-library:${versions.hamcrest}"
|
||||
|
||||
compile "org.apache.httpcomponents:httpcore:${versions.httpcore}"
|
||||
compile "org.apache.httpcomponents:httpclient:${versions.httpclient}"
|
||||
compile "org.apache.httpcomponents:fluent-hc:${versions.httpclient}"
|
||||
compile "commons-codec:commons-codec:${versions.commonscodec}"
|
||||
compile "commons-logging:commons-logging:${versions.commonslogging}"
|
||||
|
||||
compile project(':libs:core')
|
||||
|
||||
// pulls in the jar built by this project and its dependencies
|
||||
@ -73,3 +79,17 @@ tasks.test.enabled = false
|
||||
// this project doesn't get published
|
||||
tasks.dependencyLicenses.enabled = false
|
||||
tasks.dependenciesInfo.enabled = false
|
||||
|
||||
tasks.thirdPartyAudit.excludes = [
|
||||
//commons-logging optional dependencies
|
||||
'org.apache.avalon.framework.logger.Logger',
|
||||
'org.apache.log.Hierarchy',
|
||||
'org.apache.log.Logger',
|
||||
'org.apache.log4j.Category',
|
||||
'org.apache.log4j.Level',
|
||||
'org.apache.log4j.Logger',
|
||||
'org.apache.log4j.Priority',
|
||||
//commons-logging provided dependencies
|
||||
'javax.servlet.ServletContextEvent',
|
||||
'javax.servlet.ServletContextListener'
|
||||
]
|
||||
|
@ -19,6 +19,12 @@
|
||||
|
||||
package org.elasticsearch.packaging.test;
|
||||
|
||||
import org.apache.http.client.fluent.Request;
|
||||
import org.elasticsearch.packaging.util.Archives;
|
||||
import org.elasticsearch.packaging.util.Platforms;
|
||||
import org.elasticsearch.packaging.util.ServerUtils;
|
||||
import org.elasticsearch.packaging.util.Shell;
|
||||
import org.elasticsearch.packaging.util.Shell.Result;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.FixMethodOrder;
|
||||
@ -28,9 +34,33 @@ import org.junit.runners.MethodSorters;
|
||||
import org.elasticsearch.packaging.util.Distribution;
|
||||
import org.elasticsearch.packaging.util.Installation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.elasticsearch.packaging.util.Archives.ARCHIVE_OWNER;
|
||||
import static org.elasticsearch.packaging.util.Cleanup.cleanEverything;
|
||||
import static org.elasticsearch.packaging.util.Archives.installArchive;
|
||||
import static org.elasticsearch.packaging.util.Archives.verifyArchiveInstallation;
|
||||
import static org.elasticsearch.packaging.util.FileMatcher.Fileness.File;
|
||||
import static org.elasticsearch.packaging.util.FileMatcher.file;
|
||||
import static org.elasticsearch.packaging.util.FileMatcher.p660;
|
||||
import static org.elasticsearch.packaging.util.FileUtils.append;
|
||||
import static org.elasticsearch.packaging.util.FileUtils.cp;
|
||||
import static org.elasticsearch.packaging.util.FileUtils.getTempDir;
|
||||
import static org.elasticsearch.packaging.util.FileUtils.mkdir;
|
||||
import static org.elasticsearch.packaging.util.FileUtils.rm;
|
||||
import static org.elasticsearch.packaging.util.ServerUtils.makeRequest;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.isEmptyString;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeThat;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
/**
|
||||
@ -61,4 +91,226 @@ public abstract class ArchiveTestCase {
|
||||
installation = installArchive(distribution());
|
||||
verifyArchiveInstallation(installation, distribution());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test20PluginsListWithNoPlugins() {
|
||||
assumeThat(installation, is(notNullValue()));
|
||||
|
||||
final Installation.Executables bin = installation.executables();
|
||||
final Shell sh = new Shell();
|
||||
final Result r = sh.run(bin.elasticsearchPlugin + " list");
|
||||
|
||||
assertThat(r.stdout, isEmptyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test30AbortWhenJavaMissing() {
|
||||
assumeThat(installation, is(notNullValue()));
|
||||
|
||||
final Installation.Executables bin = installation.executables();
|
||||
final Shell sh = new Shell();
|
||||
|
||||
Platforms.onWindows(() -> {
|
||||
// on windows, removing java from PATH and removing JAVA_HOME is less involved than changing the permissions of the java
|
||||
// executable. we also don't check permissions in the windows scripts anyway
|
||||
final String originalPath = sh.run("$Env:PATH").stdout.trim();
|
||||
final String newPath = Arrays.stream(originalPath.split(";"))
|
||||
.filter(path -> path.contains("Java") == false)
|
||||
.collect(joining(";"));
|
||||
|
||||
// note the lack of a $ when clearing the JAVA_HOME env variable - with a $ it deletes the java home directory
|
||||
// https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/providers/environment-provider?view=powershell-6
|
||||
//
|
||||
// this won't persist to another session so we don't have to reset anything
|
||||
final Result runResult = sh.runIgnoreExitCode(
|
||||
"$Env:PATH = '" + newPath + "'; " +
|
||||
"Remove-Item Env:JAVA_HOME; " +
|
||||
bin.elasticsearch
|
||||
);
|
||||
|
||||
assertThat(runResult.exitCode, is(1));
|
||||
assertThat(runResult.stderr, containsString("could not find java; set JAVA_HOME or ensure java is in PATH"));
|
||||
});
|
||||
|
||||
Platforms.onLinux(() -> {
|
||||
final String javaPath = sh.run("which java").stdout.trim();
|
||||
|
||||
try {
|
||||
sh.run("chmod -x '" + javaPath + "'");
|
||||
final Result runResult = sh.runIgnoreExitCode(bin.elasticsearch.toString());
|
||||
assertThat(runResult.exitCode, is(1));
|
||||
assertThat(runResult.stdout, containsString("could not find java; set JAVA_HOME or ensure java is in PATH"));
|
||||
} finally {
|
||||
sh.run("chmod +x '" + javaPath + "'");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test40CreateKeystoreManually() {
|
||||
assumeThat(installation, is(notNullValue()));
|
||||
|
||||
final Installation.Executables bin = installation.executables();
|
||||
final Shell sh = new Shell();
|
||||
|
||||
Platforms.onLinux(() -> sh.run("sudo -u " + ARCHIVE_OWNER + " " + bin.elasticsearchKeystore + " create"));
|
||||
|
||||
// this is a hack around the fact that we can't run a command in the same session as the same user but not as administrator.
|
||||
// the keystore ends up being owned by the Administrators group, so we manually set it to be owned by the vagrant user here.
|
||||
// from the server's perspective the permissions aren't really different, this is just to reflect what we'd expect in the tests.
|
||||
// when we run these commands as a role user we won't have to do this
|
||||
Platforms.onWindows(() -> sh.run(
|
||||
bin.elasticsearchKeystore + " create; " +
|
||||
"$account = New-Object System.Security.Principal.NTAccount 'vagrant'; " +
|
||||
"$acl = Get-Acl '" + installation.config("elasticsearch.keystore") + "'; " +
|
||||
"$acl.SetOwner($account); " +
|
||||
"Set-Acl '" + installation.config("elasticsearch.keystore") + "' $acl"
|
||||
));
|
||||
|
||||
assertThat(installation.config("elasticsearch.keystore"), file(File, ARCHIVE_OWNER, ARCHIVE_OWNER, p660));
|
||||
|
||||
Platforms.onLinux(() -> {
|
||||
final Result r = sh.run("sudo -u " + ARCHIVE_OWNER + " " + bin.elasticsearchKeystore + " list");
|
||||
assertThat(r.stdout, containsString("keystore.seed"));
|
||||
});
|
||||
|
||||
Platforms.onWindows(() -> {
|
||||
final Result r = sh.run(bin.elasticsearchKeystore + " list");
|
||||
assertThat(r.stdout, containsString("keystore.seed"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test50StartAndStop() throws IOException {
|
||||
assumeThat(installation, is(notNullValue()));
|
||||
|
||||
// cleanup from previous test
|
||||
rm(installation.config("elasticsearch.keystore"));
|
||||
|
||||
Archives.runElasticsearch(installation);
|
||||
|
||||
final String gcLogName = Platforms.LINUX
|
||||
? "gc.log.0.current"
|
||||
: "gc.log";
|
||||
assertTrue("gc logs exist", Files.exists(installation.logs.resolve(gcLogName)));
|
||||
ServerUtils.runElasticsearchTests();
|
||||
|
||||
Archives.stopElasticsearch(installation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test60AutoCreateKeystore() {
|
||||
assumeThat(installation, is(notNullValue()));
|
||||
|
||||
assertThat(installation.config("elasticsearch.keystore"), file(File, ARCHIVE_OWNER, ARCHIVE_OWNER, p660));
|
||||
|
||||
final Installation.Executables bin = installation.executables();
|
||||
final Shell sh = new Shell();
|
||||
|
||||
Platforms.onLinux(() -> {
|
||||
final Result result = sh.run("sudo -u " + ARCHIVE_OWNER + " " + bin.elasticsearchKeystore + " list");
|
||||
assertThat(result.stdout, containsString("keystore.seed"));
|
||||
});
|
||||
|
||||
Platforms.onWindows(() -> {
|
||||
final Result result = sh.run(bin.elasticsearchKeystore + " list");
|
||||
assertThat(result.stdout, containsString("keystore.seed"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test70CustomPathConfAndJvmOptions() throws IOException {
|
||||
assumeThat(installation, is(notNullValue()));
|
||||
|
||||
final Path tempConf = getTempDir().resolve("esconf-alternate");
|
||||
|
||||
try {
|
||||
mkdir(tempConf);
|
||||
cp(installation.config("elasticsearch.yml"), tempConf.resolve("elasticsearch.yml"));
|
||||
cp(installation.config("log4j2.properties"), tempConf.resolve("log4j2.properties"));
|
||||
|
||||
// we have to disable Log4j from using JMX lest it will hit a security
|
||||
// manager exception before we have configured logging; this will fail
|
||||
// startup since we detect usages of logging before it is configured
|
||||
final String jvmOptions =
|
||||
"-Xms512m\n" +
|
||||
"-Xmx512m\n" +
|
||||
"-Dlog4j2.disable.jmx=true\n";
|
||||
append(tempConf.resolve("jvm.options"), jvmOptions);
|
||||
|
||||
final Shell sh = new Shell();
|
||||
Platforms.onLinux(() -> sh.run("chown -R elasticsearch:elasticsearch " + tempConf));
|
||||
Platforms.onWindows(() -> sh.run(
|
||||
"$account = New-Object System.Security.Principal.NTAccount 'vagrant'; " +
|
||||
"$tempConf = Get-ChildItem '" + tempConf + "' -Recurse; " +
|
||||
"$tempConf += Get-Item '" + tempConf + "'; " +
|
||||
"$tempConf | ForEach-Object { " +
|
||||
"$acl = Get-Acl $_.FullName; " +
|
||||
"$acl.SetOwner($account); " +
|
||||
"Set-Acl $_.FullName $acl " +
|
||||
"}"
|
||||
));
|
||||
|
||||
final Shell serverShell = new Shell();
|
||||
serverShell.getEnv().put("ES_PATH_CONF", tempConf.toString());
|
||||
serverShell.getEnv().put("ES_JAVA_OPTS", "-XX:-UseCompressedOops");
|
||||
|
||||
Archives.runElasticsearch(installation, serverShell);
|
||||
|
||||
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\""));
|
||||
|
||||
Archives.stopElasticsearch(installation);
|
||||
|
||||
} finally {
|
||||
rm(tempConf);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test80RelativePathConf() throws IOException {
|
||||
assumeThat(installation, is(notNullValue()));
|
||||
|
||||
final Path temp = getTempDir().resolve("esconf-alternate");
|
||||
final Path tempConf = temp.resolve("config");
|
||||
|
||||
try {
|
||||
mkdir(tempConf);
|
||||
Stream.of(
|
||||
"elasticsearch.yml",
|
||||
"log4j2.properties",
|
||||
"jvm.options"
|
||||
).forEach(file -> cp(installation.config(file), tempConf.resolve(file)));
|
||||
|
||||
append(tempConf.resolve("elasticsearch.yml"), "node.name: relative");
|
||||
|
||||
final Shell sh = new Shell();
|
||||
Platforms.onLinux(() -> sh.run("chown -R elasticsearch:elasticsearch " + temp));
|
||||
Platforms.onWindows(() -> sh.run(
|
||||
"$account = New-Object System.Security.Principal.NTAccount 'vagrant'; " +
|
||||
"$tempConf = Get-ChildItem '" + temp + "' -Recurse; " +
|
||||
"$tempConf += Get-Item '" + temp + "'; " +
|
||||
"$tempConf | ForEach-Object { " +
|
||||
"$acl = Get-Acl $_.FullName; " +
|
||||
"$acl.SetOwner($account); " +
|
||||
"Set-Acl $_.FullName $acl " +
|
||||
"}"
|
||||
));
|
||||
|
||||
final Shell serverShell = new Shell(temp);
|
||||
serverShell.getEnv().put("ES_PATH_CONF", "config");
|
||||
Archives.runElasticsearch(installation, serverShell);
|
||||
|
||||
final String nodesResponse = makeRequest(Request.Get("http://localhost:9200/_nodes"));
|
||||
assertThat(nodesResponse, containsString("\"name\":\"relative\""));
|
||||
|
||||
Archives.stopElasticsearch(installation);
|
||||
|
||||
} finally {
|
||||
rm(tempConf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -19,11 +19,14 @@
|
||||
|
||||
package org.elasticsearch.packaging.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.elasticsearch.packaging.util.FileMatcher.Fileness.Directory;
|
||||
import static org.elasticsearch.packaging.util.FileMatcher.Fileness.File;
|
||||
import static org.elasticsearch.packaging.util.FileMatcher.file;
|
||||
@ -36,17 +39,26 @@ import static org.elasticsearch.packaging.util.FileUtils.getPackagingArchivesDir
|
||||
import static org.elasticsearch.packaging.util.FileUtils.lsGlob;
|
||||
|
||||
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.core.Is.is;
|
||||
import static org.hamcrest.collection.IsEmptyCollection.empty;
|
||||
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Installation and verification logic for archive distributions
|
||||
*/
|
||||
public class Archives {
|
||||
|
||||
// in the future we'll run as a role user on Windows
|
||||
public static final String ARCHIVE_OWNER = Platforms.WINDOWS
|
||||
? "vagrant"
|
||||
: "elasticsearch";
|
||||
|
||||
public static Installation installArchive(Distribution distribution) {
|
||||
return installArchive(distribution, getDefaultArchiveInstallPath(), getCurrentVersion());
|
||||
}
|
||||
@ -63,22 +75,20 @@ public class Archives {
|
||||
|
||||
if (distribution.packaging == Distribution.Packaging.TAR) {
|
||||
|
||||
if (Platforms.LINUX) {
|
||||
sh.bash("tar -C " + baseInstallPath + " -xzpf " + distributionFile);
|
||||
} else {
|
||||
Platforms.onLinux(() -> sh.run("tar -C " + baseInstallPath + " -xzpf " + distributionFile));
|
||||
|
||||
if (Platforms.WINDOWS) {
|
||||
throw new RuntimeException("Distribution " + distribution + " is not supported on windows");
|
||||
}
|
||||
|
||||
} else if (distribution.packaging == Distribution.Packaging.ZIP) {
|
||||
|
||||
if (Platforms.LINUX) {
|
||||
sh.bash("unzip " + distributionFile + " -d " + baseInstallPath);
|
||||
} else {
|
||||
sh.powershell(
|
||||
"Add-Type -AssemblyName 'System.IO.Compression.Filesystem'; " +
|
||||
"[IO.Compression.ZipFile]::ExtractToDirectory('" + distributionFile + "', '" + baseInstallPath + "')"
|
||||
);
|
||||
}
|
||||
Platforms.onLinux(() -> sh.run("unzip " + distributionFile + " -d " + baseInstallPath));
|
||||
|
||||
Platforms.onWindows(() -> sh.run(
|
||||
"Add-Type -AssemblyName 'System.IO.Compression.Filesystem'; " +
|
||||
"[IO.Compression.ZipFile]::ExtractToDirectory('" + distributionFile + "', '" + baseInstallPath + "')"
|
||||
));
|
||||
|
||||
} else {
|
||||
throw new RuntimeException("Distribution " + distribution + " is not a known archive type");
|
||||
@ -93,9 +103,8 @@ public class Archives {
|
||||
assertThat("only the intended installation exists", installations, hasSize(1));
|
||||
assertThat("only the intended installation exists", installations.get(0), is(fullInstallPath));
|
||||
|
||||
if (Platforms.LINUX) {
|
||||
setupArchiveUsersLinux(fullInstallPath);
|
||||
}
|
||||
Platforms.onLinux(() -> setupArchiveUsersLinux(fullInstallPath));
|
||||
Platforms.onWindows(() -> setupArchiveUsersWindows(fullInstallPath));
|
||||
|
||||
return new Installation(fullInstallPath);
|
||||
}
|
||||
@ -103,17 +112,17 @@ public class Archives {
|
||||
private static void setupArchiveUsersLinux(Path installPath) {
|
||||
final Shell sh = new Shell();
|
||||
|
||||
if (sh.bashIgnoreExitCode("getent group elasticsearch").isSuccess() == false) {
|
||||
if (sh.runIgnoreExitCode("getent group elasticsearch").isSuccess() == false) {
|
||||
if (isDPKG()) {
|
||||
sh.bash("addgroup --system elasticsearch");
|
||||
sh.run("addgroup --system elasticsearch");
|
||||
} else {
|
||||
sh.bash("groupadd -r elasticsearch");
|
||||
sh.run("groupadd -r elasticsearch");
|
||||
}
|
||||
}
|
||||
|
||||
if (sh.bashIgnoreExitCode("id elasticsearch").isSuccess() == false) {
|
||||
if (sh.runIgnoreExitCode("id elasticsearch").isSuccess() == false) {
|
||||
if (isDPKG()) {
|
||||
sh.bash("adduser " +
|
||||
sh.run("adduser " +
|
||||
"--quiet " +
|
||||
"--system " +
|
||||
"--no-create-home " +
|
||||
@ -122,7 +131,7 @@ public class Archives {
|
||||
"--shell /bin/false " +
|
||||
"elasticsearch");
|
||||
} else {
|
||||
sh.bash("useradd " +
|
||||
sh.run("useradd " +
|
||||
"--system " +
|
||||
"-M " +
|
||||
"--gid elasticsearch " +
|
||||
@ -131,20 +140,29 @@ public class Archives {
|
||||
"elasticsearch");
|
||||
}
|
||||
}
|
||||
sh.bash("chown -R elasticsearch:elasticsearch " + installPath);
|
||||
sh.run("chown -R elasticsearch:elasticsearch " + installPath);
|
||||
}
|
||||
|
||||
private static void setupArchiveUsersWindows(Path installPath) {
|
||||
// we want the installation to be owned as the vagrant user rather than the Administrators group
|
||||
|
||||
final Shell sh = new Shell();
|
||||
sh.run(
|
||||
"$account = New-Object System.Security.Principal.NTAccount 'vagrant'; " +
|
||||
"$install = Get-ChildItem -Path '" + installPath + "' -Recurse; " +
|
||||
"$install += Get-Item -Path '" + installPath + "'; " +
|
||||
"$install | ForEach-Object { " +
|
||||
"$acl = Get-Acl $_.FullName; " +
|
||||
"$acl.SetOwner($account); " +
|
||||
"Set-Acl $_.FullName $acl " +
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
public static void verifyArchiveInstallation(Installation installation, Distribution distribution) {
|
||||
// on Windows for now we leave the installation owned by the vagrant user that the tests run as. Since the vagrant account
|
||||
// is a local administrator, the files really end up being owned by the local administrators group. In the future we'll
|
||||
// install and run elasticesearch with a role user on Windows
|
||||
final String owner = Platforms.WINDOWS
|
||||
? "BUILTIN\\Administrators"
|
||||
: "elasticsearch";
|
||||
|
||||
verifyOssInstallation(installation, distribution, owner);
|
||||
verifyOssInstallation(installation, distribution, ARCHIVE_OWNER);
|
||||
if (distribution.flavor == Distribution.Flavor.DEFAULT) {
|
||||
verifyDefaultInstallation(installation, distribution, owner);
|
||||
verifyDefaultInstallation(installation, distribution, ARCHIVE_OWNER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,38 +178,38 @@ public class Archives {
|
||||
assertThat(Files.exists(es.data), is(false));
|
||||
assertThat(Files.exists(es.scripts), is(false));
|
||||
|
||||
assertThat(es.home.resolve("bin"), file(Directory, owner, owner, p755));
|
||||
assertThat(es.home.resolve("lib"), file(Directory, owner, owner, p755));
|
||||
assertThat(Files.exists(es.config.resolve("elasticsearch.keystore")), is(false));
|
||||
assertThat(es.bin, file(Directory, owner, owner, p755));
|
||||
assertThat(es.lib, file(Directory, owner, owner, p755));
|
||||
assertThat(Files.exists(es.config("elasticsearch.keystore")), is(false));
|
||||
|
||||
Stream.of(
|
||||
"bin/elasticsearch",
|
||||
"bin/elasticsearch-env",
|
||||
"bin/elasticsearch-keystore",
|
||||
"bin/elasticsearch-plugin",
|
||||
"bin/elasticsearch-translog"
|
||||
"elasticsearch",
|
||||
"elasticsearch-env",
|
||||
"elasticsearch-keystore",
|
||||
"elasticsearch-plugin",
|
||||
"elasticsearch-translog"
|
||||
).forEach(executable -> {
|
||||
|
||||
assertThat(es.home.resolve(executable), file(File, owner, owner, p755));
|
||||
assertThat(es.bin(executable), file(File, owner, owner, p755));
|
||||
|
||||
if (distribution.packaging == Distribution.Packaging.ZIP) {
|
||||
assertThat(es.home.resolve(executable + ".bat"), file(File, owner));
|
||||
assertThat(es.bin(executable + ".bat"), file(File, owner));
|
||||
}
|
||||
});
|
||||
|
||||
if (distribution.packaging == Distribution.Packaging.ZIP) {
|
||||
Stream.of(
|
||||
"bin/elasticsearch-service.bat",
|
||||
"bin/elasticsearch-service-mgr.exe",
|
||||
"bin/elasticsearch-service-x64.exe"
|
||||
).forEach(executable -> assertThat(es.home.resolve(executable), file(File, owner)));
|
||||
"elasticsearch-service.bat",
|
||||
"elasticsearch-service-mgr.exe",
|
||||
"elasticsearch-service-x64.exe"
|
||||
).forEach(executable -> assertThat(es.bin(executable), file(File, owner)));
|
||||
}
|
||||
|
||||
Stream.of(
|
||||
"elasticsearch.yml",
|
||||
"jvm.options",
|
||||
"log4j2.properties"
|
||||
).forEach(config -> assertThat(es.config.resolve(config), file(File, owner, owner, p660)));
|
||||
).forEach(config -> assertThat(es.config(config), file(File, owner, owner, p660)));
|
||||
|
||||
Stream.of(
|
||||
"NOTICE.txt",
|
||||
@ -203,30 +221,30 @@ public class Archives {
|
||||
private static void verifyDefaultInstallation(Installation es, Distribution distribution, String owner) {
|
||||
|
||||
Stream.of(
|
||||
"bin/elasticsearch-certgen",
|
||||
"bin/elasticsearch-certutil",
|
||||
"bin/elasticsearch-croneval",
|
||||
"bin/elasticsearch-migrate",
|
||||
"bin/elasticsearch-saml-metadata",
|
||||
"bin/elasticsearch-setup-passwords",
|
||||
"bin/elasticsearch-sql-cli",
|
||||
"bin/elasticsearch-syskeygen",
|
||||
"bin/elasticsearch-users",
|
||||
"bin/x-pack-env",
|
||||
"bin/x-pack-security-env",
|
||||
"bin/x-pack-watcher-env"
|
||||
"elasticsearch-certgen",
|
||||
"elasticsearch-certutil",
|
||||
"elasticsearch-croneval",
|
||||
"elasticsearch-migrate",
|
||||
"elasticsearch-saml-metadata",
|
||||
"elasticsearch-setup-passwords",
|
||||
"elasticsearch-sql-cli",
|
||||
"elasticsearch-syskeygen",
|
||||
"elasticsearch-users",
|
||||
"x-pack-env",
|
||||
"x-pack-security-env",
|
||||
"x-pack-watcher-env"
|
||||
).forEach(executable -> {
|
||||
|
||||
assertThat(es.home.resolve(executable), file(File, owner, owner, p755));
|
||||
assertThat(es.bin(executable), file(File, owner, owner, p755));
|
||||
|
||||
if (distribution.packaging == Distribution.Packaging.ZIP) {
|
||||
assertThat(es.home.resolve(executable + ".bat"), file(File, owner));
|
||||
assertThat(es.bin(executable + ".bat"), file(File, owner));
|
||||
}
|
||||
});
|
||||
|
||||
// at this time we only install the current version of archive distributions, but if that changes we'll need to pass
|
||||
// the version through here
|
||||
assertThat(es.home.resolve("bin/elasticsearch-sql-cli-" + getCurrentVersion() + ".jar"), file(File, owner, owner, p755));
|
||||
assertThat(es.bin("elasticsearch-sql-cli-" + getCurrentVersion() + ".jar"), file(File, owner, owner, p755));
|
||||
|
||||
Stream.of(
|
||||
"users",
|
||||
@ -234,7 +252,72 @@ public class Archives {
|
||||
"roles.yml",
|
||||
"role_mapping.yml",
|
||||
"log4j2.properties"
|
||||
).forEach(config -> assertThat(es.config.resolve(config), file(File, owner, owner, p660)));
|
||||
).forEach(config -> assertThat(es.config(config), file(File, owner, owner, p660)));
|
||||
}
|
||||
|
||||
public static void runElasticsearch(Installation installation) throws IOException {
|
||||
runElasticsearch(installation, new Shell());
|
||||
}
|
||||
|
||||
public static void runElasticsearch(Installation installation, Shell sh) throws IOException {
|
||||
final Path pidFile = installation.home.resolve("elasticsearch.pid");
|
||||
|
||||
final Installation.Executables bin = installation.executables();
|
||||
|
||||
Platforms.onLinux(() -> {
|
||||
// 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
|
||||
// these tests run as Administrator. 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;"
|
||||
);
|
||||
});
|
||||
|
||||
ServerUtils.waitForElasticsearch();
|
||||
|
||||
assertTrue(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));
|
||||
}
|
||||
|
||||
public static void stopElasticsearch(Installation installation) {
|
||||
Path pidFile = installation.home.resolve("elasticsearch.pid");
|
||||
assertTrue(Files.exists(pidFile));
|
||||
String pid = slurp(pidFile).trim();
|
||||
assertThat(pid, not(isEmptyOrNullString()));
|
||||
|
||||
final Shell sh = new Shell();
|
||||
Platforms.onLinux(() -> sh.run("kill -SIGTERM " + pid));
|
||||
Platforms.onWindows(() -> sh.run("Get-Process -Id " + pid + " | Stop-Process -Force"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -56,31 +56,28 @@ public class Cleanup {
|
||||
final Shell sh = new Shell();
|
||||
|
||||
// kill elasticsearch processes
|
||||
if (Platforms.WINDOWS) {
|
||||
Platforms.onLinux(() -> {
|
||||
sh.runIgnoreExitCode("pkill -u elasticsearch");
|
||||
sh.runIgnoreExitCode("ps aux | grep -i 'org.elasticsearch.bootstrap.Elasticsearch' | awk {'print $2'} | xargs kill -9");
|
||||
});
|
||||
|
||||
Platforms.onWindows(() -> {
|
||||
// the view of processes returned by Get-Process doesn't expose command line arguments, so we use WMI here
|
||||
sh.powershellIgnoreExitCode(
|
||||
sh.runIgnoreExitCode(
|
||||
"Get-WmiObject Win32_Process | " +
|
||||
"Where-Object { $_.CommandLine -Match 'org.elasticsearch.bootstrap.Elasticsearch' } | " +
|
||||
"ForEach-Object { $_.Terminate() }"
|
||||
);
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
sh.bashIgnoreExitCode("pkill -u elasticsearch");
|
||||
sh.bashIgnoreExitCode("ps aux | grep -i 'org.elasticsearch.bootstrap.Elasticsearch' | awk {'print $2'} | xargs kill -9");
|
||||
|
||||
}
|
||||
|
||||
if (Platforms.LINUX) {
|
||||
purgePackagesLinux();
|
||||
}
|
||||
Platforms.onLinux(Cleanup::purgePackagesLinux);
|
||||
|
||||
// remove elasticsearch users
|
||||
if (Platforms.LINUX) {
|
||||
sh.bashIgnoreExitCode("userdel elasticsearch");
|
||||
sh.bashIgnoreExitCode("groupdel elasticsearch");
|
||||
}
|
||||
Platforms.onLinux(() -> {
|
||||
sh.runIgnoreExitCode("userdel elasticsearch");
|
||||
sh.runIgnoreExitCode("groupdel elasticsearch");
|
||||
});
|
||||
// when we run es as a role user on windows, add the equivalent here
|
||||
|
||||
// delete files that may still exist
|
||||
lsGlob(getTempDir(), "elasticsearch*").forEach(FileUtils::rm);
|
||||
@ -95,7 +92,7 @@ public class Cleanup {
|
||||
// disable elasticsearch service
|
||||
// todo add this for windows when adding tests for service intallation
|
||||
if (Platforms.LINUX && isSystemd()) {
|
||||
sh.bash("systemctl unmask systemd-sysctl.service");
|
||||
sh.run("systemctl unmask systemd-sysctl.service");
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,19 +100,19 @@ public class Cleanup {
|
||||
final Shell sh = new Shell();
|
||||
|
||||
if (isRPM()) {
|
||||
sh.bashIgnoreExitCode("rpm --quiet -e elasticsearch elasticsearch-oss");
|
||||
sh.runIgnoreExitCode("rpm --quiet -e elasticsearch elasticsearch-oss");
|
||||
}
|
||||
|
||||
if (isYUM()) {
|
||||
sh.bashIgnoreExitCode("yum remove -y elasticsearch elasticsearch-oss");
|
||||
sh.runIgnoreExitCode("yum remove -y elasticsearch elasticsearch-oss");
|
||||
}
|
||||
|
||||
if (isDPKG()) {
|
||||
sh.bashIgnoreExitCode("dpkg --purge elasticsearch elasticsearch-oss");
|
||||
sh.runIgnoreExitCode("dpkg --purge elasticsearch elasticsearch-oss");
|
||||
}
|
||||
|
||||
if (isAptGet()) {
|
||||
sh.bashIgnoreExitCode("apt-get --quiet --yes purge elasticsearch elasticsearch-oss");
|
||||
sh.runIgnoreExitCode("apt-get --quiet --yes purge elasticsearch elasticsearch-oss");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,14 @@ package org.elasticsearch.packaging.util;
|
||||
|
||||
import org.elasticsearch.core.internal.io.IOUtils;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.attribute.FileOwnerAttributeView;
|
||||
import java.nio.file.attribute.PosixFileAttributes;
|
||||
@ -63,6 +66,22 @@ public class FileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static Path mkdir(Path path) {
|
||||
try {
|
||||
return Files.createDirectories(path);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Path cp(Path source, Path target) {
|
||||
try {
|
||||
return Files.copy(source, target);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Path mv(Path source, Path target) {
|
||||
try {
|
||||
return Files.move(source, target);
|
||||
@ -71,9 +90,19 @@ public class FileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void append(Path file, String text) {
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8,
|
||||
StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
|
||||
|
||||
writer.write(text);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String slurp(Path file) {
|
||||
try {
|
||||
return String.join("\n", Files.readAllLines(file));
|
||||
return String.join("\n", Files.readAllLines(file, StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ import java.nio.file.Path;
|
||||
public class Installation {
|
||||
|
||||
public final Path home;
|
||||
public final Path bin; // this isn't a first-class installation feature but we include it for convenience
|
||||
public final Path lib; // same
|
||||
public final Path config;
|
||||
public final Path data;
|
||||
public final Path logs;
|
||||
@ -36,6 +38,9 @@ public class Installation {
|
||||
|
||||
public Installation(Path home, Path config, Path data, Path logs, Path plugins, Path modules, Path scripts) {
|
||||
this.home = home;
|
||||
this.bin = home.resolve("bin");
|
||||
this.lib = home.resolve("lib");
|
||||
|
||||
this.config = config;
|
||||
this.data = data;
|
||||
this.logs = logs;
|
||||
@ -55,4 +60,31 @@ public class Installation {
|
||||
home.resolve("scripts")
|
||||
);
|
||||
}
|
||||
|
||||
public Path bin(String executableName) {
|
||||
return bin.resolve(executableName);
|
||||
}
|
||||
|
||||
public Path config(String configFileName) {
|
||||
return config.resolve(configFileName);
|
||||
}
|
||||
|
||||
public Executables executables() {
|
||||
return new Executables();
|
||||
}
|
||||
|
||||
public class Executables {
|
||||
|
||||
public final Path elasticsearch = platformExecutable("elasticsearch");
|
||||
public final Path elasticsearchPlugin = platformExecutable("elasticsearch-plugin");
|
||||
public final Path elasticsearchKeystore = platformExecutable("elasticsearch-keystore");
|
||||
public final Path elasticsearchTranslog = platformExecutable("elasticsearch-translog");
|
||||
|
||||
private Path platformExecutable(String name) {
|
||||
final String platformExecutableName = Platforms.WINDOWS
|
||||
? name + ".bat"
|
||||
: name;
|
||||
return bin(platformExecutableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,41 +28,61 @@ public class Platforms {
|
||||
if (WINDOWS) {
|
||||
return false;
|
||||
}
|
||||
return new Shell().bashIgnoreExitCode("which dpkg").isSuccess();
|
||||
return new Shell().runIgnoreExitCode("which dpkg").isSuccess();
|
||||
}
|
||||
|
||||
public static boolean isAptGet() {
|
||||
if (WINDOWS) {
|
||||
return false;
|
||||
}
|
||||
return new Shell().bashIgnoreExitCode("which apt-get").isSuccess();
|
||||
return new Shell().runIgnoreExitCode("which apt-get").isSuccess();
|
||||
}
|
||||
|
||||
public static boolean isRPM() {
|
||||
if (WINDOWS) {
|
||||
return false;
|
||||
}
|
||||
return new Shell().bashIgnoreExitCode("which rpm").isSuccess();
|
||||
return new Shell().runIgnoreExitCode("which rpm").isSuccess();
|
||||
}
|
||||
|
||||
public static boolean isYUM() {
|
||||
if (WINDOWS) {
|
||||
return false;
|
||||
}
|
||||
return new Shell().bashIgnoreExitCode("which yum").isSuccess();
|
||||
return new Shell().runIgnoreExitCode("which yum").isSuccess();
|
||||
}
|
||||
|
||||
public static boolean isSystemd() {
|
||||
if (WINDOWS) {
|
||||
return false;
|
||||
}
|
||||
return new Shell().bashIgnoreExitCode("which systemctl").isSuccess();
|
||||
return new Shell().runIgnoreExitCode("which systemctl").isSuccess();
|
||||
}
|
||||
|
||||
public static boolean isSysVInit() {
|
||||
if (WINDOWS) {
|
||||
return false;
|
||||
}
|
||||
return new Shell().bashIgnoreExitCode("which service").isSuccess();
|
||||
return new Shell().runIgnoreExitCode("which service").isSuccess();
|
||||
}
|
||||
|
||||
public static void onWindows(PlatformAction action) {
|
||||
if (WINDOWS) {
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
|
||||
public static void onLinux(PlatformAction action) {
|
||||
if (LINUX) {
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Essentially a Runnable, but we make the distinction so it's more clear that these are synchronous
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface PlatformAction {
|
||||
void run();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.packaging.util;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.fluent.Request;
|
||||
import org.apache.http.conn.HttpHostConnectException;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class ServerUtils {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(ServerUtils.class);
|
||||
|
||||
private static final long waitTime = TimeUnit.SECONDS.toMillis(60);
|
||||
private static final long timeoutLength = TimeUnit.SECONDS.toMillis(10);
|
||||
|
||||
public static void waitForElasticsearch() throws IOException {
|
||||
waitForElasticsearch("green", null);
|
||||
}
|
||||
|
||||
public static void waitForElasticsearch(String status, String index) throws IOException {
|
||||
|
||||
Objects.requireNonNull(status);
|
||||
|
||||
// we loop here rather than letting httpclient handle retries so we can measure the entire waiting time
|
||||
final long startTime = System.currentTimeMillis();
|
||||
long timeElapsed = 0;
|
||||
boolean started = false;
|
||||
while (started == false && timeElapsed < waitTime) {
|
||||
try {
|
||||
|
||||
final HttpResponse response = Request.Get("http://localhost:9200/_cluster/health")
|
||||
.connectTimeout((int) timeoutLength)
|
||||
.socketTimeout((int) timeoutLength)
|
||||
.execute()
|
||||
.returnResponse();
|
||||
|
||||
if (response.getStatusLine().getStatusCode() >= 300) {
|
||||
final String statusLine = response.getStatusLine().toString();
|
||||
final String body = EntityUtils.toString(response.getEntity());
|
||||
throw new RuntimeException("Connecting to elasticsearch cluster health API failed:\n" + statusLine+ "\n" + body);
|
||||
}
|
||||
|
||||
started = true;
|
||||
|
||||
} catch (HttpHostConnectException e) {
|
||||
// we want to retry if the connection is refused
|
||||
LOG.info("Got connection refused when waiting for cluster health", e);
|
||||
}
|
||||
|
||||
timeElapsed = System.currentTimeMillis() - startTime;
|
||||
}
|
||||
|
||||
if (started == false) {
|
||||
throw new RuntimeException("Elasticsearch did not start");
|
||||
}
|
||||
|
||||
final String url;
|
||||
if (index == null) {
|
||||
url = "http://localhost:9200/_cluster/health?wait_for_status=" + status + "&timeout=60s&pretty";
|
||||
} else {
|
||||
url = "http://localhost:9200/_cluster/health/" + index + "?wait_for_status=" + status + "&timeout=60s&pretty";
|
||||
|
||||
}
|
||||
|
||||
final String body = makeRequest(Request.Get(url));
|
||||
assertThat("cluster health response must contain desired status", body, containsString(status));
|
||||
}
|
||||
|
||||
public static void runElasticsearchTests() throws IOException {
|
||||
makeRequest(
|
||||
Request.Post("http://localhost:9200/library/book/1?refresh=true&pretty")
|
||||
.bodyString("{ \"title\": \"Book #1\", \"pages\": 123 }", ContentType.APPLICATION_JSON));
|
||||
|
||||
makeRequest(
|
||||
Request.Post("http://localhost:9200/library/book/2?refresh=true&pretty")
|
||||
.bodyString("{ \"title\": \"Book #2\", \"pages\": 456 }", ContentType.APPLICATION_JSON));
|
||||
|
||||
String count = makeRequest(Request.Get("http://localhost:9200/_count?pretty"));
|
||||
assertThat(count, containsString("\"count\" : 2"));
|
||||
|
||||
makeRequest(Request.Delete("http://localhost:9200/_all"));
|
||||
}
|
||||
|
||||
public static String makeRequest(Request request) throws IOException {
|
||||
final HttpResponse response = request.execute().returnResponse();
|
||||
final String body = EntityUtils.toString(response.getEntity());
|
||||
|
||||
if (response.getStatusLine().getStatusCode() >= 300) {
|
||||
throw new RuntimeException("Request failed:\n" + response.getStatusLine().toString() + "\n" + body);
|
||||
}
|
||||
|
||||
return body;
|
||||
|
||||
}
|
||||
}
|
@ -58,58 +58,50 @@ public class Shell {
|
||||
this.workingDirectory = workingDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a script in a bash shell, throwing an exception if its exit code is nonzero
|
||||
*/
|
||||
public Result bash(String script) {
|
||||
return run(bashCommand(script));
|
||||
public Map<String, String> getEnv() {
|
||||
return env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a script in a bash shell
|
||||
* Run the provided string as a shell script. On Linux the {@code bash -c [script]} syntax will be used, and on Windows
|
||||
* the {@code powershell.exe -Command [script]} syntax will be used. Throws an exception if the exit code of the script is nonzero
|
||||
*/
|
||||
public Result bashIgnoreExitCode(String script) {
|
||||
return runIgnoreExitCode(bashCommand(script));
|
||||
public Result run(String script) {
|
||||
return runScript(getScriptCommand(script));
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #run(String)}, but does not throw an exception if the exit code of the script is nonzero
|
||||
*/
|
||||
public Result runIgnoreExitCode(String script) {
|
||||
return runScriptIgnoreExitCode(getScriptCommand(script));
|
||||
}
|
||||
|
||||
private String[] getScriptCommand(String script) {
|
||||
if (Platforms.WINDOWS) {
|
||||
return powershellCommand(script);
|
||||
} else {
|
||||
return bashCommand(script);
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] bashCommand(String script) {
|
||||
return Stream.concat(Stream.of("bash", "-c"), Stream.of(script)).toArray(String[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a script in a powershell shell, throwing an exception if its exit code is nonzero
|
||||
*/
|
||||
public Result powershell(String script) {
|
||||
return run(powershellCommand(script));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a script in a powershell shell
|
||||
*/
|
||||
public Result powershellIgnoreExitCode(String script) {
|
||||
return runIgnoreExitCode(powershellCommand(script));
|
||||
}
|
||||
|
||||
private static String[] powershellCommand(String script) {
|
||||
return Stream.concat(Stream.of("powershell.exe", "-Command"), Stream.of(script)).toArray(String[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an executable file, passing all elements of {@code command} after the first as arguments. Throws an exception if the process'
|
||||
* exit code is nonzero
|
||||
*/
|
||||
private Result run(String[] command) {
|
||||
Result result = runIgnoreExitCode(command);
|
||||
private Result runScript(String[] command) {
|
||||
Result result = runScriptIgnoreExitCode(command);
|
||||
if (result.isSuccess() == false) {
|
||||
throw new RuntimeException("Command was not successful: [" + String.join(" ", command) + "] result: " + result.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an executable file, passing all elements of {@code command} after the first as arguments
|
||||
*/
|
||||
private Result runIgnoreExitCode(String[] command) {
|
||||
private Result runScriptIgnoreExitCode(String[] command) {
|
||||
ProcessBuilder builder = new ProcessBuilder();
|
||||
builder.command(command);
|
||||
|
||||
|
@ -1,178 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
# This file is used to test the tar gz package.
|
||||
|
||||
# WARNING: This testing file must be executed as root and can
|
||||
# dramatically change your system. It should only be executed
|
||||
# in a throw-away VM like those made by the Vagrantfile at
|
||||
# the root of the Elasticsearch source code. This should
|
||||
# cause the script to fail if it is executed any other way:
|
||||
[ -f /etc/is_vagrant_vm ] || {
|
||||
>&2 echo "must be run on a vagrant VM"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# The test case can be executed with the Bash Automated
|
||||
# Testing System tool available at https://github.com/sstephenson/bats
|
||||
# Thanks to Sam Stephenson!
|
||||
|
||||
# Licensed to Elasticsearch under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright
|
||||
# ownership. Elasticsearch licenses this file to you under
|
||||
# the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Load test utilities
|
||||
load $BATS_UTILS/utils.bash
|
||||
load $BATS_UTILS/tar.bash
|
||||
load $BATS_UTILS/plugins.bash
|
||||
|
||||
setup() {
|
||||
skip_not_tar_gz
|
||||
export ESHOME=/tmp/elasticsearch
|
||||
export_elasticsearch_paths
|
||||
}
|
||||
|
||||
##################################
|
||||
# Install TAR GZ package
|
||||
##################################
|
||||
@test "[TAR] tar command is available" {
|
||||
# Cleans everything for the 1st execution
|
||||
clean_before_test
|
||||
run tar --version
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "[TAR] archive is available" {
|
||||
local version=$(cat version)
|
||||
count=$(find . -type f -name "${PACKAGE_NAME}-${version}.tar.gz" | wc -l)
|
||||
[ "$count" -eq 1 ]
|
||||
}
|
||||
|
||||
@test "[TAR] archive is not installed" {
|
||||
count=$(find /tmp -type d -name 'elasticsearch*' | wc -l)
|
||||
[ "$count" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "[TAR] install archive" {
|
||||
# Install the archive
|
||||
install_archive
|
||||
set_debug_logging
|
||||
|
||||
count=$(find /tmp -type d -name 'elasticsearch*' | wc -l)
|
||||
[ "$count" -eq 1 ]
|
||||
|
||||
# Its simpler to check that the install was correct in this test rather
|
||||
# than in another test because install_archive sets a number of path
|
||||
# variables that verify_archive_installation reads. To separate this into
|
||||
# another test you'd have to recreate the variables.
|
||||
verify_archive_installation
|
||||
}
|
||||
|
||||
@test "[TAR] verify elasticsearch-plugin list runs without any plugins installed" {
|
||||
# previously this would fail because the archive installations did
|
||||
# not create an empty plugins directory
|
||||
local plugins_list=`$ESHOME/bin/elasticsearch-plugin list`
|
||||
[[ -z $plugins_list ]]
|
||||
}
|
||||
|
||||
@test "[TAR] elasticsearch fails if java executable is not found" {
|
||||
local JAVA=$(which java)
|
||||
|
||||
sudo chmod -x $JAVA
|
||||
run "$ESHOME/bin/elasticsearch"
|
||||
sudo chmod +x $JAVA
|
||||
|
||||
[ "$status" -eq 1 ]
|
||||
local expected="could not find java; set JAVA_HOME or ensure java is in PATH"
|
||||
[[ "$output" == *"$expected"* ]] || {
|
||||
echo "Expected error message [$expected] but found: $output"
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@test "[TAR] test creating elasticearch.keystore" {
|
||||
sudo -E -u elasticsearch "$ESHOME/bin/elasticsearch-keystore" create
|
||||
assert_file "$ESCONFIG/elasticsearch.keystore" f elasticsearch elasticsearch 660
|
||||
sudo -E -u elasticsearch "$ESHOME/bin/elasticsearch-keystore" list | grep "keystore.seed"
|
||||
# cleanup for the next test
|
||||
rm -rf "$ESCONFIG/elasticsearch.keystore"
|
||||
}
|
||||
|
||||
##################################
|
||||
# Check that Elasticsearch is working
|
||||
##################################
|
||||
@test "[TAR] test elasticsearch" {
|
||||
start_elasticsearch_service
|
||||
run_elasticsearch_tests
|
||||
stop_elasticsearch_service
|
||||
}
|
||||
|
||||
@test "[TAR] test auto-creating elasticearch.keystore" {
|
||||
# a keystore should automatically be created after the service is started
|
||||
assert_file "$ESCONFIG/elasticsearch.keystore" f elasticsearch elasticsearch 660
|
||||
# the keystore should be seeded
|
||||
sudo -E -u elasticsearch "$ESHOME/bin/elasticsearch-keystore" list | grep "keystore.seed"
|
||||
}
|
||||
|
||||
@test "[TAR] start Elasticsearch with custom JVM options" {
|
||||
local es_java_opts=$ES_JAVA_OPTS
|
||||
local es_path_conf=$ES_PATH_CONF
|
||||
local temp=`mktemp -d`
|
||||
cp "$ESCONFIG"/elasticsearch.yml "$temp"
|
||||
cp "$ESCONFIG"/log4j2.properties "$temp"
|
||||
touch "$temp/jvm.options"
|
||||
chown -R elasticsearch:elasticsearch "$temp"
|
||||
echo "-Xms512m" >> "$temp/jvm.options"
|
||||
echo "-Xmx512m" >> "$temp/jvm.options"
|
||||
# we have to disable Log4j from using JMX lest it will hit a security
|
||||
# manager exception before we have configured logging; this will fail
|
||||
# startup since we detect usages of logging before it is configured
|
||||
echo "-Dlog4j2.disable.jmx=true" >> "$temp/jvm.options"
|
||||
export ES_PATH_CONF="$temp"
|
||||
export ES_JAVA_OPTS="-XX:-UseCompressedOops"
|
||||
start_elasticsearch_service
|
||||
curl -s -XGET localhost:9200/_nodes | fgrep '"heap_init_in_bytes":536870912'
|
||||
curl -s -XGET localhost:9200/_nodes | fgrep '"using_compressed_ordinary_object_pointers":"false"'
|
||||
stop_elasticsearch_service
|
||||
export ES_PATH_CONF=$es_path_conf
|
||||
export ES_JAVA_OPTS=$es_java_opts
|
||||
}
|
||||
|
||||
@test "[TAR] GC logs exist" {
|
||||
start_elasticsearch_service
|
||||
assert_file_exist $ESHOME/logs/gc.log.0.current
|
||||
stop_elasticsearch_service
|
||||
}
|
||||
|
||||
@test "[TAR] relative ES_PATH_CONF" {
|
||||
local es_path_conf=$ES_PATH_CONF
|
||||
local temp=`mktemp -d`
|
||||
mkdir "$temp"/config
|
||||
cp "$ESCONFIG"/elasticsearch.yml "$temp"/config
|
||||
cp "$ESCONFIG"/log4j2.properties "$temp"/config
|
||||
cp "$ESCONFIG/jvm.options" "$temp/config"
|
||||
chown -R elasticsearch:elasticsearch "$temp"
|
||||
echo "node.name: relative" >> "$temp"/config/elasticsearch.yml
|
||||
cd "$temp"
|
||||
export ES_PATH_CONF=config
|
||||
start_elasticsearch_service
|
||||
curl -s -XGET localhost:9200/_nodes | fgrep '"name":"relative"'
|
||||
stop_elasticsearch_service
|
||||
export ES_PATH_CONF=$es_path_conf
|
||||
}
|
||||
|
||||
@test "[TAR] remove tar" {
|
||||
rm -rf "/tmp/elasticsearch"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user