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:
parent
e750462e0c
commit
b3f3a4312b
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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}
|
|
@ -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);
|
||||
}
|
||||
} 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;
|
||||
|
|
|
@ -61,27 +61,9 @@ 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, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printPlugin(Environment env, Terminal terminal, Path plugin, String prefix) throws IOException {
|
||||
terminal.println(Terminal.Verbosity.SILENT, prefix + plugin.getFileName().toString());
|
||||
|
|
|
@ -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")));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,19 +101,8 @@ 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),
|
||||
env.pluginsFile().resolve(name),
|
||||
"description", description,
|
||||
"name", name,
|
||||
"version", "1.0",
|
||||
|
@ -132,16 +112,6 @@ public class ListPluginsCommandTests extends ESTestCase {
|
|||
"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);
|
||||
}
|
||||
|
||||
public void testPluginsDirMissing() throws Exception {
|
||||
Files.delete(env.pluginsFile());
|
||||
IOException e = expectThrows(IOException.class, () -> listPlugins(home));
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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']
|
||||
}
|
|
@ -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
|
|
@ -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 {}
|
|
@ -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
|
|
@ -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 {}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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 }
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
Set<Bundle> plugins = getPluginBundles(pluginsDirectory);
|
||||
for (final Bundle bundle : plugins) {
|
||||
pluginsList.add(bundle.plugin);
|
||||
pluginsNames.add(bundle.plugin.getName());
|
||||
}
|
||||
seenBundles.addAll(bundles);
|
||||
pluginsNames.add(plugin.name());
|
||||
}
|
||||
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,55 +285,14 @@ 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)) {
|
||||
|
@ -368,27 +304,11 @@ public class PluginsService extends AbstractComponent {
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
Loading…
Reference in New Issue