Skip to content

Commit 5ceef9e

Browse files
authored
Migrate systemd packaging tests from bats to java (elastic#39954)
* initial work * further testing * migrated * fix build * test * passing test with systemd * fix compilation * failing new test * all tests passing systemd * testcases in package test * passing all tests for systemd * limits are applied for systemd only * code review followup * is enabled return false * missing assertions * json log name
1 parent b4d88aa commit 5ceef9e

File tree

5 files changed

+242
-274
lines changed

5 files changed

+242
-274
lines changed

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

+194-13
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,45 @@
2020
package org.elasticsearch.packaging.test;
2121

2222
import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering;
23+
import org.apache.http.client.fluent.Request;
24+
import org.elasticsearch.packaging.util.FileUtils;
2325
import org.elasticsearch.packaging.util.Shell;
2426
import org.elasticsearch.packaging.util.Shell.Result;
27+
import org.hamcrest.CoreMatchers;
2528
import org.junit.Before;
2629

2730
import java.io.IOException;
2831
import java.nio.charset.StandardCharsets;
2932
import java.nio.file.Files;
3033
import java.nio.file.Path;
34+
import java.nio.file.Paths;
3135
import java.nio.file.StandardOpenOption;
3236
import java.util.regex.Matcher;
3337
import java.util.regex.Pattern;
3438

39+
import static org.elasticsearch.packaging.util.FileUtils.append;
3540
import static org.elasticsearch.packaging.util.FileUtils.assertPathsDontExist;
41+
import static org.elasticsearch.packaging.util.FileUtils.assertPathsExist;
42+
import static org.elasticsearch.packaging.util.FileUtils.cp;
43+
import static org.elasticsearch.packaging.util.FileUtils.fileWithGlobExist;
44+
import static org.elasticsearch.packaging.util.FileUtils.mkdir;
3645
import static org.elasticsearch.packaging.util.FileUtils.mv;
46+
import static org.elasticsearch.packaging.util.FileUtils.rm;
47+
import static org.elasticsearch.packaging.util.FileUtils.slurp;
3748
import static org.elasticsearch.packaging.util.Packages.SYSTEMD_SERVICE;
3849
import static org.elasticsearch.packaging.util.Packages.assertInstalled;
3950
import static org.elasticsearch.packaging.util.Packages.assertRemoved;
4051
import static org.elasticsearch.packaging.util.Packages.install;
4152
import static org.elasticsearch.packaging.util.Packages.remove;
53+
import static org.elasticsearch.packaging.util.Packages.restartElasticsearch;
4254
import static org.elasticsearch.packaging.util.Packages.startElasticsearch;
4355
import static org.elasticsearch.packaging.util.Packages.stopElasticsearch;
4456
import static org.elasticsearch.packaging.util.Packages.verifyPackageInstallation;
4557
import static org.elasticsearch.packaging.util.Platforms.getOsRelease;
4658
import static org.elasticsearch.packaging.util.Platforms.isSystemd;
59+
import static org.elasticsearch.packaging.util.ServerUtils.makeRequest;
4760
import static org.elasticsearch.packaging.util.ServerUtils.runElasticsearchTests;
61+
import static org.hamcrest.CoreMatchers.equalTo;
4862
import static org.hamcrest.CoreMatchers.not;
4963
import static org.hamcrest.CoreMatchers.notNullValue;
5064
import static org.hamcrest.Matchers.containsString;
@@ -55,42 +69,50 @@
5569

5670
@TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class)
5771
public abstract class PackageTestCase extends PackagingTestCase {
72+
private Shell sh;
5873

5974
@Before
6075
public void onlyCompatibleDistributions() {
6176
assumeTrue("only compatible distributions", distribution().packaging.compatible);
77+
sh = newShell();
6278
}
6379

6480
public void test10InstallPackage() throws IOException {
6581
assertRemoved(distribution());
6682
installation = install(distribution());
6783
assertInstalled(distribution());
68-
verifyPackageInstallation(installation, distribution(), newShell());
84+
verifyPackageInstallation(installation, distribution(), sh);
6985
}
7086

7187
public void test20PluginsCommandWhenNoPlugins() {
7288
assumeThat(installation, is(notNullValue()));
7389

74-
assertThat(newShell().run(installation.bin("elasticsearch-plugin") + " list").stdout, isEmptyString());
90+
assertThat(sh.run(installation.bin("elasticsearch-plugin") + " list").stdout, isEmptyString());
7591
}
7692

77-
public void test30InstallDoesNotStartServer() {
93+
public void test30DaemonIsNotEnabledOnRestart() {
94+
if (isSystemd()) {
95+
sh.run("systemctl daemon-reload");
96+
String isEnabledOutput = sh.runIgnoreExitCode("systemctl is-enabled elasticsearch.service").stdout.trim();
97+
assertThat(isEnabledOutput, equalTo("disabled"));
98+
}
99+
}
100+
101+
public void test31InstallDoesNotStartServer() {
78102
assumeThat(installation, is(notNullValue()));
79103

80-
assertThat(newShell().run("ps aux").stdout, not(containsString("org.elasticsearch.bootstrap.Elasticsearch")));
104+
assertThat(sh.run("ps aux").stdout, not(containsString("org.elasticsearch.bootstrap.Elasticsearch")));
81105
}
82106

83107
public void assertRunsWithJavaHome() throws IOException {
84-
Shell sh = newShell();
85-
86108
String systemJavaHome = sh.run("echo $SYSTEM_JAVA_HOME").stdout.trim();
87109
byte[] originalEnvFile = Files.readAllBytes(installation.envFile);
88110
try {
89111
Files.write(installation.envFile, ("JAVA_HOME=" + systemJavaHome + "\n").getBytes(StandardCharsets.UTF_8),
90112
StandardOpenOption.APPEND);
91-
startElasticsearch();
113+
startElasticsearch(sh);
92114
runElasticsearchTests();
93-
stopElasticsearch();
115+
stopElasticsearch(sh);
94116
} finally {
95117
Files.write(installation.envFile, originalEnvFile);
96118
}
@@ -99,7 +121,7 @@ public void assertRunsWithJavaHome() throws IOException {
99121
assertThat(new String(Files.readAllBytes(log), StandardCharsets.UTF_8), containsString(systemJavaHome));
100122
}
101123

102-
public void test31JavaHomeOverride() throws IOException {
124+
public void test32JavaHomeOverride() throws IOException {
103125
assumeThat(installation, is(notNullValue()));
104126
// we always run with java home when no bundled jdk is included, so this test would be repetitive
105127
assumeThat(distribution().hasJdk, is(true));
@@ -121,11 +143,20 @@ public void test42BundledJdkRemoved() throws IOException {
121143
}
122144

123145
public void test40StartServer() throws IOException {
146+
String start = sh.runIgnoreExitCode("date ").stdout.trim();
124147
assumeThat(installation, is(notNullValue()));
125148

126-
startElasticsearch();
149+
startElasticsearch(sh);
150+
151+
String journalEntries = sh.runIgnoreExitCode("journalctl _SYSTEMD_UNIT=elasticsearch.service " +
152+
"--since \"" + start + "\" --output cat | wc -l").stdout.trim();
153+
assertThat(journalEntries, equalTo("0"));
154+
155+
assertPathsExist(installation.pidDir.resolve("elasticsearch.pid"));
156+
assertPathsExist(installation.logs.resolve("elasticsearch_server.json"));
157+
127158
runElasticsearchTests();
128-
verifyPackageInstallation(installation, distribution(), newShell()); // check startup script didn't change permissions
159+
verifyPackageInstallation(installation, distribution(), sh); // check startup script didn't change permissions
129160
}
130161

131162
public void test50Remove() {
@@ -134,7 +165,6 @@ public void test50Remove() {
134165
remove(distribution());
135166

136167
// removing must stop the service
137-
final Shell sh = newShell();
138168
assertThat(sh.run("ps aux").stdout, not(containsString("org.elasticsearch.bootstrap.Elasticsearch")));
139169

140170
if (isSystemd()) {
@@ -184,9 +214,160 @@ public void test60Reinstall() throws IOException {
184214

185215
installation = install(distribution());
186216
assertInstalled(distribution());
187-
verifyPackageInstallation(installation, distribution(), newShell());
217+
verifyPackageInstallation(installation, distribution(), sh);
188218

189219
remove(distribution());
190220
assertRemoved(distribution());
191221
}
222+
223+
public void test70RestartServer() throws IOException {
224+
try {
225+
installation = install(distribution());
226+
assertInstalled(distribution());
227+
228+
startElasticsearch(sh);
229+
restartElasticsearch(sh);
230+
runElasticsearchTests();
231+
stopElasticsearch(sh);
232+
} finally {
233+
cleanup();
234+
}
235+
}
236+
237+
238+
public void test72TestRuntimeDirectory() throws IOException {
239+
try {
240+
installation = install(distribution());
241+
FileUtils.rm(installation.pidDir);
242+
startElasticsearch(sh);
243+
assertPathsExist(installation.pidDir);
244+
stopElasticsearch(sh);
245+
} finally {
246+
cleanup();
247+
}
248+
}
249+
250+
public void test73gcLogsExist() throws IOException {
251+
installation = install(distribution());
252+
startElasticsearch(sh);
253+
// it can be gc.log or gc.log.0.current
254+
assertThat(installation.logs, fileWithGlobExist("gc.log*"));
255+
stopElasticsearch(sh);
256+
}
257+
258+
// TEST CASES FOR SYSTEMD ONLY
259+
260+
261+
/**
262+
* # Simulates the behavior of a system restart:
263+
* # the PID directory is deleted by the operating system
264+
* # but it should not block ES from starting
265+
* # see https://github.com/elastic/elasticsearch/issues/11594
266+
*/
267+
public void test80DeletePID_DIRandRestart() throws IOException {
268+
assumeTrue(isSystemd());
269+
270+
rm(installation.pidDir);
271+
272+
sh.run("systemd-tmpfiles --create");
273+
274+
startElasticsearch(sh);
275+
276+
final Path pidFile = installation.pidDir.resolve("elasticsearch.pid");
277+
278+
assertTrue(Files.exists(pidFile));
279+
280+
stopElasticsearch(sh);
281+
}
282+
283+
public void test81CustomPathConfAndJvmOptions() throws IOException {
284+
assumeTrue(isSystemd());
285+
286+
assumeThat(installation, is(notNullValue()));
287+
assertPathsExist(installation.envFile);
288+
289+
stopElasticsearch(sh);
290+
291+
// The custom config directory is not under /tmp or /var/tmp because
292+
// systemd's private temp directory functionally means different
293+
// processes can have different views of what's in these directories
294+
String temp = sh.runIgnoreExitCode("mktemp -p /etc -d").stdout.trim();
295+
final Path tempConf = Paths.get(temp);
296+
297+
try {
298+
mkdir(tempConf);
299+
cp(installation.config("elasticsearch.yml"), tempConf.resolve("elasticsearch.yml"));
300+
cp(installation.config("log4j2.properties"), tempConf.resolve("log4j2.properties"));
301+
302+
// we have to disable Log4j from using JMX lest it will hit a security
303+
// manager exception before we have configured logging; this will fail
304+
// startup since we detect usages of logging before it is configured
305+
final String jvmOptions =
306+
"-Xms512m\n" +
307+
"-Xmx512m\n" +
308+
"-Dlog4j2.disable.jmx=true\n";
309+
append(tempConf.resolve("jvm.options"), jvmOptions);
310+
311+
sh.runIgnoreExitCode("chown -R elasticsearch:elasticsearch " + tempConf);
312+
313+
final Shell serverShell = newShell();
314+
cp(installation.envFile, tempConf.resolve("elasticsearch.bk"));//backup
315+
append(installation.envFile, "ES_PATH_CONF=" + tempConf + "\n");
316+
append(installation.envFile, "ES_JAVA_OPTS=-XX:-UseCompressedOops");
317+
318+
startElasticsearch(serverShell);
319+
320+
final String nodesResponse = makeRequest(Request.Get("http://localhost:9200/_nodes"));
321+
assertThat(nodesResponse, CoreMatchers.containsString("\"heap_init_in_bytes\":536870912"));
322+
assertThat(nodesResponse, CoreMatchers.containsString("\"using_compressed_ordinary_object_pointers\":\"false\""));
323+
324+
stopElasticsearch(serverShell);
325+
326+
} finally {
327+
rm(installation.envFile);
328+
cp(tempConf.resolve("elasticsearch.bk"), installation.envFile);
329+
rm(tempConf);
330+
cleanup();
331+
}
332+
}
333+
334+
public void test82SystemdMask() throws IOException {
335+
try {
336+
assumeTrue(isSystemd());
337+
338+
sh.run("systemctl mask systemd-sysctl.service");
339+
340+
installation = install(distribution());
341+
342+
sh.run("systemctl unmask systemd-sysctl.service");
343+
} finally {
344+
cleanup();
345+
}
346+
}
347+
348+
public void test83serviceFileSetsLimits() throws IOException {
349+
// Limits are changed on systemd platforms only
350+
assumeTrue(isSystemd());
351+
352+
installation = install(distribution());
353+
354+
startElasticsearch(sh);
355+
356+
final Path pidFile = installation.pidDir.resolve("elasticsearch.pid");
357+
assertTrue(Files.exists(pidFile));
358+
String pid = slurp(pidFile).trim();
359+
String maxFileSize = sh.run("cat /proc/%s/limits | grep \"Max file size\" | awk '{ print $4 }'", pid).stdout.trim();
360+
assertThat(maxFileSize, equalTo("unlimited"));
361+
362+
String maxProcesses = sh.run("cat /proc/%s/limits | grep \"Max processes\" | awk '{ print $3 }'", pid).stdout.trim();
363+
assertThat(maxProcesses, equalTo("4096"));
364+
365+
String maxOpenFiles = sh.run("cat /proc/%s/limits | grep \"Max open files\" | awk '{ print $4 }'", pid).stdout.trim();
366+
assertThat(maxOpenFiles, equalTo("65535"));
367+
368+
String maxAddressSpace = sh.run("cat /proc/%s/limits | grep \"Max address space\" | awk '{ print $4 }'", pid).stdout.trim();
369+
assertThat(maxAddressSpace, equalTo("unlimited"));
370+
371+
stopElasticsearch(sh);
372+
}
192373
}

qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileUtils.java

+27
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
package org.elasticsearch.packaging.util;
2121

2222
import org.elasticsearch.core.internal.io.IOUtils;
23+
import org.hamcrest.FeatureMatcher;
24+
import org.hamcrest.Matcher;
2325

2426
import java.io.BufferedWriter;
2527
import java.io.IOException;
@@ -34,9 +36,11 @@
3436
import java.nio.file.attribute.PosixFileAttributes;
3537
import java.util.ArrayList;
3638
import java.util.Arrays;
39+
import java.util.Collections;
3740
import java.util.List;
3841

3942
import static org.hamcrest.MatcherAssert.assertThat;
43+
import static org.hamcrest.Matchers.emptyIterable;
4044
import static org.hamcrest.core.IsNot.not;
4145
import static org.hamcrest.text.IsEmptyString.isEmptyOrNullString;
4246
import static org.junit.Assert.assertFalse;
@@ -69,6 +73,15 @@ public static void rm(Path... paths) {
6973
}
7074
}
7175

76+
public static Path mktempDir(Path path) {
77+
try {
78+
return Files.createTempDirectory(path,"tmp");
79+
} catch (IOException e) {
80+
throw new RuntimeException(e);
81+
}
82+
}
83+
84+
7285
public static Path mkdir(Path path) {
7386
try {
7487
return Files.createDirectories(path);
@@ -176,6 +189,20 @@ public static void assertPathsExist(Path... paths) {
176189
Arrays.stream(paths).forEach(path -> assertTrue(path + " should exist", Files.exists(path)));
177190
}
178191

192+
public static Matcher<Path> fileWithGlobExist(String glob) throws IOException {
193+
return new FeatureMatcher<Path,Iterable<Path>>(not(emptyIterable()),"File with pattern exist", "file with pattern"){
194+
195+
@Override
196+
protected Iterable<Path> featureValueOf(Path actual) {
197+
try {
198+
return Files.newDirectoryStream(actual,glob);
199+
} catch (IOException e) {
200+
return Collections.emptyList();
201+
}
202+
}
203+
};
204+
}
205+
179206
public static void assertPathsDontExist(Path... paths) {
180207
Arrays.stream(paths).forEach(path -> assertFalse(path + " should not exist", Files.exists(path)));
181208
}

0 commit comments

Comments
 (0)