Create keystore on package install (#28928)

This commit removes the ability to specify that a plugin requires the
keystore and instead creates the keystore on package installation or
when Elasticsearch is started for the first time. The reason that we opt
to create the keystore on package installation is to ensure that the
keystore has the correct permissions (the package installation scripts
run as root as opposed to Elasticsearch running as the elasticsearch
user) and to enable removing the keystore on package removal if the
keystore is not modified.
This commit is contained in:
Jason Tedor 2018-03-12 12:48:00 -04:00 committed by GitHub
parent a7b53fd3b7
commit 6331bcaf76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 116 additions and 179 deletions

View File

@ -43,6 +43,3 @@ extended.plugins=${extendedPlugins}
#
# 'has.native.controller': whether or not the plugin has a native controller
has.native.controller=${hasNativeController}
#
# 'requires.keystore': whether or not the plugin needs the elasticsearch keystore be created
requires.keystore=${requiresKeystore}

View File

@ -104,11 +104,18 @@ chmod g+s /etc/elasticsearch
chmod 0750 /etc/elasticsearch
if [ -f /etc/default/elasticsearch ]; then
chown root:elasticsearch /etc/default/elasticsearch
chown root:elasticsearch /etc/default/elasticsearch
fi
if [ -f /etc/sysconfig/elasticsearch ]; then
chown root:elasticsearch /etc/sysconfig/elasticsearch
chown root:elasticsearch /etc/sysconfig/elasticsearch
fi
if [ ! -f "$ES_PATH_CONF"/elasticsearch.keystore ]; then
/usr/share/elasticsearch/bin/elasticsearch-keystore create
chown root:elasticsearch "$ES_PATH_CONF"/elasticsearch.keystore
chmod 660 "$ES_PATH_CONF"/elasticsearch.keystore
md5sum "$ES_PATH_CONF"/elasticsearch.keystore > "$ES_PATH_CONF"/.elasticsearch.keystore.initial_md5sum
fi
${scripts.footer}

View File

@ -44,6 +44,11 @@ case "$1" in
;;
esac
ES_ENV_FILE="${path.env}"
if [ -f "$ES_ENV_FILE" ]; then
. "$ES_ENV_FILE"
fi
# Stops the service
if [ "$STOP_REQUIRED" = "true" ]; then
echo -n "Stopping elasticsearch service..."
@ -67,6 +72,12 @@ if [ "$STOP_REQUIRED" = "true" ]; then
echo " OK"
fi
if [ -f "$ES_PATH_CONF"/elasticsearch.keystore ]; then
if md5sum --status -c "$ES_PATH_CONF"/.elasticsearch.keystore.initial_md5sum; then
rm "$ES_PATH_CONF"/elasticsearch.keystore "$ES_PATH_CONF"/.elasticsearch.keystore.initial_md5sum
fi
fi
if [ "$REMOVE_SERVICE" = "true" ]; then
if command -v systemctl >/dev/null; then
systemctl disable elasticsearch.service > /dev/null 2>&1 || true

View File

@ -686,12 +686,6 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
}
}
movePlugin(tmpRoot, destination);
for (PluginInfo info : pluginInfos) {
if (info.requiresKeystore()) {
createKeystoreIfNeeded(terminal, env, info);
break;
}
}
String[] plugins = pluginInfos.stream().map(PluginInfo::getName).toArray(String[]::new);
terminal.println("-> Installed " + metaInfo.getName() + " with: " + Strings.arrayToCommaDelimitedString(plugins));
}
@ -716,9 +710,6 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
installPluginSupportFiles(info, tmpRoot, env.binFile().resolve(info.getName()),
env.configFile().resolve(info.getName()), deleteOnFailure);
movePlugin(tmpRoot, destination);
if (info.requiresKeystore()) {
createKeystoreIfNeeded(terminal, env, info);
}
terminal.println("-> Installed " + info.getName());
}
@ -824,15 +815,6 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
IOUtils.rm(tmpConfigDir); // clean up what we just copied
}
private void createKeystoreIfNeeded(Terminal terminal, Environment env, PluginInfo info) throws Exception {
KeyStoreWrapper keystore = KeyStoreWrapper.load(env.configFile());
if (keystore == null) {
terminal.println("Elasticsearch keystore is required by plugin [" + info.getName() + "], creating...");
keystore = KeyStoreWrapper.create();
keystore.save(env.configFile(), new char[0]);
}
}
private static void setOwnerGroup(final Path path, final PosixFileAttributes attributes) throws IOException {
Objects.requireNonNull(attributes);
PosixFileAttributeView fileAttributeView = Files.getFileAttributeView(path, PosixFileAttributeView.class);

View File

@ -1140,45 +1140,6 @@ public class InstallPluginCommandTests extends ESTestCase {
assertTrue(e.getMessage(), e.getMessage().contains("SHA-1 mismatch, expected foobar"));
}
public void testKeystoreNotRequired() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
String pluginZip = createPluginUrl("fake", pluginDir, "requires.keystore", "false");
installPlugin(pluginZip, env.v1());
assertFalse(Files.exists(KeyStoreWrapper.keystorePath(env.v2().configFile())));
}
public void testKeystoreRequiredAlreadyExists() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
KeyStoreWrapper keystore = KeyStoreWrapper.create();
keystore.save(env.v2().configFile(), new char[0]);
byte[] expectedBytes = Files.readAllBytes(KeyStoreWrapper.keystorePath(env.v2().configFile()));
Path pluginDir = createPluginDir(temp);
String pluginZip = createPluginUrl("fake", pluginDir, "requires.keystore", "true");
installPlugin(pluginZip, env.v1());
byte[] gotBytes = Files.readAllBytes(KeyStoreWrapper.keystorePath(env.v2().configFile()));
assertArrayEquals("Keystore was modified", expectedBytes, gotBytes);
}
public void testKeystoreRequiredCreated() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
String pluginZip = createPluginUrl("fake", pluginDir, "requires.keystore", "true");
installPlugin(pluginZip, env.v1());
assertTrue(Files.exists(KeyStoreWrapper.keystorePath(env.v2().configFile())));
}
public void testKeystoreRequiredCreatedWithMetaPlugin() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Files.createDirectory(pluginDir);
writePlugin("fake", pluginDir, "requires.keystore", "true");
String metaZip = createMetaPluginUrl("my_plugins", metaDir);
installPlugin(metaZip, env.v1());
assertTrue(Files.exists(KeyStoreWrapper.keystorePath(env.v2().configFile())));
}
private Function<byte[], String> checksum(final MessageDigest digest) {
return checksumAndString(digest, "");
}

View File

@ -25,7 +25,6 @@ import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
@ -93,7 +92,7 @@ public class ListPluginsCommandTests extends ESTestCase {
final String description,
final String name,
final String classname) throws IOException {
buildFakePlugin(env, null, description, name, classname, false, false);
buildFakePlugin(env, null, description, name, classname, false);
}
private static void buildFakePlugin(
@ -102,17 +101,16 @@ public class ListPluginsCommandTests extends ESTestCase {
final String description,
final String name,
final String classname) throws IOException {
buildFakePlugin(env, metaPlugin, description, name, classname, false, false);
buildFakePlugin(env, metaPlugin, description, name, classname, false);
}
private static void buildFakePlugin(
final Environment env,
final String description,
final String name,
final String classname,
final boolean hasNativeController,
final boolean requiresKeystore) throws IOException {
buildFakePlugin(env, null, description, name, classname, hasNativeController, requiresKeystore);
final Environment env,
final String description,
final String name,
final String classname,
final boolean hasNativeController) throws IOException {
buildFakePlugin(env, null, description, name, classname, hasNativeController);
}
private static void buildFakePlugin(
@ -121,8 +119,7 @@ public class ListPluginsCommandTests extends ESTestCase {
final String description,
final String name,
final String classname,
final boolean hasNativeController,
final boolean requiresKeystore) throws IOException {
final boolean hasNativeController) throws IOException {
Path dest = metaPlugin != null ? env.pluginsFile().resolve(metaPlugin) : env.pluginsFile();
PluginTestUtil.writePluginProperties(
dest.resolve(name),
@ -132,8 +129,7 @@ public class ListPluginsCommandTests extends ESTestCase {
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", "1.8",
"classname", classname,
"has.native.controller", Boolean.toString(hasNativeController),
"requires.keystore", Boolean.toString(requiresKeystore));
"has.native.controller", Boolean.toString(hasNativeController));
}
private static void buildFakeMetaPlugin(
@ -195,14 +191,13 @@ public class ListPluginsCommandTests extends ESTestCase {
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Requires Keystore: false",
"Extended Plugins: []",
" * Classname: org.fake"),
terminal.getOutput());
}
public void testPluginWithNativeController() throws Exception {
buildFakePlugin(env, "fake desc 1", "fake_plugin1", "org.fake", true, false);
buildFakePlugin(env, "fake desc 1", "fake_plugin1", "org.fake", true);
String[] params = { "-v" };
MockTerminal terminal = listPlugins(home, params);
assertEquals(
@ -216,28 +211,6 @@ public class ListPluginsCommandTests extends ESTestCase {
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: true",
"Requires Keystore: false",
"Extended Plugins: []",
" * Classname: org.fake"),
terminal.getOutput());
}
public void testPluginWithRequiresKeystore() throws Exception {
buildFakePlugin(env, "fake desc 1", "fake_plugin1", "org.fake", false, true);
String[] params = { "-v" };
MockTerminal terminal = listPlugins(home, params);
assertEquals(
buildMultiline(
"Plugins directory: " + env.pluginsFile(),
"fake_plugin1",
"- Plugin information:",
"Name: fake_plugin1",
"Description: fake desc 1",
"Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Requires Keystore: true",
"Extended Plugins: []",
" * Classname: org.fake"),
terminal.getOutput());
@ -259,7 +232,6 @@ public class ListPluginsCommandTests extends ESTestCase {
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Requires Keystore: false",
"Extended Plugins: []",
" * Classname: org.fake",
"fake_plugin2",
@ -270,7 +242,6 @@ public class ListPluginsCommandTests extends ESTestCase {
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Requires Keystore: false",
"Extended Plugins: []",
" * Classname: org.fake2"),
terminal.getOutput());
@ -294,7 +265,6 @@ public class ListPluginsCommandTests extends ESTestCase {
"\tElasticsearch Version: " + Version.CURRENT.toString(),
"\tJava Version: 1.8",
"\tNative Controller: false",
"\tRequires Keystore: false",
"\tExtended Plugins: []",
"\t * Classname: org.fake",
"\tfake_plugin2",
@ -305,7 +275,6 @@ public class ListPluginsCommandTests extends ESTestCase {
"\tElasticsearch Version: " + Version.CURRENT.toString(),
"\tJava Version: 1.8",
"\tNative Controller: false",
"\tRequires Keystore: false",
"\tExtended Plugins: []",
"\t * Classname: org.fake2"),
terminal.getOutput());

View File

@ -100,6 +100,14 @@ setup() {
}
}
@test "[TAR] test creating elasticearch.keystore" {
sudo -E -u elasticsearch "$ESHOME/bin/elasticsearch-keystore" create
assert_file "$ESCONFIG/elasticsearch.keystore" f elasticsearch elasticsearch 660
sudo -E -u elasticsearch "$ESHOME/bin/elasticsearch-keystore" list | grep "keystore.seed"
# cleanup for the next test
rm -rf "$ESCONFIG/elasticsearch.keystore"
}
##################################
# Check that Elasticsearch is working
##################################
@ -109,6 +117,13 @@ setup() {
stop_elasticsearch_service
}
@test "[TAR] test auto-creating elasticearch.keystore" {
# a keystore should automatically be created after the service is started
assert_file "$ESCONFIG/elasticsearch.keystore" f elasticsearch elasticsearch 660
# the keystore should be seeded
sudo -E -u elasticsearch "$ESHOME/bin/elasticsearch-keystore" list | grep "keystore.seed"
}
@test "[TAR] start Elasticsearch with custom JVM options" {
local es_java_opts=$ES_JAVA_OPTS
local es_path_conf=$ES_PATH_CONF

View File

@ -149,6 +149,9 @@ setup() {
# 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"
@ -170,6 +173,8 @@ setup() {
@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"

View File

@ -155,6 +155,7 @@ setup() {
}
@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"
@ -181,6 +182,7 @@ setup() {
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"

View File

@ -95,6 +95,11 @@ verify_package_installation() {
assert_file "$ESHOME/bin/elasticsearch-translog" f root root 755
assert_file "$ESHOME/lib" d root root 755
assert_file "$ESCONFIG" d root elasticsearch 2750
assert_file "$ESCONFIG/elasticsearch.keystore" f root elasticsearch 660
sudo -u elasticsearch "$ESHOME/bin/elasticsearch-keystore" list | grep "keystore.seed"
assert_file "$ESCONFIG/.elasticsearch.keystore.initial_md5sum" f root elasticsearch 644
assert_file "$ESCONFIG/elasticsearch.yml" f root elasticsearch 660
assert_file "$ESCONFIG/jvm.options" f root elasticsearch 660
assert_file "$ESCONFIG/log4j2.properties" f root elasticsearch 660

View File

@ -101,4 +101,5 @@ verify_archive_installation() {
assert_file "$ESHOME/NOTICE.txt" f elasticsearch elasticsearch 644
assert_file "$ESHOME/LICENSE.txt" f elasticsearch elasticsearch 644
assert_file "$ESHOME/README.textile" f elasticsearch elasticsearch 644
assert_file_not_exist "$ESCONFIG/elasticsearch.keystore"
}

View File

@ -226,13 +226,16 @@ final class Bootstrap {
} catch (IOException e) {
throw new BootstrapException(e);
}
if (keystore == null) {
return null; // no keystore
}
try {
keystore.decrypt(new char[0] /* TODO: read password from stdin */);
KeyStoreWrapper.upgrade(keystore, initialEnv.configFile(), new char[0]);
if (keystore == null) {
final KeyStoreWrapper keyStoreWrapper = KeyStoreWrapper.create();
keyStoreWrapper.save(initialEnv.configFile(), new char[0]);
return keyStoreWrapper;
} else {
keystore.decrypt(new char[0] /* TODO: read password from stdin */);
KeyStoreWrapper.upgrade(keystore, initialEnv.configFile(), new char[0]);
}
} catch (Exception e) {
throw new BootstrapException(e);
}

View File

@ -23,7 +23,6 @@ import org.elasticsearch.Version;
import org.elasticsearch.bootstrap.JarHell;
import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.FileSystemUtils;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
@ -32,18 +31,14 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -63,7 +58,6 @@ public class PluginInfo implements Writeable, ToXContentObject {
private final String classname;
private final List<String> extendedPlugins;
private final boolean hasNativeController;
private final boolean requiresKeystore;
/**
* Construct plugin info.
@ -76,10 +70,9 @@ public class PluginInfo implements Writeable, ToXContentObject {
* @param classname the entry point to the plugin
* @param extendedPlugins other plugins this plugin extends through SPI
* @param hasNativeController whether or not the plugin has a native controller
* @param requiresKeystore whether or not the plugin requires the elasticsearch keystore to be created
*/
public PluginInfo(String name, String description, String version, Version elasticsearchVersion, String javaVersion,
String classname, List<String> extendedPlugins, boolean hasNativeController, boolean requiresKeystore) {
String classname, List<String> extendedPlugins, boolean hasNativeController) {
this.name = name;
this.description = description;
this.version = version;
@ -88,7 +81,6 @@ public class PluginInfo implements Writeable, ToXContentObject {
this.classname = classname;
this.extendedPlugins = Collections.unmodifiableList(extendedPlugins);
this.hasNativeController = hasNativeController;
this.requiresKeystore = requiresKeystore;
}
/**
@ -121,10 +113,12 @@ public class PluginInfo implements Writeable, ToXContentObject {
} else {
hasNativeController = false;
}
if (in.getVersion().onOrAfter(Version.V_6_0_0_beta2)) {
requiresKeystore = in.readBoolean();
} else {
requiresKeystore = false;
if (in.getVersion().onOrAfter(Version.V_6_0_0_beta2) && in.getVersion().before(Version.V_7_0_0_alpha1)) {
/*
* Elasticsearch versions in [6.0.0-beta2, 7.0.0) allowed plugins to specify that they require the keystore and this was
* serialized into the plugin info. Therefore, we have to read and ignore this value from the stream.
*/
in.readBoolean();
}
}
@ -144,8 +138,12 @@ public class PluginInfo implements Writeable, ToXContentObject {
if (out.getVersion().onOrAfter(Version.V_5_4_0)) {
out.writeBoolean(hasNativeController);
}
if (out.getVersion().onOrAfter(Version.V_6_0_0_beta2)) {
out.writeBoolean(requiresKeystore);
if (out.getVersion().onOrAfter(Version.V_6_0_0_beta2) && out.getVersion().before(Version.V_7_0_0_alpha1)) {
/*
* Elasticsearch versions in [6.0.0-beta2, 7.0.0) allowed plugins to specify that they require the keystore and this was
* serialized into the plugin info. Therefore, we have to write out a value for this boolean.
*/
out.writeBoolean(false);
}
}
@ -234,16 +232,8 @@ public class PluginInfo implements Writeable, ToXContentObject {
}
}
String requiresKeystoreValue = propsMap.remove("requires.keystore");
if (requiresKeystoreValue == null) {
requiresKeystoreValue = "false";
}
final boolean requiresKeystore;
try {
requiresKeystore = Booleans.parseBoolean(requiresKeystoreValue);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("property [requires.keystore] must be [true] or [false]," +
" but was [" + requiresKeystoreValue + "]", e);
if (esVersion.before(Version.V_6_3_0) && esVersion.onOrAfter(Version.V_6_0_0_beta2)) {
propsMap.remove("requires.keystore");
}
if (propsMap.isEmpty() == false) {
@ -251,7 +241,7 @@ public class PluginInfo implements Writeable, ToXContentObject {
}
return new PluginInfo(name, description, version, esVersion, javaVersionString,
classname, extendedPlugins, hasNativeController, requiresKeystore);
classname, extendedPlugins, hasNativeController);
}
/**
@ -326,15 +316,6 @@ public class PluginInfo implements Writeable, ToXContentObject {
return hasNativeController;
}
/**
* Whether or not the plugin requires the elasticsearch keystore to exist.
*
* @return {@code true} if the plugin requires a keystore, {@code false} otherwise
*/
public boolean requiresKeystore() {
return requiresKeystore;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
@ -347,7 +328,6 @@ public class PluginInfo implements Writeable, ToXContentObject {
builder.field("classname", classname);
builder.field("extended_plugins", extendedPlugins);
builder.field("has_native_controller", hasNativeController);
builder.field("requires_keystore", requiresKeystore);
}
builder.endObject();
@ -387,7 +367,6 @@ public class PluginInfo implements Writeable, ToXContentObject {
.append(prefix).append("Elasticsearch Version: ").append(elasticsearchVersion).append("\n")
.append(prefix).append("Java Version: ").append(javaVersion).append("\n")
.append(prefix).append("Native Controller: ").append(hasNativeController).append("\n")
.append(prefix).append("Requires Keystore: ").append(requiresKeystore).append("\n")
.append(prefix).append("Extended Plugins: ").append(extendedPlugins).append("\n")
.append(prefix).append(" * Classname: ").append(classname);
return information.toString();

View File

@ -110,7 +110,7 @@ public class PluginsService extends AbstractComponent {
for (Class<? extends Plugin> pluginClass : classpathPlugins) {
Plugin plugin = loadPlugin(pluginClass, settings, configPath);
PluginInfo pluginInfo = new PluginInfo(pluginClass.getName(), "classpath plugin", "NA", Version.CURRENT, "1.8",
pluginClass.getName(), Collections.emptyList(), false, false);
pluginClass.getName(), Collections.emptyList(), false);
if (logger.isTraceEnabled()) {
logger.trace("plugin loaded from classpath [{}]", pluginInfo);
}

View File

@ -145,14 +145,14 @@ public class NodeInfoStreamingTests extends ESTestCase {
for (int i = 0; i < numPlugins; i++) {
plugins.add(new PluginInfo(randomAlphaOfLengthBetween(3, 10), randomAlphaOfLengthBetween(3, 10),
randomAlphaOfLengthBetween(3, 10), VersionUtils.randomVersion(random()), "1.8",
randomAlphaOfLengthBetween(3, 10), Collections.emptyList(), randomBoolean(), randomBoolean()));
randomAlphaOfLengthBetween(3, 10), Collections.emptyList(), randomBoolean()));
}
int numModules = randomIntBetween(0, 5);
List<PluginInfo> modules = new ArrayList<>();
for (int i = 0; i < numModules; i++) {
modules.add(new PluginInfo(randomAlphaOfLengthBetween(3, 10), randomAlphaOfLengthBetween(3, 10),
randomAlphaOfLengthBetween(3, 10), VersionUtils.randomVersion(random()), "1.8",
randomAlphaOfLengthBetween(3, 10), Collections.emptyList(), randomBoolean(), randomBoolean()));
randomAlphaOfLengthBetween(3, 10), Collections.emptyList(), randomBoolean()));
}
pluginsAndModules = new PluginsAndModules(plugins, modules);
}

View File

@ -185,7 +185,7 @@ public class PluginInfoTests extends ESTestCase {
public void testSerialize() throws Exception {
PluginInfo info = new PluginInfo("c", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
Collections.singletonList("foo"), randomBoolean(), randomBoolean());
Collections.singletonList("foo"), randomBoolean());
BytesStreamOutput output = new BytesStreamOutput();
info.writeTo(output);
ByteBuffer buffer = ByteBuffer.wrap(output.bytes().toBytesRef().bytes);
@ -198,15 +198,15 @@ public class PluginInfoTests extends ESTestCase {
public void testPluginListSorted() {
List<PluginInfo> plugins = new ArrayList<>();
plugins.add(new PluginInfo("c", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
Collections.emptyList(), randomBoolean(), randomBoolean()));
Collections.emptyList(), randomBoolean()));
plugins.add(new PluginInfo("b", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
Collections.emptyList(), randomBoolean(), randomBoolean()));
Collections.emptyList(), randomBoolean()));
plugins.add(new PluginInfo( "e", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
Collections.emptyList(), randomBoolean(), randomBoolean()));
Collections.emptyList(), randomBoolean()));
plugins.add(new PluginInfo("a", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
Collections.emptyList(), randomBoolean(), randomBoolean()));
Collections.emptyList(), randomBoolean()));
plugins.add(new PluginInfo("d", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
Collections.emptyList(), randomBoolean(), randomBoolean()));
Collections.emptyList(), randomBoolean()));
PluginsAndModules pluginsInfo = new PluginsAndModules(plugins, Collections.emptyList());
final List<PluginInfo> infos = pluginsInfo.getPluginInfos();

View File

@ -283,7 +283,7 @@ public class PluginsServiceTests extends ESTestCase {
public void testSortBundlesCycleSelfReference() throws Exception {
Path pluginDir = createTempDir();
PluginInfo info = new PluginInfo("foo", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("foo"), false, false);
"MyPlugin", Collections.singletonList("foo"), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info, pluginDir);
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
PluginsService.sortBundles(Collections.singleton(bundle))
@ -295,16 +295,16 @@ public class PluginsServiceTests extends ESTestCase {
Path pluginDir = createTempDir();
Set<PluginsService.Bundle> bundles = new LinkedHashSet<>(); // control iteration order, so we get know the beginning of the cycle
PluginInfo info = new PluginInfo("foo", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Arrays.asList("bar", "other"), false, false);
"MyPlugin", Arrays.asList("bar", "other"), false);
bundles.add(new PluginsService.Bundle(info, pluginDir));
PluginInfo info2 = new PluginInfo("bar", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("baz"), false, false);
"MyPlugin", Collections.singletonList("baz"), false);
bundles.add(new PluginsService.Bundle(info2, pluginDir));
PluginInfo info3 = new PluginInfo("baz", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("foo"), false, false);
"MyPlugin", Collections.singletonList("foo"), false);
bundles.add(new PluginsService.Bundle(info3, pluginDir));
PluginInfo info4 = new PluginInfo("other", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.emptyList(), false, false);
"MyPlugin", Collections.emptyList(), false);
bundles.add(new PluginsService.Bundle(info4, pluginDir));
IllegalStateException e = expectThrows(IllegalStateException.class, () -> PluginsService.sortBundles(bundles));
@ -314,7 +314,7 @@ public class PluginsServiceTests extends ESTestCase {
public void testSortBundlesSingle() throws Exception {
Path pluginDir = createTempDir();
PluginInfo info = new PluginInfo("foo", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.emptyList(), false, false);
"MyPlugin", Collections.emptyList(), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info, pluginDir);
List<PluginsService.Bundle> sortedBundles = PluginsService.sortBundles(Collections.singleton(bundle));
assertThat(sortedBundles, Matchers.contains(bundle));
@ -324,15 +324,15 @@ public class PluginsServiceTests extends ESTestCase {
Path pluginDir = createTempDir();
Set<PluginsService.Bundle> bundles = new LinkedHashSet<>(); // control iteration order
PluginInfo info1 = new PluginInfo("foo", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.emptyList(), false, false);
"MyPlugin", Collections.emptyList(), false);
PluginsService.Bundle bundle1 = new PluginsService.Bundle(info1, pluginDir);
bundles.add(bundle1);
PluginInfo info2 = new PluginInfo("bar", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.emptyList(), false, false);
"MyPlugin", Collections.emptyList(), false);
PluginsService.Bundle bundle2 = new PluginsService.Bundle(info2, pluginDir);
bundles.add(bundle2);
PluginInfo info3 = new PluginInfo("baz", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.emptyList(), false, false);
"MyPlugin", Collections.emptyList(), false);
PluginsService.Bundle bundle3 = new PluginsService.Bundle(info3, pluginDir);
bundles.add(bundle3);
List<PluginsService.Bundle> sortedBundles = PluginsService.sortBundles(bundles);
@ -342,7 +342,7 @@ public class PluginsServiceTests extends ESTestCase {
public void testSortBundlesMissingDep() throws Exception {
Path pluginDir = createTempDir();
PluginInfo info = new PluginInfo("foo", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("dne"), false, false);
"MyPlugin", Collections.singletonList("dne"), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info, pluginDir);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () ->
PluginsService.sortBundles(Collections.singleton(bundle))
@ -354,19 +354,19 @@ public class PluginsServiceTests extends ESTestCase {
Path pluginDir = createTempDir();
Set<PluginsService.Bundle> bundles = new LinkedHashSet<>(); // control iteration order
PluginInfo info1 = new PluginInfo("grandparent", "desc", "1.0",Version.CURRENT, "1.8",
"MyPlugin", Collections.emptyList(), false, false);
"MyPlugin", Collections.emptyList(), false);
PluginsService.Bundle bundle1 = new PluginsService.Bundle(info1, pluginDir);
bundles.add(bundle1);
PluginInfo info2 = new PluginInfo("foo", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("common"), false, false);
"MyPlugin", Collections.singletonList("common"), false);
PluginsService.Bundle bundle2 = new PluginsService.Bundle(info2, pluginDir);
bundles.add(bundle2);
PluginInfo info3 = new PluginInfo("bar", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("common"), false, false);
"MyPlugin", Collections.singletonList("common"), false);
PluginsService.Bundle bundle3 = new PluginsService.Bundle(info3, pluginDir);
bundles.add(bundle3);
PluginInfo info4 = new PluginInfo("common", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("grandparent"), false, false);
"MyPlugin", Collections.singletonList("grandparent"), false);
PluginsService.Bundle bundle4 = new PluginsService.Bundle(info4, pluginDir);
bundles.add(bundle4);
List<PluginsService.Bundle> sortedBundles = PluginsService.sortBundles(bundles);
@ -377,11 +377,11 @@ public class PluginsServiceTests extends ESTestCase {
Path pluginDir = createTempDir();
Set<PluginsService.Bundle> bundles = new LinkedHashSet<>(); // control iteration order
PluginInfo info1 = new PluginInfo("dep", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.emptyList(), false, false);
"MyPlugin", Collections.emptyList(), false);
PluginsService.Bundle bundle1 = new PluginsService.Bundle(info1, pluginDir);
bundles.add(bundle1);
PluginInfo info2 = new PluginInfo("myplugin", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("dep"), false, false);
"MyPlugin", Collections.singletonList("dep"), false);
PluginsService.Bundle bundle2 = new PluginsService.Bundle(info2, pluginDir);
bundles.add(bundle2);
List<PluginsService.Bundle> sortedBundles = PluginsService.sortBundles(bundles);
@ -440,7 +440,7 @@ public class PluginsServiceTests extends ESTestCase {
Map<String, Set<URL>> transitiveDeps = new HashMap<>();
transitiveDeps.put("dep", Collections.singleton(dupJar.toUri().toURL()));
PluginInfo info1 = new PluginInfo("myplugin", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("dep"), false, false);
"MyPlugin", Collections.singletonList("dep"), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
PluginsService.checkBundleJarHell(bundle, transitiveDeps));
@ -459,7 +459,7 @@ public class PluginsServiceTests extends ESTestCase {
transitiveDeps.put("dep1", Collections.singleton(dupJar.toUri().toURL()));
transitiveDeps.put("dep2", Collections.singleton(dupJar.toUri().toURL()));
PluginInfo info1 = new PluginInfo("myplugin", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Arrays.asList("dep1", "dep2"), false, false);
"MyPlugin", Arrays.asList("dep1", "dep2"), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
PluginsService.checkBundleJarHell(bundle, transitiveDeps));
@ -476,7 +476,7 @@ public class PluginsServiceTests extends ESTestCase {
Path pluginJar = pluginDir.resolve("plugin.jar");
makeJar(pluginJar, Level.class);
PluginInfo info1 = new PluginInfo("myplugin", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.emptyList(), false, false);
"MyPlugin", Collections.emptyList(), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
PluginsService.checkBundleJarHell(bundle, new HashMap<>()));
@ -495,7 +495,7 @@ public class PluginsServiceTests extends ESTestCase {
Map<String, Set<URL>> transitiveDeps = new HashMap<>();
transitiveDeps.put("dep", Collections.singleton(depJar.toUri().toURL()));
PluginInfo info1 = new PluginInfo("myplugin", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Collections.singletonList("dep"), false, false);
"MyPlugin", Collections.singletonList("dep"), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
PluginsService.checkBundleJarHell(bundle, transitiveDeps));
@ -518,7 +518,7 @@ public class PluginsServiceTests extends ESTestCase {
transitiveDeps.put("dep1", Collections.singleton(dep1Jar.toUri().toURL()));
transitiveDeps.put("dep2", Collections.singleton(dep2Jar.toUri().toURL()));
PluginInfo info1 = new PluginInfo("myplugin", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Arrays.asList("dep1", "dep2"), false, false);
"MyPlugin", Arrays.asList("dep1", "dep2"), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
PluginsService.checkBundleJarHell(bundle, transitiveDeps));
@ -541,7 +541,7 @@ public class PluginsServiceTests extends ESTestCase {
transitiveDeps.put("dep1", Collections.singleton(dep1Jar.toUri().toURL()));
transitiveDeps.put("dep2", Collections.singleton(dep2Jar.toUri().toURL()));
PluginInfo info1 = new PluginInfo("myplugin", "desc", "1.0", Version.CURRENT, "1.8",
"MyPlugin", Arrays.asList("dep1", "dep2"), false, false);
"MyPlugin", Arrays.asList("dep1", "dep2"), false);
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
PluginsService.checkBundleJarHell(bundle, transitiveDeps);
Set<URL> deps = transitiveDeps.get("myplugin");
@ -590,14 +590,14 @@ public class PluginsServiceTests extends ESTestCase {
public void testIncompatibleElasticsearchVersion() throws Exception {
PluginInfo info = new PluginInfo("my_plugin", "desc", "1.0", Version.V_5_0_0,
"1.8", "FakePlugin", Collections.emptyList(), false, false);
"1.8", "FakePlugin", Collections.emptyList(), false);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> PluginsService.verifyCompatibility(info));
assertThat(e.getMessage(), containsString("was built for Elasticsearch version 5.0.0"));
}
public void testIncompatibleJavaVersion() throws Exception {
PluginInfo info = new PluginInfo("my_plugin", "desc", "1.0", Version.CURRENT,
"1000000.0", "FakePlugin", Collections.emptyList(), false, false);
"1000000.0", "FakePlugin", Collections.emptyList(), false);
IllegalStateException e = expectThrows(IllegalStateException.class, () -> PluginsService.verifyCompatibility(info));
assertThat(e.getMessage(), containsString("my_plugin requires Java"));
}