diff --git a/qa/vagrant/build.gradle b/qa/vagrant/build.gradle index 37190632b44bb..4a0c91469629d 100644 --- a/qa/vagrant/build.gradle +++ b/qa/vagrant/build.gradle @@ -28,7 +28,8 @@ plugins { dependencies { compile "junit:junit:${versions.junit}" - compile "org.hamcrest:hamcrest-all:${versions.hamcrest}" + compile "org.hamcrest:hamcrest-core:${versions.hamcrest}" + compile "org.hamcrest:hamcrest-library:${versions.hamcrest}" compile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}" compile "org.apache.httpcomponents:httpcore:${versions.httpcore}" @@ -91,13 +92,5 @@ tasks.thirdPartyAudit.excludes = [ 'org.apache.log4j.Priority', // commons-logging provided dependencies 'javax.servlet.ServletContextEvent', - 'javax.servlet.ServletContextListener', - // from randomized testing - 'org.apache.tools.ant.BuildException', - 'org.apache.tools.ant.DirectoryScanner', - 'org.apache.tools.ant.Task', - 'org.apache.tools.ant.types.FileSet', - 'org.easymock.EasyMock', - 'org.easymock.IArgumentMatcher', - 'org.jmock.core.Constraint' + 'javax.servlet.ServletContextListener' ] diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/PackagingTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/PackagingTests.java index fa7f8e8ef78c5..57b647e1207c2 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/PackagingTests.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/PackagingTests.java @@ -19,10 +19,19 @@ package org.elasticsearch.packaging; +import org.elasticsearch.packaging.test.DefaultDebPreservationTests; +import org.elasticsearch.packaging.test.DefaultDebBasicTests; +import org.elasticsearch.packaging.test.DefaultRpmPreservationTests; +import org.elasticsearch.packaging.test.DefaultRpmBasicTests; +import org.elasticsearch.packaging.test.OssDebPreservationTests; +import org.elasticsearch.packaging.test.OssDebBasicTests; +import org.elasticsearch.packaging.test.OssRpmPreservationTests; +import org.elasticsearch.packaging.test.OssRpmBasicTests; import org.elasticsearch.packaging.test.OssTarTests; import org.elasticsearch.packaging.test.OssZipTests; import org.elasticsearch.packaging.test.DefaultTarTests; import org.elasticsearch.packaging.test.DefaultZipTests; +import org.elasticsearch.packaging.test.PackageDependenciesTests; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -31,8 +40,17 @@ @RunWith(Suite.class) @SuiteClasses({ DefaultTarTests.class, - DefaultZipTests.class, OssTarTests.class, - OssZipTests.class + DefaultZipTests.class, + OssZipTests.class, + PackageDependenciesTests.class, + DefaultRpmBasicTests.class, + OssRpmBasicTests.class, + DefaultDebBasicTests.class, + OssDebBasicTests.class, + DefaultDebPreservationTests.class, + OssDebPreservationTests.class, + DefaultRpmPreservationTests.class, + OssRpmPreservationTests.class }) public class PackagingTests {} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DebPreservationTestCase.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DebPreservationTestCase.java new file mode 100644 index 0000000000000..c584f5d2e44fa --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DebPreservationTestCase.java @@ -0,0 +1,127 @@ +/* + * 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.test; + +import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; +import org.elasticsearch.packaging.util.Distribution; +import org.elasticsearch.packaging.util.Installation; +import org.elasticsearch.packaging.util.Shell; +import org.junit.Before; +import org.junit.BeforeClass; + +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.elasticsearch.packaging.util.Cleanup.cleanEverything; +import static org.elasticsearch.packaging.util.FileUtils.assertPathsDontExist; +import static org.elasticsearch.packaging.util.FileUtils.assertPathsExist; +import static org.elasticsearch.packaging.util.Packages.SYSVINIT_SCRIPT; +import static org.elasticsearch.packaging.util.Packages.assertInstalled; +import static org.elasticsearch.packaging.util.Packages.assertRemoved; +import static org.elasticsearch.packaging.util.Packages.install; +import static org.elasticsearch.packaging.util.Packages.remove; +import static org.elasticsearch.packaging.util.Packages.packageStatus; +import static org.elasticsearch.packaging.util.Packages.verifyPackageInstallation; +import static org.elasticsearch.packaging.util.Platforms.isDPKG; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeThat; +import static org.junit.Assume.assumeTrue; + +@TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) +public abstract class DebPreservationTestCase extends PackagingTestCase { + + private static Installation installation; + + protected abstract Distribution distribution(); + + @BeforeClass + public static void cleanup() { + installation = null; + cleanEverything(); + } + + @Before + public void onlyCompatibleDistributions() { + assumeTrue("only dpkg platforms", isDPKG()); + assumeTrue("only compatible distributions", distribution().packaging.compatible); + } + + public void test10Install() { + assertRemoved(distribution()); + installation = install(distribution()); + assertInstalled(distribution()); + verifyPackageInstallation(installation, distribution()); + } + + public void test20Remove() { + assumeThat(installation, is(notNullValue())); + + remove(distribution()); + + // some config files were not removed + + assertPathsExist( + installation.config, + installation.config("elasticsearch.yml"), + installation.config("jvm.options"), + installation.config("log4j2.properties") + ); + + // keystore was removed + + assertPathsDontExist( + installation.config("elasticsearch.keystore"), + installation.config(".elasticsearch.keystore.initial_md5sum") + ); + + // doc files were removed + + assertPathsDontExist( + Paths.get("/usr/share/doc/" + distribution().flavor.name), + Paths.get("/usr/share/doc/" + distribution().flavor.name + "/copyright") + ); + + // sysvinit service file was not removed + assertTrue(Files.exists(SYSVINIT_SCRIPT)); + + // defaults file was not removed + assertTrue(Files.exists(installation.envFile)); + } + + public void test30Purge() { + assumeThat(installation, is(notNullValue())); + + final Shell sh = new Shell(); + sh.run("dpkg --purge " + distribution().flavor.name); + + assertRemoved(distribution()); + + assertPathsDontExist( + installation.config, + installation.envFile, + SYSVINIT_SCRIPT + ); + + assertThat(packageStatus(distribution()).exitCode, is(1)); + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultDebBasicTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultDebBasicTests.java new file mode 100644 index 0000000000000..cd40c0e9e814d --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultDebBasicTests.java @@ -0,0 +1,31 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class DefaultDebBasicTests extends PackageTestCase { + + @Override + protected Distribution distribution() { + return Distribution.DEFAULT_DEB; + } + +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultDebPreservationTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultDebPreservationTests.java new file mode 100644 index 0000000000000..d8b8c7f562bd9 --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultDebPreservationTests.java @@ -0,0 +1,30 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class DefaultDebPreservationTests extends DebPreservationTestCase { + + @Override + protected Distribution distribution() { + return Distribution.DEFAULT_DEB; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultRpmBasicTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultRpmBasicTests.java new file mode 100644 index 0000000000000..a8ce7b48685bd --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultRpmBasicTests.java @@ -0,0 +1,30 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class DefaultRpmBasicTests extends PackageTestCase { + + @Override + protected Distribution distribution() { + return Distribution.DEFAULT_RPM; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultRpmPreservationTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultRpmPreservationTests.java new file mode 100644 index 0000000000000..633492cce6c2f --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultRpmPreservationTests.java @@ -0,0 +1,30 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class DefaultRpmPreservationTests extends RpmPreservationTestCase { + + @Override + protected Distribution distribution() { + return Distribution.DEFAULT_RPM; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebBasicTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebBasicTests.java new file mode 100644 index 0000000000000..5d779ac46536e --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebBasicTests.java @@ -0,0 +1,30 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class OssDebBasicTests extends PackageTestCase { + + @Override + protected Distribution distribution() { + return Distribution.OSS_DEB; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebPreservationTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebPreservationTests.java new file mode 100644 index 0000000000000..cfce73bb16000 --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebPreservationTests.java @@ -0,0 +1,30 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class OssDebPreservationTests extends DebPreservationTestCase { + + @Override + protected Distribution distribution() { + return Distribution.OSS_DEB; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmBasicTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmBasicTests.java new file mode 100644 index 0000000000000..d3320c0795589 --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmBasicTests.java @@ -0,0 +1,30 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class OssRpmBasicTests extends PackageTestCase { + + @Override + protected Distribution distribution() { + return Distribution.OSS_RPM; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmPreservationTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmPreservationTests.java new file mode 100644 index 0000000000000..87071d687d03e --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmPreservationTests.java @@ -0,0 +1,30 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class OssRpmPreservationTests extends RpmPreservationTestCase { + + @Override + protected Distribution distribution() { + return Distribution.OSS_RPM; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageDependenciesTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageDependenciesTests.java new file mode 100644 index 0000000000000..6861ef0a3ff1e --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageDependenciesTests.java @@ -0,0 +1,73 @@ +/* + * 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.test; + +import org.elasticsearch.packaging.util.Platforms; +import org.elasticsearch.packaging.util.Shell; +import org.elasticsearch.packaging.util.Shell.Result; + +import java.util.regex.Pattern; + +import static junit.framework.TestCase.assertTrue; +import static org.elasticsearch.packaging.util.Distribution.DEFAULT_DEB; +import static org.elasticsearch.packaging.util.Distribution.DEFAULT_RPM; +import static org.elasticsearch.packaging.util.Distribution.OSS_DEB; +import static org.elasticsearch.packaging.util.Distribution.OSS_RPM; +import static org.elasticsearch.packaging.util.FileUtils.getDistributionFile; +import static org.junit.Assume.assumeTrue; + +/** + * Tests that linux packages correctly declare their dependencies and their conflicts + */ +public class PackageDependenciesTests extends PackagingTestCase { + + public void testDebDependencies() { + assumeTrue(Platforms.isDPKG()); + + final Shell sh = new Shell(); + + final Result defaultResult = sh.run("dpkg -I " + getDistributionFile(DEFAULT_DEB)); + final Result ossResult = sh.run("dpkg -I " + getDistributionFile(OSS_DEB)); + + assertTrue(Pattern.compile("(?m)^ Depends:.*bash.*").matcher(defaultResult.stdout).find()); + assertTrue(Pattern.compile("(?m)^ Depends:.*bash.*").matcher(ossResult.stdout).find()); + + assertTrue(Pattern.compile("(?m)^ Conflicts: elasticsearch-oss$").matcher(defaultResult.stdout).find()); + assertTrue(Pattern.compile("(?m)^ Conflicts: elasticsearch$").matcher(ossResult.stdout).find()); + } + + public void testRpmDependencies() { + assumeTrue(Platforms.isRPM()); + + final Shell sh = new Shell(); + + final Result defaultDeps = sh.run("rpm -qpR " + getDistributionFile(DEFAULT_RPM)); + final Result ossDeps = sh.run("rpm -qpR " + getDistributionFile(OSS_RPM)); + + assertTrue(Pattern.compile("(?m)^/bin/bash\\s*$").matcher(defaultDeps.stdout).find()); + assertTrue(Pattern.compile("(?m)^/bin/bash\\s*$").matcher(ossDeps.stdout).find()); + + final Result defaultConflicts = sh.run("rpm -qp --conflicts " + getDistributionFile(DEFAULT_RPM)); + final Result ossConflicts = sh.run("rpm -qp --conflicts " + getDistributionFile(OSS_RPM)); + + assertTrue(Pattern.compile("(?m)^elasticsearch-oss\\s*$").matcher(defaultConflicts.stdout).find()); + assertTrue(Pattern.compile("(?m)^elasticsearch\\s*$").matcher(ossConflicts.stdout).find()); + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageTestCase.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageTestCase.java new file mode 100644 index 0000000000000..28a767e95aef2 --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageTestCase.java @@ -0,0 +1,168 @@ +/* + * 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.test; + +import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; +import org.elasticsearch.packaging.util.Distribution; +import org.elasticsearch.packaging.util.Installation; +import org.elasticsearch.packaging.util.Shell; + +import org.elasticsearch.packaging.util.Shell.Result; +import org.junit.Before; +import org.junit.BeforeClass; + +import java.io.IOException; +import java.nio.file.Files; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.elasticsearch.packaging.util.Cleanup.cleanEverything; +import static org.elasticsearch.packaging.util.FileUtils.assertPathsDontExist; +import static org.elasticsearch.packaging.util.Packages.SYSTEMD_SERVICE; +import static org.elasticsearch.packaging.util.Packages.assertInstalled; +import static org.elasticsearch.packaging.util.Packages.assertRemoved; +import static org.elasticsearch.packaging.util.Packages.install; +import static org.elasticsearch.packaging.util.Packages.remove; +import static org.elasticsearch.packaging.util.Packages.startElasticsearch; +import static org.elasticsearch.packaging.util.Packages.verifyPackageInstallation; +import static org.elasticsearch.packaging.util.Platforms.getOsRelease; +import static org.elasticsearch.packaging.util.Platforms.isSystemd; +import static org.elasticsearch.packaging.util.ServerUtils.runElasticsearchTests; + +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.isEmptyString; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assume.assumeThat; +import static org.junit.Assume.assumeTrue; + +@TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) +public abstract class PackageTestCase extends PackagingTestCase { + + private static Installation installation; + + protected abstract Distribution distribution(); + + @BeforeClass + public static void cleanup() { + installation = null; + cleanEverything(); + } + + @Before + public void onlyCompatibleDistributions() { + assumeTrue("only compatible distributions", distribution().packaging.compatible); + } + + public void test10InstallPackage() { + assertRemoved(distribution()); + installation = install(distribution()); + assertInstalled(distribution()); + verifyPackageInstallation(installation, distribution()); + } + + public void test20PluginsCommandWhenNoPlugins() { + assumeThat(installation, is(notNullValue())); + + final Shell sh = new Shell(); + assertThat(sh.run(installation.bin("elasticsearch-plugin") + " list").stdout, isEmptyString()); + } + + public void test30InstallDoesNotStartServer() { + assumeThat(installation, is(notNullValue())); + + final Shell sh = new Shell(); + assertThat(sh.run("ps aux").stdout, not(containsString("org.elasticsearch.bootstrap.Elasticsearch"))); + } + + public void test40StartServer() throws IOException { + assumeThat(installation, is(notNullValue())); + + startElasticsearch(); + runElasticsearchTests(); + verifyPackageInstallation(installation, distribution()); // check startup script didn't change permissions + } + + public void test50Remove() { + assumeThat(installation, is(notNullValue())); + + remove(distribution()); + + // removing must stop the service + final Shell sh = new Shell(); + assertThat(sh.run("ps aux").stdout, not(containsString("org.elasticsearch.bootstrap.Elasticsearch"))); + + if (isSystemd()) { + + final int statusExitCode; + + // Before version 231 systemctl returned exit code 3 for both services that were stopped, and nonexistent + // services [1]. In version 231 and later it returns exit code 4 for non-existent services. + // + // The exception is Centos 7 and oel 7 where it returns exit code 4 for non-existent services from a systemd reporting a version + // earlier than 231. Centos 6 does not have an /etc/os-release, but that's fine because it also doesn't use systemd. + // + // [1] https://github.com/systemd/systemd/pull/3385 + if (getOsRelease().contains("ID=\"centos\"") || getOsRelease().contains("ID=\"ol\"")) { + statusExitCode = 4; + } else { + + final Result versionResult = sh.run("systemctl --version"); + final Matcher matcher = Pattern.compile("^systemd (\\d+)\n").matcher(versionResult.stdout); + matcher.find(); + final int version = Integer.parseInt(matcher.group(1)); + + statusExitCode = version < 231 + ? 3 + : 4; + } + + assertThat(sh.runIgnoreExitCode("systemctl status elasticsearch.service").exitCode, is(statusExitCode)); + assertThat(sh.runIgnoreExitCode("systemctl is-enabled elasticsearch.service").exitCode, is(1)); + + } + + assertPathsDontExist( + installation.bin, + installation.lib, + installation.modules, + installation.plugins, + installation.logs, + installation.pidDir + ); + + assertFalse(Files.exists(SYSTEMD_SERVICE)); + } + + public void test60Reinstall() { + assumeThat(installation, is(notNullValue())); + + installation = install(distribution()); + assertInstalled(distribution()); + verifyPackageInstallation(installation, distribution()); + + remove(distribution()); + assertRemoved(distribution()); + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/RpmPreservationTestCase.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/RpmPreservationTestCase.java new file mode 100644 index 0000000000000..527c1d2cc13a2 --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/RpmPreservationTestCase.java @@ -0,0 +1,141 @@ +/* + * 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.test; + +import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; +import org.elasticsearch.packaging.util.Distribution; +import org.elasticsearch.packaging.util.Installation; +import org.elasticsearch.packaging.util.Shell; +import org.junit.Before; +import org.junit.BeforeClass; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; + +import static org.elasticsearch.packaging.util.Cleanup.cleanEverything; +import static org.elasticsearch.packaging.util.FileUtils.append; +import static org.elasticsearch.packaging.util.FileUtils.assertPathsDontExist; +import static org.elasticsearch.packaging.util.Packages.SYSTEMD_SERVICE; +import static org.elasticsearch.packaging.util.Packages.SYSVINIT_SCRIPT; +import static org.elasticsearch.packaging.util.Packages.assertInstalled; +import static org.elasticsearch.packaging.util.Packages.assertRemoved; +import static org.elasticsearch.packaging.util.Packages.install; +import static org.elasticsearch.packaging.util.Packages.remove; +import static org.elasticsearch.packaging.util.Packages.verifyPackageInstallation; +import static org.elasticsearch.packaging.util.Platforms.isRPM; +import static org.elasticsearch.packaging.util.Platforms.isSystemd; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeThat; +import static org.junit.Assume.assumeTrue; + +@TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) +public abstract class RpmPreservationTestCase extends PackagingTestCase { + + private static Installation installation; + + protected abstract Distribution distribution(); + + @BeforeClass + public static void cleanup() { + installation = null; + cleanEverything(); + } + + @Before + public void onlyCompatibleDistributions() { + assumeTrue("only rpm platforms", isRPM()); + assumeTrue("only compatible distributions", distribution().packaging.compatible); + } + + public void test10Install() { + assertRemoved(distribution()); + installation = install(distribution()); + assertInstalled(distribution()); + verifyPackageInstallation(installation, distribution()); + } + + public void test20Remove() { + assumeThat(installation, is(notNullValue())); + + remove(distribution()); + + // config was removed + assertFalse(Files.exists(installation.config)); + + // sysvinit service file was removed + assertFalse(Files.exists(SYSVINIT_SCRIPT)); + + // defaults file was removed + assertFalse(Files.exists(installation.envFile)); + } + + public void test30PreserveConfig() { + final Shell sh = new Shell(); + + installation = install(distribution()); + assertInstalled(distribution()); + verifyPackageInstallation(installation, distribution()); + + sh.run("echo foobar | " + installation.executables().elasticsearchKeystore + " add --stdin foo.bar"); + Stream.of( + installation.config("elasticsearch.yml"), + installation.config("jvm.options"), + installation.config("log4j2.properties") + ).forEach(path -> append(path, "# foo")); + + remove(distribution()); + assertRemoved(distribution()); + + if (isSystemd()) { + assertThat(sh.runIgnoreExitCode("systemctl is-enabled elasticsearch.service").exitCode, is(1)); + } + + assertPathsDontExist( + installation.bin, + installation.lib, + installation.modules, + installation.plugins, + installation.logs, + installation.pidDir, + installation.envFile, + SYSVINIT_SCRIPT, + SYSTEMD_SERVICE + ); + + assertTrue(Files.exists(installation.config)); + assertTrue(Files.exists(installation.config("elasticsearch.keystore"))); + + Stream.of( + "elasticsearch.yml", + "jvm.options", + "log4j2.properties" + ).forEach(configFile -> { + final Path original = installation.config(configFile); + final Path saved = installation.config(configFile + ".rpmsave"); + assertFalse(original + " should not exist", Files.exists(original)); + assertTrue(saved + " should exist", Files.exists(saved)); + }); + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Archives.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Archives.java index 6ffec813eb041..9e9a453ca8422 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Archives.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Archives.java @@ -35,7 +35,7 @@ import static org.elasticsearch.packaging.util.FileMatcher.p755; import static org.elasticsearch.packaging.util.FileUtils.getCurrentVersion; import static org.elasticsearch.packaging.util.FileUtils.getDefaultArchiveInstallPath; -import static org.elasticsearch.packaging.util.FileUtils.getPackagingArchivesDir; +import static org.elasticsearch.packaging.util.FileUtils.getDistributionFile; import static org.elasticsearch.packaging.util.FileUtils.lsGlob; import static org.elasticsearch.packaging.util.FileUtils.mv; @@ -66,7 +66,7 @@ public static Installation installArchive(Distribution distribution) { public static Installation installArchive(Distribution distribution, Path fullInstallPath, String version) { final Shell sh = new Shell(); - final Path distributionFile = getPackagingArchivesDir().resolve(distribution.filename(version)); + final Path distributionFile = getDistributionFile(distribution); final Path baseInstallPath = fullInstallPath.getParent(); final Path extractedPath = baseInstallPath.resolve("elasticsearch-" + version); @@ -106,7 +106,7 @@ public static Installation installArchive(Distribution distribution, Path fullIn Platforms.onLinux(() -> setupArchiveUsersLinux(fullInstallPath)); Platforms.onWindows(() -> setupArchiveUsersWindows(fullInstallPath)); - return new Installation(fullInstallPath); + return Installation.ofArchive(fullInstallPath); } private static void setupArchiveUsersLinux(Path installPath) { @@ -176,7 +176,6 @@ private static void verifyOssInstallation(Installation es, Distribution distribu ).forEach(dir -> assertThat(dir, file(Directory, owner, owner, p755))); assertThat(Files.exists(es.data), is(false)); - assertThat(Files.exists(es.scripts), is(false)); assertThat(es.bin, file(Directory, owner, owner, p755)); assertThat(es.lib, file(Directory, owner, owner, p755)); @@ -209,7 +208,7 @@ private static void verifyOssInstallation(Installation es, Distribution distribu "elasticsearch.yml", "jvm.options", "log4j2.properties" - ).forEach(config -> assertThat(es.config(config), file(File, owner, owner, p660))); + ).forEach(configFile -> assertThat(es.config(configFile), file(File, owner, owner, p660))); Stream.of( "NOTICE.txt", @@ -252,7 +251,7 @@ private static void verifyDefaultInstallation(Installation es, Distribution dist "roles.yml", "role_mapping.yml", "log4j2.properties" - ).forEach(config -> assertThat(es.config(config), file(File, owner, owner, p660))); + ).forEach(configFile -> assertThat(es.config(configFile), file(File, owner, owner, p660))); } public static void runElasticsearch(Installation installation) throws IOException { diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Cleanup.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Cleanup.java index 4ff2998988c5f..fda61e9fb36e5 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Cleanup.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Cleanup.java @@ -27,11 +27,9 @@ import static org.elasticsearch.packaging.util.FileUtils.getTempDir; import static org.elasticsearch.packaging.util.FileUtils.lsGlob; -import static org.elasticsearch.packaging.util.Platforms.isAptGet; import static org.elasticsearch.packaging.util.Platforms.isDPKG; import static org.elasticsearch.packaging.util.Platforms.isRPM; import static org.elasticsearch.packaging.util.Platforms.isSystemd; -import static org.elasticsearch.packaging.util.Platforms.isYUM; public class Cleanup { @@ -100,19 +98,14 @@ private static void purgePackagesLinux() { final Shell sh = new Shell(); if (isRPM()) { - sh.runIgnoreExitCode("rpm --quiet -e elasticsearch elasticsearch-oss"); - } - - if (isYUM()) { - sh.runIgnoreExitCode("yum remove -y elasticsearch elasticsearch-oss"); + // Doing rpm erase on both packages in one command will remove neither since both cannot be installed + // this may leave behind config files in /etc/elasticsearch, but a later step in this cleanup will get them + sh.runIgnoreExitCode("rpm --quiet -e elasticsearch"); + sh.runIgnoreExitCode("rpm --quiet -e elasticsearch-oss"); } if (isDPKG()) { sh.runIgnoreExitCode("dpkg --purge elasticsearch elasticsearch-oss"); } - - if (isAptGet()) { - sh.runIgnoreExitCode("apt-get --quiet --yes purge elasticsearch elasticsearch-oss"); - } } } diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileMatcher.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileMatcher.java index 9fdf6d60081a3..34bae68f97f3e 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileMatcher.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileMatcher.java @@ -47,6 +47,7 @@ public class FileMatcher extends TypeSafeMatcher { public enum Fileness { File, Directory } public static final Set p755 = fromString("rwxr-xr-x"); + public static final Set p750 = fromString("rwxr-x---"); public static final Set p660 = fromString("rw-rw----"); public static final Set p644 = fromString("rw-r--r--"); diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileUtils.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileUtils.java index 315dc6ffee1f9..10d1b3ee6b6de 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileUtils.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/FileUtils.java @@ -33,11 +33,14 @@ import java.nio.file.attribute.FileOwnerAttributeView; import java.nio.file.attribute.PosixFileAttributes; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.text.IsEmptyString.isEmptyOrNullString; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * Wrappers and convenience methods for common filesystem operations @@ -160,4 +163,20 @@ public static Path getPackagingArchivesDir() { assertThat(fromEnv, not(isEmptyOrNullString())); return Paths.get(fromEnv); } + + public static Path getDistributionFile(Distribution distribution) { + return getDistributionFile(distribution, getCurrentVersion()); + } + + public static Path getDistributionFile(Distribution distribution, String version) { + return getPackagingArchivesDir().resolve(distribution.filename(version)); + } + + public static void assertPathsExist(Path... paths) { + Arrays.stream(paths).forEach(path -> assertTrue(path + " should exist", Files.exists(path))); + } + + public static void assertPathsDontExist(Path... paths) { + Arrays.stream(paths).forEach(path -> assertFalse(path + " should not exist", Files.exists(path))); + } } diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Installation.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Installation.java index 68da440400a36..40dc546f2306d 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Installation.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Installation.java @@ -20,6 +20,7 @@ package org.elasticsearch.packaging.util; import java.nio.file.Path; +import java.nio.file.Paths; /** * Represents an installation of Elasticsearch @@ -34,9 +35,10 @@ public class Installation { public final Path logs; public final Path plugins; public final Path modules; - public final Path scripts; + public final Path pidDir; + public final Path envFile; - public Installation(Path home, Path config, Path data, Path logs, Path plugins, Path modules, Path scripts) { + public Installation(Path home, Path config, Path data, Path logs, Path plugins, Path modules, Path pidDir, Path envFile) { this.home = home; this.bin = home.resolve("bin"); this.lib = home.resolve("lib"); @@ -46,18 +48,38 @@ public Installation(Path home, Path config, Path data, Path logs, Path plugins, this.logs = logs; this.plugins = plugins; this.modules = modules; - this.scripts = scripts; + this.pidDir = pidDir; + this.envFile = envFile; } - public Installation(Path home) { - this( + public static Installation ofArchive(Path home) { + return new Installation( home, home.resolve("config"), home.resolve("data"), home.resolve("logs"), home.resolve("plugins"), home.resolve("modules"), - home.resolve("scripts") + null, + null + ); + } + + public static Installation ofPackage(Distribution.Packaging packaging) { + + final Path envFile = (packaging == Distribution.Packaging.RPM) + ? Paths.get("/etc/sysconfig/elasticsearch") + : Paths.get("/etc/default/elasticsearch"); + + return new Installation( + Paths.get("/usr/share/elasticsearch"), + Paths.get("/etc/elasticsearch"), + Paths.get("/var/lib/elasticsearch"), + Paths.get("/var/log/elasticsearch"), + Paths.get("/usr/share/elasticsearch/plugins"), + Paths.get("/usr/share/elasticsearch/modules"), + Paths.get("/var/run/elasticsearch"), + envFile ); } diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Packages.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Packages.java new file mode 100644 index 0000000000000..6e80d9e027df2 --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Packages.java @@ -0,0 +1,259 @@ +/* + * 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.elasticsearch.packaging.util.Shell.Result; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +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; +import static org.elasticsearch.packaging.util.FileMatcher.p644; +import static org.elasticsearch.packaging.util.FileMatcher.p660; +import static org.elasticsearch.packaging.util.FileMatcher.p750; +import static org.elasticsearch.packaging.util.FileMatcher.p755; +import static org.elasticsearch.packaging.util.FileUtils.getCurrentVersion; +import static org.elasticsearch.packaging.util.FileUtils.getDistributionFile; +import static org.elasticsearch.packaging.util.Platforms.isSysVInit; +import static org.elasticsearch.packaging.util.Platforms.isSystemd; +import static org.elasticsearch.packaging.util.ServerUtils.waitForElasticsearch; +import static org.hamcrest.CoreMatchers.anyOf; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Packages { + + public static final Path SYSVINIT_SCRIPT = Paths.get("/etc/init.d/elasticsearch"); + public static final Path SYSTEMD_SERVICE = Paths.get("/usr/lib/systemd/system/elasticsearch.service"); + + public static void assertInstalled(Distribution distribution) { + final Result status = packageStatus(distribution); + assertThat(status.exitCode, is(0)); + + Platforms.onDPKG(() -> assertFalse(Pattern.compile("(?m)^Status:.+deinstall ok").matcher(status.stdout).find())); + } + + public static void assertRemoved(Distribution distribution) { + final Result status = packageStatus(distribution); + + Platforms.onRPM(() -> assertThat(status.exitCode, is(1))); + + Platforms.onDPKG(() -> { + assertThat(status.exitCode, anyOf(is(0), is(1))); + if (status.exitCode == 0) { + assertTrue(Pattern.compile("(?m)^Status:.+deinstall ok").matcher(status.stdout).find()); + } + }); + } + + public static Result packageStatus(Distribution distribution) { + final Shell sh = new Shell(); + final Result result; + + if (distribution.packaging == Distribution.Packaging.RPM) { + result = sh.runIgnoreExitCode("rpm -qe " + distribution.flavor.name); + } else { + result = sh.runIgnoreExitCode("dpkg -s " + distribution.flavor.name); + } + + return result; + } + + public static Installation install(Distribution distribution) { + return install(distribution, getCurrentVersion()); + } + + public static Installation install(Distribution distribution, String version) { + final Shell sh = new Shell(); + final Path distributionFile = getDistributionFile(distribution, version); + + Platforms.onRPM(() -> sh.run("rpm -i " + distributionFile)); + Platforms.onDPKG(() -> sh.run("dpkg -i " + distributionFile)); + + return Installation.ofPackage(distribution.packaging); + } + + public static void remove(Distribution distribution) { + final Shell sh = new Shell(); + + Platforms.onRPM(() -> { + sh.run("rpm -e " + distribution.flavor.name); + final Result status = packageStatus(distribution); + assertThat(status.exitCode, is(1)); + }); + + Platforms.onDPKG(() -> { + sh.run("dpkg -r " + distribution.flavor.name); + final Result status = packageStatus(distribution); + assertThat(status.exitCode, is(0)); + assertTrue(Pattern.compile("(?m)^Status:.+deinstall ok").matcher(status.stdout).find()); + }); + } + + public static void verifyPackageInstallation(Installation installation, Distribution distribution) { + verifyOssInstallation(installation, distribution); + if (distribution.flavor == Distribution.Flavor.DEFAULT) { + verifyDefaultInstallation(installation); + } + } + + + private static void verifyOssInstallation(Installation es, Distribution distribution) { + final Shell sh = new Shell(); + + sh.run("id elasticsearch"); + sh.run("getent group elasticsearch"); + + final Result passwdResult = sh.run("getent passwd elasticsearch"); + final Path homeDir = Paths.get(passwdResult.stdout.trim().split(":")[5]); + assertFalse("elasticsearch user home directory must not exist", Files.exists(homeDir)); + + Stream.of( + es.home, + es.plugins, + es.modules + ).forEach(dir -> assertThat(dir, file(Directory, "root", "root", p755))); + + assertThat(es.pidDir, file(Directory, "elasticsearch", "elasticsearch", p755)); + + Stream.of( + es.data, + es.logs + ).forEach(dir -> assertThat(dir, file(Directory, "elasticsearch", "elasticsearch", p750))); + + // we shell out here because java's posix file permission view doesn't support special modes + assertThat(es.config, file(Directory, "root", "elasticsearch", p750)); + assertThat(sh.run("find \"" + es.config + "\" -maxdepth 0 -printf \"%m\"").stdout, containsString("2750")); + + Stream.of( + "elasticsearch.keystore", + "elasticsearch.yml", + "jvm.options", + "log4j2.properties" + ).forEach(configFile -> assertThat(es.config(configFile), file(File, "root", "elasticsearch", p660))); + assertThat(es.config(".elasticsearch.keystore.initial_md5sum"), file(File, "root", "elasticsearch", p644)); + + assertThat(sh.run("sudo -u elasticsearch " + es.bin("elasticsearch-keystore") + " list").stdout, containsString("keystore.seed")); + + Stream.of( + es.bin, + es.lib + ).forEach(dir -> assertThat(dir, file(Directory, "root", "root", p755))); + + Stream.of( + "elasticsearch", + "elasticsearch-plugin", + "elasticsearch-keystore", + "elasticsearch-translog" + ).forEach(executable -> assertThat(es.bin(executable), file(File, "root", "root", p755))); + + Stream.of( + "NOTICE.txt", + "README.textile" + ).forEach(doc -> assertThat(es.home.resolve(doc), file(File, "root", "root", p644))); + + assertThat(es.envFile, file(File, "root", "elasticsearch", p660)); + + if (distribution.packaging == Distribution.Packaging.RPM) { + assertThat(es.home.resolve("LICENSE.txt"), file(File, "root", "root", p644)); + } else { + Path copyrightDir = Paths.get(sh.run("readlink -f /usr/share/doc/" + distribution.flavor.name).stdout.trim()); + assertThat(copyrightDir, file(Directory, "root", "root", p755)); + assertThat(copyrightDir.resolve("copyright"), file(File, "root", "root", p644)); + } + + if (isSystemd()) { + Stream.of( + SYSTEMD_SERVICE, + Paths.get("/usr/lib/tmpfiles.d/elasticsearch.conf"), + Paths.get("/usr/lib/sysctl.d/elasticsearch.conf") + ).forEach(confFile -> assertThat(confFile, file(File, "root", "root", p644))); + + final String sysctlExecutable = (distribution.packaging == Distribution.Packaging.RPM) + ? "/usr/sbin/sysctl" + : "/sbin/sysctl"; + assertThat(sh.run(sysctlExecutable + " vm.max_map_count").stdout, containsString("vm.max_map_count = 262144")); + } + + if (isSysVInit()) { + assertThat(SYSVINIT_SCRIPT, file(File, "root", "root", p750)); + } + } + + private static void verifyDefaultInstallation(Installation es) { + + Stream.of( + "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.bin(executable), file(File, "root", "root", p755))); + + // 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.bin("elasticsearch-sql-cli-" + getCurrentVersion() + ".jar"), file(File, "root", "root", p755)); + + Stream.of( + "users", + "users_roles", + "roles.yml", + "role_mapping.yml", + "log4j2.properties" + ).forEach(configFile -> assertThat(es.config(configFile), file(File, "root", "elasticsearch", p660))); + } + + public static void startElasticsearch() throws IOException { + final Shell sh = new Shell(); + 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"); + } + + waitForElasticsearch(); + + if (isSystemd()) { + sh.run("systemctl is-active elasticsearch.service"); + sh.run("systemctl status elasticsearch.service"); + } else { + sh.run("service elasticsearch status"); + } + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Platforms.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Platforms.java index 5ffbc31820022..c7ca1284ca69a 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Platforms.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/Platforms.java @@ -19,23 +19,28 @@ package org.elasticsearch.packaging.util; +import java.nio.file.Paths; + +import static org.elasticsearch.packaging.util.FileUtils.slurp; + public class Platforms { public static final String OS_NAME = System.getProperty("os.name"); public static final boolean LINUX = OS_NAME.startsWith("Linux"); public static final boolean WINDOWS = OS_NAME.startsWith("Windows"); - public static boolean isDPKG() { - if (WINDOWS) { - return false; + public static String getOsRelease() { + if (LINUX) { + return slurp(Paths.get("/etc/os-release")); + } else { + throw new RuntimeException("os-release is only supported on linux"); } - return new Shell().runIgnoreExitCode("which dpkg").isSuccess(); } - public static boolean isAptGet() { + public static boolean isDPKG() { if (WINDOWS) { return false; } - return new Shell().runIgnoreExitCode("which apt-get").isSuccess(); + return new Shell().runIgnoreExitCode("which dpkg").isSuccess(); } public static boolean isRPM() { @@ -45,13 +50,6 @@ public static boolean isRPM() { return new Shell().runIgnoreExitCode("which rpm").isSuccess(); } - public static boolean isYUM() { - if (WINDOWS) { - return false; - } - return new Shell().runIgnoreExitCode("which yum").isSuccess(); - } - public static boolean isSystemd() { if (WINDOWS) { return false; @@ -78,6 +76,18 @@ public static void onLinux(PlatformAction action) { } } + public static void onRPM(PlatformAction action) { + if (isRPM()) { + action.run(); + } + } + + public static void onDPKG(PlatformAction action) { + if (isDPKG()) { + action.run(); + } + } + /** * Essentially a Runnable, but we make the distinction so it's more clear that these are synchronous */ diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/ServerUtils.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/ServerUtils.java index ff006a34e6892..6331b4bf46e9a 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/ServerUtils.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/util/ServerUtils.java @@ -72,7 +72,7 @@ public static void waitForElasticsearch(String status, String index) throws IOEx } catch (HttpHostConnectException e) { // we want to retry if the connection is refused - LOG.info("Got connection refused when waiting for cluster health", e); + LOG.debug("Got connection refused when waiting for cluster health", e); } timeElapsed = System.currentTimeMillis() - startTime; diff --git a/qa/vagrant/src/test/resources/packaging/tests/30_deb_package.bats b/qa/vagrant/src/test/resources/packaging/tests/30_deb_package.bats deleted file mode 100644 index 749c72c8b312f..0000000000000 --- a/qa/vagrant/src/test/resources/packaging/tests/30_deb_package.bats +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/env bats - -# This file is used to test the installation and removal -# of a Debian 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/packages.bash -load $BATS_UTILS/plugins.bash - -# Cleans everything for the 1st execution -setup() { - skip_not_dpkg - export_elasticsearch_paths -} - -@test "[DEB] package depends on bash" { - dpkg -I elasticsearch-oss-$(cat version).deb | grep "Depends:.*bash.*" -} - -@test "[DEB] package conflicts" { - dpkg -I elasticsearch-oss-$(cat version).deb | grep "^ Conflicts: elasticsearch$" - dpkg -I elasticsearch-$(cat version).deb | grep "^ Conflicts: elasticsearch-oss$" -} - -################################## -# Install DEB package -################################## -@test "[DEB] dpkg command is available" { - clean_before_test - dpkg --version -} - -@test "[DEB] package is available" { - count=$(ls elasticsearch-oss-$(cat version).deb | wc -l) - [ "$count" -eq 1 ] -} - -@test "[DEB] package is not installed" { - run dpkg -s 'elasticsearch-oss' - [ "$status" -eq 1 ] -} - -@test "[DEB] temporarily remove java and ensure the install fails" { - move_java - run dpkg -i elasticsearch-oss-$(cat version).deb - output=$status - unmove_java - [ "$output" -eq 1 ] -} - -@test "[DEB] install package" { - dpkg -i elasticsearch-oss-$(cat version).deb -} - -@test "[DEB] package is installed" { - dpkg -s 'elasticsearch-oss' -} - -@test "[DEB] verify package installation" { - verify_package_installation -} - -@test "[DEB] verify elasticsearch-plugin list runs without any plugins installed" { - local plugins_list=`$ESHOME/bin/elasticsearch-plugin list` - [[ -z $plugins_list ]] -} - -@test "[DEB] elasticsearch isn't started by package install" { - # Wait a second to give Elasticsearch a change to start if it is going to. - # This isn't perfect by any means but its something. - sleep 1 - ! ps aux | grep elasticsearch | grep java - # You might be tempted to use jps instead of the above but that'd have to - # look like: - # ! sudo -u elasticsearch jps | grep -i elasticsearch - # which isn't really easier to read than the above. -} - -@test "[DEB] test elasticsearch" { - start_elasticsearch_service - run_elasticsearch_tests -} - -@test "[DEB] verify package installation after start" { - # Checks that the startup scripts didn't change the permissions - verify_package_installation -} - -################################## -# Uninstall DEB package -################################## -@test "[DEB] remove package" { - dpkg -r 'elasticsearch-oss' -} - -@test "[DEB] package has been removed" { - run dpkg -s 'elasticsearch-oss' - [ "$status" -eq 0 ] - echo "$output" | grep -i "status" | grep -i "deinstall ok" -} - -@test "[DEB] verify package removal" { - # The removal must stop the service - count=$(ps | grep Elasticsearch | wc -l) - [ "$count" -eq 0 ] - - # The removal must disable the service - # see prerm file - if is_systemd; then - missing_exit_code=4 - if [ $(systemctl --version | head -1 | awk '{print $2}') -lt 231 ]; then - # systemd before version 231 used exit code 3 when the service did not exist - missing_exit_code=3 - fi - run systemctl status elasticsearch.service - [ "$status" -eq $missing_exit_code ] - - run systemctl is-enabled elasticsearch.service - [ "$status" -eq 1 ] - fi - - # Those directories are deleted when removing the package - # see postrm file - assert_file_not_exist "/var/log/elasticsearch" - assert_file_not_exist "/usr/share/elasticsearch/plugins" - assert_file_not_exist "/usr/share/elasticsearch/modules" - assert_file_not_exist "/var/run/elasticsearch" - - # Those directories are removed by the package manager - assert_file_not_exist "/usr/share/elasticsearch/bin" - assert_file_not_exist "/usr/share/elasticsearch/lib" - assert_file_not_exist "/usr/share/elasticsearch/modules" - assert_file_not_exist "/usr/share/elasticsearch/modules/lang-painless" - - # The configuration files are still here - assert_file_exist "/etc/elasticsearch" - # TODO: use ucf to handle these better for Debian-based systems - assert_file_not_exist "/etc/elasticsearch/elasticsearch.keystore" - assert_file_not_exist "/etc/elasticsearch/.elasticsearch.keystore.initial_md5sum" - assert_file_exist "/etc/elasticsearch/elasticsearch.yml" - assert_file_exist "/etc/elasticsearch/jvm.options" - assert_file_exist "/etc/elasticsearch/log4j2.properties" - - # The env file is still here - assert_file_exist "/etc/default/elasticsearch" - - # The service files are still here - assert_file_exist "/etc/init.d/elasticsearch" -} - -@test "[DEB] purge package" { - # User installed scripts aren't removed so we'll just get them ourselves - rm -rf $ESSCRIPTS - dpkg --purge 'elasticsearch-oss' -} - -@test "[DEB] verify package purge" { - # all remaining files are deleted by the purge - assert_file_not_exist "/etc/elasticsearch" - assert_file_not_exist "/etc/elasticsearch/elasticsearch.keystore" - assert_file_not_exist "/etc/elasticsearch/.elasticsearch.keystore.initial_md5sum" - assert_file_not_exist "/etc/elasticsearch/elasticsearch.yml" - assert_file_not_exist "/etc/elasticsearch/jvm.options" - assert_file_not_exist "/etc/elasticsearch/log4j2.properties" - - assert_file_not_exist "/etc/default/elasticsearch" - - assert_file_not_exist "/etc/init.d/elasticsearch" - assert_file_not_exist "/usr/lib/systemd/system/elasticsearch.service" - - assert_file_not_exist "/usr/share/elasticsearch" - - assert_file_not_exist "/usr/share/doc/elasticsearch-oss" - assert_file_not_exist "/usr/share/doc/elasticsearch-oss/copyright" -} - -@test "[DEB] package has been completly removed" { - run dpkg -s 'elasticsearch-oss' - [ "$status" -eq 1 ] -} - -@test "[DEB] reinstall package" { - dpkg -i elasticsearch-oss-$(cat version).deb -} - -@test "[DEB] package is installed by reinstall" { - dpkg -s 'elasticsearch-oss' -} - -@test "[DEB] verify package reinstallation" { - verify_package_installation -} - -@test "[DEB] repurge package" { - dpkg --purge 'elasticsearch-oss' -} - -@test "[DEB] package has been completly removed again" { - run dpkg -s 'elasticsearch-oss' - [ "$status" -eq 1 ] -} diff --git a/qa/vagrant/src/test/resources/packaging/tests/40_rpm_package.bats b/qa/vagrant/src/test/resources/packaging/tests/40_rpm_package.bats deleted file mode 100644 index cb12d4b50e02b..0000000000000 --- a/qa/vagrant/src/test/resources/packaging/tests/40_rpm_package.bats +++ /dev/null @@ -1,220 +0,0 @@ -#!/usr/bin/env bats - -# This file is used to test the installation of a RPM 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/packages.bash -load $BATS_UTILS/plugins.bash - -# Cleans everything for the 1st execution -setup() { - skip_not_rpm - export_elasticsearch_paths -} - -@test "[RPM] package depends on bash" { - rpm -qpR elasticsearch-oss-$(cat version).rpm | grep '/bin/bash' -} - -@test "[RPM] package conflicts" { - rpm -qp --conflicts elasticsearch-oss-$(cat version).rpm | grep "^elasticsearch\s*$" - rpm -qp --conflicts elasticsearch-$(cat version).rpm | grep "^elasticsearch-oss\s*$" -} - -################################## -# Install RPM package -################################## -@test "[RPM] rpm command is available" { - clean_before_test - rpm --version -} - -@test "[RPM] package is available" { - count=$(ls elasticsearch-oss-$(cat version).rpm | wc -l) - [ "$count" -eq 1 ] -} - -@test "[RPM] package is not installed" { - run rpm -qe 'elasticsearch-oss' - [ "$status" -eq 1 ] -} - -@test "[RPM] temporarily remove java and ensure the install fails" { - move_java - run rpm -i elasticsearch-oss-$(cat version).rpm - output=$status - unmove_java - [ "$output" -eq 1 ] -} - -@test "[RPM] install package" { - rpm -i elasticsearch-oss-$(cat version).rpm -} - -@test "[RPM] package is installed" { - rpm -qe 'elasticsearch-oss' -} - -@test "[RPM] verify package installation" { - verify_package_installation -} - -@test "[RPM] verify elasticsearch-plugin list runs without any plugins installed" { - local plugins_list=`$ESHOME/bin/elasticsearch-plugin list` - [[ -z $plugins_list ]] -} - -@test "[RPM] elasticsearch isn't started by package install" { - # Wait a second to give Elasticsearch a change to start if it is going to. - # This isn't perfect by any means but its something. - sleep 1 - ! ps aux | grep elasticsearch | grep java -} - -@test "[RPM] test elasticsearch" { - start_elasticsearch_service - run_elasticsearch_tests -} - -@test "[RPM] verify package installation after start" { - # Checks that the startup scripts didn't change the permissions - verify_package_installation -} - -@test "[RPM] remove package" { - # User installed scripts aren't removed so we'll just get them ourselves - rm -rf $ESSCRIPTS - rpm -e 'elasticsearch-oss' -} - -@test "[RPM] package has been removed" { - run rpm -qe 'elasticsearch-oss' - [ "$status" -eq 1 ] -} - -@test "[RPM] verify package removal" { - # The removal must stop the service - count=$(ps | grep Elasticsearch | wc -l) - [ "$count" -eq 0 ] - - # The removal must disable the service - # see prerm file - if is_systemd; then - run systemctl is-enabled elasticsearch.service - [ "$status" -eq 1 ] - fi - - # Those directories are deleted when removing the package - # see postrm file - assert_file_not_exist "/var/log/elasticsearch" - assert_file_not_exist "/usr/share/elasticsearch/plugins" - assert_file_not_exist "/var/run/elasticsearch" - - # Those directories are removed by the package manager - assert_file_not_exist "/usr/share/elasticsearch/bin" - assert_file_not_exist "/usr/share/elasticsearch/lib" - assert_file_not_exist "/usr/share/elasticsearch/modules" - - assert_file_not_exist "/etc/elasticsearch" - - assert_file_not_exist "/etc/init.d/elasticsearch" - assert_file_not_exist "/usr/lib/systemd/system/elasticsearch.service" - - assert_file_not_exist "/etc/sysconfig/elasticsearch" -} - -@test "[RPM] reinstall package" { - rpm -i elasticsearch-oss-$(cat version).rpm -} - -@test "[RPM] package is installed by reinstall" { - rpm -qe 'elasticsearch-oss' -} - -@test "[RPM] verify package reinstallation" { - verify_package_installation -} - -@test "[RPM] reremove package" { - echo foobar | "$ESHOME/bin/elasticsearch-keystore" add --stdin foo.bar - echo "# ping" >> "/etc/elasticsearch/elasticsearch.yml" - echo "# ping" >> "/etc/elasticsearch/jvm.options" - echo "# ping" >> "/etc/elasticsearch/log4j2.properties" - rpm -e 'elasticsearch-oss' -} - -@test "[RPM] verify preservation" { - # The removal must disable the service - # see prerm file - if is_systemd; then - run systemctl is-enabled elasticsearch.service - [ "$status" -eq 1 ] - fi - - # Those directories are deleted when removing the package - # see postrm file - assert_file_not_exist "/var/log/elasticsearch" - assert_file_not_exist "/usr/share/elasticsearch/plugins" - assert_file_not_exist "/usr/share/elasticsearch/modules" - assert_file_not_exist "/var/run/elasticsearch" - - assert_file_not_exist "/usr/share/elasticsearch/bin" - assert_file_not_exist "/usr/share/elasticsearch/lib" - assert_file_not_exist "/usr/share/elasticsearch/modules" - assert_file_not_exist "/usr/share/elasticsearch/modules/lang-painless" - - assert_file_exist "/etc/elasticsearch/elasticsearch.keystore" - assert_file_not_exist "/etc/elasticsearch/elasticsearch.yml" - assert_file_exist "/etc/elasticsearch/elasticsearch.yml.rpmsave" - assert_file_not_exist "/etc/elasticsearch/jvm.options" - assert_file_exist "/etc/elasticsearch/jvm.options.rpmsave" - assert_file_not_exist "/etc/elasticsearch/log4j2.properties" - assert_file_exist "/etc/elasticsearch/log4j2.properties.rpmsave" - - assert_file_not_exist "/etc/init.d/elasticsearch" - assert_file_not_exist "/usr/lib/systemd/system/elasticsearch.service" - - assert_file_not_exist "/etc/sysconfig/elasticsearch" -} - -@test "[RPM] finalize package removal" { - # cleanup - rm -rf /etc/elasticsearch -} - -@test "[RPM] package has been removed again" { - run rpm -qe 'elasticsearch-oss' - [ "$status" -eq 1 ] -}