Simplify Plugin Manager for official plugins
Plugin Manager can now use another simplified form when a user wants to install an official plugin hosted at elasticsearch download service. The form we use is: ```sh bin/plugin install pluginname ``` As plugins share now the same version as elasticsearch, we can automatically guess what is the exact current version of the plugin manager script. Also, download service will now use `/org.elasticsearch.plugins/pluginName/pluginName-version.zip` URL path to download a plugin. If the older form is provided (`user/plugin/version` or `user/plugin`), we will still use: * elasticsearch download service at `/user/plugin/plugin-version.zip` * maven central with groupIp=user, artifactId=plugin and version=version * github with user=user, repoName=plugin and tag=version * github with user=user, repoName=plugin and branch=master if no version is set Note that community plugin providers can use other download services by using `--url` option. If you try to use the new form with a non core elasticsearch plugin, the plugin manager will reject it and will give you all known core plugins. ``` Usage: -u, --url [plugin location] : Set exact URL to download the plugin from -i, --install [plugin name] : Downloads and installs listed plugins [*] -t, --timeout [duration] : Timeout setting: 30s, 1m, 1h... (infinite by default) -r, --remove [plugin name] : Removes listed plugins -l, --list : List installed plugins -v, --verbose : Prints verbose messages -s, --silent : Run in silent mode -h, --help : Prints this help message [*] Plugin name could be: elasticsearch-plugin-name for Elasticsearch 2.0 Core plugin (download from download.elastic.co) elasticsearch/plugin/version for elasticsearch commercial plugins (download from download.elastic.co) groupId/artifactId/version for community plugins (download from maven central or oss sonatype) username/repository for site plugins (download from github master) Elasticsearch Core plugins: - elasticsearch-analysis-icu - elasticsearch-analysis-kuromoji - elasticsearch-analysis-phonetic - elasticsearch-analysis-smartcn - elasticsearch-analysis-stempel - elasticsearch-cloud-aws - elasticsearch-cloud-azure - elasticsearch-cloud-gce - elasticsearch-delete-by-query - elasticsearch-lang-javascript - elasticsearch-lang-python ```
This commit is contained in:
parent
992716ac5c
commit
d57de59158
|
@ -73,7 +73,7 @@ public class PluginManager {
|
|||
// By default timeout is 0 which means no timeout
|
||||
public static final TimeValue DEFAULT_TIMEOUT = TimeValue.timeValueMillis(0);
|
||||
|
||||
private static final ImmutableSet<Object> BLACKLIST = ImmutableSet.builder()
|
||||
private static final ImmutableSet<String> BLACKLIST = ImmutableSet.<String>builder()
|
||||
.add("elasticsearch",
|
||||
"elasticsearch.bat",
|
||||
"elasticsearch.in.sh",
|
||||
|
@ -81,6 +81,21 @@ public class PluginManager {
|
|||
"plugin.bat",
|
||||
"service.bat").build();
|
||||
|
||||
private static final ImmutableSet<String> OFFICIAL_PLUGINS = ImmutableSet.<String>builder()
|
||||
.add(
|
||||
"elasticsearch-analysis-icu",
|
||||
"elasticsearch-analysis-kuromoji",
|
||||
"elasticsearch-analysis-phonetic",
|
||||
"elasticsearch-analysis-smartcn",
|
||||
"elasticsearch-analysis-stempel",
|
||||
"elasticsearch-cloud-aws",
|
||||
"elasticsearch-cloud-azure",
|
||||
"elasticsearch-cloud-gce",
|
||||
"elasticsearch-delete-by-query",
|
||||
"elasticsearch-lang-javascript",
|
||||
"elasticsearch-lang-python"
|
||||
).build();
|
||||
|
||||
private final Environment environment;
|
||||
private String url;
|
||||
private OutputMode outputMode;
|
||||
|
@ -133,6 +148,10 @@ public class PluginManager {
|
|||
// ignore
|
||||
log("Failed: " + ExceptionsHelper.detailedMessage(e));
|
||||
}
|
||||
} else {
|
||||
if (PluginHandle.isOfficialPlugin(pluginHandle.repo, pluginHandle.user, pluginHandle.version)) {
|
||||
checkForOfficialPlugins(pluginHandle.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!downloaded) {
|
||||
|
@ -384,6 +403,15 @@ public class PluginManager {
|
|||
}
|
||||
}
|
||||
|
||||
protected static void checkForOfficialPlugins(String name) {
|
||||
// We make sure that users can use only new short naming for official plugins only
|
||||
if (!OFFICIAL_PLUGINS.contains(name)) {
|
||||
throw new IllegalArgumentException(name +
|
||||
" is not an official plugin so you should install it using elasticsearch/" +
|
||||
name + "/latest naming form.");
|
||||
}
|
||||
}
|
||||
|
||||
public Path[] getListInstalledPlugins() throws IOException {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(environment.pluginsFile())) {
|
||||
return Iterators.toArray(stream.iterator(), Path.class);
|
||||
|
@ -597,9 +625,15 @@ public class PluginManager {
|
|||
SysOut.println(" -h, --help : Prints this help message");
|
||||
SysOut.newline();
|
||||
SysOut.println(" [*] Plugin name could be:");
|
||||
SysOut.println(" elasticsearch/plugin/version for official elasticsearch plugins (download from download.elasticsearch.org)");
|
||||
SysOut.println(" elasticsearch-plugin-name for Elasticsearch 2.0 Core plugin (download from download.elastic.co)");
|
||||
SysOut.println(" elasticsearch/plugin/version for elasticsearch commercial plugins (download from download.elastic.co)");
|
||||
SysOut.println(" groupId/artifactId/version for community plugins (download from maven central or oss sonatype)");
|
||||
SysOut.println(" username/repository for site plugins (download from github master)");
|
||||
SysOut.newline();
|
||||
SysOut.println("Elasticsearch Core plugins:");
|
||||
for (String o : OFFICIAL_PLUGINS) {
|
||||
SysOut.println(" - " + o);
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
SysOut.newline();
|
||||
|
@ -652,17 +686,26 @@ public class PluginManager {
|
|||
List<URL> urls() {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
if (version != null) {
|
||||
// Elasticsearch download service
|
||||
addUrl(urls, "http://download.elasticsearch.org/" + user + "/" + repo + "/" + repo + "-" + version + ".zip");
|
||||
// Maven central repository
|
||||
addUrl(urls, "http://search.maven.org/remotecontent?filepath=" + user.replace('.', '/') + "/" + repo + "/" + version + "/" + repo + "-" + version + ".zip");
|
||||
// Sonatype repository
|
||||
addUrl(urls, "https://oss.sonatype.org/service/local/repositories/releases/content/" + user.replace('.', '/') + "/" + repo + "/" + version + "/" + repo + "-" + version + ".zip");
|
||||
// Github repository
|
||||
addUrl(urls, "https://github.com/" + user + "/" + repo + "/archive/" + version + ".zip");
|
||||
// Elasticsearch new download service uses groupId org.elasticsearch.plugins from 2.0.0
|
||||
if (user == null) {
|
||||
// TODO Update to https
|
||||
addUrl(urls, String.format(Locale.ROOT, "http://download.elastic.co/org.elasticsearch.plugins/%1$s/%1$s-%2$s.zip", repo, version));
|
||||
} else {
|
||||
// Elasticsearch old download service
|
||||
// TODO Update to https
|
||||
addUrl(urls, String.format(Locale.ROOT, "http://download.elastic.co/%1$s/%2$s/%2$s-%3$s.zip", user, repo, version));
|
||||
// Maven central repository
|
||||
addUrl(urls, String.format(Locale.ROOT, "http://search.maven.org/remotecontent?filepath=%1$s/%2$s/%3$s/%2$s-%3$s.zip", user.replace('.', '/'), repo, version));
|
||||
// Sonatype repository
|
||||
addUrl(urls, String.format(Locale.ROOT, "https://oss.sonatype.org/service/local/repositories/releases/content/%1$s/%2$s/%3$s/%2$s-%3$s.zip", user.replace('.', '/'), repo, version));
|
||||
// Github repository
|
||||
addUrl(urls, String.format(Locale.ROOT, "https://github.com/%1$s/%2$s/archive/%3$s.zip", user, repo, version));
|
||||
}
|
||||
}
|
||||
if (user != null) {
|
||||
// Github repository for master branch (assume site)
|
||||
addUrl(urls, String.format(Locale.ROOT, "https://github.com/%1$s/%2$s/archive/master.zip", user, repo));
|
||||
}
|
||||
// Github repository for master branch (assume site)
|
||||
addUrl(urls, "https://github.com/" + user + "/" + repo + "/archive/master.zip");
|
||||
return urls;
|
||||
}
|
||||
|
||||
|
@ -708,6 +751,10 @@ public class PluginManager {
|
|||
}
|
||||
}
|
||||
|
||||
if (isOfficialPlugin(repo, user, version)) {
|
||||
return new PluginHandle(repo, Version.CURRENT.number(), null, repo);
|
||||
}
|
||||
|
||||
if (repo.startsWith("elasticsearch-")) {
|
||||
// remove elasticsearch- prefix
|
||||
String endname = repo.substring("elasticsearch-".length());
|
||||
|
@ -722,6 +769,10 @@ public class PluginManager {
|
|||
|
||||
return new PluginHandle(repo, version, user, repo);
|
||||
}
|
||||
|
||||
static boolean isOfficialPlugin(String repo, String user, String version) {
|
||||
return version == null && user == null && !Strings.isNullOrEmpty(repo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,9 +54,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertDire
|
|||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFileExists;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.Matchers.arrayWithSize;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
@ClusterScope(scope = Scope.TEST, numDataNodes = 0, transportClientRatio = 0.0)
|
||||
@LuceneTestCase.SuppressFileSystems("*") // TODO: clean up this test to allow extra files
|
||||
|
@ -513,6 +511,27 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOfficialPluginName_ThrowsException() throws IOException {
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-analysis-icu");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-analysis-kuromoji");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-analysis-phonetic");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-analysis-smartcn");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-analysis-stempel");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-cloud-aws");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-cloud-azure");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-cloud-gce");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-delete-by-query");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-lang-javascript");
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-lang-python");
|
||||
|
||||
try {
|
||||
PluginManager.checkForOfficialPlugins("elasticsearch-mapper-attachment");
|
||||
fail("elasticsearch-mapper-attachment should not be allowed");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// We expect that error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a URL string that represents the resource with the given {@code resourceName}.
|
||||
|
|
|
@ -20,16 +20,18 @@
|
|||
package org.elasticsearch.plugins;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/**
|
||||
|
@ -55,4 +57,14 @@ public class PluginManagerUnitTests extends ElasticsearchTestCase {
|
|||
|
||||
assertThat(configDirPath, is(expectedDirPath));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimplifiedNaming() throws IOException {
|
||||
String pluginName = randomAsciiOfLength(10);
|
||||
PluginManager.PluginHandle handle = PluginManager.PluginHandle.parse(pluginName);
|
||||
assertThat(handle.urls(), hasSize(1));
|
||||
URL expected = new URL("http", "download.elastic.co", "/org.elasticsearch.plugins/" + pluginName + "/" +
|
||||
pluginName + "-" + Version.CURRENT.number() + ".zip");
|
||||
assertThat(handle.urls().get(0), is(expected));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -731,3 +731,42 @@ to prevent clashes with the watcher plugin
|
|||
=== Percolator stats
|
||||
|
||||
Changed the `percolate.getTime` stat (total time spent on percolating) to `percolate.time` state.
|
||||
|
||||
=== Plugin Manager for official plugins
|
||||
|
||||
Some of the elasticsearch official plugins have been moved to elasticsearch repository and will be released at the
|
||||
same time as elasticsearch itself, using the same version number.
|
||||
|
||||
In that case, the plugin manager can now use a simpler form to identify an official plugin. Instead of:
|
||||
|
||||
[source,sh]
|
||||
---------------
|
||||
bin/plugin install elasticsearch/plugin_name/version
|
||||
---------------
|
||||
|
||||
You can use:
|
||||
|
||||
[source,sh]
|
||||
---------------
|
||||
bin/plugin install plugin_name
|
||||
---------------
|
||||
|
||||
The plugin manager will recognize this form and will be able to download the right version for your elasticsearch
|
||||
version.
|
||||
|
||||
For older versions of elasticsearch, you still have to use the older form.
|
||||
|
||||
For the record, official plugins which can use this new simplified form are:
|
||||
|
||||
* elasticsearch-analysis-icu
|
||||
* elasticsearch-analysis-kuromoji
|
||||
* elasticsearch-analysis-phonetic
|
||||
* elasticsearch-analysis-smartcn
|
||||
* elasticsearch-analysis-stempel
|
||||
* elasticsearch-cloud-aws
|
||||
* elasticsearch-cloud-azure
|
||||
* elasticsearch-cloud-gce
|
||||
* elasticsearch-delete-by-query
|
||||
* elasticsearch-lang-javascript
|
||||
* elasticsearch-lang-python
|
||||
|
||||
|
|
|
@ -14,19 +14,26 @@ and more.
|
|||
==== Installing plugins
|
||||
|
||||
Installing plugins can either be done manually by placing them under the
|
||||
`plugins` directory, or using the `plugin` script. Several plugins can
|
||||
be found under the https://github.com/elasticsearch[elasticsearch]
|
||||
organization in GitHub, starting with `elasticsearch-`.
|
||||
`plugins` directory, or using the `plugin` script.
|
||||
|
||||
Installing plugins typically take the following form:
|
||||
|
||||
[source,shell]
|
||||
-----------------------------------
|
||||
bin/plugin --install plugin_name
|
||||
-----------------------------------
|
||||
|
||||
The plugin will be automatically downloaded in this case from `download.elastic.co` download service using the
|
||||
same version as your elasticsearch version.
|
||||
|
||||
For older version of elasticsearch (prior to 2.0.0) or community plugins, you would use the following form:
|
||||
|
||||
[source,shell]
|
||||
-----------------------------------
|
||||
bin/plugin --install <org>/<user/component>/<version>
|
||||
-----------------------------------
|
||||
|
||||
The plugins will be
|
||||
automatically downloaded in this case from `download.elastic.co`,
|
||||
The plugins will be automatically downloaded in this case from `download.elastic.co` (for older plugins),
|
||||
and in case they don't exist there, from maven (central and sonatype).
|
||||
|
||||
Note that when the plugin is located in maven central or sonatype
|
||||
|
|
Loading…
Reference in New Issue