Plugins: Remove meta plugins (#30670)

Meta plugins existed only for a short time, in order to enable breaking
up x-pack into multiple plugins. However, now that x-pack is no longer
installed as a plugin, the need for them has disappeared. This commit
removes the meta plugins infrastructure.
This commit is contained in:
Ryan Ernst 2018-05-18 10:56:08 -07:00 committed by GitHub
parent e750462e0c
commit b3f3a4312b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 43 additions and 1503 deletions

View File

@ -1,106 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.gradle.plugin
import org.elasticsearch.gradle.BuildPlugin
import org.elasticsearch.gradle.test.RestTestPlugin
import org.elasticsearch.gradle.test.RunTask
import org.elasticsearch.gradle.test.StandaloneRestTestPlugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.FileCopyDetails
import org.gradle.api.file.RelativePath
import org.gradle.api.tasks.bundling.Zip
class MetaPluginBuildPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.plugins.apply(StandaloneRestTestPlugin)
project.plugins.apply(RestTestPlugin)
createBundleTask(project)
boolean isModule = project.path.startsWith(':modules:') || project.path.startsWith(':x-pack:plugin')
project.integTestCluster {
dependsOn(project.bundlePlugin)
distribution = 'integ-test-zip'
}
BuildPlugin.configurePomGeneration(project)
project.afterEvaluate {
PluginBuildPlugin.addZipPomGeneration(project)
if (isModule) {
if (project.integTestCluster.distribution == 'integ-test-zip') {
project.integTestCluster.module(project)
}
} else {
project.integTestCluster.plugin(project.path)
}
}
RunTask run = project.tasks.create('run', RunTask)
run.dependsOn(project.bundlePlugin)
if (isModule == false) {
run.clusterConfig.plugin(project.path)
}
}
private static void createBundleTask(Project project) {
MetaPluginPropertiesTask buildProperties = project.tasks.create('pluginProperties', MetaPluginPropertiesTask.class)
// create the actual bundle task, which zips up all the files for the plugin
Zip bundle = project.tasks.create(name: 'bundlePlugin', type: Zip, dependsOn: [buildProperties]) {
from(buildProperties.descriptorOutput.parentFile) {
// plugin properties file
include(buildProperties.descriptorOutput.name)
}
// due to how the renames work for each bundled plugin, we must exclude empty dirs or every subdir
// within bundled plugin zips will show up at the root as an empty dir
includeEmptyDirs = false
}
project.assemble.dependsOn(bundle)
// also make the zip available as a configuration (used when depending on this project)
project.configurations.create('zip')
project.artifacts.add('zip', bundle)
// a super hacky way to inject code to run at the end of each of the bundled plugin's configuration
// to add itself back to this meta plugin zip
project.afterEvaluate {
buildProperties.extension.plugins.each { String bundledPluginProjectName ->
Project bundledPluginProject = project.project(bundledPluginProjectName)
bundledPluginProject.afterEvaluate {
String bundledPluginName = bundledPluginProject.esplugin.name
bundle.configure {
dependsOn bundledPluginProject.bundlePlugin
from(project.zipTree(bundledPluginProject.bundlePlugin.outputs.files.singleFile)) {
eachFile { FileCopyDetails details ->
// we want each path to have the plugin name interjected
details.relativePath = new RelativePath(true, bundledPluginName, details.relativePath.toString())
}
}
}
}
}
}
}
}

View File

@ -1,46 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.gradle.plugin
import org.gradle.api.Project
import org.gradle.api.tasks.Input
/**
* A container for meta plugin properties that will be written to the meta plugin descriptor, for easy
* manipulation in the gradle DSL.
*/
class MetaPluginPropertiesExtension {
@Input
String name
@Input
String description
/**
* The plugins this meta plugin wraps.
* Note this is not written to the plugin descriptor, but used to setup the final zip file task.
*/
@Input
List<String> plugins
MetaPluginPropertiesExtension(Project project) {
name = project.name
}
}

View File

@ -1,68 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.gradle.plugin
import org.gradle.api.InvalidUserDataException
import org.gradle.api.Task
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.OutputFile
class MetaPluginPropertiesTask extends Copy {
MetaPluginPropertiesExtension extension
@OutputFile
File descriptorOutput = new File(project.buildDir, 'generated-resources/meta-plugin-descriptor.properties')
MetaPluginPropertiesTask() {
File templateFile = new File(project.buildDir, "templates/${descriptorOutput.name}")
Task copyPluginPropertiesTemplate = project.tasks.create('copyPluginPropertiesTemplate') {
doLast {
InputStream resourceTemplate = PluginPropertiesTask.getResourceAsStream("/${descriptorOutput.name}")
templateFile.parentFile.mkdirs()
templateFile.setText(resourceTemplate.getText('UTF-8'), 'UTF-8')
}
}
dependsOn(copyPluginPropertiesTemplate)
extension = project.extensions.create('es_meta_plugin', MetaPluginPropertiesExtension, project)
project.afterEvaluate {
// check require properties are set
if (extension.name == null) {
throw new InvalidUserDataException('name is a required setting for es_meta_plugin')
}
if (extension.description == null) {
throw new InvalidUserDataException('description is a required setting for es_meta_plugin')
}
// configure property substitution
from(templateFile.parentFile).include(descriptorOutput.name)
into(descriptorOutput.parentFile)
Map<String, String> properties = generateSubstitutions()
expand(properties)
inputs.properties(properties)
}
}
Map<String, String> generateSubstitutions() {
return ['name': extension.name,
'description': extension.description
]
}
}

View File

@ -24,7 +24,7 @@ import org.elasticsearch.gradle.BuildPlugin
import org.elasticsearch.gradle.LoggedExec
import org.elasticsearch.gradle.Version
import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.plugin.MetaPluginBuildPlugin
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
import org.elasticsearch.gradle.plugin.PluginPropertiesExtension
import org.gradle.api.AntBuilder
@ -842,19 +842,15 @@ class ClusterFormationTasks {
}
static void verifyProjectHasBuildPlugin(String name, Version version, Project project, Project pluginProject) {
if (pluginProject.plugins.hasPlugin(PluginBuildPlugin) == false && pluginProject.plugins.hasPlugin(MetaPluginBuildPlugin) == false) {
if (pluginProject.plugins.hasPlugin(PluginBuildPlugin) == false) {
throw new GradleException("Task [${name}] cannot add plugin [${pluginProject.path}] with version [${version}] to project's " +
"[${project.path}] dependencies: the plugin is not an esplugin or es_meta_plugin")
"[${project.path}] dependencies: the plugin is not an esplugin")
}
}
/** Find the plugin name in the given project, whether a regular plugin or meta plugin. */
/** Find the plugin name in the given project. */
static String findPluginName(Project pluginProject) {
PluginPropertiesExtension extension = pluginProject.extensions.findByName('esplugin')
if (extension != null) {
return extension.name
} else {
return pluginProject.extensions.findByName('es_meta_plugin').name
}
return extension.name
}
}

View File

@ -1,20 +0,0 @@
#
# Licensed to Elasticsearch under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
implementation-class=org.elasticsearch.gradle.plugin.MetaPluginBuildPlugin

View File

@ -1,20 +0,0 @@
# Elasticsearch meta plugin descriptor file
# This file must exist as 'meta-plugin-descriptor.properties' inside a plugin.
#
### example meta plugin for "meta-foo"
#
# meta-foo.zip <-- zip file for the meta plugin, with this structure:
# |____ <bundled_plugin_1> <-- The plugin files for bundled_plugin_1
# |____ <bundled_plugin_2> <-- The plugin files for bundled_plugin_2
# |____ meta-plugin-descriptor.properties <-- example contents below:
#
# description=My meta plugin
# name=meta-foo
#
### mandatory elements for all meta plugins:
#
# 'description': simple summary of the meta plugin
description=${description}
#
# 'name': the meta plugin name
name=${name}

View File

@ -87,8 +87,8 @@ import static org.elasticsearch.cli.Terminal.Verbosity.VERBOSE;
* <li>A URL to a plugin zip</li>
* </ul>
*
* Plugins are packaged as zip files. Each packaged plugin must contain a plugin properties file
* or a meta plugin properties file. See {@link PluginInfo} and {@link MetaPluginInfo}, respectively.
* Plugins are packaged as zip files. Each packaged plugin must contain a plugin properties file.
* See {@link PluginInfo}.
* <p>
* The installation process first extracts the plugin files into a temporary
* directory in order to verify the plugin satisfies the following requirements:
@ -106,11 +106,6 @@ import static org.elasticsearch.cli.Terminal.Verbosity.VERBOSE;
* files specific to the plugin. The config files be installed into a subdirectory of the
* elasticsearch config directory, using the name of the plugin. If any files to be installed
* already exist, they will be skipped.
* <p>
* If the plugin is a meta plugin, the installation process installs each plugin separately
* inside the meta plugin directory. The {@code bin} and {@code config} directory are also moved
* inside the meta plugin directory.
* </p>
*/
class InstallPluginCommand extends EnvironmentAwareCommand {
@ -550,7 +545,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
}
// checking for existing version of the plugin
private void verifyPluginName(Path pluginPath, String pluginName, Path candidateDir) throws UserException, IOException {
private void verifyPluginName(Path pluginPath, String pluginName) throws UserException, IOException {
// don't let user install plugin conflicting with module...
// they might be unavoidably in maven central and are packaged up the same way)
if (MODULES.contains(pluginName)) {
@ -567,28 +562,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
pluginName);
throw new UserException(PLUGIN_EXISTS, message);
}
// checks meta plugins too
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pluginPath)) {
for (Path plugin : stream) {
if (candidateDir.equals(plugin.resolve(pluginName))) {
continue;
}
if (MetaPluginInfo.isMetaPlugin(plugin) && Files.exists(plugin.resolve(pluginName))) {
final MetaPluginInfo info = MetaPluginInfo.readFromProperties(plugin);
final String message = String.format(
Locale.ROOT,
"plugin name [%s] already exists in a meta plugin; if you need to update the meta plugin, " +
"uninstall it first using command 'remove %s'",
plugin.resolve(pluginName).toAbsolutePath(),
info.getName());
throw new UserException(PLUGIN_EXISTS, message);
}
}
}
}
/** 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, Environment env) throws Exception {
final PluginInfo info = PluginInfo.readFromProperties(pluginRoot);
if (info.hasNativeController()) {
throw new IllegalStateException("plugins can not have native controllers");
@ -596,7 +573,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
PluginsService.verifyCompatibility(info);
// checking for existing version of the plugin
verifyPluginName(env.pluginsFile(), info.getName(), pluginRoot);
verifyPluginName(env.pluginsFile(), info.getName());
PluginsService.checkForFailedPluginRemovals(env.pluginsFile());
@ -635,11 +612,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
List<Path> deleteOnFailure = new ArrayList<>();
deleteOnFailure.add(tmpRoot);
try {
if (MetaPluginInfo.isMetaPlugin(tmpRoot)) {
installMetaPlugin(terminal, isBatch, tmpRoot, env, deleteOnFailure);
} else {
installPlugin(terminal, isBatch, tmpRoot, env, deleteOnFailure);
}
installPlugin(terminal, isBatch, tmpRoot, env, deleteOnFailure);
} catch (Exception installProblem) {
try {
IOUtils.rm(deleteOnFailure.toArray(new Path[0]));
@ -650,71 +623,13 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
}
}
/**
* Installs the meta plugin and all the bundled plugins from {@code tmpRoot} into the plugins dir.
* If a bundled plugin has a bin dir and/or a config dir, those are copied.
*/
private void installMetaPlugin(Terminal terminal, boolean isBatch, Path tmpRoot,
Environment env, List<Path> deleteOnFailure) throws Exception {
final MetaPluginInfo metaInfo = MetaPluginInfo.readFromProperties(tmpRoot);
verifyPluginName(env.pluginsFile(), metaInfo.getName(), tmpRoot);
final Path destination = env.pluginsFile().resolve(metaInfo.getName());
deleteOnFailure.add(destination);
terminal.println(VERBOSE, metaInfo.toString());
final List<Path> pluginPaths = new ArrayList<>();
try (DirectoryStream<Path> paths = Files.newDirectoryStream(tmpRoot)) {
// Extract bundled plugins path and validate plugin names
for (Path plugin : paths) {
if (MetaPluginInfo.isPropertiesFile(plugin)) {
continue;
}
final PluginInfo info = PluginInfo.readFromProperties(plugin);
PluginsService.verifyCompatibility(info);
verifyPluginName(env.pluginsFile(), info.getName(), plugin);
pluginPaths.add(plugin);
}
}
// read optional security policy from each bundled plugin, and confirm all exceptions one time with user
Set<String> permissions = new HashSet<>();
final List<PluginInfo> pluginInfos = new ArrayList<>();
for (Path plugin : pluginPaths) {
final PluginInfo info = loadPluginInfo(terminal, plugin, isBatch, env);
pluginInfos.add(info);
Path policy = plugin.resolve(PluginInfo.ES_PLUGIN_POLICY);
if (Files.exists(policy)) {
permissions.addAll(PluginSecurity.parsePermissions(policy, env.tmpFile()));
}
}
PluginSecurity.confirmPolicyExceptions(terminal, permissions, isBatch);
// move support files and rename as needed to prepare the exploded plugin for its final location
for (int i = 0; i < pluginPaths.size(); ++i) {
Path pluginPath = pluginPaths.get(i);
PluginInfo info = pluginInfos.get(i);
installPluginSupportFiles(info, pluginPath, env.binFile().resolve(metaInfo.getName()),
env.configFile().resolve(metaInfo.getName()), deleteOnFailure);
// ensure the plugin dir within the tmpRoot has the correct name
if (pluginPath.getFileName().toString().equals(info.getName()) == false) {
Files.move(pluginPath, pluginPath.getParent().resolve(info.getName()), StandardCopyOption.ATOMIC_MOVE);
}
}
movePlugin(tmpRoot, destination);
String[] plugins = pluginInfos.stream().map(PluginInfo::getName).toArray(String[]::new);
terminal.println("-> Installed " + metaInfo.getName() + " with: " + Strings.arrayToCommaDelimitedString(plugins));
}
/**
* Installs the plugin from {@code tmpRoot} into the plugins dir.
* If the plugin has a bin dir and/or a config dir, those are moved.
*/
private void installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot,
Environment env, List<Path> deleteOnFailure) throws Exception {
final PluginInfo info = loadPluginInfo(terminal, tmpRoot, isBatch, env);
final PluginInfo info = loadPluginInfo(terminal, tmpRoot, env);
// read optional security policy (extra permissions), if it exists, confirm or warn the user
Path policy = tmpRoot.resolve(PluginInfo.ES_PLUGIN_POLICY);
final Set<String> permissions;

View File

@ -61,25 +61,7 @@ class ListPluginsCommand extends EnvironmentAwareCommand {
}
Collections.sort(plugins);
for (final Path plugin : plugins) {
if (MetaPluginInfo.isMetaPlugin(plugin)) {
MetaPluginInfo metaInfo = MetaPluginInfo.readFromProperties(plugin);
List<Path> subPluginPaths = new ArrayList<>();
try (DirectoryStream<Path> subPaths = Files.newDirectoryStream(plugin)) {
for (Path subPlugin : subPaths) {
if (MetaPluginInfo.isPropertiesFile(subPlugin)) {
continue;
}
subPluginPaths.add(subPlugin);
}
}
Collections.sort(subPluginPaths);
terminal.println(Terminal.Verbosity.SILENT, metaInfo.getName());
for (Path subPlugin : subPluginPaths) {
printPlugin(env, terminal, subPlugin, "\t");
}
} else {
printPlugin(env, terminal, plugin, "");
}
printPlugin(env, terminal, plugin, "");
}
}

View File

@ -219,18 +219,6 @@ public class InstallPluginCommandTests extends ESTestCase {
return createPlugin(name, structure, additionalProps).toUri().toURL().toString();
}
/** creates an meta plugin .zip and returns the url for testing */
static String createMetaPluginUrl(String name, Path structure) throws IOException {
return createMetaPlugin(name, structure).toUri().toURL().toString();
}
static void writeMetaPlugin(String name, Path structure) throws IOException {
PluginTestUtil.writeMetaPluginProperties(structure,
"description", "fake desc",
"name", name
);
}
static void writePlugin(String name, Path structure, String... additionalProps) throws IOException {
String[] properties = Stream.concat(Stream.of(
"description", "fake desc",
@ -261,11 +249,6 @@ public class InstallPluginCommandTests extends ESTestCase {
return writeZip(structure, null);
}
static Path createMetaPlugin(String name, Path structure) throws IOException {
writeMetaPlugin(name, structure);
return writeZip(structure, null);
}
void installPlugin(String pluginUrl, Path home) throws Exception {
installPlugin(pluginUrl, home, skipJarHellCommand);
}
@ -275,11 +258,6 @@ public class InstallPluginCommandTests extends ESTestCase {
command.execute(terminal, pluginUrl, false, env);
}
void assertMetaPlugin(String metaPlugin, String name, Path original, Environment env) throws IOException {
assertPluginInternal(name, env.pluginsFile().resolve(metaPlugin));
assertConfigAndBin(metaPlugin, original, env);
}
void assertPlugin(String name, Path original, Environment env) throws IOException {
assertPluginInternal(name, env.pluginsFile());
assertConfigAndBin(name, original, env);
@ -388,23 +366,9 @@ public class InstallPluginCommandTests extends ESTestCase {
assertPlugin("fake", pluginDir, env.v2());
}
public void testWithMetaPlugin() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
Files.createDirectory(pluginDir.resolve("fake1"));
writePlugin("fake1", pluginDir.resolve("fake1"));
Files.createDirectory(pluginDir.resolve("fake2"));
writePlugin("fake2", pluginDir.resolve("fake2"));
String pluginZip = createMetaPluginUrl("my_plugins", pluginDir);
installPlugin(pluginZip, env.v1());
assertMetaPlugin("my_plugins", "fake1", pluginDir, env.v2());
assertMetaPlugin("my_plugins", "fake2", pluginDir, env.v2());
}
public void testInstallFailsIfPreviouslyRemovedPluginFailed() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Path pluginDir = createPluginDir(temp);
String pluginZip = createPluginUrl("fake", pluginDir);
final Path removing = env.v2().pluginsFile().resolve(".removing-failed");
Files.createDirectory(removing);
@ -414,11 +378,6 @@ public class InstallPluginCommandTests extends ESTestCase {
"found file [%s] from a failed attempt to remove the plugin [failed]; execute [elasticsearch-plugin remove failed]",
removing);
assertThat(e, hasToString(containsString(expected)));
// test with meta plugin
String metaZip = createMetaPluginUrl("my_plugins", metaDir);
final IllegalStateException e1 = expectThrows(IllegalStateException.class, () -> installPlugin(metaZip, env.v1()));
assertThat(e1, hasToString(containsString(expected)));
}
public void testSpaceInUrl() throws Exception {
@ -500,23 +459,6 @@ public class InstallPluginCommandTests extends ESTestCase {
assertInstallCleaned(environment.v2());
}
public void testJarHellInMetaPlugin() throws Exception {
// jar hell test needs a real filesystem
assumeTrue("real filesystem", isReal);
Tuple<Path, Environment> environment = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
Files.createDirectory(pluginDir.resolve("fake1"));
writePlugin("fake1", pluginDir.resolve("fake1"));
Files.createDirectory(pluginDir.resolve("fake2"));
writePlugin("fake2", pluginDir.resolve("fake2")); // adds plugin.jar with Fake2Plugin
writeJar(pluginDir.resolve("fake2").resolve("other.jar"), "Fake2Plugin");
String pluginZip = createMetaPluginUrl("my_plugins", pluginDir);
IllegalStateException e = expectThrows(IllegalStateException.class,
() -> installPlugin(pluginZip, environment.v1(), defaultCommand));
assertTrue(e.getMessage(), e.getMessage().contains("jar hell"));
assertInstallCleaned(environment.v2());
}
public void testIsolatedPlugins() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
// these both share the same FakePlugin class
@ -540,23 +482,6 @@ public class InstallPluginCommandTests extends ESTestCase {
assertInstallCleaned(env.v2());
}
public void testExistingMetaPlugin() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaZip = createPluginDir(temp);
Path pluginDir = metaZip.resolve("fake");
Files.createDirectory(pluginDir);
String pluginZip = createPluginUrl("fake", pluginDir);
installPlugin(pluginZip, env.v1());
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("already exists"));
assertInstallCleaned(env.v2());
String anotherZip = createMetaPluginUrl("another_plugins", metaZip);
e = expectThrows(UserException.class, () -> installPlugin(anotherZip, 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);
@ -568,43 +493,20 @@ public class InstallPluginCommandTests extends ESTestCase {
assertPlugin("fake", pluginDir, env.v2());
}
public void testMetaBin() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Files.createDirectory(pluginDir);
writePlugin("fake", pluginDir);
Path binDir = pluginDir.resolve("bin");
Files.createDirectory(binDir);
Files.createFile(binDir.resolve("somescript"));
String pluginZip = createMetaPluginUrl("my_plugins", metaDir);
installPlugin(pluginZip, env.v1());
assertMetaPlugin("my_plugins","fake", pluginDir, env.v2());
}
public void testBinNotDir() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Files.createDirectory(pluginDir);
Path pluginDir = createPluginDir(temp);
Path binDir = pluginDir.resolve("bin");
Files.createFile(binDir);
String pluginZip = createPluginUrl("fake", pluginDir);
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("not a directory"));
assertInstallCleaned(env.v2());
String metaZip = createMetaPluginUrl("my_plugins", metaDir);
e = expectThrows(UserException.class, () -> installPlugin(metaZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("not a directory"));
assertInstallCleaned(env.v2());
}
public void testBinContainsDir() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Files.createDirectory(pluginDir);
Path pluginDir = createPluginDir(temp);
Path dirInBinDir = pluginDir.resolve("bin").resolve("foo");
Files.createDirectories(dirInBinDir);
Files.createFile(dirInBinDir.resolve("somescript"));
@ -612,11 +514,6 @@ public class InstallPluginCommandTests extends ESTestCase {
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("Directories not allowed in bin dir for plugin"));
assertInstallCleaned(env.v2());
String metaZip = createMetaPluginUrl("my_plugins", metaDir);
e = expectThrows(UserException.class, () -> installPlugin(metaZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("Directories not allowed in bin dir for plugin"));
assertInstallCleaned(env.v2());
}
public void testBinConflict() throws Exception {
@ -649,27 +546,6 @@ public class InstallPluginCommandTests extends ESTestCase {
}
}
public void testMetaBinPermissions() throws Exception {
assumeTrue("posix filesystem", isPosix);
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Files.createDirectory(pluginDir);
writePlugin("fake", pluginDir);
Path binDir = pluginDir.resolve("bin");
Files.createDirectory(binDir);
Files.createFile(binDir.resolve("somescript"));
String pluginZip = createMetaPluginUrl("my_plugins", metaDir);
try (PosixPermissionsResetter binAttrs = new PosixPermissionsResetter(env.v2().binFile())) {
Set<PosixFilePermission> perms = binAttrs.getCopyPermissions();
// make sure at least one execute perm is missing, so we know we forced it during installation
perms.remove(PosixFilePermission.GROUP_EXECUTE);
binAttrs.setPermissions(perms);
installPlugin(pluginZip, env.v1());
assertMetaPlugin("my_plugins", "fake", pluginDir, env.v2());
}
}
public void testPluginPermissions() throws Exception {
assumeTrue("posix filesystem", isPosix);
@ -761,32 +637,9 @@ public class InstallPluginCommandTests extends ESTestCase {
assertTrue(Files.exists(envConfigDir.resolve("other.yml")));
}
public void testExistingMetaConfig() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path envConfigDir = env.v2().configFile().resolve("my_plugins");
Files.createDirectories(envConfigDir);
Files.write(envConfigDir.resolve("custom.yml"), "existing config".getBytes(StandardCharsets.UTF_8));
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Files.createDirectory(pluginDir);
writePlugin("fake", pluginDir);
Path configDir = pluginDir.resolve("config");
Files.createDirectory(configDir);
Files.write(configDir.resolve("custom.yml"), "new config".getBytes(StandardCharsets.UTF_8));
Files.createFile(configDir.resolve("other.yml"));
String pluginZip = createMetaPluginUrl("my_plugins", metaDir);
installPlugin(pluginZip, env.v1());
assertMetaPlugin("my_plugins", "fake", pluginDir, env.v2());
List<String> configLines = Files.readAllLines(envConfigDir.resolve("custom.yml"), StandardCharsets.UTF_8);
assertEquals(1, configLines.size());
assertEquals("existing config", configLines.get(0));
assertTrue(Files.exists(envConfigDir.resolve("other.yml")));
}
public void testConfigNotDir() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Path pluginDir = createPluginDir(temp);
Files.createDirectories(pluginDir);
Path configDir = pluginDir.resolve("config");
Files.createFile(configDir);
@ -794,11 +647,6 @@ public class InstallPluginCommandTests extends ESTestCase {
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("not a directory"));
assertInstallCleaned(env.v2());
String metaZip = createMetaPluginUrl("my_plugins", metaDir);
e = expectThrows(UserException.class, () -> installPlugin(metaZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("not a directory"));
assertInstallCleaned(env.v2());
}
public void testConfigContainsDir() throws Exception {
@ -815,19 +663,12 @@ public class InstallPluginCommandTests extends ESTestCase {
public void testMissingDescriptor() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path pluginDir = metaDir.resolve("fake");
Files.createDirectory(pluginDir);
Path pluginDir = createPluginDir(temp);
Files.createFile(pluginDir.resolve("fake.yml"));
String pluginZip = writeZip(pluginDir, null).toUri().toURL().toString();
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("plugin-descriptor.properties"));
assertInstallCleaned(env.v2());
String metaZip = createMetaPluginUrl("my_plugins", metaDir);
e = expectThrows(NoSuchFileException.class, () -> installPlugin(metaZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("plugin-descriptor.properties"));
assertInstallCleaned(env.v2());
}
public void testContainsIntermediateDirectory() throws Exception {
@ -840,16 +681,6 @@ public class InstallPluginCommandTests extends ESTestCase {
assertInstallCleaned(env.v2());
}
public void testContainsIntermediateDirectoryMeta() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
Files.createFile(pluginDir.resolve(MetaPluginInfo.ES_META_PLUGIN_PROPERTIES));
String pluginZip = writeZip(pluginDir, "elasticsearch").toUri().toURL().toString();
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
assertThat(e.getMessage(), containsString("This plugin was built with an older plugin structure"));
assertInstallCleaned(env.v2());
}
public void testZipRelativeOutsideEntryName() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path zip = createTempDir().resolve("broken.zip");
@ -958,29 +789,6 @@ public class InstallPluginCommandTests extends ESTestCase {
"if you need to update the plugin, uninstall it first using command 'remove fake'"));
}
public void testMetaPluginAlreadyInstalled() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
{
// install fake plugin
Path pluginDir = createPluginDir(temp);
String pluginZip = createPluginUrl("fake", pluginDir);
installPlugin(pluginZip, env.v1());
}
Path pluginDir = createPluginDir(temp);
Files.createDirectory(pluginDir.resolve("fake"));
writePlugin("fake", pluginDir.resolve("fake"));
Files.createDirectory(pluginDir.resolve("other"));
writePlugin("other", pluginDir.resolve("other"));
String metaZip = createMetaPluginUrl("meta", pluginDir);
final UserException e = expectThrows(UserException.class,
() -> installPlugin(metaZip, env.v1(), randomFrom(skipJarHellCommand, defaultCommand)));
assertThat(
e.getMessage(),
equalTo("plugin directory [" + env.v2().pluginsFile().resolve("fake") + "] already exists; " +
"if you need to update the plugin, uninstall it first using command 'remove fake'"));
}
private void installPlugin(MockTerminal terminal, boolean isBatch) throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
@ -1224,24 +1032,6 @@ public class InstallPluginCommandTests extends ESTestCase {
assertPlugin("fake", pluginDir, env.v2());
}
public void testMetaPluginPolicyConfirmation() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path fake1Dir = metaDir.resolve("fake1");
Files.createDirectory(fake1Dir);
writePluginSecurityPolicy(fake1Dir, "setAccessible", "setFactory");
writePlugin("fake1", fake1Dir);
Path fake2Dir = metaDir.resolve("fake2");
Files.createDirectory(fake2Dir);
writePluginSecurityPolicy(fake2Dir, "setAccessible", "accessDeclaredMembers");
writePlugin("fake2", fake2Dir);
String pluginZip = createMetaPluginUrl("meta-plugin", metaDir);
assertPolicyConfirmation(env, pluginZip, "plugin requires additional permissions");
assertMetaPlugin("meta-plugin", "fake1", metaDir, env.v2());
assertMetaPlugin("meta-plugin", "fake2", metaDir, env.v2());
}
public void testPluginWithNativeController() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
@ -1250,21 +1040,4 @@ public class InstallPluginCommandTests extends ESTestCase {
final IllegalStateException e = expectThrows(IllegalStateException.class, () -> installPlugin(pluginZip, env.v1()));
assertThat(e, hasToString(containsString("plugins can not have native controllers")));
}
public void testMetaPluginWithNativeController() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path metaDir = createPluginDir(temp);
Path fake1Dir = metaDir.resolve("fake1");
Files.createDirectory(fake1Dir);
writePluginSecurityPolicy(fake1Dir, "setAccessible", "setFactory");
writePlugin("fake1", fake1Dir);
Path fake2Dir = metaDir.resolve("fake2");
Files.createDirectory(fake2Dir);
writePlugin("fake2", fake2Dir, "has.native.controller", "true");
String pluginZip = createMetaPluginUrl("meta-plugin", metaDir);
final IllegalStateException e = expectThrows(IllegalStateException.class, () -> installPlugin(pluginZip, env.v1()));
assertThat(e, hasToString(containsString("plugins can not have native controllers")));
}
}

View File

@ -92,16 +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);
}
private static void buildFakePlugin(
final Environment env,
final String metaPlugin,
final String description,
final String name,
final String classname) throws IOException {
buildFakePlugin(env, metaPlugin, description, name, classname, false);
buildFakePlugin(env, description, name, classname, false);
}
private static void buildFakePlugin(
@ -110,36 +101,15 @@ public class ListPluginsCommandTests extends ESTestCase {
final String name,
final String classname,
final boolean hasNativeController) throws IOException {
buildFakePlugin(env, null, description, name, classname, hasNativeController);
}
private static void buildFakePlugin(
final Environment env,
final String metaPlugin,
final String description,
final String name,
final String classname,
final boolean hasNativeController) throws IOException {
Path dest = metaPlugin != null ? env.pluginsFile().resolve(metaPlugin) : env.pluginsFile();
PluginTestUtil.writePluginProperties(
dest.resolve(name),
"description", description,
"name", name,
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", "1.8",
"classname", classname,
"has.native.controller", Boolean.toString(hasNativeController));
}
private static void buildFakeMetaPlugin(
final Environment env,
final String description,
final String name) throws IOException {
PluginTestUtil.writeMetaPluginProperties(
env.pluginsFile().resolve(name),
"description", description,
"name", name);
"name", name,
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", "1.8",
"classname", classname,
"has.native.controller", Boolean.toString(hasNativeController));
}
public void testPluginsDirMissing() throws Exception {
@ -166,16 +136,6 @@ public class ListPluginsCommandTests extends ESTestCase {
assertEquals(buildMultiline("fake1", "fake2"), terminal.getOutput());
}
public void testMetaPlugin() throws Exception {
buildFakeMetaPlugin(env, "fake meta desc", "meta_plugin");
buildFakePlugin(env, "meta_plugin", "fake desc", "fake1", "org.fake1");
buildFakePlugin(env, "meta_plugin", "fake desc 2", "fake2", "org.fake2");
buildFakePlugin(env, "fake desc 3", "fake3", "org.fake3");
buildFakePlugin(env, "fake desc 4", "fake4", "org.fake4");
MockTerminal terminal = listPlugins(home);
assertEquals(buildMultiline("fake3", "fake4", "meta_plugin", "\tfake1", "\tfake2"), terminal.getOutput());
}
public void testPluginWithVerbose() throws Exception {
buildFakePlugin(env, "fake desc", "fake_plugin", "org.fake");
String[] params = { "-v" };
@ -247,39 +207,6 @@ public class ListPluginsCommandTests extends ESTestCase {
terminal.getOutput());
}
public void testPluginWithVerboseMetaPlugins() throws Exception {
buildFakeMetaPlugin(env, "fake meta desc", "meta_plugin");
buildFakePlugin(env, "meta_plugin", "fake desc 1", "fake_plugin1", "org.fake");
buildFakePlugin(env, "meta_plugin", "fake desc 2", "fake_plugin2", "org.fake2");
String[] params = { "-v" };
MockTerminal terminal = listPlugins(home, params);
assertEquals(
buildMultiline(
"Plugins directory: " + env.pluginsFile(),
"meta_plugin",
"\tfake_plugin1",
"\t- Plugin information:",
"\tName: fake_plugin1",
"\tDescription: fake desc 1",
"\tVersion: 1.0",
"\tElasticsearch Version: " + Version.CURRENT.toString(),
"\tJava Version: 1.8",
"\tNative Controller: false",
"\tExtended Plugins: []",
"\t * Classname: org.fake",
"\tfake_plugin2",
"\t- Plugin information:",
"\tName: fake_plugin2",
"\tDescription: fake desc 2",
"\tVersion: 1.0",
"\tElasticsearch Version: " + Version.CURRENT.toString(),
"\tJava Version: 1.8",
"\tNative Controller: false",
"\tExtended Plugins: []",
"\t * Classname: org.fake2"),
terminal.getOutput());
}
public void testPluginWithoutVerboseMultiplePlugins() throws Exception {
buildFakePlugin(env, "fake desc 1", "fake_plugin1", "org.fake");
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
@ -307,19 +234,6 @@ public class ListPluginsCommandTests extends ESTestCase {
e.getMessage());
}
public void testMetaPluginWithWrongDescriptorFile() throws Exception{
buildFakeMetaPlugin(env, "fake meta desc", "meta_plugin");
final Path pluginDir = env.pluginsFile().resolve("meta_plugin").resolve("fake_plugin1");
PluginTestUtil.writePluginProperties(pluginDir, "description", "fake desc");
IllegalArgumentException e = expectThrows(
IllegalArgumentException.class,
() -> listPlugins(home));
final Path descriptorPath = pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES);
assertEquals(
"property [name] is missing in [" + descriptorPath.toString() + "]",
e.getMessage());
}
public void testExistingIncompatiblePlugin() throws Exception {
PluginTestUtil.writePluginProperties(env.pluginsFile().resolve("fake_plugin1"),
"description", "fake desc 1",
@ -340,27 +254,4 @@ public class ListPluginsCommandTests extends ESTestCase {
terminal = listPlugins(home, params);
assertEquals("fake_plugin1\nfake_plugin2\n", terminal.getOutput());
}
public void testExistingIncompatibleMetaPlugin() throws Exception {
buildFakeMetaPlugin(env, "fake meta desc", "meta_plugin");
PluginTestUtil.writePluginProperties(env.pluginsFile().resolve("meta_plugin").resolve("fake_plugin1"),
"description", "fake desc 1",
"name", "fake_plugin1",
"version", "1.0",
"elasticsearch.version", Version.fromString("1.0.0").toString(),
"java.version", System.getProperty("java.specification.version"),
"classname", "org.fake1");
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
MockTerminal terminal = listPlugins(home);
String message = "plugin [fake_plugin1] was built for Elasticsearch version 1.0 but version " + Version.CURRENT + " is required";
assertEquals(
"fake_plugin2\nmeta_plugin\n\tfake_plugin1\n" + "WARNING: " + message + "\n",
terminal.getOutput());
String[] params = {"-s"};
terminal = listPlugins(home, params);
assertEquals("fake_plugin2\nmeta_plugin\n\tfake_plugin1\n", terminal.getOutput());
}
}

View File

@ -103,16 +103,6 @@ public class RemovePluginCommandTests extends ESTestCase {
"classname", "SomeClass");
}
void createMetaPlugin(String name, String... plugins) throws Exception {
PluginTestUtil.writeMetaPluginProperties(
env.pluginsFile().resolve(name),
"description", "dummy",
"name", name);
for (String plugin : plugins) {
createPlugin(env.pluginsFile().resolve(name), plugin);
}
}
static MockTerminal removePlugin(String name, Path home, boolean purge) throws Exception {
Environment env = TestEnvironment.newEnvironment(Settings.builder().put("path.home", home).build());
MockTerminal terminal = new MockTerminal();
@ -159,19 +149,6 @@ public class RemovePluginCommandTests extends ESTestCase {
assertRemoveCleaned(env);
}
public void testBasicMeta() throws Exception {
createMetaPlugin("meta", "fake1");
createPlugin("other");
removePlugin("meta", home, randomBoolean());
assertFalse(Files.exists(env.pluginsFile().resolve("meta")));
assertTrue(Files.exists(env.pluginsFile().resolve("other")));
assertRemoveCleaned(env);
UserException exc =
expectThrows(UserException.class, () -> removePlugin("fake1", home, randomBoolean()));
assertThat(exc.getMessage(), containsString("plugin [fake1] not found"));
}
public void testBin() throws Exception {
createPlugin("fake");
Path binDir = env.binFile().resolve("fake");

View File

@ -13,8 +13,6 @@ The Elasticsearch repository contains examples of:
which contains a rescore plugin.
* a https://github.com/elastic/elasticsearch/tree/master/plugins/examples/script-expert-scoring[Java plugin]
which contains a script plugin.
* a https://github.com/elastic/elasticsearch/tree/master/plugins/examples/meta-plugin[Java plugin]
which contains a meta plugin.
These examples provide the bare bones needed to get started. For more
information about how to write a plugin, we recommend looking at the plugins
@ -120,19 +118,3 @@ AccessController.doPrivileged(
See http://www.oracle.com/technetwork/java/seccodeguide-139067.html[Secure Coding Guidelines for Java SE]
for more information.
[float]
=== Meta Plugin
It is also possible to bundle multiple plugins into a meta plugin.
A directory for each sub-plugin must be contained in a directory called `elasticsearch.
The meta plugin must also contain a file called `meta-plugin-descriptor.properties` in the directory named
`elasticsearch`.
The format for this file is described in detail in this example:
["source","properties",subs="attributes"]
--------------------------------------------------
include::{plugin-properties-files}/meta-plugin-descriptor.properties[]
--------------------------------------------------
A meta plugin can be installed/removed like a normal plugin with the `bin/elasticsearch-plugin` command.

View File

@ -1,28 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// A meta plugin packaging example that bundles multiple plugins in a single zip.
apply plugin: 'elasticsearch.es-meta-plugin'
es_meta_plugin {
name 'meta-plugin'
description 'example meta plugin'
plugins = ['dummy-plugin1', 'dummy-plugin2']
}

View File

@ -1,29 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
apply plugin: 'elasticsearch.esplugin'
esplugin {
name 'dummy-plugin1'
description 'A dummy plugin'
classname 'org.elasticsearch.example.DummyPlugin1'
}
test.enabled = false
integTestRunner.enabled = false

View File

@ -1,29 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.example;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.SearchPlugin;
import java.util.List;
import static java.util.Collections.singletonList;
public class DummyPlugin1 extends Plugin {}

View File

@ -1,29 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
apply plugin: 'elasticsearch.esplugin'
esplugin {
name 'dummy-plugin2'
description 'Another dummy plugin'
classname 'org.elasticsearch.example.DummyPlugin2'
}
test.enabled = false
integTestRunner.enabled = false

View File

@ -1,29 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.example;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.SearchPlugin;
import java.util.List;
import static java.util.Collections.singletonList;
public class DummyPlugin2 extends Plugin {}

View File

@ -1,4 +0,0 @@
# The name of the meta plugin
name=my_meta_plugin
# The description of the meta plugin
description=A meta plugin example

View File

@ -1,39 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
public class SmokeTestPluginsClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestPluginsClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws Exception {
return ESClientYamlSuiteTestCase.createParameters();
}
}

View File

@ -1,14 +0,0 @@
# Integration tests for testing meta plugins
#
"Check meta plugin install":
- do:
cluster.state: {}
# Get master node id
- set: { master_node: master }
- do:
nodes.info: {}
- match: { nodes.$master.plugins.0.name: dummy-plugin1 }
- match: { nodes.$master.plugins.1.name: dummy-plugin2 }

View File

@ -170,91 +170,6 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
}
}
/**
* Two plugins in a meta module - one with a controller daemon and one without.
*/
public void testControllerSpawnMeta() throws Exception {
runTestControllerSpawnMeta(Environment::pluginsFile, false);
runTestControllerSpawnMeta(Environment::modulesFile, true);
}
private void runTestControllerSpawnMeta(
final Function<Environment, Path> pluginsDirFinder, final boolean expectSpawn) throws Exception {
/*
* On Windows you can not directly run a batch file - you have to run cmd.exe with the batch
* file as an argument and that's out of the remit of the controller daemon process spawner.
*/
assumeFalse("This test does not work on Windows", Constants.WINDOWS);
Path esHome = createTempDir().resolve("esHome");
Settings.Builder settingsBuilder = Settings.builder();
settingsBuilder.put(Environment.PATH_HOME_SETTING.getKey(), esHome.toString());
Settings settings = settingsBuilder.build();
Environment environment = TestEnvironment.newEnvironment(settings);
Path metaModule = pluginsDirFinder.apply(environment).resolve("meta_module");
Files.createDirectories(environment.modulesFile());
Files.createDirectories(metaModule);
PluginTestUtil.writeMetaPluginProperties(
metaModule,
"description", "test_plugin",
"name", "meta_plugin",
"plugins", "test_plugin,other_plugin");
// this plugin will have a controller daemon
Path plugin = metaModule.resolve("test_plugin");
Files.createDirectories(plugin);
PluginTestUtil.writePluginProperties(
plugin,
"description", "test_plugin",
"version", Version.CURRENT.toString(),
"elasticsearch.version", Version.CURRENT.toString(),
"name", "test_plugin",
"java.version", "1.8",
"classname", "TestPlugin",
"has.native.controller", "true");
Path controllerProgram = Platforms.nativeControllerPath(plugin);
createControllerProgram(controllerProgram);
// this plugin will not have a controller daemon
Path otherPlugin = metaModule.resolve("other_plugin");
Files.createDirectories(otherPlugin);
PluginTestUtil.writePluginProperties(
otherPlugin,
"description", "other_plugin",
"version", Version.CURRENT.toString(),
"elasticsearch.version", Version.CURRENT.toString(),
"name", "other_plugin",
"java.version", "1.8",
"classname", "OtherPlugin",
"has.native.controller", "false");
Spawner spawner = new Spawner();
spawner.spawnNativeControllers(environment);
List<Process> processes = spawner.getProcesses();
if (expectSpawn) {
// as there should only be a reference in the list for the plugin that had the controller daemon, we expect one here
assertThat(processes, hasSize(1));
Process process = processes.get(0);
final InputStreamReader in =
new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8);
try (BufferedReader stdoutReader = new BufferedReader(in)) {
String line = stdoutReader.readLine();
assertEquals("I am alive", line);
spawner.close();
// fail if the process does not die within one second; usually it will be even quicker but it depends on OS scheduling
assertTrue(process.waitFor(1, TimeUnit.SECONDS));
}
} else {
assertThat(processes, hasSize(0));
}
}
public void testControllerSpawnWithIncorrectDescriptor() throws IOException {
// this plugin will have a controller daemon
Path esHome = createTempDir().resolve("esHome");

View File

@ -1,149 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.plugins;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* An in-memory representation of the meta plugin descriptor.
*/
public class MetaPluginInfo {
static final String ES_META_PLUGIN_PROPERTIES = "meta-plugin-descriptor.properties";
private final String name;
private final String description;
/**
* Construct plugin info.
*
* @param name the name of the plugin
* @param description a description of the plugin
*/
private MetaPluginInfo(String name, String description) {
this.name = name;
this.description = description;
}
/**
* @return Whether the provided {@code path} is a meta plugin.
*/
public static boolean isMetaPlugin(final Path path) {
return Files.exists(path.resolve(ES_META_PLUGIN_PROPERTIES));
}
/**
* @return Whether the provided {@code path} is a meta properties file.
*/
public static boolean isPropertiesFile(final Path path) {
return ES_META_PLUGIN_PROPERTIES.equals(path.getFileName().toString());
}
/** reads (and validates) meta plugin metadata descriptor file */
/**
* Reads and validates the meta plugin descriptor file.
*
* @param path the path to the root directory for the meta plugin
* @return the meta plugin info
* @throws IOException if an I/O exception occurred reading the meta plugin descriptor
*/
public static MetaPluginInfo readFromProperties(final Path path) throws IOException {
final Path descriptor = path.resolve(ES_META_PLUGIN_PROPERTIES);
final Map<String, String> propsMap;
{
final Properties props = new Properties();
try (InputStream stream = Files.newInputStream(descriptor)) {
props.load(stream);
}
propsMap = props.stringPropertyNames().stream().collect(Collectors.toMap(Function.identity(), props::getProperty));
}
final String name = propsMap.remove("name");
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException(
"property [name] is missing for meta plugin in [" + descriptor + "]");
}
final String description = propsMap.remove("description");
if (description == null) {
throw new IllegalArgumentException(
"property [description] is missing for meta plugin [" + name + "]");
}
if (propsMap.isEmpty() == false) {
throw new IllegalArgumentException("Unknown properties in meta plugin descriptor: " + propsMap.keySet());
}
return new MetaPluginInfo(name, description);
}
/**
* The name of the meta plugin.
*
* @return the meta plugin name
*/
public String getName() {
return name;
}
/**
* The description of the meta plugin.
*
* @return the meta plugin description
*/
public String getDescription() {
return description;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MetaPluginInfo that = (MetaPluginInfo) o;
if (!name.equals(that.name)) return false;
return true;
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
final StringBuilder information = new StringBuilder()
.append("- Plugin information:\n")
.append("Name: ").append(name).append("\n")
.append("Description: ").append(description);
return information.toString();
}
}

View File

@ -140,16 +140,12 @@ public class PluginsService extends AbstractComponent {
// TODO: remove this leniency, but tests bogusly rely on it
if (isAccessibleDirectory(pluginsDirectory, logger)) {
checkForFailedPluginRemovals(pluginsDirectory);
// call findBundles directly to get the meta plugin names
List<BundleCollection> plugins = findBundles(pluginsDirectory, "plugin");
for (final BundleCollection plugin : plugins) {
final Collection<Bundle> bundles = plugin.bundles();
for (final Bundle bundle : bundles) {
pluginsList.add(bundle.plugin);
}
seenBundles.addAll(bundles);
pluginsNames.add(plugin.name());
Set<Bundle> plugins = getPluginBundles(pluginsDirectory);
for (final Bundle bundle : plugins) {
pluginsList.add(bundle.plugin);
pluginsNames.add(bundle.plugin.getName());
}
seenBundles.addAll(plugins);
}
} catch (IOException ex) {
throw new IllegalStateException("Unable to initialize plugins", ex);
@ -253,17 +249,8 @@ public class PluginsService extends AbstractComponent {
return info;
}
/**
* An abstraction over a single plugin and meta-plugins.
*/
interface BundleCollection {
String name();
Collection<Bundle> bundles();
}
// a "bundle" is a group of plugins in a single classloader
// really should be 1-1, but we are not so fortunate
static class Bundle implements BundleCollection {
// a "bundle" is a group of jars in a single classloader
static class Bundle {
final PluginInfo plugin;
final Set<URL> urls;
@ -283,16 +270,6 @@ public class PluginsService extends AbstractComponent {
this.urls = Objects.requireNonNull(urls);
}
@Override
public String name() {
return plugin.getName();
}
@Override
public Collection<Bundle> bundles() {
return Collections.singletonList(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -308,87 +285,30 @@ public class PluginsService extends AbstractComponent {
}
/**
* Represents a meta-plugin and the {@link Bundle}s corresponding to its constituents.
*/
static class MetaBundle implements BundleCollection {
private final String name;
private final List<Bundle> bundles;
MetaBundle(final String name, final List<Bundle> bundles) {
this.name = name;
this.bundles = bundles;
}
@Override
public String name() {
return name;
}
@Override
public Collection<Bundle> bundles() {
return bundles;
}
}
/**
* Extracts all installed plugin directories from the provided {@code rootPath} expanding meta-plugins if needed.
* Extracts all installed plugin directories from the provided {@code rootPath}.
*
* @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 Tuple<List<Path>, Map<String, List<Path>>> groupedPluginDirs = findGroupedPluginDirs(rootPath);
return Stream.concat(
groupedPluginDirs.v1().stream(),
groupedPluginDirs.v2().values().stream().flatMap(Collection::stream))
.collect(Collectors.toList());
}
/**
* Extracts all installed plugin directories from the provided {@code rootPath} expanding meta-plugins if needed. The plugins are
* grouped into plugins and meta-plugins. The meta-plugins are keyed by the meta-plugin name.
*
* @param rootPath the path where the plugins are installed
* @return a tuple of plugins as the first component and meta-plugins keyed by meta-plugin name as the second component
* @throws IOException if an I/O exception occurred reading the directories
*/
private static Tuple<List<Path>, Map<String, List<Path>>> findGroupedPluginDirs(final Path rootPath) throws IOException {
final List<Path> plugins = new ArrayList<>();
final Map<String, List<Path>> metaPlugins = new LinkedHashMap<>();
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(".removing-")) {
continue;
}
if (seen.add(plugin.getFileName().toString()) == false) {
throw new IllegalStateException("duplicate plugin: " + plugin);
}
if (MetaPluginInfo.isMetaPlugin(plugin)) {
final String name = plugin.getFileName().toString();
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);
}
metaPlugins.computeIfAbsent(name, n -> new ArrayList<>()).add(subPlugin);
}
}
} else {
plugins.add(plugin);
}
plugins.add(plugin);
}
}
}
return Tuple.tuple(plugins, metaPlugins);
return plugins;
}
/**
@ -425,32 +345,21 @@ public class PluginsService extends AbstractComponent {
/** Get bundles for plugins installed in the given modules directory. */
static Set<Bundle> getModuleBundles(Path modulesDirectory) throws IOException {
return findBundles(modulesDirectory, "module").stream().flatMap(b -> b.bundles().stream()).collect(Collectors.toSet());
return findBundles(modulesDirectory, "module");
}
/** Get bundles for plugins installed in the given plugins directory. */
static Set<Bundle> getPluginBundles(final Path pluginsDirectory) throws IOException {
return findBundles(pluginsDirectory, "plugin").stream().flatMap(b -> b.bundles().stream()).collect(Collectors.toSet());
return findBundles(pluginsDirectory, "plugin");
}
// searches subdirectories under the given directory for plugin directories
private static List<BundleCollection> findBundles(final Path directory, String type) throws IOException {
final List<BundleCollection> bundles = new ArrayList<>();
final Set<Bundle> seenBundles = new HashSet<>();
final Tuple<List<Path>, Map<String, List<Path>>> groupedPluginDirs = findGroupedPluginDirs(directory);
for (final Path plugin : groupedPluginDirs.v1()) {
final Bundle bundle = readPluginBundle(seenBundles, plugin, type);
private static Set<Bundle> findBundles(final Path directory, String type) throws IOException {
final Set<Bundle> bundles = new HashSet<>();
for (final Path plugin : findPluginDirs(directory)) {
final Bundle bundle = readPluginBundle(bundles, plugin, type);
bundles.add(bundle);
}
for (final Map.Entry<String, List<Path>> metaPlugin : groupedPluginDirs.v2().entrySet()) {
final List<Bundle> metaPluginBundles = new ArrayList<>();
for (final Path metaPluginPlugin : metaPlugin.getValue()) {
final Bundle bundle = readPluginBundle(seenBundles, metaPluginPlugin, type);
metaPluginBundles.add(bundle);
}
final MetaBundle metaBundle = new MetaBundle(metaPlugin.getKey(), metaPluginBundles);
bundles.add(metaBundle);
}
return bundles;
}

View File

@ -1,120 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.plugins;
import org.apache.lucene.util.LuceneTestCase;
import org.elasticsearch.Version;
import org.elasticsearch.test.ESTestCase;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
@LuceneTestCase.SuppressFileSystems(value = "ExtrasFS")
public class MetaPluginInfoTests extends ESTestCase {
public void testReadFromProperties() throws Exception {
Path pluginDir = createTempDir().resolve("fake-meta-plugin");
PluginTestUtil.writeMetaPluginProperties(pluginDir,
"description", "fake desc",
"name", "my_meta_plugin");
MetaPluginInfo info = MetaPluginInfo.readFromProperties(pluginDir);
assertEquals("my_meta_plugin", info.getName());
assertEquals("fake desc", info.getDescription());
}
public void testReadFromPropertiesNameMissing() throws Exception {
Path pluginDir = createTempDir().resolve("fake-meta-plugin");
PluginTestUtil.writeMetaPluginProperties(pluginDir);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> MetaPluginInfo.readFromProperties(pluginDir));
assertThat(e.getMessage(), containsString("property [name] is missing for"));
PluginTestUtil.writeMetaPluginProperties(pluginDir, "name", "");
e = expectThrows(IllegalArgumentException.class, () -> MetaPluginInfo.readFromProperties(pluginDir));
assertThat(e.getMessage(), containsString("property [name] is missing for"));
}
public void testReadFromPropertiesDescriptionMissing() throws Exception {
Path pluginDir = createTempDir().resolve("fake-meta-plugin");
PluginTestUtil.writeMetaPluginProperties(pluginDir, "name", "fake-meta-plugin");
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> MetaPluginInfo.readFromProperties(pluginDir));
assertThat(e.getMessage(), containsString("[description] is missing"));
}
public void testUnknownProperties() throws Exception {
Path pluginDir = createTempDir().resolve("fake-meta-plugin");
PluginTestUtil.writeMetaPluginProperties(pluginDir,
"extra", "property",
"unknown", "property",
"description", "fake desc",
"name", "my_meta_plugin");
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> MetaPluginInfo.readFromProperties(pluginDir));
assertThat(e.getMessage(), containsString("Unknown properties in meta plugin descriptor"));
}
public void testExtractAllPluginsWithDuplicates() throws Exception {
Path pluginDir = createTempDir().resolve("plugins");
// Simple plugin
Path plugin1 = pluginDir.resolve("plugin1");
Files.createDirectories(plugin1);
PluginTestUtil.writePluginProperties(plugin1,
"description", "fake desc",
"name", "plugin1",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"classname", "FakePlugin");
// Meta plugin
Path metaPlugin = pluginDir.resolve("meta_plugin");
Files.createDirectory(metaPlugin);
PluginTestUtil.writeMetaPluginProperties(metaPlugin,
"description", "fake desc",
"name", "meta_plugin");
Path plugin2 = metaPlugin.resolve("plugin1");
Files.createDirectory(plugin2);
PluginTestUtil.writePluginProperties(plugin2,
"description", "fake desc",
"name", "plugin1",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"classname", "FakePlugin");
Path plugin3 = metaPlugin.resolve("plugin2");
Files.createDirectory(plugin3);
PluginTestUtil.writePluginProperties(plugin3,
"description", "fake desc",
"name", "plugin2",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"classname", "FakePlugin");
IllegalStateException exc =
expectThrows(IllegalStateException.class, () -> PluginsService.findPluginDirs(pluginDir));
assertThat(exc.getMessage(), containsString("duplicate plugin"));
assertThat(exc.getMessage(), endsWith("plugin1"));
}
}

View File

@ -620,34 +620,7 @@ public class PluginsServiceTests extends ESTestCase {
Files.copy(jar, fake.resolve("plugin.jar"));
}
final Path fakeMeta = plugins.resolve("fake-meta");
PluginTestUtil.writeMetaPluginProperties(fakeMeta, "description", "description", "name", "fake-meta");
final Path fakeMetaCore = fakeMeta.resolve("fake-meta-core");
PluginTestUtil.writePluginProperties(
fakeMetaCore,
"description", "description",
"name", "fake-meta-core",
"version", "1.0.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"classname", "test.DummyPlugin");
try (InputStream jar = PluginsServiceTests.class.getResourceAsStream("dummy-plugin.jar")) {
Files.copy(jar, fakeMetaCore.resolve("plugin.jar"));
}
assertThat(PluginsService.findPluginDirs(plugins), containsInAnyOrder(fake, fakeMetaCore));
}
public void testMissingMandatoryPlugin() {
final Settings settings =
Settings.builder()
.put("path.home", createTempDir())
.put("plugin.mandatory", "fake")
.build();
final IllegalStateException e = expectThrows(IllegalStateException.class, () -> newPluginsService(settings));
assertThat(e, hasToString(containsString("missing mandatory plugins [fake]")));
assertThat(PluginsService.findPluginDirs(plugins), containsInAnyOrder(fake));
}
public void testExistingMandatoryClasspathPlugin() {
@ -696,38 +669,4 @@ public class PluginsServiceTests extends ESTestCase {
.build();
newPluginsService(settings);
}
public void testExistingMandatoryMetaPlugin() throws IOException {
// This test opens a child classloader, reading a jar under the test temp
// dir (a dummy plugin). Classloaders are closed by GC, so when test teardown
// occurs the jar is deleted while the classloader is still open. However, on
// windows, files cannot be deleted when they are still open by a process.
assumeFalse("windows deletion behavior is asinine", Constants.WINDOWS);
final Path pathHome = createTempDir();
final Path plugins = pathHome.resolve("plugins");
final Path fakeMeta = plugins.resolve("fake-meta");
PluginTestUtil.writeMetaPluginProperties(fakeMeta, "description", "description", "name", "fake-meta");
final Path fake = fakeMeta.resolve("fake");
PluginTestUtil.writePluginProperties(
fake,
"description", "description",
"name", "fake",
"version", "1.0.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"classname", "test.DummyPlugin");
try (InputStream jar = PluginsServiceTests.class.getResourceAsStream("dummy-plugin.jar")) {
Files.copy(jar, fake.resolve("plugin.jar"));
}
final Settings settings =
Settings.builder()
.put("path.home", pathHome)
.put("plugin.mandatory", "fake-meta")
.build();
newPluginsService(settings);
}
}

View File

@ -27,9 +27,6 @@ import java.util.Properties;
/** Utility methods for testing plugins */
public class PluginTestUtil {
public static void writeMetaPluginProperties(Path pluginDir, String... stringProps) throws IOException {
writeProperties(pluginDir.resolve(MetaPluginInfo.ES_META_PLUGIN_PROPERTIES), stringProps);
}
public static void writePluginProperties(Path pluginDir, String... stringProps) throws IOException {
writeProperties(pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES), stringProps);

View File

@ -1,6 +1,5 @@
import org.elasticsearch.gradle.LoggedExec
import org.elasticsearch.gradle.MavenFilteringHack
import org.elasticsearch.gradle.plugin.MetaPluginBuildPlugin
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
import org.elasticsearch.gradle.test.NodeInfo

View File

@ -1,8 +1,3 @@
import org.elasticsearch.gradle.plugin.MetaPluginBuildPlugin
import org.elasticsearch.gradle.plugin.MetaPluginPropertiesExtension
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
import org.elasticsearch.gradle.plugin.PluginPropertiesExtension
apply plugin: 'elasticsearch.vagrantsupport'
apply plugin: 'elasticsearch.vagrant'