Skip to content

Commit a13e8c3

Browse files
committed
[test] port archive distribution packaging tests (elastic#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.
1 parent eb30825 commit a13e8c3

File tree

11 files changed

+675
-298
lines changed

11 files changed

+675
-298
lines changed

buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/VagrantTestPlugin.groovy

+8-2
Original file line numberDiff line numberDiff line change
@@ -550,9 +550,15 @@ class VagrantTestPlugin implements Plugin<Project> {
550550
javaPackagingTest.command = 'ssh'
551551
javaPackagingTest.args = ['--command', 'sudo bash "$PACKAGING_TESTS/run-tests.sh"']
552552
} else {
553+
// powershell sessions run over winrm always run as administrator, whether --elevated is passed or not. however
554+
// remote sessions have some restrictions on what they can do, such as impersonating another user (or the same user
555+
// without administrator elevation), which we need to do for these tests. passing --elevated runs the session
556+
// as a scheduled job locally on the vm as a true administrator to get around this limitation
557+
//
558+
// https://github.com/hashicorp/vagrant/blob/9c299a2a357fcf87f356bb9d56e18a037a53d138/plugins/communicators/winrm/communicator.rb#L195-L225
559+
// https://devops-collective-inc.gitbooks.io/secrets-of-powershell-remoting/content/manuscript/accessing-remote-computers.html
553560
javaPackagingTest.command = 'winrm'
554-
// winrm commands run as administrator
555-
javaPackagingTest.args = ['--command', 'powershell -File "$Env:PACKAGING_TESTS/run-tests.ps1"']
561+
javaPackagingTest.args = ['--elevated', '--command', 'powershell -File "$Env:PACKAGING_TESTS/run-tests.ps1"']
556562
}
557563

558564
TaskExecutionAdapter javaPackagingReproListener = createReproListener(project, javaPackagingTest.path)

qa/vagrant/build.gradle

+20
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ dependencies {
3131
compile "org.hamcrest:hamcrest-core:${versions.hamcrest}"
3232
compile "org.hamcrest:hamcrest-library:${versions.hamcrest}"
3333

34+
compile "org.apache.httpcomponents:httpcore:${versions.httpcore}"
35+
compile "org.apache.httpcomponents:httpclient:${versions.httpclient}"
36+
compile "org.apache.httpcomponents:fluent-hc:${versions.httpclient}"
37+
compile "commons-codec:commons-codec:${versions.commonscodec}"
38+
compile "commons-logging:commons-logging:${versions.commonslogging}"
39+
3440
compile project(':libs:core')
3541

3642
// pulls in the jar built by this project and its dependencies
@@ -73,3 +79,17 @@ tasks.test.enabled = false
7379
// this project doesn't get published
7480
tasks.dependencyLicenses.enabled = false
7581
tasks.dependenciesInfo.enabled = false
82+
83+
tasks.thirdPartyAudit.excludes = [
84+
//commons-logging optional dependencies
85+
'org.apache.avalon.framework.logger.Logger',
86+
'org.apache.log.Hierarchy',
87+
'org.apache.log.Logger',
88+
'org.apache.log4j.Category',
89+
'org.apache.log4j.Level',
90+
'org.apache.log4j.Logger',
91+
'org.apache.log4j.Priority',
92+
//commons-logging provided dependencies
93+
'javax.servlet.ServletContextEvent',
94+
'javax.servlet.ServletContextListener'
95+
]

qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java

+252
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919

2020
package org.elasticsearch.packaging.test;
2121

22+
import org.apache.http.client.fluent.Request;
23+
import org.elasticsearch.packaging.util.Archives;
24+
import org.elasticsearch.packaging.util.Platforms;
25+
import org.elasticsearch.packaging.util.ServerUtils;
26+
import org.elasticsearch.packaging.util.Shell;
27+
import org.elasticsearch.packaging.util.Shell.Result;
2228
import org.junit.Before;
2329
import org.junit.BeforeClass;
2430
import org.junit.FixMethodOrder;
@@ -28,9 +34,33 @@
2834
import org.elasticsearch.packaging.util.Distribution;
2935
import org.elasticsearch.packaging.util.Installation;
3036

37+
import java.io.IOException;
38+
import java.nio.file.Files;
39+
import java.nio.file.Path;
40+
import java.util.Arrays;
41+
import java.util.stream.Stream;
42+
43+
import static java.util.stream.Collectors.joining;
44+
import static org.elasticsearch.packaging.util.Archives.ARCHIVE_OWNER;
3145
import static org.elasticsearch.packaging.util.Cleanup.cleanEverything;
3246
import static org.elasticsearch.packaging.util.Archives.installArchive;
3347
import static org.elasticsearch.packaging.util.Archives.verifyArchiveInstallation;
48+
import static org.elasticsearch.packaging.util.FileMatcher.Fileness.File;
49+
import static org.elasticsearch.packaging.util.FileMatcher.file;
50+
import static org.elasticsearch.packaging.util.FileMatcher.p660;
51+
import static org.elasticsearch.packaging.util.FileUtils.append;
52+
import static org.elasticsearch.packaging.util.FileUtils.cp;
53+
import static org.elasticsearch.packaging.util.FileUtils.getTempDir;
54+
import static org.elasticsearch.packaging.util.FileUtils.mkdir;
55+
import static org.elasticsearch.packaging.util.FileUtils.rm;
56+
import static org.elasticsearch.packaging.util.ServerUtils.makeRequest;
57+
import static org.hamcrest.CoreMatchers.containsString;
58+
import static org.hamcrest.CoreMatchers.is;
59+
import static org.hamcrest.CoreMatchers.notNullValue;
60+
import static org.hamcrest.MatcherAssert.assertThat;
61+
import static org.hamcrest.Matchers.isEmptyString;
62+
import static org.junit.Assert.assertTrue;
63+
import static org.junit.Assume.assumeThat;
3464
import static org.junit.Assume.assumeTrue;
3565

3666
/**
@@ -61,4 +91,226 @@ public void test10Install() {
6191
installation = installArchive(distribution());
6292
verifyArchiveInstallation(installation, distribution());
6393
}
94+
95+
@Test
96+
public void test20PluginsListWithNoPlugins() {
97+
assumeThat(installation, is(notNullValue()));
98+
99+
final Installation.Executables bin = installation.executables();
100+
final Shell sh = new Shell();
101+
final Result r = sh.run(bin.elasticsearchPlugin + " list");
102+
103+
assertThat(r.stdout, isEmptyString());
104+
}
105+
106+
@Test
107+
public void test30AbortWhenJavaMissing() {
108+
assumeThat(installation, is(notNullValue()));
109+
110+
final Installation.Executables bin = installation.executables();
111+
final Shell sh = new Shell();
112+
113+
Platforms.onWindows(() -> {
114+
// on windows, removing java from PATH and removing JAVA_HOME is less involved than changing the permissions of the java
115+
// executable. we also don't check permissions in the windows scripts anyway
116+
final String originalPath = sh.run("$Env:PATH").stdout.trim();
117+
final String newPath = Arrays.stream(originalPath.split(";"))
118+
.filter(path -> path.contains("Java") == false)
119+
.collect(joining(";"));
120+
121+
// note the lack of a $ when clearing the JAVA_HOME env variable - with a $ it deletes the java home directory
122+
// https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/providers/environment-provider?view=powershell-6
123+
//
124+
// this won't persist to another session so we don't have to reset anything
125+
final Result runResult = sh.runIgnoreExitCode(
126+
"$Env:PATH = '" + newPath + "'; " +
127+
"Remove-Item Env:JAVA_HOME; " +
128+
bin.elasticsearch
129+
);
130+
131+
assertThat(runResult.exitCode, is(1));
132+
assertThat(runResult.stderr, containsString("could not find java; set JAVA_HOME or ensure java is in PATH"));
133+
});
134+
135+
Platforms.onLinux(() -> {
136+
final String javaPath = sh.run("which java").stdout.trim();
137+
138+
try {
139+
sh.run("chmod -x '" + javaPath + "'");
140+
final Result runResult = sh.runIgnoreExitCode(bin.elasticsearch.toString());
141+
assertThat(runResult.exitCode, is(1));
142+
assertThat(runResult.stdout, containsString("could not find java; set JAVA_HOME or ensure java is in PATH"));
143+
} finally {
144+
sh.run("chmod +x '" + javaPath + "'");
145+
}
146+
});
147+
}
148+
149+
@Test
150+
public void test40CreateKeystoreManually() {
151+
assumeThat(installation, is(notNullValue()));
152+
153+
final Installation.Executables bin = installation.executables();
154+
final Shell sh = new Shell();
155+
156+
Platforms.onLinux(() -> sh.run("sudo -u " + ARCHIVE_OWNER + " " + bin.elasticsearchKeystore + " create"));
157+
158+
// 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.
159+
// the keystore ends up being owned by the Administrators group, so we manually set it to be owned by the vagrant user here.
160+
// from the server's perspective the permissions aren't really different, this is just to reflect what we'd expect in the tests.
161+
// when we run these commands as a role user we won't have to do this
162+
Platforms.onWindows(() -> sh.run(
163+
bin.elasticsearchKeystore + " create; " +
164+
"$account = New-Object System.Security.Principal.NTAccount 'vagrant'; " +
165+
"$acl = Get-Acl '" + installation.config("elasticsearch.keystore") + "'; " +
166+
"$acl.SetOwner($account); " +
167+
"Set-Acl '" + installation.config("elasticsearch.keystore") + "' $acl"
168+
));
169+
170+
assertThat(installation.config("elasticsearch.keystore"), file(File, ARCHIVE_OWNER, ARCHIVE_OWNER, p660));
171+
172+
Platforms.onLinux(() -> {
173+
final Result r = sh.run("sudo -u " + ARCHIVE_OWNER + " " + bin.elasticsearchKeystore + " list");
174+
assertThat(r.stdout, containsString("keystore.seed"));
175+
});
176+
177+
Platforms.onWindows(() -> {
178+
final Result r = sh.run(bin.elasticsearchKeystore + " list");
179+
assertThat(r.stdout, containsString("keystore.seed"));
180+
});
181+
}
182+
183+
@Test
184+
public void test50StartAndStop() throws IOException {
185+
assumeThat(installation, is(notNullValue()));
186+
187+
// cleanup from previous test
188+
rm(installation.config("elasticsearch.keystore"));
189+
190+
Archives.runElasticsearch(installation);
191+
192+
final String gcLogName = Platforms.LINUX
193+
? "gc.log.0.current"
194+
: "gc.log";
195+
assertTrue("gc logs exist", Files.exists(installation.logs.resolve(gcLogName)));
196+
ServerUtils.runElasticsearchTests();
197+
198+
Archives.stopElasticsearch(installation);
199+
}
200+
201+
@Test
202+
public void test60AutoCreateKeystore() {
203+
assumeThat(installation, is(notNullValue()));
204+
205+
assertThat(installation.config("elasticsearch.keystore"), file(File, ARCHIVE_OWNER, ARCHIVE_OWNER, p660));
206+
207+
final Installation.Executables bin = installation.executables();
208+
final Shell sh = new Shell();
209+
210+
Platforms.onLinux(() -> {
211+
final Result result = sh.run("sudo -u " + ARCHIVE_OWNER + " " + bin.elasticsearchKeystore + " list");
212+
assertThat(result.stdout, containsString("keystore.seed"));
213+
});
214+
215+
Platforms.onWindows(() -> {
216+
final Result result = sh.run(bin.elasticsearchKeystore + " list");
217+
assertThat(result.stdout, containsString("keystore.seed"));
218+
});
219+
}
220+
221+
@Test
222+
public void test70CustomPathConfAndJvmOptions() throws IOException {
223+
assumeThat(installation, is(notNullValue()));
224+
225+
final Path tempConf = getTempDir().resolve("esconf-alternate");
226+
227+
try {
228+
mkdir(tempConf);
229+
cp(installation.config("elasticsearch.yml"), tempConf.resolve("elasticsearch.yml"));
230+
cp(installation.config("log4j2.properties"), tempConf.resolve("log4j2.properties"));
231+
232+
// we have to disable Log4j from using JMX lest it will hit a security
233+
// manager exception before we have configured logging; this will fail
234+
// startup since we detect usages of logging before it is configured
235+
final String jvmOptions =
236+
"-Xms512m\n" +
237+
"-Xmx512m\n" +
238+
"-Dlog4j2.disable.jmx=true\n";
239+
append(tempConf.resolve("jvm.options"), jvmOptions);
240+
241+
final Shell sh = new Shell();
242+
Platforms.onLinux(() -> sh.run("chown -R elasticsearch:elasticsearch " + tempConf));
243+
Platforms.onWindows(() -> sh.run(
244+
"$account = New-Object System.Security.Principal.NTAccount 'vagrant'; " +
245+
"$tempConf = Get-ChildItem '" + tempConf + "' -Recurse; " +
246+
"$tempConf += Get-Item '" + tempConf + "'; " +
247+
"$tempConf | ForEach-Object { " +
248+
"$acl = Get-Acl $_.FullName; " +
249+
"$acl.SetOwner($account); " +
250+
"Set-Acl $_.FullName $acl " +
251+
"}"
252+
));
253+
254+
final Shell serverShell = new Shell();
255+
serverShell.getEnv().put("ES_PATH_CONF", tempConf.toString());
256+
serverShell.getEnv().put("ES_JAVA_OPTS", "-XX:-UseCompressedOops");
257+
258+
Archives.runElasticsearch(installation, serverShell);
259+
260+
final String nodesResponse = makeRequest(Request.Get("http://localhost:9200/_nodes"));
261+
assertThat(nodesResponse, containsString("\"heap_init_in_bytes\":536870912"));
262+
assertThat(nodesResponse, containsString("\"using_compressed_ordinary_object_pointers\":\"false\""));
263+
264+
Archives.stopElasticsearch(installation);
265+
266+
} finally {
267+
rm(tempConf);
268+
}
269+
}
270+
271+
@Test
272+
public void test80RelativePathConf() throws IOException {
273+
assumeThat(installation, is(notNullValue()));
274+
275+
final Path temp = getTempDir().resolve("esconf-alternate");
276+
final Path tempConf = temp.resolve("config");
277+
278+
try {
279+
mkdir(tempConf);
280+
Stream.of(
281+
"elasticsearch.yml",
282+
"log4j2.properties",
283+
"jvm.options"
284+
).forEach(file -> cp(installation.config(file), tempConf.resolve(file)));
285+
286+
append(tempConf.resolve("elasticsearch.yml"), "node.name: relative");
287+
288+
final Shell sh = new Shell();
289+
Platforms.onLinux(() -> sh.run("chown -R elasticsearch:elasticsearch " + temp));
290+
Platforms.onWindows(() -> sh.run(
291+
"$account = New-Object System.Security.Principal.NTAccount 'vagrant'; " +
292+
"$tempConf = Get-ChildItem '" + temp + "' -Recurse; " +
293+
"$tempConf += Get-Item '" + temp + "'; " +
294+
"$tempConf | ForEach-Object { " +
295+
"$acl = Get-Acl $_.FullName; " +
296+
"$acl.SetOwner($account); " +
297+
"Set-Acl $_.FullName $acl " +
298+
"}"
299+
));
300+
301+
final Shell serverShell = new Shell(temp);
302+
serverShell.getEnv().put("ES_PATH_CONF", "config");
303+
Archives.runElasticsearch(installation, serverShell);
304+
305+
final String nodesResponse = makeRequest(Request.Get("http://localhost:9200/_nodes"));
306+
assertThat(nodesResponse, containsString("\"name\":\"relative\""));
307+
308+
Archives.stopElasticsearch(installation);
309+
310+
} finally {
311+
rm(tempConf);
312+
}
313+
}
314+
315+
64316
}

0 commit comments

Comments
 (0)