Plugins: Separate plugin semantic validation from properties format validation (#28581)
This commit moves the semantic validation (like which version a plugin was built for or which java version it is compatible with) from reading a plugin descriptor, leaving the checks on the format of the descriptor intact. relates #28540
This commit is contained in:
parent
920dff7053
commit
ea381969be
|
@ -565,6 +565,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
||||||
/** Load information about the plugin, and verify it can be installed with no errors. */
|
/** Load information about the plugin, and verify it can be installed with no errors. */
|
||||||
private PluginInfo loadPluginInfo(Terminal terminal, Path pluginRoot, boolean isBatch, Environment env) throws Exception {
|
private PluginInfo loadPluginInfo(Terminal terminal, Path pluginRoot, boolean isBatch, Environment env) throws Exception {
|
||||||
final PluginInfo info = PluginInfo.readFromProperties(pluginRoot);
|
final PluginInfo info = PluginInfo.readFromProperties(pluginRoot);
|
||||||
|
PluginsService.verifyCompatibility(info);
|
||||||
|
|
||||||
// checking for existing version of the plugin
|
// checking for existing version of the plugin
|
||||||
verifyPluginName(env.pluginsFile(), info.getName(), pluginRoot);
|
verifyPluginName(env.pluginsFile(), info.getName(), pluginRoot);
|
||||||
|
@ -649,6 +650,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final PluginInfo info = PluginInfo.readFromProperties(plugin);
|
final PluginInfo info = PluginInfo.readFromProperties(plugin);
|
||||||
|
PluginsService.verifyCompatibility(info);
|
||||||
verifyPluginName(env.pluginsFile(), info.getName(), plugin);
|
verifyPluginName(env.pluginsFile(), info.getName(), plugin);
|
||||||
pluginPaths.add(plugin);
|
pluginPaths.add(plugin);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.elasticsearch.plugins;
|
package org.elasticsearch.plugins;
|
||||||
|
|
||||||
import joptsimple.OptionSet;
|
import joptsimple.OptionSet;
|
||||||
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.cli.EnvironmentAwareCommand;
|
import org.elasticsearch.cli.EnvironmentAwareCommand;
|
||||||
import org.elasticsearch.cli.Terminal;
|
import org.elasticsearch.cli.Terminal;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
|
@ -84,15 +85,11 @@ class ListPluginsCommand extends EnvironmentAwareCommand {
|
||||||
|
|
||||||
private void printPlugin(Environment env, Terminal terminal, Path plugin, String prefix) throws IOException {
|
private void printPlugin(Environment env, Terminal terminal, Path plugin, String prefix) throws IOException {
|
||||||
terminal.println(Terminal.Verbosity.SILENT, prefix + plugin.getFileName().toString());
|
terminal.println(Terminal.Verbosity.SILENT, prefix + plugin.getFileName().toString());
|
||||||
try {
|
|
||||||
PluginInfo info = PluginInfo.readFromProperties(env.pluginsFile().resolve(plugin.toAbsolutePath()));
|
PluginInfo info = PluginInfo.readFromProperties(env.pluginsFile().resolve(plugin.toAbsolutePath()));
|
||||||
terminal.println(Terminal.Verbosity.VERBOSE, info.toString(prefix));
|
terminal.println(Terminal.Verbosity.VERBOSE, info.toString(prefix));
|
||||||
} catch (IllegalArgumentException e) {
|
if (info.getElasticsearchVersion().equals(Version.CURRENT) == false) {
|
||||||
if (e.getMessage().contains("incompatible with version")) {
|
terminal.println("WARNING: plugin [" + info.getName() + "] was built for Elasticsearch version " + info.getVersion() +
|
||||||
terminal.println("WARNING: " + e.getMessage());
|
" but version " + Version.CURRENT + " is required");
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ class RemovePluginCommand extends EnvironmentAwareCommand {
|
||||||
|
|
||||||
// first make sure nothing extends this plugin
|
// first make sure nothing extends this plugin
|
||||||
List<String> usedBy = new ArrayList<>();
|
List<String> usedBy = new ArrayList<>();
|
||||||
Set<PluginsService.Bundle> bundles = PluginsService.getPluginBundles(env.pluginsFile(), false);
|
Set<PluginsService.Bundle> bundles = PluginsService.getPluginBundles(env.pluginsFile());
|
||||||
for (PluginsService.Bundle bundle : bundles) {
|
for (PluginsService.Bundle bundle : bundles) {
|
||||||
for (String extendedPlugin : bundle.plugin.getExtendedPlugins()) {
|
for (String extendedPlugin : bundle.plugin.getExtendedPlugins()) {
|
||||||
if (extendedPlugin.equals(pluginName)) {
|
if (extendedPlugin.equals(pluginName)) {
|
||||||
|
|
|
@ -362,11 +362,7 @@ public class ListPluginsCommandTests extends ESTestCase {
|
||||||
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
|
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
|
||||||
|
|
||||||
MockTerminal terminal = listPlugins(home);
|
MockTerminal terminal = listPlugins(home);
|
||||||
final String message = String.format(Locale.ROOT,
|
String message = "plugin [fake_plugin1] was built for Elasticsearch version 1.0 but version " + Version.CURRENT + " is required";
|
||||||
"plugin [%s] is incompatible with version [%s]; was designed for version [%s]",
|
|
||||||
"fake_plugin1",
|
|
||||||
Version.CURRENT.toString(),
|
|
||||||
"1.0.0");
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"fake_plugin1\n" + "WARNING: " + message + "\n" + "fake_plugin2\n",
|
"fake_plugin1\n" + "WARNING: " + message + "\n" + "fake_plugin2\n",
|
||||||
terminal.getOutput());
|
terminal.getOutput());
|
||||||
|
@ -388,11 +384,7 @@ public class ListPluginsCommandTests extends ESTestCase {
|
||||||
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
|
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
|
||||||
|
|
||||||
MockTerminal terminal = listPlugins(home);
|
MockTerminal terminal = listPlugins(home);
|
||||||
final String message = String.format(Locale.ROOT,
|
String message = "plugin [fake_plugin1] was built for Elasticsearch version 1.0 but version " + Version.CURRENT + " is required";
|
||||||
"plugin [%s] is incompatible with version [%s]; was designed for version [%s]",
|
|
||||||
"fake_plugin1",
|
|
||||||
Version.CURRENT.toString(),
|
|
||||||
"1.0.0");
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"fake_plugin2\nmeta_plugin\n\tfake_plugin1\n" + "WARNING: " + message + "\n",
|
"fake_plugin2\nmeta_plugin\n\tfake_plugin1\n" + "WARNING: " + message + "\n",
|
||||||
terminal.getOutput());
|
terminal.getOutput());
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.http.HttpTransportSettings;
|
import org.elasticsearch.http.HttpTransportSettings;
|
||||||
import org.elasticsearch.plugins.PluginInfo;
|
import org.elasticsearch.plugins.PluginInfo;
|
||||||
|
import org.elasticsearch.plugins.PluginsService;
|
||||||
import org.elasticsearch.secure_sm.SecureSM;
|
import org.elasticsearch.secure_sm.SecureSM;
|
||||||
import org.elasticsearch.transport.TcpTransport;
|
import org.elasticsearch.transport.TcpTransport;
|
||||||
|
|
||||||
|
@ -161,7 +162,7 @@ final class Security {
|
||||||
static Map<String,Policy> getPluginPermissions(Environment environment) throws IOException, NoSuchAlgorithmException {
|
static Map<String,Policy> getPluginPermissions(Environment environment) throws IOException, NoSuchAlgorithmException {
|
||||||
Map<String,Policy> map = new HashMap<>();
|
Map<String,Policy> map = new HashMap<>();
|
||||||
// collect up set of plugins and modules by listing directories.
|
// collect up set of plugins and modules by listing directories.
|
||||||
Set<Path> pluginsAndModules = new LinkedHashSet<>(PluginInfo.extractAllPlugins(environment.pluginsFile()));
|
Set<Path> pluginsAndModules = new LinkedHashSet<>(PluginsService.findPluginDirs(environment.pluginsFile()));
|
||||||
|
|
||||||
if (Files.exists(environment.modulesFile())) {
|
if (Files.exists(environment.modulesFile())) {
|
||||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(environment.modulesFile())) {
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(environment.modulesFile())) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.lucene.util.IOUtils;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.plugins.Platforms;
|
import org.elasticsearch.plugins.Platforms;
|
||||||
import org.elasticsearch.plugins.PluginInfo;
|
import org.elasticsearch.plugins.PluginInfo;
|
||||||
|
import org.elasticsearch.plugins.PluginsService;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -70,7 +71,7 @@ final class Spawner implements Closeable {
|
||||||
* For each plugin, attempt to spawn the controller daemon. Silently ignore any plugin that
|
* For each plugin, attempt to spawn the controller daemon. Silently ignore any plugin that
|
||||||
* don't include a controller for the correct platform.
|
* don't include a controller for the correct platform.
|
||||||
*/
|
*/
|
||||||
List<Path> paths = PluginInfo.extractAllPlugins(pluginsFile);
|
List<Path> paths = PluginsService.findPluginDirs(pluginsFile);
|
||||||
for (Path plugin : paths) {
|
for (Path plugin : paths) {
|
||||||
final PluginInfo info = PluginInfo.readFromProperties(plugin);
|
final PluginInfo info = PluginInfo.readFromProperties(plugin);
|
||||||
final Path spawnPath = Platforms.nativeControllerPath(plugin);
|
final Path spawnPath = Platforms.nativeControllerPath(plugin);
|
||||||
|
|
|
@ -150,67 +150,13 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts all {@link PluginInfo} from the provided {@code rootPath} expanding meta plugins if needed.
|
* Reads the plugin descriptor file.
|
||||||
* @param rootPath the path where the plugins are installed
|
|
||||||
* @return A list of all plugin paths installed in the {@code rootPath}
|
|
||||||
* @throws IOException if an I/O exception occurred reading the plugin descriptors
|
|
||||||
*/
|
|
||||||
public static List<Path> extractAllPlugins(final Path rootPath) throws IOException {
|
|
||||||
final List<Path> plugins = new LinkedList<>(); // order is already lost, but some filesystems have it
|
|
||||||
final Set<String> seen = new HashSet<>();
|
|
||||||
if (Files.exists(rootPath)) {
|
|
||||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(rootPath)) {
|
|
||||||
for (Path plugin : stream) {
|
|
||||||
if (FileSystemUtils.isDesktopServicesStore(plugin) ||
|
|
||||||
plugin.getFileName().toString().startsWith(".removing-")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (seen.add(plugin.getFileName().toString()) == false) {
|
|
||||||
throw new IllegalStateException("duplicate plugin: " + plugin);
|
|
||||||
}
|
|
||||||
if (MetaPluginInfo.isMetaPlugin(plugin)) {
|
|
||||||
try (DirectoryStream<Path> subStream = Files.newDirectoryStream(plugin)) {
|
|
||||||
for (Path subPlugin : subStream) {
|
|
||||||
if (MetaPluginInfo.isPropertiesFile(subPlugin) ||
|
|
||||||
FileSystemUtils.isDesktopServicesStore(subPlugin)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (seen.add(subPlugin.getFileName().toString()) == false) {
|
|
||||||
throw new IllegalStateException("duplicate plugin: " + subPlugin);
|
|
||||||
}
|
|
||||||
plugins.add(subPlugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
plugins.add(plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads and validates the plugin descriptor file.
|
|
||||||
*
|
*
|
||||||
* @param path the path to the root directory for the plugin
|
* @param path the path to the root directory for the plugin
|
||||||
* @return the plugin info
|
* @return the plugin info
|
||||||
* @throws IOException if an I/O exception occurred reading the plugin descriptor
|
* @throws IOException if an I/O exception occurred reading the plugin descriptor
|
||||||
*/
|
*/
|
||||||
public static PluginInfo readFromProperties(final Path path) throws IOException {
|
public static PluginInfo readFromProperties(final Path path) throws IOException {
|
||||||
return readFromProperties(path, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads and validates the plugin descriptor file. If {@code enforceVersion} is false then version enforcement for the plugin descriptor
|
|
||||||
* is skipped.
|
|
||||||
*
|
|
||||||
* @param path the path to the root directory for the plugin
|
|
||||||
* @param enforceVersion whether or not to enforce the version when reading plugin descriptors
|
|
||||||
* @return the plugin info
|
|
||||||
* @throws IOException if an I/O exception occurred reading the plugin descriptor
|
|
||||||
*/
|
|
||||||
static PluginInfo readFromProperties(final Path path, final boolean enforceVersion) throws IOException {
|
|
||||||
final Path descriptor = path.resolve(ES_PLUGIN_PROPERTIES);
|
final Path descriptor = path.resolve(ES_PLUGIN_PROPERTIES);
|
||||||
|
|
||||||
final Map<String, String> propsMap;
|
final Map<String, String> propsMap;
|
||||||
|
@ -244,22 +190,12 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
||||||
"property [elasticsearch.version] is missing for plugin [" + name + "]");
|
"property [elasticsearch.version] is missing for plugin [" + name + "]");
|
||||||
}
|
}
|
||||||
final Version esVersion = Version.fromString(esVersionString);
|
final Version esVersion = Version.fromString(esVersionString);
|
||||||
if (enforceVersion && esVersion.equals(Version.CURRENT) == false) {
|
|
||||||
final String message = String.format(
|
|
||||||
Locale.ROOT,
|
|
||||||
"plugin [%s] is incompatible with version [%s]; was designed for version [%s]",
|
|
||||||
name,
|
|
||||||
Version.CURRENT.toString(),
|
|
||||||
esVersionString);
|
|
||||||
throw new IllegalArgumentException(message);
|
|
||||||
}
|
|
||||||
final String javaVersionString = propsMap.remove("java.version");
|
final String javaVersionString = propsMap.remove("java.version");
|
||||||
if (javaVersionString == null) {
|
if (javaVersionString == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"property [java.version] is missing for plugin [" + name + "]");
|
"property [java.version] is missing for plugin [" + name + "]");
|
||||||
}
|
}
|
||||||
JarHell.checkVersionFormat(javaVersionString);
|
JarHell.checkVersionFormat(javaVersionString);
|
||||||
JarHell.checkJavaVersion(name, javaVersionString);
|
|
||||||
final String classname = propsMap.remove("classname");
|
final String classname = propsMap.remove("classname");
|
||||||
if (classname == null) {
|
if (classname == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.elasticsearch.common.collect.Tuple;
|
||||||
import org.elasticsearch.common.component.AbstractComponent;
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.component.LifecycleComponent;
|
import org.elasticsearch.common.component.LifecycleComponent;
|
||||||
import org.elasticsearch.common.inject.Module;
|
import org.elasticsearch.common.inject.Module;
|
||||||
|
import org.elasticsearch.common.io.FileSystemUtils;
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
import org.elasticsearch.common.logging.Loggers;
|
||||||
import org.elasticsearch.common.settings.Setting;
|
import org.elasticsearch.common.settings.Setting;
|
||||||
import org.elasticsearch.common.settings.Setting.Property;
|
import org.elasticsearch.common.settings.Setting.Property;
|
||||||
|
@ -56,6 +57,7 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -278,6 +280,59 @@ public class PluginsService extends AbstractComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts all installed plugin directories from the provided {@code rootPath} expanding meta plugins if needed.
|
||||||
|
* @param rootPath the path where the plugins are installed
|
||||||
|
* @return A list of all plugin paths installed in the {@code rootPath}
|
||||||
|
* @throws IOException if an I/O exception occurred reading the directories
|
||||||
|
*/
|
||||||
|
public static List<Path> findPluginDirs(final Path rootPath) throws IOException {
|
||||||
|
final List<Path> plugins = new ArrayList<>();
|
||||||
|
final Set<String> seen = new HashSet<>();
|
||||||
|
if (Files.exists(rootPath)) {
|
||||||
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(rootPath)) {
|
||||||
|
for (Path plugin : stream) {
|
||||||
|
if (FileSystemUtils.isDesktopServicesStore(plugin) ||
|
||||||
|
plugin.getFileName().toString().startsWith(".removing-") ||
|
||||||
|
plugin.getFileName().toString().startsWith(".installing-")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (seen.add(plugin.getFileName().toString()) == false) {
|
||||||
|
throw new IllegalStateException("duplicate plugin: " + plugin);
|
||||||
|
}
|
||||||
|
if (MetaPluginInfo.isMetaPlugin(plugin)) {
|
||||||
|
try (DirectoryStream<Path> subStream = Files.newDirectoryStream(plugin)) {
|
||||||
|
for (Path subPlugin : subStream) {
|
||||||
|
if (MetaPluginInfo.isPropertiesFile(subPlugin) ||
|
||||||
|
FileSystemUtils.isDesktopServicesStore(subPlugin)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (seen.add(subPlugin.getFileName().toString()) == false) {
|
||||||
|
throw new IllegalStateException("duplicate plugin: " + subPlugin);
|
||||||
|
}
|
||||||
|
plugins.add(subPlugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
plugins.add(plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the given plugin is compatible with the current Elasticsearch installation.
|
||||||
|
*/
|
||||||
|
static void verifyCompatibility(PluginInfo info) {
|
||||||
|
if (info.getElasticsearchVersion().equals(Version.CURRENT) == false) {
|
||||||
|
throw new IllegalArgumentException("Plugin [" + info.getName() + "] was built for Elasticsearch version "
|
||||||
|
+ info.getElasticsearchVersion() + " but version " + Version.CURRENT + " is running");
|
||||||
|
}
|
||||||
|
JarHell.checkJavaVersion(info.getName(), info.getJavaVersion());
|
||||||
|
}
|
||||||
|
|
||||||
// similar in impl to getPluginBundles, but DO NOT try to make them share code.
|
// similar in impl to getPluginBundles, but DO NOT try to make them share code.
|
||||||
// we don't need to inherit all the leniency, and things are different enough.
|
// we don't need to inherit all the leniency, and things are different enough.
|
||||||
static Set<Bundle> getModuleBundles(Path modulesDirectory) throws IOException {
|
static Set<Bundle> getModuleBundles(Path modulesDirectory) throws IOException {
|
||||||
|
@ -326,28 +381,15 @@ public class PluginsService extends AbstractComponent {
|
||||||
* @throws IOException if an I/O exception occurs reading the plugin bundles
|
* @throws IOException if an I/O exception occurs reading the plugin bundles
|
||||||
*/
|
*/
|
||||||
static Set<Bundle> getPluginBundles(final Path pluginsDirectory) throws IOException {
|
static Set<Bundle> getPluginBundles(final Path pluginsDirectory) throws IOException {
|
||||||
return getPluginBundles(pluginsDirectory, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the plugin bundles from the specified directory. If {@code enforceVersion} is true, then the version in each plugin descriptor
|
|
||||||
* must match the current version.
|
|
||||||
*
|
|
||||||
* @param pluginsDirectory the directory
|
|
||||||
* @param enforceVersion whether or not to enforce the version when reading plugin descriptors
|
|
||||||
* @return the set of plugin bundles in the specified directory
|
|
||||||
* @throws IOException if an I/O exception occurs reading the plugin bundles
|
|
||||||
*/
|
|
||||||
static Set<Bundle> getPluginBundles(final Path pluginsDirectory, final boolean enforceVersion) throws IOException {
|
|
||||||
Logger logger = Loggers.getLogger(PluginsService.class);
|
Logger logger = Loggers.getLogger(PluginsService.class);
|
||||||
Set<Bundle> bundles = new LinkedHashSet<>();
|
Set<Bundle> bundles = new LinkedHashSet<>();
|
||||||
|
|
||||||
List<Path> infos = PluginInfo.extractAllPlugins(pluginsDirectory);
|
List<Path> infos = findPluginDirs(pluginsDirectory);
|
||||||
for (Path plugin : infos) {
|
for (Path plugin : infos) {
|
||||||
logger.trace("--- adding plugin [{}]", plugin.toAbsolutePath());
|
logger.trace("--- adding plugin [{}]", plugin.toAbsolutePath());
|
||||||
final PluginInfo info;
|
final PluginInfo info;
|
||||||
try {
|
try {
|
||||||
info = PluginInfo.readFromProperties(plugin, enforceVersion);
|
info = PluginInfo.readFromProperties(plugin);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IllegalStateException("Could not load plugin descriptor for existing plugin ["
|
throw new IllegalStateException("Could not load plugin descriptor for existing plugin ["
|
||||||
+ plugin.getFileName() + "]. Was the plugin built before 2.0?", e);
|
+ plugin.getFileName() + "]. Was the plugin built before 2.0?", e);
|
||||||
|
@ -480,6 +522,8 @@ public class PluginsService extends AbstractComponent {
|
||||||
private Plugin loadBundle(Bundle bundle, Map<String, Plugin> loaded) {
|
private Plugin loadBundle(Bundle bundle, Map<String, Plugin> loaded) {
|
||||||
String name = bundle.plugin.getName();
|
String name = bundle.plugin.getName();
|
||||||
|
|
||||||
|
verifyCompatibility(bundle.plugin);
|
||||||
|
|
||||||
// collect loaders of extended plugins
|
// collect loaders of extended plugins
|
||||||
List<ClassLoader> extendedLoaders = new ArrayList<>();
|
List<ClassLoader> extendedLoaders = new ArrayList<>();
|
||||||
for (String extendedPluginName : bundle.plugin.getExtendedPlugins()) {
|
for (String extendedPluginName : bundle.plugin.getExtendedPlugins()) {
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class MetaPluginInfoTests extends ESTestCase {
|
||||||
"classname", "FakePlugin");
|
"classname", "FakePlugin");
|
||||||
|
|
||||||
IllegalStateException exc =
|
IllegalStateException exc =
|
||||||
expectThrows(IllegalStateException.class, () -> PluginInfo.extractAllPlugins(pluginDir));
|
expectThrows(IllegalStateException.class, () -> PluginsService.findPluginDirs(pluginDir));
|
||||||
assertThat(exc.getMessage(), containsString("duplicate plugin"));
|
assertThat(exc.getMessage(), containsString("duplicate plugin"));
|
||||||
assertThat(exc.getMessage(), endsWith("plugin1"));
|
assertThat(exc.getMessage(), endsWith("plugin1"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,20 +103,6 @@ public class PluginInfoTests extends ESTestCase {
|
||||||
assertThat(e.getMessage(), containsString("[java.version] is missing"));
|
assertThat(e.getMessage(), containsString("[java.version] is missing"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReadFromPropertiesJavaVersionIncompatible() throws Exception {
|
|
||||||
String pluginName = "fake-plugin";
|
|
||||||
Path pluginDir = createTempDir().resolve(pluginName);
|
|
||||||
PluginTestUtil.writePluginProperties(pluginDir,
|
|
||||||
"description", "fake desc",
|
|
||||||
"name", pluginName,
|
|
||||||
"elasticsearch.version", Version.CURRENT.toString(),
|
|
||||||
"java.version", "1000000.0",
|
|
||||||
"classname", "FakePlugin",
|
|
||||||
"version", "1.0");
|
|
||||||
IllegalStateException e = expectThrows(IllegalStateException.class, () -> PluginInfo.readFromProperties(pluginDir));
|
|
||||||
assertThat(e.getMessage(), containsString(pluginName + " requires Java"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testReadFromPropertiesBadJavaVersionFormat() throws Exception {
|
public void testReadFromPropertiesBadJavaVersionFormat() throws Exception {
|
||||||
String pluginName = "fake-plugin";
|
String pluginName = "fake-plugin";
|
||||||
Path pluginDir = createTempDir().resolve(pluginName);
|
Path pluginDir = createTempDir().resolve(pluginName);
|
||||||
|
@ -143,17 +129,6 @@ public class PluginInfoTests extends ESTestCase {
|
||||||
assertThat(e.getMessage(), containsString("version needs to contain major, minor, and revision"));
|
assertThat(e.getMessage(), containsString("version needs to contain major, minor, and revision"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReadFromPropertiesOldElasticsearchVersion() throws Exception {
|
|
||||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
|
||||||
PluginTestUtil.writePluginProperties(pluginDir,
|
|
||||||
"description", "fake desc",
|
|
||||||
"name", "my_plugin",
|
|
||||||
"version", "1.0",
|
|
||||||
"elasticsearch.version", Version.V_5_0_0.toString());
|
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> PluginInfo.readFromProperties(pluginDir));
|
|
||||||
assertThat(e.getMessage(), containsString("was designed for version [5.0.0]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testReadFromPropertiesJvmMissingClassname() throws Exception {
|
public void testReadFromPropertiesJvmMissingClassname() throws Exception {
|
||||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
Path pluginDir = createTempDir().resolve("fake-plugin");
|
||||||
PluginTestUtil.writePluginProperties(pluginDir,
|
PluginTestUtil.writePluginProperties(pluginDir,
|
||||||
|
|
|
@ -590,4 +590,18 @@ public class PluginsServiceTests extends ESTestCase {
|
||||||
IllegalStateException e = expectThrows(IllegalStateException.class, () -> newPluginsService(settings));
|
IllegalStateException e = expectThrows(IllegalStateException.class, () -> newPluginsService(settings));
|
||||||
assertEquals("Plugin [myplugin] cannot extend non-extensible plugin [nonextensible]", e.getMessage());
|
assertEquals("Plugin [myplugin] cannot extend non-extensible plugin [nonextensible]", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
IllegalStateException e = expectThrows(IllegalStateException.class, () -> PluginsService.verifyCompatibility(info));
|
||||||
|
assertThat(e.getMessage(), containsString("my_plugin requires Java"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue