Allowing custom folder name for plugin installation (#848)
Signed-off-by: Vacha Shah <vachshah@amazon.com>
This commit is contained in:
parent
6bc4ce017a
commit
19e54d6624
|
@ -105,6 +105,7 @@ class PluginBuildPlugin implements Plugin<Project> {
|
|||
'opensearchVersion' : Version.fromString(VersionProperties.getOpenSearch()).toString(),
|
||||
'javaVersion' : project.targetCompatibility as String,
|
||||
'classname' : extension1.classname,
|
||||
'customFolderName' : extension1.customFolderName,
|
||||
'extendedPlugins' : extension1.extendedPlugins.join(','),
|
||||
'hasNativeController' : extension1.hasNativeController,
|
||||
'requiresKeystore' : extension1.requiresKeystore
|
||||
|
|
|
@ -51,6 +51,8 @@ public class PluginPropertiesExtension {
|
|||
|
||||
private String classname;
|
||||
|
||||
private String customFolderName = "";
|
||||
|
||||
/** Other plugins this plugin extends through SPI */
|
||||
private List<String> extendedPlugins = new ArrayList<>();
|
||||
|
||||
|
@ -76,6 +78,14 @@ public class PluginPropertiesExtension {
|
|||
this.project = project;
|
||||
}
|
||||
|
||||
public String getCustomFolderName() {
|
||||
return customFolderName;
|
||||
}
|
||||
|
||||
public void setCustomFolderName(String customFolderName) {
|
||||
this.customFolderName = customFolderName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name == null ? project.getName() : name;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ java.version=${javaVersion}
|
|||
opensearch.version=${opensearchVersion}
|
||||
### optional elements for plugins:
|
||||
#
|
||||
# 'custom.foldername': the custom name of the folder in which the plugin is installed.
|
||||
custom.foldername=${customFolderName}
|
||||
#
|
||||
# 'extended.plugins': other plugins this plugin extends through SPI
|
||||
extended.plugins=${extendedPlugins}
|
||||
#
|
||||
|
|
|
@ -261,7 +261,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
|||
final Path extractedZip = unzip(pluginZip, env.pluginsFile());
|
||||
deleteOnFailure.add(extractedZip);
|
||||
final PluginInfo pluginInfo = installPlugin(terminal, isBatch, extractedZip, env, deleteOnFailure);
|
||||
terminal.println("-> Installed " + pluginInfo.getName());
|
||||
terminal.println("-> Installed " + pluginInfo.getName() + " with folder name " + pluginInfo.getTargetFolderName());
|
||||
// swap the entry by plugin id for one with the installed plugin name, it gives a cleaner error message for URL installs
|
||||
deleteOnFailures.remove(pluginId);
|
||||
deleteOnFailures.put(pluginInfo.getName(), deleteOnFailure);
|
||||
|
@ -780,7 +780,9 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
|||
throw new UserException(ExitCodes.USAGE, "plugin '" + pluginName + "' cannot be installed as a plugin, it is a system module");
|
||||
}
|
||||
|
||||
final Path destination = pluginPath.resolve(pluginName);
|
||||
// scan all the installed plugins to see if the plugin being installed already exists
|
||||
// either with the plugin name or a custom folder name
|
||||
Path destination = PluginHelper.verifyIfPluginExists(pluginPath, pluginName);
|
||||
if (Files.exists(destination)) {
|
||||
final String message = String.format(
|
||||
Locale.ROOT,
|
||||
|
@ -864,14 +866,15 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
|||
}
|
||||
PluginSecurity.confirmPolicyExceptions(terminal, permissions, isBatch);
|
||||
|
||||
final Path destination = env.pluginsFile().resolve(info.getName());
|
||||
String targetFolderName = info.getTargetFolderName();
|
||||
final Path destination = env.pluginsFile().resolve(targetFolderName);
|
||||
deleteOnFailure.add(destination);
|
||||
|
||||
installPluginSupportFiles(
|
||||
info,
|
||||
tmpRoot,
|
||||
env.binFile().resolve(info.getName()),
|
||||
env.configFile().resolve(info.getName()),
|
||||
env.binFile().resolve(targetFolderName),
|
||||
env.configFile().resolve(targetFolderName),
|
||||
deleteOnFailure
|
||||
);
|
||||
movePlugin(tmpRoot, destination);
|
||||
|
|
|
@ -75,8 +75,8 @@ class ListPluginsCommand extends EnvironmentAwareCommand {
|
|||
}
|
||||
|
||||
private void printPlugin(Environment env, Terminal terminal, Path plugin, String prefix) throws IOException {
|
||||
terminal.println(Terminal.Verbosity.SILENT, prefix + plugin.getFileName().toString());
|
||||
PluginInfo info = PluginInfo.readFromProperties(env.pluginsFile().resolve(plugin));
|
||||
terminal.println(Terminal.Verbosity.SILENT, prefix + info.getName());
|
||||
terminal.println(Terminal.Verbosity.VERBOSE, info.toString(prefix));
|
||||
if (info.getOpenSearchVersion().equals(Version.CURRENT) == false) {
|
||||
terminal.errorPrintln(
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
* this file be licensed under the Apache-2.0 license or a
|
||||
* compatible open source license.
|
||||
*/
|
||||
|
||||
package org.opensearch.plugins;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A helper class for the plugin-cli tasks.
|
||||
*/
|
||||
public class PluginHelper {
|
||||
|
||||
/**
|
||||
* Verify if a plugin exists with any folder name.
|
||||
* @param pluginPath the path for the plugins directory.
|
||||
* @param pluginName the name of the concerned plugin.
|
||||
* @return the path of the folder if the plugin exists.
|
||||
* @throws IOException if any I/O exception occurs while performing a file operation
|
||||
*/
|
||||
public static Path verifyIfPluginExists(Path pluginPath, String pluginName) throws IOException {
|
||||
List<Path> pluginSubFolders = Files.walk(pluginPath, 1).filter(Files::isDirectory).collect(Collectors.toList());
|
||||
for (Path customPluginFolderPath : pluginSubFolders) {
|
||||
if (customPluginFolderPath != pluginPath
|
||||
&& !((customPluginFolderPath.getFileName().toString()).contains(".installing"))
|
||||
&& !((customPluginFolderPath.getFileName().toString()).contains(".removing"))) {
|
||||
final PluginInfo info = PluginInfo.readFromProperties(customPluginFolderPath);
|
||||
if (info.getName().equals(pluginName)) {
|
||||
return customPluginFolderPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pluginPath.resolve(pluginName);
|
||||
}
|
||||
}
|
|
@ -114,9 +114,20 @@ class RemovePluginCommand extends EnvironmentAwareCommand {
|
|||
);
|
||||
}
|
||||
|
||||
final Path pluginDir = env.pluginsFile().resolve(pluginName);
|
||||
final Path pluginConfigDir = env.configFile().resolve(pluginName);
|
||||
final Path removing = env.pluginsFile().resolve(".removing-" + pluginName);
|
||||
Path pluginDir = env.pluginsFile().resolve(pluginName);
|
||||
Path pluginConfigDir = env.configFile().resolve(pluginName);
|
||||
Path removing = env.pluginsFile().resolve(".removing-" + pluginName);
|
||||
|
||||
/*
|
||||
* If the plugin directory is not found with the plugin name, scan the list of all installed plugins
|
||||
* to find if the concerned plugin is installed with a custom folder name.
|
||||
*/
|
||||
if (!Files.exists(pluginDir)) {
|
||||
terminal.println("searching in other folders to find if plugin exists with custom folder name");
|
||||
pluginDir = PluginHelper.verifyIfPluginExists(env.pluginsFile(), pluginName);
|
||||
pluginConfigDir = env.configFile().resolve(pluginDir.getFileName());
|
||||
removing = env.pluginsFile().resolve(".removing-" + pluginDir.getFileName());
|
||||
}
|
||||
|
||||
terminal.println("-> removing [" + pluginName + "]...");
|
||||
/*
|
||||
|
|
|
@ -576,6 +576,17 @@ public class InstallPluginCommandTests extends OpenSearchTestCase {
|
|||
assertInstallCleaned(env.v2());
|
||||
}
|
||||
|
||||
public void testExistingPluginWithCustomFolderName() throws Exception {
|
||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
String pluginZip = createPluginUrl("fake", pluginDir, "custom.foldername", "fake-folder");
|
||||
installPlugin(pluginZip, env.v1());
|
||||
assertPlugin("fake-folder", pluginDir, env.v2());
|
||||
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("already exists"));
|
||||
assertInstallCleaned(env.v2());
|
||||
}
|
||||
|
||||
public void testBin() throws Exception {
|
||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
|
@ -873,6 +884,14 @@ public class InstallPluginCommandTests extends OpenSearchTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public void testPluginInstallationWithCustomFolderName() throws Exception {
|
||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
String pluginZip = createPluginUrl("fake", pluginDir, "custom.foldername", "fake-folder");
|
||||
installPlugin(pluginZip, env.v1());
|
||||
assertPlugin("fake-folder", pluginDir, env.v2());
|
||||
}
|
||||
|
||||
private void installPlugin(MockTerminal terminal, boolean isBatch) throws Exception {
|
||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
|
|
|
@ -124,6 +124,8 @@ public class ListPluginsCommandTests extends OpenSearchTestCase {
|
|||
"1.8",
|
||||
"classname",
|
||||
classname,
|
||||
"custom.foldername",
|
||||
"custom-folder",
|
||||
"has.native.controller",
|
||||
Boolean.toString(hasNativeController)
|
||||
);
|
||||
|
@ -169,7 +171,8 @@ public class ListPluginsCommandTests extends OpenSearchTestCase {
|
|||
"Java Version: 1.8",
|
||||
"Native Controller: false",
|
||||
"Extended Plugins: []",
|
||||
" * Classname: org.fake"
|
||||
" * Classname: org.fake",
|
||||
"Folder name: custom-folder"
|
||||
),
|
||||
terminal.getOutput()
|
||||
);
|
||||
|
@ -191,7 +194,8 @@ public class ListPluginsCommandTests extends OpenSearchTestCase {
|
|||
"Java Version: 1.8",
|
||||
"Native Controller: true",
|
||||
"Extended Plugins: []",
|
||||
" * Classname: org.fake"
|
||||
" * Classname: org.fake",
|
||||
"Folder name: custom-folder"
|
||||
),
|
||||
terminal.getOutput()
|
||||
);
|
||||
|
@ -215,6 +219,7 @@ public class ListPluginsCommandTests extends OpenSearchTestCase {
|
|||
"Native Controller: false",
|
||||
"Extended Plugins: []",
|
||||
" * Classname: org.fake",
|
||||
"Folder name: custom-folder",
|
||||
"fake_plugin2",
|
||||
"- Plugin information:",
|
||||
"Name: fake_plugin2",
|
||||
|
@ -224,7 +229,8 @@ public class ListPluginsCommandTests extends OpenSearchTestCase {
|
|||
"Java Version: 1.8",
|
||||
"Native Controller: false",
|
||||
"Extended Plugins: []",
|
||||
" * Classname: org.fake2"
|
||||
" * Classname: org.fake2",
|
||||
"Folder name: custom-folder"
|
||||
),
|
||||
terminal.getOutput()
|
||||
);
|
||||
|
|
|
@ -50,7 +50,9 @@ import java.io.StringReader;
|
|||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
|
@ -90,34 +92,34 @@ public class RemovePluginCommandTests extends OpenSearchTestCase {
|
|||
env = TestEnvironment.newEnvironment(settings);
|
||||
}
|
||||
|
||||
void createPlugin(String name) throws IOException {
|
||||
createPlugin(env.pluginsFile(), name);
|
||||
void createPlugin(String name, String... additionalProps) throws IOException {
|
||||
createPlugin(env.pluginsFile(), name, Version.CURRENT, additionalProps);
|
||||
}
|
||||
|
||||
void createPlugin(String name, Version version) throws IOException {
|
||||
createPlugin(env.pluginsFile(), name, version);
|
||||
}
|
||||
|
||||
void createPlugin(Path path, String name) throws IOException {
|
||||
createPlugin(path, name, Version.CURRENT);
|
||||
}
|
||||
|
||||
void createPlugin(Path path, String name, Version version) throws IOException {
|
||||
PluginTestUtil.writePluginProperties(
|
||||
path.resolve(name),
|
||||
"description",
|
||||
"dummy",
|
||||
"name",
|
||||
name,
|
||||
"version",
|
||||
"1.0",
|
||||
"opensearch.version",
|
||||
version.toString(),
|
||||
"java.version",
|
||||
System.getProperty("java.specification.version"),
|
||||
"classname",
|
||||
"SomeClass"
|
||||
);
|
||||
void createPlugin(Path path, String name, Version version, String... additionalProps) throws IOException {
|
||||
String[] properties = Stream.concat(
|
||||
Stream.of(
|
||||
"description",
|
||||
"dummy",
|
||||
"name",
|
||||
name,
|
||||
"version",
|
||||
"1.0",
|
||||
"opensearch.version",
|
||||
version.toString(),
|
||||
"java.version",
|
||||
System.getProperty("java.specification.version"),
|
||||
"classname",
|
||||
"SomeClass"
|
||||
),
|
||||
Arrays.stream(additionalProps)
|
||||
).toArray(String[]::new);
|
||||
String pluginFolderName = additionalProps.length == 0 ? name : additionalProps[1];
|
||||
PluginTestUtil.writePluginProperties(path.resolve(pluginFolderName), properties);
|
||||
}
|
||||
|
||||
static MockTerminal removePlugin(String name, Path home, boolean purge) throws Exception {
|
||||
|
@ -154,6 +156,17 @@ public class RemovePluginCommandTests extends OpenSearchTestCase {
|
|||
assertRemoveCleaned(env);
|
||||
}
|
||||
|
||||
public void testRemovePluginWithCustomFolderName() throws Exception {
|
||||
createPlugin("fake", "custom.foldername", "custom-folder");
|
||||
Files.createFile(env.pluginsFile().resolve("custom-folder").resolve("plugin.jar"));
|
||||
Files.createDirectory(env.pluginsFile().resolve("custom-folder").resolve("subdir"));
|
||||
createPlugin("other");
|
||||
removePlugin("fake", home, randomBoolean());
|
||||
assertFalse(Files.exists(env.pluginsFile().resolve("custom-folder")));
|
||||
assertTrue(Files.exists(env.pluginsFile().resolve("other")));
|
||||
assertRemoveCleaned(env);
|
||||
}
|
||||
|
||||
public void testRemoveOldVersion() throws Exception {
|
||||
createPlugin(
|
||||
"fake",
|
||||
|
@ -261,6 +274,7 @@ public class RemovePluginCommandTests extends OpenSearchTestCase {
|
|||
BufferedReader reader = new BufferedReader(new StringReader(terminal.getOutput()));
|
||||
BufferedReader errorReader = new BufferedReader(new StringReader(terminal.getErrorOutput()))
|
||||
) {
|
||||
assertEquals("searching in other folders to find if plugin exists with custom folder name", reader.readLine());
|
||||
assertEquals("-> removing [fake]...", reader.readLine());
|
||||
assertEquals(
|
||||
"ERROR: plugin [fake] not found; run 'opensearch-plugin list' to get list of installed plugins",
|
||||
|
|
|
@ -69,6 +69,7 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
private final Version opensearchVersion;
|
||||
private final String javaVersion;
|
||||
private final String classname;
|
||||
private final String customFolderName;
|
||||
private final List<String> extendedPlugins;
|
||||
private final boolean hasNativeController;
|
||||
|
||||
|
@ -81,17 +82,19 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
* @param opensearchVersion the version of OpenSearch the plugin was built for
|
||||
* @param javaVersion the version of Java the plugin was built with
|
||||
* @param classname the entry point to the plugin
|
||||
* @param customFolderName the custom folder name for the plugin
|
||||
* @param extendedPlugins other plugins this plugin extends through SPI
|
||||
* @param hasNativeController whether or not the plugin has a native controller
|
||||
*/
|
||||
public PluginInfo(String name, String description, String version, Version opensearchVersion, String javaVersion,
|
||||
String classname, List<String> extendedPlugins, boolean hasNativeController) {
|
||||
String classname, String customFolderName, List<String> extendedPlugins, boolean hasNativeController) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.version = version;
|
||||
this.opensearchVersion = opensearchVersion;
|
||||
this.javaVersion = javaVersion;
|
||||
this.classname = classname;
|
||||
this.customFolderName = customFolderName;
|
||||
this.extendedPlugins = Collections.unmodifiableList(extendedPlugins);
|
||||
this.hasNativeController = hasNativeController;
|
||||
}
|
||||
|
@ -116,6 +119,11 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
javaVersion = "1.8";
|
||||
}
|
||||
this.classname = in.readString();
|
||||
if (in.getVersion().after(Version.V_1_0_0)) {
|
||||
customFolderName = in.readString();
|
||||
} else {
|
||||
customFolderName = this.name;
|
||||
}
|
||||
if (in.getVersion().onOrAfter(LegacyESVersion.V_6_2_0)) {
|
||||
extendedPlugins = in.readStringList();
|
||||
} else {
|
||||
|
@ -141,6 +149,13 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
out.writeString(javaVersion);
|
||||
}
|
||||
out.writeString(classname);
|
||||
if (out.getVersion().after(Version.V_1_0_0)) {
|
||||
if (customFolderName != null) {
|
||||
out.writeString(customFolderName);
|
||||
} else {
|
||||
out.writeString(name);
|
||||
}
|
||||
}
|
||||
if (out.getVersion().onOrAfter(LegacyESVersion.V_6_2_0)) {
|
||||
out.writeStringCollection(extendedPlugins);
|
||||
}
|
||||
|
@ -207,6 +222,14 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
"property [classname] is missing for plugin [" + name + "]");
|
||||
}
|
||||
|
||||
final String customFolderNameValue = propsMap.remove("custom.foldername");
|
||||
final String customFolderName;
|
||||
if (esVersion.after(Version.V_1_0_0)) {
|
||||
customFolderName = customFolderNameValue;
|
||||
} else {
|
||||
customFolderName = name;
|
||||
}
|
||||
|
||||
final String extendedString = propsMap.remove("extended.plugins");
|
||||
final List<String> extendedPlugins;
|
||||
if (extendedString == null) {
|
||||
|
@ -248,7 +271,7 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
}
|
||||
|
||||
return new PluginInfo(name, description, version, esVersion, javaVersionString,
|
||||
classname, extendedPlugins, hasNativeController);
|
||||
classname, customFolderName, extendedPlugins, hasNativeController);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,6 +301,15 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
return classname;
|
||||
}
|
||||
|
||||
/**
|
||||
* The custom folder name for the plugin.
|
||||
*
|
||||
* @return the custom folder name for the plugin
|
||||
*/
|
||||
public String getFolderName() {
|
||||
return customFolderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Other plugins this plugin extends through SPI.
|
||||
*
|
||||
|
@ -323,6 +355,15 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
return hasNativeController;
|
||||
}
|
||||
|
||||
/**
|
||||
* The target folder name for the plugin.
|
||||
*
|
||||
* @return the custom folder name for the plugin if the folder name is specified, else return the id with kebab-case.
|
||||
*/
|
||||
public String getTargetFolderName() {
|
||||
return (this.customFolderName == null || this.customFolderName.isEmpty()) ? this.name : this.customFolderName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
|
@ -333,6 +374,7 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
builder.field("java_version", javaVersion);
|
||||
builder.field("description", description);
|
||||
builder.field("classname", classname);
|
||||
builder.field("custom_foldername", customFolderName);
|
||||
builder.field("extended_plugins", extendedPlugins);
|
||||
builder.field("has_native_controller", hasNativeController);
|
||||
}
|
||||
|
@ -375,7 +417,8 @@ public class PluginInfo implements Writeable, ToXContentObject {
|
|||
.append(prefix).append("Java Version: ").append(javaVersion).append("\n")
|
||||
.append(prefix).append("Native Controller: ").append(hasNativeController).append("\n")
|
||||
.append(prefix).append("Extended Plugins: ").append(extendedPlugins).append("\n")
|
||||
.append(prefix).append(" * Classname: ").append(classname);
|
||||
.append(prefix).append(" * Classname: ").append(classname).append("\n")
|
||||
.append(prefix).append("Folder name: ").append(customFolderName);
|
||||
return information.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ public class PluginsService implements ReportingService<PluginsAndModules> {
|
|||
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);
|
||||
pluginClass.getName(), null, Collections.emptyList(), false);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("plugin loaded from classpath [{}]", pluginInfo);
|
||||
}
|
||||
|
|
|
@ -159,16 +159,18 @@ public class NodeInfoStreamingTests extends OpenSearchTestCase {
|
|||
int numPlugins = randomIntBetween(0, 5);
|
||||
List<PluginInfo> plugins = new ArrayList<>();
|
||||
for (int i = 0; i < numPlugins; i++) {
|
||||
plugins.add(new PluginInfo(randomAlphaOfLengthBetween(3, 10), randomAlphaOfLengthBetween(3, 10),
|
||||
String name = randomAlphaOfLengthBetween(3, 10);
|
||||
plugins.add(new PluginInfo(name, randomAlphaOfLengthBetween(3, 10),
|
||||
randomAlphaOfLengthBetween(3, 10), VersionUtils.randomVersion(random()), "1.8",
|
||||
randomAlphaOfLengthBetween(3, 10), Collections.emptyList(), randomBoolean()));
|
||||
randomAlphaOfLengthBetween(3, 10), name, 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),
|
||||
String name = randomAlphaOfLengthBetween(3, 10);
|
||||
modules.add(new PluginInfo(name, randomAlphaOfLengthBetween(3, 10),
|
||||
randomAlphaOfLengthBetween(3, 10), VersionUtils.randomVersion(random()), "1.8",
|
||||
randomAlphaOfLengthBetween(3, 10), Collections.emptyList(), randomBoolean()));
|
||||
randomAlphaOfLengthBetween(3, 10), name, Collections.emptyList(), randomBoolean()));
|
||||
}
|
||||
pluginsAndModules = new PluginsAndModules(plugins, modules);
|
||||
}
|
||||
|
|
|
@ -70,6 +70,44 @@ public class PluginInfoTests extends OpenSearchTestCase {
|
|||
assertThat(info.getExtendedPlugins(), empty());
|
||||
}
|
||||
|
||||
public void testReadFromPropertiesWithFolderNameAndVersionBefore() throws Exception {
|
||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
||||
PluginTestUtil.writePluginProperties(pluginDir,
|
||||
"description", "fake desc",
|
||||
"name", "my_plugin",
|
||||
"version", "1.0",
|
||||
"opensearch.version", Version.V_1_0_0.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"classname", "FakePlugin",
|
||||
"custom.foldername", "custom-folder");
|
||||
PluginInfo info = PluginInfo.readFromProperties(pluginDir);
|
||||
assertEquals("my_plugin", info.getName());
|
||||
assertEquals("fake desc", info.getDescription());
|
||||
assertEquals("1.0", info.getVersion());
|
||||
assertEquals("FakePlugin", info.getClassname());
|
||||
assertEquals("my_plugin", info.getTargetFolderName());
|
||||
assertThat(info.getExtendedPlugins(), empty());
|
||||
}
|
||||
|
||||
public void testReadFromPropertiesWithFolderNameAndVersionAfter() throws Exception {
|
||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
||||
PluginTestUtil.writePluginProperties(pluginDir,
|
||||
"description", "fake desc",
|
||||
"name", "my_plugin",
|
||||
"version", "1.0",
|
||||
"opensearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"classname", "FakePlugin",
|
||||
"custom.foldername", "custom-folder");
|
||||
PluginInfo info = PluginInfo.readFromProperties(pluginDir);
|
||||
assertEquals("my_plugin", info.getName());
|
||||
assertEquals("fake desc", info.getDescription());
|
||||
assertEquals("1.0", info.getVersion());
|
||||
assertEquals("FakePlugin", info.getClassname());
|
||||
assertEquals("custom-folder", info.getTargetFolderName());
|
||||
assertThat(info.getExtendedPlugins(), empty());
|
||||
}
|
||||
|
||||
public void testReadFromPropertiesNameMissing() throws Exception {
|
||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
||||
PluginTestUtil.writePluginProperties(pluginDir);
|
||||
|
@ -199,7 +237,7 @@ public class PluginInfoTests extends OpenSearchTestCase {
|
|||
|
||||
public void testSerialize() throws Exception {
|
||||
PluginInfo info = new PluginInfo("c", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
|
||||
Collections.singletonList("foo"), randomBoolean());
|
||||
"c", Collections.singletonList("foo"), randomBoolean());
|
||||
BytesStreamOutput output = new BytesStreamOutput();
|
||||
info.writeTo(output);
|
||||
ByteBuffer buffer = ByteBuffer.wrap(output.bytes().toBytesRef().bytes);
|
||||
|
@ -212,15 +250,15 @@ public class PluginInfoTests extends OpenSearchTestCase {
|
|||
public void testPluginListSorted() {
|
||||
List<PluginInfo> plugins = new ArrayList<>();
|
||||
plugins.add(new PluginInfo("c", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
|
||||
Collections.emptyList(), randomBoolean()));
|
||||
null, Collections.emptyList(), randomBoolean()));
|
||||
plugins.add(new PluginInfo("b", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
|
||||
Collections.emptyList(), randomBoolean()));
|
||||
null, Collections.emptyList(), randomBoolean()));
|
||||
plugins.add(new PluginInfo( "e", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
|
||||
Collections.emptyList(), randomBoolean()));
|
||||
null, Collections.emptyList(), randomBoolean()));
|
||||
plugins.add(new PluginInfo("a", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
|
||||
Collections.emptyList(), randomBoolean()));
|
||||
null, Collections.emptyList(), randomBoolean()));
|
||||
plugins.add(new PluginInfo("d", "foo", "dummy", Version.CURRENT, "1.8", "dummyclass",
|
||||
Collections.emptyList(), randomBoolean()));
|
||||
null, Collections.emptyList(), randomBoolean()));
|
||||
PluginsAndModules pluginsInfo = new PluginsAndModules(plugins, Collections.emptyList());
|
||||
|
||||
final List<PluginInfo> infos = pluginsInfo.getPluginInfos();
|
||||
|
|
|
@ -323,7 +323,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, Collections.singletonList("foo"), false);
|
||||
PluginsService.Bundle bundle = new PluginsService.Bundle(info, pluginDir);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
|
||||
PluginsService.sortBundles(Collections.singleton(bundle))
|
||||
|
@ -335,16 +335,16 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, Collections.emptyList(), false);
|
||||
bundles.add(new PluginsService.Bundle(info4, pluginDir));
|
||||
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () -> PluginsService.sortBundles(bundles));
|
||||
|
@ -354,7 +354,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
public void testSortBundlesSingle() throws Exception {
|
||||
Path pluginDir = createTempDir();
|
||||
PluginInfo info = new PluginInfo("foo", "desc", "1.0", Version.CURRENT, "1.8",
|
||||
"MyPlugin", Collections.emptyList(), false);
|
||||
"MyPlugin", null, 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));
|
||||
|
@ -364,15 +364,15 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, Collections.emptyList(), false);
|
||||
PluginsService.Bundle bundle3 = new PluginsService.Bundle(info3, pluginDir);
|
||||
bundles.add(bundle3);
|
||||
List<PluginsService.Bundle> sortedBundles = PluginsService.sortBundles(bundles);
|
||||
|
@ -382,7 +382,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", "", Collections.singletonList("dne"), false);
|
||||
PluginsService.Bundle bundle = new PluginsService.Bundle(info, pluginDir);
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () ->
|
||||
PluginsService.sortBundles(Collections.singleton(bundle))
|
||||
|
@ -394,19 +394,19 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, Collections.singletonList("grandparent"), false);
|
||||
PluginsService.Bundle bundle4 = new PluginsService.Bundle(info4, pluginDir);
|
||||
bundles.add(bundle4);
|
||||
List<PluginsService.Bundle> sortedBundles = PluginsService.sortBundles(bundles);
|
||||
|
@ -417,11 +417,11 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, 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);
|
||||
"MyPlugin", null, Collections.singletonList("dep"), false);
|
||||
PluginsService.Bundle bundle2 = new PluginsService.Bundle(info2, pluginDir);
|
||||
bundles.add(bundle2);
|
||||
List<PluginsService.Bundle> sortedBundles = PluginsService.sortBundles(bundles);
|
||||
|
@ -480,7 +480,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, Collections.singletonList("dep"), false);
|
||||
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
|
||||
PluginsService.checkBundleJarHell(JarHell.parseClassPath(), bundle, transitiveDeps));
|
||||
|
@ -499,7 +499,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, Arrays.asList("dep1", "dep2"), false);
|
||||
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
|
||||
PluginsService.checkBundleJarHell(JarHell.parseClassPath(), bundle, transitiveDeps));
|
||||
|
@ -516,7 +516,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, Collections.emptyList(), false);
|
||||
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
|
||||
PluginsService.checkBundleJarHell(JarHell.parseClassPath(), bundle, new HashMap<>()));
|
||||
|
@ -535,7 +535,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, Collections.singletonList("dep"), false);
|
||||
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
|
||||
PluginsService.checkBundleJarHell(JarHell.parseClassPath(), bundle, transitiveDeps));
|
||||
|
@ -558,7 +558,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, Arrays.asList("dep1", "dep2"), false);
|
||||
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () ->
|
||||
PluginsService.checkBundleJarHell(JarHell.parseClassPath(), bundle, transitiveDeps));
|
||||
|
@ -581,7 +581,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
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);
|
||||
"MyPlugin", null, Arrays.asList("dep1", "dep2"), false);
|
||||
PluginsService.Bundle bundle = new PluginsService.Bundle(info1, pluginDir);
|
||||
PluginsService.checkBundleJarHell(JarHell.parseClassPath(), bundle, transitiveDeps);
|
||||
Set<URL> deps = transitiveDeps.get("myplugin");
|
||||
|
@ -630,14 +630,14 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
|
||||
public void testIncompatibleOpenSearchVersion() throws Exception {
|
||||
PluginInfo info = new PluginInfo("my_plugin", "desc", "1.0", LegacyESVersion.V_6_0_0,
|
||||
"1.8", "FakePlugin", Collections.emptyList(), false);
|
||||
"1.8", "FakePlugin", null, Collections.emptyList(), false);
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> PluginsService.verifyCompatibility(info));
|
||||
assertThat(e.getMessage(), containsString("was built for OpenSearch version 6.0.0"));
|
||||
}
|
||||
|
||||
public void testIncompatibleJavaVersion() throws Exception {
|
||||
PluginInfo info = new PluginInfo("my_plugin", "desc", "1.0", Version.CURRENT,
|
||||
"1000000.0", "FakePlugin", Collections.emptyList(), false);
|
||||
"1000000.0", "FakePlugin", null, Collections.emptyList(), false);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () -> PluginsService.verifyCompatibility(info));
|
||||
assertThat(e.getMessage(), containsString("my_plugin requires Java"));
|
||||
}
|
||||
|
@ -761,7 +761,7 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
public void testExtensiblePlugin() {
|
||||
TestExtensiblePlugin extensiblePlugin = new TestExtensiblePlugin();
|
||||
PluginsService.loadExtensions(Collections.singletonList(
|
||||
Tuple.tuple(new PluginInfo("extensible", null, null, null, null, null, Collections.emptyList(), false), extensiblePlugin)
|
||||
Tuple.tuple(new PluginInfo("extensible", null, null, null, null, null, null, Collections.emptyList(), false), extensiblePlugin)
|
||||
));
|
||||
|
||||
assertThat(extensiblePlugin.extensions, notNullValue());
|
||||
|
@ -770,8 +770,9 @@ public class PluginsServiceTests extends OpenSearchTestCase {
|
|||
extensiblePlugin = new TestExtensiblePlugin();
|
||||
TestPlugin testPlugin = new TestPlugin();
|
||||
PluginsService.loadExtensions(Arrays.asList(
|
||||
Tuple.tuple(new PluginInfo("extensible", null, null, null, null, null, Collections.emptyList(), false), extensiblePlugin),
|
||||
Tuple.tuple(new PluginInfo("test", null, null, null, null, null, Collections.singletonList("extensible"), false), testPlugin)
|
||||
Tuple.tuple(new PluginInfo("extensible", null, null, null, null, null, null, Collections.emptyList(), false), extensiblePlugin),
|
||||
Tuple.tuple(new PluginInfo("test", null, null, null, null, null, null, Collections.singletonList("extensible"), false),
|
||||
testPlugin)
|
||||
));
|
||||
|
||||
assertThat(extensiblePlugin.extensions, notNullValue());
|
||||
|
|
Loading…
Reference in New Issue