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.LoggedExec
|
||||||
import org.elasticsearch.gradle.Version
|
import org.elasticsearch.gradle.Version
|
||||||
import org.elasticsearch.gradle.VersionProperties
|
import org.elasticsearch.gradle.VersionProperties
|
||||||
import org.elasticsearch.gradle.plugin.MetaPluginBuildPlugin
|
|
||||||
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
|
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
|
||||||
import org.elasticsearch.gradle.plugin.PluginPropertiesExtension
|
import org.elasticsearch.gradle.plugin.PluginPropertiesExtension
|
||||||
import org.gradle.api.AntBuilder
|
import org.gradle.api.AntBuilder
|
||||||
|
@ -842,19 +842,15 @@ class ClusterFormationTasks {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verifyProjectHasBuildPlugin(String name, Version version, Project project, Project pluginProject) {
|
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 " +
|
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) {
|
static String findPluginName(Project pluginProject) {
|
||||||
PluginPropertiesExtension extension = pluginProject.extensions.findByName('esplugin')
|
PluginPropertiesExtension extension = pluginProject.extensions.findByName('esplugin')
|
||||||
if (extension != null) {
|
|
||||||
return extension.name
|
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>
|
* <li>A URL to a plugin zip</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* Plugins are packaged as zip files. Each packaged plugin must contain a plugin properties file
|
* 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.
|
* See {@link PluginInfo}.
|
||||||
* <p>
|
* <p>
|
||||||
* The installation process first extracts the plugin files into a temporary
|
* The installation process first extracts the plugin files into a temporary
|
||||||
* directory in order to verify the plugin satisfies the following requirements:
|
* 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
|
* 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
|
* elasticsearch config directory, using the name of the plugin. If any files to be installed
|
||||||
* already exist, they will be skipped.
|
* 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 {
|
class InstallPluginCommand extends EnvironmentAwareCommand {
|
||||||
|
|
||||||
|
@ -550,7 +545,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checking for existing version of the plugin
|
// 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...
|
// don't let user install plugin conflicting with module...
|
||||||
// they might be unavoidably in maven central and are packaged up the same way)
|
// they might be unavoidably in maven central and are packaged up the same way)
|
||||||
if (MODULES.contains(pluginName)) {
|
if (MODULES.contains(pluginName)) {
|
||||||
|
@ -567,28 +562,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
||||||
pluginName);
|
pluginName);
|
||||||
throw new UserException(PLUGIN_EXISTS, message);
|
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. */
|
/** 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);
|
final PluginInfo info = PluginInfo.readFromProperties(pluginRoot);
|
||||||
if (info.hasNativeController()) {
|
if (info.hasNativeController()) {
|
||||||
throw new IllegalStateException("plugins can not have native controllers");
|
throw new IllegalStateException("plugins can not have native controllers");
|
||||||
|
@ -596,7 +573,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
||||||
PluginsService.verifyCompatibility(info);
|
PluginsService.verifyCompatibility(info);
|
||||||
|
|
||||||
// checking for existing version of the plugin
|
// checking for existing version of the plugin
|
||||||
verifyPluginName(env.pluginsFile(), info.getName(), pluginRoot);
|
verifyPluginName(env.pluginsFile(), info.getName());
|
||||||
|
|
||||||
PluginsService.checkForFailedPluginRemovals(env.pluginsFile());
|
PluginsService.checkForFailedPluginRemovals(env.pluginsFile());
|
||||||
|
|
||||||
|
@ -635,11 +612,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
||||||
List<Path> deleteOnFailure = new ArrayList<>();
|
List<Path> deleteOnFailure = new ArrayList<>();
|
||||||
deleteOnFailure.add(tmpRoot);
|
deleteOnFailure.add(tmpRoot);
|
||||||
try {
|
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) {
|
} catch (Exception installProblem) {
|
||||||
try {
|
try {
|
||||||
IOUtils.rm(deleteOnFailure.toArray(new Path[0]));
|
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.
|
* 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.
|
* If the plugin has a bin dir and/or a config dir, those are moved.
|
||||||
*/
|
*/
|
||||||
private void installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot,
|
private void installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot,
|
||||||
Environment env, List<Path> deleteOnFailure) throws Exception {
|
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
|
// read optional security policy (extra permissions), if it exists, confirm or warn the user
|
||||||
Path policy = tmpRoot.resolve(PluginInfo.ES_PLUGIN_POLICY);
|
Path policy = tmpRoot.resolve(PluginInfo.ES_PLUGIN_POLICY);
|
||||||
final Set<String> permissions;
|
final Set<String> permissions;
|
||||||
|
|
|
@ -61,27 +61,9 @@ class ListPluginsCommand extends EnvironmentAwareCommand {
|
||||||
}
|
}
|
||||||
Collections.sort(plugins);
|
Collections.sort(plugins);
|
||||||
for (final Path plugin : 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, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void printPlugin(Environment env, Terminal terminal, Path plugin, String prefix) throws IOException {
|
private void printPlugin(Environment env, Terminal terminal, Path plugin, String prefix) throws IOException {
|
||||||
terminal.println(Terminal.Verbosity.SILENT, prefix + plugin.getFileName().toString());
|
terminal.println(Terminal.Verbosity.SILENT, prefix + plugin.getFileName().toString());
|
||||||
|
|
|
@ -219,18 +219,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
return createPlugin(name, structure, additionalProps).toUri().toURL().toString();
|
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 {
|
static void writePlugin(String name, Path structure, String... additionalProps) throws IOException {
|
||||||
String[] properties = Stream.concat(Stream.of(
|
String[] properties = Stream.concat(Stream.of(
|
||||||
"description", "fake desc",
|
"description", "fake desc",
|
||||||
|
@ -261,11 +249,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
return writeZip(structure, null);
|
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 {
|
void installPlugin(String pluginUrl, Path home) throws Exception {
|
||||||
installPlugin(pluginUrl, home, skipJarHellCommand);
|
installPlugin(pluginUrl, home, skipJarHellCommand);
|
||||||
}
|
}
|
||||||
|
@ -275,11 +258,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
command.execute(terminal, pluginUrl, false, env);
|
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 {
|
void assertPlugin(String name, Path original, Environment env) throws IOException {
|
||||||
assertPluginInternal(name, env.pluginsFile());
|
assertPluginInternal(name, env.pluginsFile());
|
||||||
assertConfigAndBin(name, original, env);
|
assertConfigAndBin(name, original, env);
|
||||||
|
@ -388,23 +366,9 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
assertPlugin("fake", pluginDir, env.v2());
|
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 {
|
public void testInstallFailsIfPreviouslyRemovedPluginFailed() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path metaDir = createPluginDir(temp);
|
Path pluginDir = createPluginDir(temp);
|
||||||
Path pluginDir = metaDir.resolve("fake");
|
|
||||||
String pluginZip = createPluginUrl("fake", pluginDir);
|
String pluginZip = createPluginUrl("fake", pluginDir);
|
||||||
final Path removing = env.v2().pluginsFile().resolve(".removing-failed");
|
final Path removing = env.v2().pluginsFile().resolve(".removing-failed");
|
||||||
Files.createDirectory(removing);
|
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]",
|
"found file [%s] from a failed attempt to remove the plugin [failed]; execute [elasticsearch-plugin remove failed]",
|
||||||
removing);
|
removing);
|
||||||
assertThat(e, hasToString(containsString(expected)));
|
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 {
|
public void testSpaceInUrl() throws Exception {
|
||||||
|
@ -500,23 +459,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
assertInstallCleaned(environment.v2());
|
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 {
|
public void testIsolatedPlugins() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
// these both share the same FakePlugin class
|
// these both share the same FakePlugin class
|
||||||
|
@ -540,23 +482,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
assertInstallCleaned(env.v2());
|
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 {
|
public void testBin() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path pluginDir = createPluginDir(temp);
|
Path pluginDir = createPluginDir(temp);
|
||||||
|
@ -568,43 +493,20 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
assertPlugin("fake", pluginDir, env.v2());
|
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 {
|
public void testBinNotDir() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path metaDir = createPluginDir(temp);
|
Path pluginDir = createPluginDir(temp);
|
||||||
Path pluginDir = metaDir.resolve("fake");
|
|
||||||
Files.createDirectory(pluginDir);
|
|
||||||
Path binDir = pluginDir.resolve("bin");
|
Path binDir = pluginDir.resolve("bin");
|
||||||
Files.createFile(binDir);
|
Files.createFile(binDir);
|
||||||
String pluginZip = createPluginUrl("fake", pluginDir);
|
String pluginZip = createPluginUrl("fake", pluginDir);
|
||||||
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
|
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
|
||||||
assertTrue(e.getMessage(), e.getMessage().contains("not a directory"));
|
assertTrue(e.getMessage(), e.getMessage().contains("not a directory"));
|
||||||
assertInstallCleaned(env.v2());
|
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 {
|
public void testBinContainsDir() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path metaDir = createPluginDir(temp);
|
Path pluginDir = createPluginDir(temp);
|
||||||
Path pluginDir = metaDir.resolve("fake");
|
|
||||||
Files.createDirectory(pluginDir);
|
|
||||||
Path dirInBinDir = pluginDir.resolve("bin").resolve("foo");
|
Path dirInBinDir = pluginDir.resolve("bin").resolve("foo");
|
||||||
Files.createDirectories(dirInBinDir);
|
Files.createDirectories(dirInBinDir);
|
||||||
Files.createFile(dirInBinDir.resolve("somescript"));
|
Files.createFile(dirInBinDir.resolve("somescript"));
|
||||||
|
@ -612,11 +514,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
|
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
|
||||||
assertTrue(e.getMessage(), e.getMessage().contains("Directories not allowed in bin dir for plugin"));
|
assertTrue(e.getMessage(), e.getMessage().contains("Directories not allowed in bin dir for plugin"));
|
||||||
assertInstallCleaned(env.v2());
|
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 {
|
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 {
|
public void testPluginPermissions() throws Exception {
|
||||||
assumeTrue("posix filesystem", isPosix);
|
assumeTrue("posix filesystem", isPosix);
|
||||||
|
|
||||||
|
@ -761,32 +637,9 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
assertTrue(Files.exists(envConfigDir.resolve("other.yml")));
|
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 {
|
public void testConfigNotDir() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path metaDir = createPluginDir(temp);
|
Path pluginDir = createPluginDir(temp);
|
||||||
Path pluginDir = metaDir.resolve("fake");
|
|
||||||
Files.createDirectories(pluginDir);
|
Files.createDirectories(pluginDir);
|
||||||
Path configDir = pluginDir.resolve("config");
|
Path configDir = pluginDir.resolve("config");
|
||||||
Files.createFile(configDir);
|
Files.createFile(configDir);
|
||||||
|
@ -794,11 +647,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
|
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
|
||||||
assertTrue(e.getMessage(), e.getMessage().contains("not a directory"));
|
assertTrue(e.getMessage(), e.getMessage().contains("not a directory"));
|
||||||
assertInstallCleaned(env.v2());
|
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 {
|
public void testConfigContainsDir() throws Exception {
|
||||||
|
@ -815,19 +663,12 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
|
|
||||||
public void testMissingDescriptor() throws Exception {
|
public void testMissingDescriptor() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path metaDir = createPluginDir(temp);
|
Path pluginDir = createPluginDir(temp);
|
||||||
Path pluginDir = metaDir.resolve("fake");
|
|
||||||
Files.createDirectory(pluginDir);
|
|
||||||
Files.createFile(pluginDir.resolve("fake.yml"));
|
Files.createFile(pluginDir.resolve("fake.yml"));
|
||||||
String pluginZip = writeZip(pluginDir, null).toUri().toURL().toString();
|
String pluginZip = writeZip(pluginDir, null).toUri().toURL().toString();
|
||||||
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> installPlugin(pluginZip, env.v1()));
|
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> installPlugin(pluginZip, env.v1()));
|
||||||
assertTrue(e.getMessage(), e.getMessage().contains("plugin-descriptor.properties"));
|
assertTrue(e.getMessage(), e.getMessage().contains("plugin-descriptor.properties"));
|
||||||
assertInstallCleaned(env.v2());
|
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 {
|
public void testContainsIntermediateDirectory() throws Exception {
|
||||||
|
@ -840,16 +681,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
assertInstallCleaned(env.v2());
|
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 {
|
public void testZipRelativeOutsideEntryName() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path zip = createTempDir().resolve("broken.zip");
|
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'"));
|
"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 {
|
private void installPlugin(MockTerminal terminal, boolean isBatch) throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path pluginDir = createPluginDir(temp);
|
Path pluginDir = createPluginDir(temp);
|
||||||
|
@ -1224,24 +1032,6 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
assertPlugin("fake", pluginDir, env.v2());
|
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 {
|
public void testPluginWithNativeController() throws Exception {
|
||||||
Tuple<Path, Environment> env = createEnv(fs, temp);
|
Tuple<Path, Environment> env = createEnv(fs, temp);
|
||||||
Path pluginDir = createPluginDir(temp);
|
Path pluginDir = createPluginDir(temp);
|
||||||
|
@ -1250,21 +1040,4 @@ public class InstallPluginCommandTests extends ESTestCase {
|
||||||
final IllegalStateException e = expectThrows(IllegalStateException.class, () -> installPlugin(pluginZip, env.v1()));
|
final IllegalStateException e = expectThrows(IllegalStateException.class, () -> installPlugin(pluginZip, env.v1()));
|
||||||
assertThat(e, hasToString(containsString("plugins can not have native controllers")));
|
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 description,
|
||||||
final String name,
|
final String name,
|
||||||
final String classname) throws IOException {
|
final String classname) throws IOException {
|
||||||
buildFakePlugin(env, null, description, name, classname, false);
|
buildFakePlugin(env, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void buildFakePlugin(
|
private static void buildFakePlugin(
|
||||||
|
@ -110,19 +101,8 @@ public class ListPluginsCommandTests extends ESTestCase {
|
||||||
final String name,
|
final String name,
|
||||||
final String classname,
|
final String classname,
|
||||||
final boolean hasNativeController) throws IOException {
|
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(
|
PluginTestUtil.writePluginProperties(
|
||||||
dest.resolve(name),
|
env.pluginsFile().resolve(name),
|
||||||
"description", description,
|
"description", description,
|
||||||
"name", name,
|
"name", name,
|
||||||
"version", "1.0",
|
"version", "1.0",
|
||||||
|
@ -132,16 +112,6 @@ public class ListPluginsCommandTests extends ESTestCase {
|
||||||
"has.native.controller", Boolean.toString(hasNativeController));
|
"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 {
|
public void testPluginsDirMissing() throws Exception {
|
||||||
Files.delete(env.pluginsFile());
|
Files.delete(env.pluginsFile());
|
||||||
IOException e = expectThrows(IOException.class, () -> listPlugins(home));
|
IOException e = expectThrows(IOException.class, () -> listPlugins(home));
|
||||||
|
@ -166,16 +136,6 @@ public class ListPluginsCommandTests extends ESTestCase {
|
||||||
assertEquals(buildMultiline("fake1", "fake2"), terminal.getOutput());
|
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 {
|
public void testPluginWithVerbose() throws Exception {
|
||||||
buildFakePlugin(env, "fake desc", "fake_plugin", "org.fake");
|
buildFakePlugin(env, "fake desc", "fake_plugin", "org.fake");
|
||||||
String[] params = { "-v" };
|
String[] params = { "-v" };
|
||||||
|
@ -247,39 +207,6 @@ public class ListPluginsCommandTests extends ESTestCase {
|
||||||
terminal.getOutput());
|
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 {
|
public void testPluginWithoutVerboseMultiplePlugins() throws Exception {
|
||||||
buildFakePlugin(env, "fake desc 1", "fake_plugin1", "org.fake");
|
buildFakePlugin(env, "fake desc 1", "fake_plugin1", "org.fake");
|
||||||
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
|
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
|
||||||
|
@ -307,19 +234,6 @@ public class ListPluginsCommandTests extends ESTestCase {
|
||||||
e.getMessage());
|
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 {
|
public void testExistingIncompatiblePlugin() throws Exception {
|
||||||
PluginTestUtil.writePluginProperties(env.pluginsFile().resolve("fake_plugin1"),
|
PluginTestUtil.writePluginProperties(env.pluginsFile().resolve("fake_plugin1"),
|
||||||
"description", "fake desc 1",
|
"description", "fake desc 1",
|
||||||
|
@ -340,27 +254,4 @@ public class ListPluginsCommandTests extends ESTestCase {
|
||||||
terminal = listPlugins(home, params);
|
terminal = listPlugins(home, params);
|
||||||
assertEquals("fake_plugin1\nfake_plugin2\n", terminal.getOutput());
|
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");
|
"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 {
|
static MockTerminal removePlugin(String name, Path home, boolean purge) throws Exception {
|
||||||
Environment env = TestEnvironment.newEnvironment(Settings.builder().put("path.home", home).build());
|
Environment env = TestEnvironment.newEnvironment(Settings.builder().put("path.home", home).build());
|
||||||
MockTerminal terminal = new MockTerminal();
|
MockTerminal terminal = new MockTerminal();
|
||||||
|
@ -159,19 +149,6 @@ public class RemovePluginCommandTests extends ESTestCase {
|
||||||
assertRemoveCleaned(env);
|
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 {
|
public void testBin() throws Exception {
|
||||||
createPlugin("fake");
|
createPlugin("fake");
|
||||||
Path binDir = env.binFile().resolve("fake");
|
Path binDir = env.binFile().resolve("fake");
|
||||||
|
|
|
@ -13,8 +13,6 @@ The Elasticsearch repository contains examples of:
|
||||||
which contains a rescore plugin.
|
which contains a rescore plugin.
|
||||||
* a https://github.com/elastic/elasticsearch/tree/master/plugins/examples/script-expert-scoring[Java plugin]
|
* a https://github.com/elastic/elasticsearch/tree/master/plugins/examples/script-expert-scoring[Java plugin]
|
||||||
which contains a script 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
|
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
|
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]
|
See http://www.oracle.com/technetwork/java/seccodeguide-139067.html[Secure Coding Guidelines for Java SE]
|
||||||
for more information.
|
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 {
|
public void testControllerSpawnWithIncorrectDescriptor() throws IOException {
|
||||||
// this plugin will have a controller daemon
|
// this plugin will have a controller daemon
|
||||||
Path esHome = createTempDir().resolve("esHome");
|
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
|
// TODO: remove this leniency, but tests bogusly rely on it
|
||||||
if (isAccessibleDirectory(pluginsDirectory, logger)) {
|
if (isAccessibleDirectory(pluginsDirectory, logger)) {
|
||||||
checkForFailedPluginRemovals(pluginsDirectory);
|
checkForFailedPluginRemovals(pluginsDirectory);
|
||||||
// call findBundles directly to get the meta plugin names
|
Set<Bundle> plugins = getPluginBundles(pluginsDirectory);
|
||||||
List<BundleCollection> plugins = findBundles(pluginsDirectory, "plugin");
|
for (final Bundle bundle : plugins) {
|
||||||
for (final BundleCollection plugin : plugins) {
|
|
||||||
final Collection<Bundle> bundles = plugin.bundles();
|
|
||||||
for (final Bundle bundle : bundles) {
|
|
||||||
pluginsList.add(bundle.plugin);
|
pluginsList.add(bundle.plugin);
|
||||||
|
pluginsNames.add(bundle.plugin.getName());
|
||||||
}
|
}
|
||||||
seenBundles.addAll(bundles);
|
seenBundles.addAll(plugins);
|
||||||
pluginsNames.add(plugin.name());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new IllegalStateException("Unable to initialize plugins", ex);
|
throw new IllegalStateException("Unable to initialize plugins", ex);
|
||||||
|
@ -253,17 +249,8 @@ public class PluginsService extends AbstractComponent {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// a "bundle" is a group of jars in a single classloader
|
||||||
* An abstraction over a single plugin and meta-plugins.
|
static class Bundle {
|
||||||
*/
|
|
||||||
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 {
|
|
||||||
final PluginInfo plugin;
|
final PluginInfo plugin;
|
||||||
final Set<URL> urls;
|
final Set<URL> urls;
|
||||||
|
|
||||||
|
@ -283,16 +270,6 @@ public class PluginsService extends AbstractComponent {
|
||||||
this.urls = Objects.requireNonNull(urls);
|
this.urls = Objects.requireNonNull(urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return plugin.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Bundle> bundles() {
|
|
||||||
return Collections.singletonList(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
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.
|
* Extracts all installed plugin directories from the provided {@code rootPath}.
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
*
|
||||||
* @param rootPath the path where the plugins are installed
|
* @param rootPath the path where the plugins are installed
|
||||||
* @return a list of all plugin paths installed in the {@code rootPath}
|
* @return a list of all plugin paths installed in the {@code rootPath}
|
||||||
* @throws IOException if an I/O exception occurred reading the directories
|
* @throws IOException if an I/O exception occurred reading the directories
|
||||||
*/
|
*/
|
||||||
public static List<Path> findPluginDirs(final Path rootPath) throws IOException {
|
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 List<Path> plugins = new ArrayList<>();
|
||||||
final Map<String, List<Path>> metaPlugins = new LinkedHashMap<>();
|
|
||||||
final Set<String> seen = new HashSet<>();
|
final Set<String> seen = new HashSet<>();
|
||||||
if (Files.exists(rootPath)) {
|
if (Files.exists(rootPath)) {
|
||||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(rootPath)) {
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(rootPath)) {
|
||||||
|
@ -368,27 +304,11 @@ public class PluginsService extends AbstractComponent {
|
||||||
if (seen.add(plugin.getFileName().toString()) == false) {
|
if (seen.add(plugin.getFileName().toString()) == false) {
|
||||||
throw new IllegalStateException("duplicate plugin: " + plugin);
|
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 plugins;
|
||||||
return Tuple.tuple(plugins, metaPlugins);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -425,32 +345,21 @@ public class PluginsService extends AbstractComponent {
|
||||||
|
|
||||||
/** Get bundles for plugins installed in the given modules directory. */
|
/** Get bundles for plugins installed in the given modules directory. */
|
||||||
static Set<Bundle> getModuleBundles(Path modulesDirectory) throws IOException {
|
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. */
|
/** Get bundles for plugins installed in the given plugins directory. */
|
||||||
static Set<Bundle> getPluginBundles(final Path pluginsDirectory) throws IOException {
|
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
|
// searches subdirectories under the given directory for plugin directories
|
||||||
private static List<BundleCollection> findBundles(final Path directory, String type) throws IOException {
|
private static Set<Bundle> findBundles(final Path directory, String type) throws IOException {
|
||||||
final List<BundleCollection> bundles = new ArrayList<>();
|
final Set<Bundle> bundles = new HashSet<>();
|
||||||
final Set<Bundle> seenBundles = new HashSet<>();
|
for (final Path plugin : findPluginDirs(directory)) {
|
||||||
final Tuple<List<Path>, Map<String, List<Path>>> groupedPluginDirs = findGroupedPluginDirs(directory);
|
final Bundle bundle = readPluginBundle(bundles, plugin, type);
|
||||||
for (final Path plugin : groupedPluginDirs.v1()) {
|
|
||||||
final Bundle bundle = readPluginBundle(seenBundles, plugin, type);
|
|
||||||
bundles.add(bundle);
|
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;
|
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"));
|
Files.copy(jar, fake.resolve("plugin.jar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
final Path fakeMeta = plugins.resolve("fake-meta");
|
assertThat(PluginsService.findPluginDirs(plugins), containsInAnyOrder(fake));
|
||||||
|
|
||||||
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]")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExistingMandatoryClasspathPlugin() {
|
public void testExistingMandatoryClasspathPlugin() {
|
||||||
|
@ -696,38 +669,4 @@ public class PluginsServiceTests extends ESTestCase {
|
||||||
.build();
|
.build();
|
||||||
newPluginsService(settings);
|
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 */
|
/** Utility methods for testing plugins */
|
||||||
public class PluginTestUtil {
|
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 {
|
public static void writePluginProperties(Path pluginDir, String... stringProps) throws IOException {
|
||||||
writeProperties(pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES), stringProps);
|
writeProperties(pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES), stringProps);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import org.elasticsearch.gradle.LoggedExec
|
import org.elasticsearch.gradle.LoggedExec
|
||||||
import org.elasticsearch.gradle.MavenFilteringHack
|
import org.elasticsearch.gradle.MavenFilteringHack
|
||||||
import org.elasticsearch.gradle.plugin.MetaPluginBuildPlugin
|
|
||||||
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
|
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
|
||||||
import org.elasticsearch.gradle.test.NodeInfo
|
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.vagrantsupport'
|
||||||
apply plugin: 'elasticsearch.vagrant'
|
apply plugin: 'elasticsearch.vagrant'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue