Plugins: Remove site plugins
Site plugins used to be used for things like kibana and marvel, but there is no longer a need since kibana (and marvel as a kibana plugin) uses node.js. This change removes site plugins, as well as the flag for jvm plugins. Now all plugins are jvm plugins.
This commit is contained in:
parent
b4538a5676
commit
3b78267c71
|
@ -112,9 +112,6 @@ public class PluginBuildPlugin extends BuildPlugin {
|
|||
include 'config/**'
|
||||
include 'bin/**'
|
||||
}
|
||||
from('src/site') {
|
||||
include '_site/**'
|
||||
}
|
||||
}
|
||||
project.assemble.dependsOn(bundle)
|
||||
|
||||
|
|
|
@ -36,15 +36,9 @@ class PluginPropertiesExtension {
|
|||
@Input
|
||||
String description
|
||||
|
||||
@Input
|
||||
boolean jvm = true
|
||||
|
||||
@Input
|
||||
String classname
|
||||
|
||||
@Input
|
||||
boolean site = false
|
||||
|
||||
@Input
|
||||
boolean isolated = true
|
||||
|
||||
|
|
|
@ -51,11 +51,11 @@ class PluginPropertiesTask extends Copy {
|
|||
if (extension.description == null) {
|
||||
throw new InvalidUserDataException('description is a required setting for esplugin')
|
||||
}
|
||||
if (extension.jvm && extension.classname == null) {
|
||||
throw new InvalidUserDataException('classname is a required setting for esplugin with jvm=true')
|
||||
if (extension.classname == null) {
|
||||
throw new InvalidUserDataException('classname is a required setting for esplugin')
|
||||
}
|
||||
doFirst {
|
||||
if (extension.jvm && extension.isolated == false) {
|
||||
if (extension.isolated == false) {
|
||||
String warning = "WARNING: Disabling plugin isolation in ${project.path} is deprecated and will be removed in the future"
|
||||
logger.warn("${'=' * warning.length()}\n${warning}\n${'=' * warning.length()}")
|
||||
}
|
||||
|
@ -74,10 +74,8 @@ class PluginPropertiesTask extends Copy {
|
|||
'version': extension.version,
|
||||
'elasticsearchVersion': VersionProperties.elasticsearch,
|
||||
'javaVersion': project.targetCompatibility as String,
|
||||
'jvm': extension.jvm as String,
|
||||
'site': extension.site as String,
|
||||
'isolated': extension.isolated as String,
|
||||
'classname': extension.jvm ? extension.classname : 'NA'
|
||||
'classname': extension.classname
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,26 +2,13 @@
|
|||
# This file must exist as 'plugin-descriptor.properties' at
|
||||
# the root directory of all plugins.
|
||||
#
|
||||
# A plugin can be 'site', 'jvm', or both.
|
||||
#
|
||||
### example site plugin for "foo":
|
||||
#
|
||||
# foo.zip <-- zip file for the plugin, with this structure:
|
||||
# _site/ <-- the contents that will be served
|
||||
# plugin-descriptor.properties <-- example contents below:
|
||||
#
|
||||
# site=true
|
||||
# description=My cool plugin
|
||||
# version=1.0
|
||||
#
|
||||
### example jvm plugin for "foo"
|
||||
### example plugin for "foo"
|
||||
#
|
||||
# foo.zip <-- zip file for the plugin, with this structure:
|
||||
# <arbitrary name1>.jar <-- classes, resources, dependencies
|
||||
# <arbitrary nameN>.jar <-- any number of jars
|
||||
# plugin-descriptor.properties <-- example contents below:
|
||||
#
|
||||
# jvm=true
|
||||
# classname=foo.bar.BazPlugin
|
||||
# description=My cool plugin
|
||||
# version=2.0
|
||||
|
@ -38,21 +25,6 @@ version=${version}
|
|||
#
|
||||
# 'name': the plugin name
|
||||
name=${name}
|
||||
|
||||
### mandatory elements for site plugins:
|
||||
#
|
||||
# 'site': set to true to indicate contents of the _site/
|
||||
# directory in the root of the plugin should be served.
|
||||
site=${site}
|
||||
#
|
||||
### mandatory elements for jvm plugins :
|
||||
#
|
||||
# 'jvm': true if the 'classname' class should be loaded
|
||||
# from jar files in the root directory of the plugin.
|
||||
# Note that only jar files in the root directory are
|
||||
# added to the classpath for the plugin! If you need
|
||||
# other resources, package them into a resources jar.
|
||||
jvm=${jvm}
|
||||
#
|
||||
# 'classname': the name of the class to load, fully-qualified.
|
||||
classname=${classname}
|
||||
|
|
|
@ -51,7 +51,7 @@ import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
|
|||
import static org.elasticsearch.rest.RestStatus.OK;
|
||||
|
||||
/**
|
||||
*
|
||||
* A component to serve http requests, backed by rest handlers.
|
||||
*/
|
||||
public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
|
||||
|
||||
|
@ -63,10 +63,6 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
|
|||
|
||||
private final NodeService nodeService;
|
||||
|
||||
private final boolean disableSites;
|
||||
|
||||
private final PluginSiteFilter pluginSiteFilter = new PluginSiteFilter();
|
||||
|
||||
@Inject
|
||||
public HttpServer(Settings settings, Environment environment, HttpServerTransport transport,
|
||||
RestController restController,
|
||||
|
@ -77,9 +73,6 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
|
|||
this.restController = restController;
|
||||
this.nodeService = nodeService;
|
||||
nodeService.setHttpServer(this);
|
||||
|
||||
this.disableSites = this.settings.getAsBoolean("http.disable_sites", false);
|
||||
|
||||
transport.httpServerAdapter(new Dispatcher(this));
|
||||
}
|
||||
|
||||
|
@ -126,27 +119,13 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
|
|||
}
|
||||
|
||||
public void internalDispatchRequest(final HttpRequest request, final HttpChannel channel) {
|
||||
String rawPath = request.rawPath();
|
||||
if (rawPath.startsWith("/_plugin/")) {
|
||||
RestFilterChain filterChain = restController.filterChain(pluginSiteFilter);
|
||||
filterChain.continueProcessing(request, channel);
|
||||
return;
|
||||
} else if (rawPath.equals("/favicon.ico")) {
|
||||
if (request.rawPath().equals("/favicon.ico")) {
|
||||
handleFavicon(request, channel);
|
||||
return;
|
||||
}
|
||||
restController.dispatchRequest(request, channel);
|
||||
}
|
||||
|
||||
|
||||
class PluginSiteFilter extends RestFilter {
|
||||
|
||||
@Override
|
||||
public void process(RestRequest request, RestChannel channel, RestFilterChain filterChain) throws IOException {
|
||||
handlePluginSite((HttpRequest) request, (HttpChannel) channel);
|
||||
}
|
||||
}
|
||||
|
||||
void handleFavicon(HttpRequest request, HttpChannel channel) {
|
||||
if (request.method() == RestRequest.Method.GET) {
|
||||
try {
|
||||
|
@ -163,129 +142,4 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
|
|||
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
|
||||
}
|
||||
}
|
||||
|
||||
void handlePluginSite(HttpRequest request, HttpChannel channel) throws IOException {
|
||||
if (disableSites) {
|
||||
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
|
||||
return;
|
||||
}
|
||||
if (request.method() == RestRequest.Method.OPTIONS) {
|
||||
// when we have OPTIONS request, simply send OK by default (with the Access Control Origin header which gets automatically added)
|
||||
channel.sendResponse(new BytesRestResponse(OK));
|
||||
return;
|
||||
}
|
||||
if (request.method() != RestRequest.Method.GET) {
|
||||
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
|
||||
return;
|
||||
}
|
||||
// TODO for a "/_plugin" endpoint, we should have a page that lists all the plugins?
|
||||
|
||||
String path = request.rawPath().substring("/_plugin/".length());
|
||||
int i1 = path.indexOf('/');
|
||||
String pluginName;
|
||||
String sitePath;
|
||||
if (i1 == -1) {
|
||||
pluginName = path;
|
||||
sitePath = null;
|
||||
// If a trailing / is missing, we redirect to the right page #2654
|
||||
String redirectUrl = request.rawPath() + "/";
|
||||
BytesRestResponse restResponse = new BytesRestResponse(RestStatus.MOVED_PERMANENTLY, "text/html", "<head><meta http-equiv=\"refresh\" content=\"0; URL=" + redirectUrl + "\"></head>");
|
||||
restResponse.addHeader("Location", redirectUrl);
|
||||
channel.sendResponse(restResponse);
|
||||
return;
|
||||
} else {
|
||||
pluginName = path.substring(0, i1);
|
||||
sitePath = path.substring(i1 + 1);
|
||||
}
|
||||
|
||||
// we default to index.html, or what the plugin provides (as a unix-style path)
|
||||
// this is a relative path under _site configured by the plugin.
|
||||
if (sitePath.length() == 0) {
|
||||
sitePath = "index.html";
|
||||
} else {
|
||||
// remove extraneous leading slashes, its not an absolute path.
|
||||
while (sitePath.length() > 0 && sitePath.charAt(0) == '/') {
|
||||
sitePath = sitePath.substring(1);
|
||||
}
|
||||
}
|
||||
final Path siteFile = environment.pluginsFile().resolve(pluginName).resolve("_site");
|
||||
|
||||
final String separator = siteFile.getFileSystem().getSeparator();
|
||||
// Convert file separators.
|
||||
sitePath = sitePath.replace("/", separator);
|
||||
|
||||
Path file = siteFile.resolve(sitePath);
|
||||
|
||||
// return not found instead of forbidden to prevent malicious requests to find out if files exist or dont exist
|
||||
if (!Files.exists(file) || FileSystemUtils.isHidden(file) || !file.toAbsolutePath().normalize().startsWith(siteFile.toAbsolutePath().normalize())) {
|
||||
channel.sendResponse(new BytesRestResponse(NOT_FOUND));
|
||||
return;
|
||||
}
|
||||
|
||||
BasicFileAttributes attributes = Files.readAttributes(file, BasicFileAttributes.class);
|
||||
if (!attributes.isRegularFile()) {
|
||||
// If it's not a dir, we send a 403
|
||||
if (!attributes.isDirectory()) {
|
||||
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
|
||||
return;
|
||||
}
|
||||
// We don't serve dir but if index.html exists in dir we should serve it
|
||||
file = file.resolve("index.html");
|
||||
if (!Files.exists(file) || FileSystemUtils.isHidden(file) || !Files.isRegularFile(file)) {
|
||||
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] data = Files.readAllBytes(file);
|
||||
channel.sendResponse(new BytesRestResponse(OK, guessMimeType(sitePath), data));
|
||||
} catch (IOException e) {
|
||||
channel.sendResponse(new BytesRestResponse(INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Don't respond with a mime type that violates the request's Accept header
|
||||
private String guessMimeType(String path) {
|
||||
int lastDot = path.lastIndexOf('.');
|
||||
if (lastDot == -1) {
|
||||
return "";
|
||||
}
|
||||
String extension = path.substring(lastDot + 1).toLowerCase(Locale.ROOT);
|
||||
String mimeType = DEFAULT_MIME_TYPES.get(extension);
|
||||
if (mimeType == null) {
|
||||
return "";
|
||||
}
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
static {
|
||||
// This is not an exhaustive list, just the most common types. Call registerMimeType() to add more.
|
||||
Map<String, String> mimeTypes = new HashMap<>();
|
||||
mimeTypes.put("txt", "text/plain");
|
||||
mimeTypes.put("css", "text/css");
|
||||
mimeTypes.put("csv", "text/csv");
|
||||
mimeTypes.put("htm", "text/html");
|
||||
mimeTypes.put("html", "text/html");
|
||||
mimeTypes.put("xml", "text/xml");
|
||||
mimeTypes.put("js", "text/javascript"); // Technically it should be application/javascript (RFC 4329), but IE8 struggles with that
|
||||
mimeTypes.put("xhtml", "application/xhtml+xml");
|
||||
mimeTypes.put("json", "application/json");
|
||||
mimeTypes.put("pdf", "application/pdf");
|
||||
mimeTypes.put("zip", "application/zip");
|
||||
mimeTypes.put("tar", "application/x-tar");
|
||||
mimeTypes.put("gif", "image/gif");
|
||||
mimeTypes.put("jpeg", "image/jpeg");
|
||||
mimeTypes.put("jpg", "image/jpeg");
|
||||
mimeTypes.put("tiff", "image/tiff");
|
||||
mimeTypes.put("tif", "image/tiff");
|
||||
mimeTypes.put("png", "image/png");
|
||||
mimeTypes.put("svg", "image/svg+xml");
|
||||
mimeTypes.put("ico", "image/vnd.microsoft.icon");
|
||||
mimeTypes.put("mp3", "audio/mpeg");
|
||||
DEFAULT_MIME_TYPES = unmodifiableMap(mimeTypes);
|
||||
}
|
||||
|
||||
public static final Map<String, String> DEFAULT_MIME_TYPES;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ package org.elasticsearch.plugins;
|
|||
|
||||
public class DummyPluginInfo extends PluginInfo {
|
||||
|
||||
private DummyPluginInfo(String name, String description, boolean site, String version, boolean jvm, String classname, boolean isolated) {
|
||||
super(name, description, site, version, jvm, classname, isolated);
|
||||
private DummyPluginInfo(String name, String description, String version, String classname, boolean isolated) {
|
||||
super(name, description, version, classname, isolated);
|
||||
}
|
||||
|
||||
public static final DummyPluginInfo INSTANCE = new DummyPluginInfo("dummy_plugin_name", "dummy plugin description", true, "dummy_plugin_version", true, "DummyPluginName", true);
|
||||
public static final DummyPluginInfo INSTANCE = new DummyPluginInfo("dummy_plugin_name", "dummy plugin description", "dummy_plugin_version", "DummyPluginName", true);
|
||||
}
|
||||
|
|
|
@ -42,19 +42,14 @@ public class PluginInfo implements Streamable, ToXContent {
|
|||
static final XContentBuilderString NAME = new XContentBuilderString("name");
|
||||
static final XContentBuilderString DESCRIPTION = new XContentBuilderString("description");
|
||||
static final XContentBuilderString URL = new XContentBuilderString("url");
|
||||
static final XContentBuilderString SITE = new XContentBuilderString("site");
|
||||
static final XContentBuilderString VERSION = new XContentBuilderString("version");
|
||||
static final XContentBuilderString JVM = new XContentBuilderString("jvm");
|
||||
static final XContentBuilderString CLASSNAME = new XContentBuilderString("classname");
|
||||
static final XContentBuilderString ISOLATED = new XContentBuilderString("isolated");
|
||||
}
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private boolean site;
|
||||
private String version;
|
||||
|
||||
private boolean jvm;
|
||||
private String classname;
|
||||
private boolean isolated;
|
||||
|
||||
|
@ -66,15 +61,11 @@ public class PluginInfo implements Streamable, ToXContent {
|
|||
*
|
||||
* @param name Its name
|
||||
* @param description Its description
|
||||
* @param site true if it's a site plugin
|
||||
* @param jvm true if it's a jvm plugin
|
||||
* @param version Version number
|
||||
*/
|
||||
PluginInfo(String name, String description, boolean site, String version, boolean jvm, String classname, boolean isolated) {
|
||||
PluginInfo(String name, String description, String version, String classname, boolean isolated) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.site = site;
|
||||
this.jvm = jvm;
|
||||
this.version = version;
|
||||
this.classname = classname;
|
||||
this.isolated = isolated;
|
||||
|
@ -101,43 +92,28 @@ public class PluginInfo implements Streamable, ToXContent {
|
|||
throw new IllegalArgumentException("Property [version] is missing for plugin [" + name + "]");
|
||||
}
|
||||
|
||||
boolean jvm = Boolean.parseBoolean(props.getProperty("jvm"));
|
||||
boolean site = Boolean.parseBoolean(props.getProperty("site"));
|
||||
if (jvm == false && site == false) {
|
||||
throw new IllegalArgumentException("Plugin [" + name + "] must be at least a jvm or site plugin");
|
||||
String esVersionString = props.getProperty("elasticsearch.version");
|
||||
if (esVersionString == null) {
|
||||
throw new IllegalArgumentException("Property [elasticsearch.version] is missing for plugin [" + name + "]");
|
||||
}
|
||||
boolean isolated = true;
|
||||
String classname = "NA";
|
||||
if (jvm) {
|
||||
String esVersionString = props.getProperty("elasticsearch.version");
|
||||
if (esVersionString == null) {
|
||||
throw new IllegalArgumentException("Property [elasticsearch.version] is missing for jvm plugin [" + name + "]");
|
||||
}
|
||||
Version esVersion = Version.fromString(esVersionString);
|
||||
if (esVersion.equals(Version.CURRENT) == false) {
|
||||
throw new IllegalArgumentException("Plugin [" + name + "] is incompatible with Elasticsearch [" + Version.CURRENT.toString() +
|
||||
"]. Was designed for version [" + esVersionString + "]");
|
||||
}
|
||||
String javaVersionString = props.getProperty("java.version");
|
||||
if (javaVersionString == null) {
|
||||
throw new IllegalArgumentException("Property [java.version] is missing for jvm plugin [" + name + "]");
|
||||
}
|
||||
JarHell.checkVersionFormat(javaVersionString);
|
||||
JarHell.checkJavaVersion(name, javaVersionString);
|
||||
isolated = Boolean.parseBoolean(props.getProperty("isolated", "true"));
|
||||
classname = props.getProperty("classname");
|
||||
if (classname == null) {
|
||||
throw new IllegalArgumentException("Property [classname] is missing for jvm plugin [" + name + "]");
|
||||
}
|
||||
Version esVersion = Version.fromString(esVersionString);
|
||||
if (esVersion.equals(Version.CURRENT) == false) {
|
||||
throw new IllegalArgumentException("Plugin [" + name + "] is incompatible with Elasticsearch [" + Version.CURRENT.toString() +
|
||||
"]. Was designed for version [" + esVersionString + "]");
|
||||
}
|
||||
String javaVersionString = props.getProperty("java.version");
|
||||
if (javaVersionString == null) {
|
||||
throw new IllegalArgumentException("Property [java.version] is missing for plugin [" + name + "]");
|
||||
}
|
||||
JarHell.checkVersionFormat(javaVersionString);
|
||||
JarHell.checkJavaVersion(name, javaVersionString);
|
||||
boolean isolated = Boolean.parseBoolean(props.getProperty("isolated", "true"));
|
||||
String classname = props.getProperty("classname");
|
||||
if (classname == null) {
|
||||
throw new IllegalArgumentException("Property [classname] is missing for plugin [" + name + "]");
|
||||
}
|
||||
|
||||
if (site) {
|
||||
if (!Files.exists(dir.resolve("_site"))) {
|
||||
throw new IllegalArgumentException("Plugin [" + name + "] is a site plugin but has no '_site/' directory");
|
||||
}
|
||||
}
|
||||
|
||||
return new PluginInfo(name, description, site, version, jvm, classname, isolated);
|
||||
return new PluginInfo(name, description, version, classname, isolated);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,46 +131,19 @@ public class PluginInfo implements Streamable, ToXContent {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return true if it's a site plugin
|
||||
*/
|
||||
public boolean isSite() {
|
||||
return site;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if it's a plugin running in the jvm
|
||||
*/
|
||||
public boolean isJvm() {
|
||||
return jvm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if jvm plugin has isolated classloader
|
||||
* @return true if plugin has isolated classloader
|
||||
*/
|
||||
public boolean isIsolated() {
|
||||
return isolated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return jvm plugin's classname
|
||||
* @return plugin's classname
|
||||
*/
|
||||
public String getClassname() {
|
||||
return classname;
|
||||
}
|
||||
|
||||
/**
|
||||
* We compute the URL for sites: "/_plugin/" + name + "/"
|
||||
*
|
||||
* @return relative URL for site plugin
|
||||
*/
|
||||
public String getUrl() {
|
||||
if (site) {
|
||||
return ("/_plugin/" + name + "/");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Version number for the plugin
|
||||
*/
|
||||
|
@ -212,8 +161,6 @@ public class PluginInfo implements Streamable, ToXContent {
|
|||
public void readFrom(StreamInput in) throws IOException {
|
||||
this.name = in.readString();
|
||||
this.description = in.readString();
|
||||
this.site = in.readBoolean();
|
||||
this.jvm = in.readBoolean();
|
||||
this.version = in.readString();
|
||||
this.classname = in.readString();
|
||||
this.isolated = in.readBoolean();
|
||||
|
@ -223,8 +170,6 @@ public class PluginInfo implements Streamable, ToXContent {
|
|||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(name);
|
||||
out.writeString(description);
|
||||
out.writeBoolean(site);
|
||||
out.writeBoolean(jvm);
|
||||
out.writeString(version);
|
||||
out.writeString(classname);
|
||||
out.writeBoolean(isolated);
|
||||
|
@ -236,15 +181,8 @@ public class PluginInfo implements Streamable, ToXContent {
|
|||
builder.field(Fields.NAME, name);
|
||||
builder.field(Fields.VERSION, version);
|
||||
builder.field(Fields.DESCRIPTION, description);
|
||||
if (site) {
|
||||
builder.field(Fields.URL, getUrl());
|
||||
}
|
||||
builder.field(Fields.JVM, jvm);
|
||||
if (jvm) {
|
||||
builder.field(Fields.CLASSNAME, classname);
|
||||
builder.field(Fields.ISOLATED, isolated);
|
||||
}
|
||||
builder.field(Fields.SITE, site);
|
||||
builder.field(Fields.CLASSNAME, classname);
|
||||
builder.field(Fields.ISOLATED, isolated);
|
||||
builder.endObject();
|
||||
|
||||
return builder;
|
||||
|
@ -274,14 +212,9 @@ public class PluginInfo implements Streamable, ToXContent {
|
|||
.append("- Plugin information:\n")
|
||||
.append("Name: ").append(name).append("\n")
|
||||
.append("Description: ").append(description).append("\n")
|
||||
.append("Site: ").append(site).append("\n")
|
||||
.append("Version: ").append(version).append("\n")
|
||||
.append("JVM: ").append(jvm).append("\n");
|
||||
|
||||
if (jvm) {
|
||||
information.append(" * Classname: ").append(classname).append("\n");
|
||||
information.append(" * Isolated: ").append(isolated);
|
||||
}
|
||||
.append(" * Classname: ").append(classname).append("\n")
|
||||
.append(" * Isolated: ").append(isolated);
|
||||
|
||||
return information.toString();
|
||||
}
|
||||
|
|
|
@ -258,9 +258,7 @@ public class PluginManager {
|
|||
}
|
||||
|
||||
// check for jar hell before any copying
|
||||
if (info.isJvm()) {
|
||||
jarHellCheck(root, info.isIsolated());
|
||||
}
|
||||
jarHellCheck(root, info.isIsolated());
|
||||
|
||||
// read optional security policy (extra permissions)
|
||||
// if it exists, confirm or warn the user
|
||||
|
|
|
@ -98,7 +98,7 @@ public class PluginsService extends AbstractComponent {
|
|||
// first we load plugins that are on the classpath. this is for tests and transport clients
|
||||
for (Class<? extends Plugin> pluginClass : classpathPlugins) {
|
||||
Plugin plugin = loadPlugin(pluginClass, settings);
|
||||
PluginInfo pluginInfo = new PluginInfo(plugin.name(), plugin.description(), false, "NA", true, pluginClass.getName(), false);
|
||||
PluginInfo pluginInfo = new PluginInfo(plugin.name(), plugin.description(), "NA", pluginClass.getName(), false);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("plugin loaded from classpath [{}]", pluginInfo);
|
||||
}
|
||||
|
@ -136,18 +136,10 @@ public class PluginsService extends AbstractComponent {
|
|||
|
||||
plugins = Collections.unmodifiableList(pluginsLoaded);
|
||||
|
||||
// We need to build a List of jvm and site plugins for checking mandatory plugins
|
||||
Map<String, Plugin> jvmPlugins = new HashMap<>();
|
||||
List<String> sitePlugins = new ArrayList<>();
|
||||
|
||||
// We need to build a List of plugins for checking mandatory plugins
|
||||
Set<String> pluginsNames = new HashSet<>();
|
||||
for (Tuple<PluginInfo, Plugin> tuple : plugins) {
|
||||
PluginInfo info = tuple.v1();
|
||||
if (info.isJvm()) {
|
||||
jvmPlugins.put(info.getName(), tuple.v2());
|
||||
}
|
||||
if (info.isSite()) {
|
||||
sitePlugins.add(info.getName());
|
||||
}
|
||||
pluginsNames.add(tuple.v1().getName());
|
||||
}
|
||||
|
||||
// Checking expected plugins
|
||||
|
@ -155,7 +147,7 @@ public class PluginsService extends AbstractComponent {
|
|||
if (mandatoryPlugins != null) {
|
||||
Set<String> missingPlugins = new HashSet<>();
|
||||
for (String mandatoryPlugin : mandatoryPlugins) {
|
||||
if (!jvmPlugins.containsKey(mandatoryPlugin) && !sitePlugins.contains(mandatoryPlugin) && !missingPlugins.contains(mandatoryPlugin)) {
|
||||
if (!pluginsNames.contains(mandatoryPlugin) && !missingPlugins.contains(mandatoryPlugin)) {
|
||||
missingPlugins.add(mandatoryPlugin);
|
||||
}
|
||||
}
|
||||
|
@ -175,10 +167,11 @@ public class PluginsService extends AbstractComponent {
|
|||
jvmPluginNames.add(pluginInfo.getName());
|
||||
}
|
||||
|
||||
logger.info("modules {}, plugins {}, sites {}", moduleNames, jvmPluginNames, sitePlugins);
|
||||
logger.info("modules {}, plugins {}", moduleNames, jvmPluginNames);
|
||||
|
||||
Map<Plugin, List<OnModuleReference>> onModuleReferences = new HashMap<>();
|
||||
for (Plugin plugin : jvmPlugins.values()) {
|
||||
for (Tuple<PluginInfo, Plugin> pluginEntry : plugins) {
|
||||
Plugin plugin = pluginEntry.v2();
|
||||
List<OnModuleReference> list = new ArrayList<>();
|
||||
for (Method method : plugin.getClass().getMethods()) {
|
||||
if (!method.getName().equals("onModule")) {
|
||||
|
@ -304,9 +297,6 @@ public class PluginsService extends AbstractComponent {
|
|||
continue; // skip over .DS_Store etc
|
||||
}
|
||||
PluginInfo info = PluginInfo.readFromProperties(module);
|
||||
if (!info.isJvm()) {
|
||||
throw new IllegalStateException("modules must be jvm plugins: " + info);
|
||||
}
|
||||
if (!info.isIsolated()) {
|
||||
throw new IllegalStateException("modules must be isolated: " + info);
|
||||
}
|
||||
|
@ -353,17 +343,14 @@ public class PluginsService extends AbstractComponent {
|
|||
}
|
||||
|
||||
List<URL> urls = new ArrayList<>();
|
||||
if (info.isJvm()) {
|
||||
// a jvm plugin: gather urls for jar files
|
||||
try (DirectoryStream<Path> jarStream = Files.newDirectoryStream(plugin, "*.jar")) {
|
||||
for (Path jar : jarStream) {
|
||||
// normalize with toRealPath to get symlinks out of our hair
|
||||
urls.add(jar.toRealPath().toUri().toURL());
|
||||
}
|
||||
try (DirectoryStream<Path> jarStream = Files.newDirectoryStream(plugin, "*.jar")) {
|
||||
for (Path jar : jarStream) {
|
||||
// normalize with toRealPath to get symlinks out of our hair
|
||||
urls.add(jar.toRealPath().toUri().toURL());
|
||||
}
|
||||
}
|
||||
final Bundle bundle;
|
||||
if (info.isJvm() && info.isIsolated() == false) {
|
||||
if (info.isIsolated() == false) {
|
||||
bundle = bundles.get(0); // purgatory
|
||||
} else {
|
||||
bundle = new Bundle();
|
||||
|
@ -395,15 +382,10 @@ public class PluginsService extends AbstractComponent {
|
|||
// create a child to load the plugins in this bundle
|
||||
ClassLoader loader = URLClassLoader.newInstance(bundle.urls.toArray(new URL[0]), getClass().getClassLoader());
|
||||
for (PluginInfo pluginInfo : bundle.plugins) {
|
||||
final Plugin plugin;
|
||||
if (pluginInfo.isJvm()) {
|
||||
// reload lucene SPI with any new services from the plugin
|
||||
reloadLuceneSPI(loader);
|
||||
Class<? extends Plugin> pluginClass = loadPluginClass(pluginInfo.getClassname(), loader);
|
||||
plugin = loadPlugin(pluginClass, settings);
|
||||
} else {
|
||||
plugin = new SitePlugin(pluginInfo.getName(), pluginInfo.getDescription());
|
||||
}
|
||||
// reload lucene SPI with any new services from the plugin
|
||||
reloadLuceneSPI(loader);
|
||||
final Class<? extends Plugin> pluginClass = loadPluginClass(pluginInfo.getClassname(), loader);
|
||||
final Plugin plugin = loadPlugin(pluginClass, settings);
|
||||
plugins.add(new Tuple<>(pluginInfo, plugin));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +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;
|
||||
|
||||
/** A site-only plugin, just serves resources */
|
||||
final class SitePlugin extends Plugin {
|
||||
final String name;
|
||||
final String description;
|
||||
|
||||
SitePlugin(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
}
|
|
@ -84,8 +84,6 @@ public class RestPluginsAction extends AbstractCatAction {
|
|||
table.addCell("name", "alias:n;desc:node name");
|
||||
table.addCell("component", "alias:c;desc:component");
|
||||
table.addCell("version", "alias:v;desc:component version");
|
||||
table.addCell("type", "alias:t;desc:type (j for JVM, s for Site)");
|
||||
table.addCell("url", "alias:u;desc:url for site plugins");
|
||||
table.addCell("description", "alias:d;default:false;desc:plugin details");
|
||||
table.endHeaders();
|
||||
return table;
|
||||
|
@ -104,22 +102,6 @@ public class RestPluginsAction extends AbstractCatAction {
|
|||
table.addCell(node.name());
|
||||
table.addCell(pluginInfo.getName());
|
||||
table.addCell(pluginInfo.getVersion());
|
||||
String type;
|
||||
if (pluginInfo.isSite()) {
|
||||
if (pluginInfo.isJvm()) {
|
||||
type = "j/s";
|
||||
} else {
|
||||
type = "s";
|
||||
}
|
||||
} else {
|
||||
if (pluginInfo.isJvm()) {
|
||||
type = "j";
|
||||
} else {
|
||||
type = "";
|
||||
}
|
||||
}
|
||||
table.addCell(type);
|
||||
table.addCell(pluginInfo.getUrl());
|
||||
table.addCell(pluginInfo.getDescription());
|
||||
table.endRow();
|
||||
}
|
||||
|
|
|
@ -40,17 +40,13 @@ public class PluginInfoTests extends ESTestCase {
|
|||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
PluginInfo info = PluginInfo.readFromProperties(pluginDir);
|
||||
assertEquals("my_plugin", info.getName());
|
||||
assertEquals("fake desc", info.getDescription());
|
||||
assertEquals("1.0", info.getVersion());
|
||||
assertEquals("FakePlugin", info.getClassname());
|
||||
assertTrue(info.isJvm());
|
||||
assertTrue(info.isIsolated());
|
||||
assertFalse(info.isSite());
|
||||
assertNull(info.getUrl());
|
||||
}
|
||||
|
||||
public void testReadFromPropertiesNameMissing() throws Exception {
|
||||
|
@ -94,27 +90,12 @@ public class PluginInfoTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testReadFromPropertiesJvmAndSiteMissing() throws Exception {
|
||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
||||
PluginTestUtil.writeProperties(pluginDir,
|
||||
"description", "fake desc",
|
||||
"version", "1.0",
|
||||
"name", "my_plugin");
|
||||
try {
|
||||
PluginInfo.readFromProperties(pluginDir);
|
||||
fail("expected jvm or site exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage().contains("must be at least a jvm or site plugin"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testReadFromPropertiesElasticsearchVersionMissing() throws Exception {
|
||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
||||
PluginTestUtil.writeProperties(pluginDir,
|
||||
"description", "fake desc",
|
||||
"name", "my_plugin",
|
||||
"version", "1.0",
|
||||
"jvm", "true");
|
||||
"version", "1.0");
|
||||
try {
|
||||
PluginInfo.readFromProperties(pluginDir);
|
||||
fail("expected missing elasticsearch version exception");
|
||||
|
@ -129,8 +110,7 @@ public class PluginInfoTests extends ESTestCase {
|
|||
"description", "fake desc",
|
||||
"name", "my_plugin",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"version", "1.0",
|
||||
"jvm", "true");
|
||||
"version", "1.0");
|
||||
try {
|
||||
PluginInfo.readFromProperties(pluginDir);
|
||||
fail("expected missing java version exception");
|
||||
|
@ -148,8 +128,7 @@ public class PluginInfoTests extends ESTestCase {
|
|||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", "1000000.0",
|
||||
"classname", "FakePlugin",
|
||||
"version", "1.0",
|
||||
"jvm", "true");
|
||||
"version", "1.0");
|
||||
try {
|
||||
PluginInfo.readFromProperties(pluginDir);
|
||||
fail("expected incompatible java version exception");
|
||||
|
@ -167,8 +146,7 @@ public class PluginInfoTests extends ESTestCase {
|
|||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", "1.7.0_80",
|
||||
"classname", "FakePlugin",
|
||||
"version", "1.0",
|
||||
"jvm", "true");
|
||||
"version", "1.0");
|
||||
try {
|
||||
PluginInfo.readFromProperties(pluginDir);
|
||||
fail("expected bad java version format exception");
|
||||
|
@ -182,7 +160,6 @@ public class PluginInfoTests extends ESTestCase {
|
|||
PluginTestUtil.writeProperties(pluginDir,
|
||||
"description", "fake desc",
|
||||
"version", "1.0",
|
||||
"jvm", "true",
|
||||
"name", "my_plugin",
|
||||
"elasticsearch.version", "bogus");
|
||||
try {
|
||||
|
@ -199,7 +176,6 @@ public class PluginInfoTests extends ESTestCase {
|
|||
"description", "fake desc",
|
||||
"name", "my_plugin",
|
||||
"version", "1.0",
|
||||
"jvm", "true",
|
||||
"elasticsearch.version", Version.V_1_7_0.toString());
|
||||
try {
|
||||
PluginInfo.readFromProperties(pluginDir);
|
||||
|
@ -216,8 +192,7 @@ public class PluginInfoTests extends ESTestCase {
|
|||
"name", "my_plugin",
|
||||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true");
|
||||
"java.version", System.getProperty("java.specification.version"));
|
||||
try {
|
||||
PluginInfo.readFromProperties(pluginDir);
|
||||
fail("expected old elasticsearch version exception");
|
||||
|
@ -226,42 +201,13 @@ public class PluginInfoTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testReadFromPropertiesSitePlugin() throws Exception {
|
||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
||||
Files.createDirectories(pluginDir.resolve("_site"));
|
||||
PluginTestUtil.writeProperties(pluginDir,
|
||||
"description", "fake desc",
|
||||
"name", "my_plugin",
|
||||
"version", "1.0",
|
||||
"site", "true");
|
||||
PluginInfo info = PluginInfo.readFromProperties(pluginDir);
|
||||
assertTrue(info.isSite());
|
||||
assertFalse(info.isJvm());
|
||||
assertEquals("NA", info.getClassname());
|
||||
}
|
||||
|
||||
public void testReadFromPropertiesSitePluginWithoutSite() throws Exception {
|
||||
Path pluginDir = createTempDir().resolve("fake-plugin");
|
||||
PluginTestUtil.writeProperties(pluginDir,
|
||||
"description", "fake desc",
|
||||
"name", "my_plugin",
|
||||
"version", "1.0",
|
||||
"site", "true");
|
||||
try {
|
||||
PluginInfo.readFromProperties(pluginDir);
|
||||
fail("didn't get expected exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage().contains("site plugin but has no '_site"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testPluginListSorted() {
|
||||
PluginsAndModules pluginsInfo = new PluginsAndModules();
|
||||
pluginsInfo.addPlugin(new PluginInfo("c", "foo", true, "dummy", true, "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("b", "foo", true, "dummy", true, "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("e", "foo", true, "dummy", true, "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("a", "foo", true, "dummy", true, "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("d", "foo", true, "dummy", true, "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("c", "foo", "dummy", "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("b", "foo", "dummy", "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("e", "foo", "dummy", "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("a", "foo", "dummy", "dummyclass", true));
|
||||
pluginsInfo.addPlugin(new PluginInfo("d", "foo", "dummy", "dummyclass", true));
|
||||
|
||||
final List<PluginInfo> infos = pluginsInfo.getPluginInfos();
|
||||
List<String> names = infos.stream().map((input) -> input.getName()).collect(Collectors.toList());
|
||||
|
|
|
@ -1,131 +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.http.client.config.RequestConfig;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.http.HttpServerTransport;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.test.ESIntegTestCase.Scope;
|
||||
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
|
||||
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||
import static org.elasticsearch.rest.RestStatus.FORBIDDEN;
|
||||
import static org.elasticsearch.rest.RestStatus.MOVED_PERMANENTLY;
|
||||
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
|
||||
import static org.elasticsearch.rest.RestStatus.OK;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasStatus;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
/**
|
||||
* We want to test site plugins
|
||||
*/
|
||||
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1)
|
||||
public class SitePluginIT extends ESIntegTestCase {
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
Path pluginDir = getDataPath("/org/elasticsearch/test_plugins");
|
||||
return settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("path.plugins", pluginDir.toAbsolutePath())
|
||||
.put("force.http.enabled", true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBuilder httpClient() {
|
||||
RequestConfig.Builder builder = RequestConfig.custom().setRedirectsEnabled(false);
|
||||
CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(builder.build()).build();
|
||||
return new HttpRequestBuilder(httpClient).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class));
|
||||
}
|
||||
|
||||
public void testRedirectSitePlugin() throws Exception {
|
||||
// We use an HTTP Client to test redirection
|
||||
HttpResponse response = httpClient().method("GET").path("/_plugin/dummy").execute();
|
||||
assertThat(response, hasStatus(MOVED_PERMANENTLY));
|
||||
assertThat(response.getBody(), containsString("/_plugin/dummy/"));
|
||||
|
||||
// We test the real URL
|
||||
response = httpClient().method("GET").path("/_plugin/dummy/").execute();
|
||||
assertThat(response, hasStatus(OK));
|
||||
assertThat(response.getBody(), containsString("<title>Dummy Site Plugin</title>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test direct access to an existing file (index.html)
|
||||
*/
|
||||
public void testAnyPage() throws Exception {
|
||||
HttpResponse response = httpClient().path("/_plugin/dummy/index.html").execute();
|
||||
assertThat(response, hasStatus(OK));
|
||||
assertThat(response.getBody(), containsString("<title>Dummy Site Plugin</title>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test normalizing of path
|
||||
*/
|
||||
public void testThatPathsAreNormalized() throws Exception {
|
||||
// more info: https://www.owasp.org/index.php/Path_Traversal
|
||||
List<String> notFoundUris = new ArrayList<>();
|
||||
notFoundUris.add("/_plugin/dummy/../../../../../log4j.properties");
|
||||
notFoundUris.add("/_plugin/dummy/../../../../../%00log4j.properties");
|
||||
notFoundUris.add("/_plugin/dummy/..%c0%af..%c0%af..%c0%af..%c0%af..%c0%aflog4j.properties");
|
||||
notFoundUris.add("/_plugin/dummy/%2E%2E/%2E%2E/%2E%2E/%2E%2E/index.html");
|
||||
notFoundUris.add("/_plugin/dummy/%2e%2e/%2e%2e/%2e%2e/%2e%2e/index.html");
|
||||
notFoundUris.add("/_plugin/dummy/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2findex.html");
|
||||
notFoundUris.add("/_plugin/dummy/%2E%2E/%2E%2E/%2E%2E/%2E%2E/index.html");
|
||||
notFoundUris.add("/_plugin/dummy/..%5C..%5C..%5C..%5C..%5Clog4j.properties");
|
||||
|
||||
for (String uri : notFoundUris) {
|
||||
HttpResponse response = httpClient().path(uri).execute();
|
||||
String message = String.format(Locale.ROOT, "URI [%s] expected to be not found", uri);
|
||||
assertThat(message, response, hasStatus(NOT_FOUND));
|
||||
}
|
||||
|
||||
// using relative path inside of the plugin should work
|
||||
HttpResponse response = httpClient().path("/_plugin/dummy/dir1/../dir1/../index.html").execute();
|
||||
assertThat(response, hasStatus(OK));
|
||||
assertThat(response.getBody(), containsString("<title>Dummy Site Plugin</title>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for #4845: https://github.com/elasticsearch/elasticsearch/issues/4845
|
||||
* Serving _site plugins do not pick up on index.html for sub directories
|
||||
*/
|
||||
public void testWelcomePageInSubDirs() throws Exception {
|
||||
HttpResponse response = httpClient().path("/_plugin/subdir/dir/").execute();
|
||||
assertThat(response, hasStatus(OK));
|
||||
assertThat(response.getBody(), containsString("<title>Dummy Site Plugin (subdir)</title>"));
|
||||
|
||||
response = httpClient().path("/_plugin/subdir/dir_without_index/").execute();
|
||||
assertThat(response, hasStatus(FORBIDDEN));
|
||||
|
||||
response = httpClient().path("/_plugin/subdir/dir_without_index/page.html").execute();
|
||||
assertThat(response, hasStatus(OK));
|
||||
assertThat(response.getBody(), containsString("<title>Dummy Site Plugin (page)</title>"));
|
||||
}
|
||||
}
|
|
@ -1,88 +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.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.elasticsearch.common.io.PathUtils;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.http.HttpServerTransport;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
|
||||
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.apache.lucene.util.Constants.WINDOWS;
|
||||
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||
import static org.elasticsearch.rest.RestStatus.OK;
|
||||
import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasStatus;
|
||||
|
||||
@ClusterScope(scope = SUITE, numDataNodes = 1)
|
||||
public class SitePluginRelativePathConfigIT extends ESIntegTestCase {
|
||||
private final Path root = PathUtils.get(".").toAbsolutePath().getRoot();
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
String cwdToRoot = getRelativePath(PathUtils.get(".").toAbsolutePath());
|
||||
Path pluginDir = PathUtils.get(cwdToRoot, relativizeToRootIfNecessary(getDataPath("/org/elasticsearch/test_plugins")).toString());
|
||||
|
||||
Path tempDir = createTempDir();
|
||||
boolean useRelativeInMiddleOfPath = randomBoolean();
|
||||
if (useRelativeInMiddleOfPath) {
|
||||
pluginDir = PathUtils.get(tempDir.toString(), getRelativePath(tempDir), pluginDir.toString());
|
||||
}
|
||||
|
||||
return settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("path.plugins", pluginDir)
|
||||
.put("force.http.enabled", true)
|
||||
.build();
|
||||
}
|
||||
|
||||
public void testThatRelativePathsDontAffectPlugins() throws Exception {
|
||||
HttpResponse response = httpClient().method("GET").path("/_plugin/dummy/").execute();
|
||||
assertThat(response, hasStatus(OK));
|
||||
}
|
||||
|
||||
private Path relativizeToRootIfNecessary(Path path) {
|
||||
if (WINDOWS) {
|
||||
return root.relativize(path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private String getRelativePath(Path path) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < path.getNameCount(); i++) {
|
||||
sb.append("..");
|
||||
sb.append(path.getFileSystem().getSeparator());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBuilder httpClient() {
|
||||
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||
return new HttpRequestBuilder(httpClient).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class));
|
||||
}
|
||||
}
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
The Elasticsearch repository contains examples of:
|
||||
|
||||
* a https://github.com/elastic/elasticsearch/tree/master/plugins/site-example[site plugin]
|
||||
for serving static HTML, JavaScript, and CSS.
|
||||
* a https://github.com/elastic/elasticsearch/tree/master/plugins/jvm-example[Java plugin]
|
||||
which contains Java code.
|
||||
|
||||
|
@ -12,20 +10,6 @@ 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
|
||||
listed in this documentation for inspiration.
|
||||
|
||||
[NOTE]
|
||||
.Site plugins
|
||||
====================================
|
||||
|
||||
The example site plugin mentioned above contains all of the scaffolding needed
|
||||
for integrating with Gradle builds. If you don't plan on using Gradle, then all
|
||||
you really need in your plugin is:
|
||||
|
||||
* The `plugin-descriptor.properties` file
|
||||
* The `_site/` directory
|
||||
* The `_site/index.html` file
|
||||
|
||||
====================================
|
||||
|
||||
[float]
|
||||
=== Plugin descriptor file
|
||||
|
||||
|
@ -43,7 +27,7 @@ instance, see
|
|||
https://github.com/elastic/elasticsearch/blob/master/plugins/site-example/build.gradle[`/plugins/site-example/build.gradle`].
|
||||
|
||||
[float]
|
||||
==== Mandatory elements for all plugins
|
||||
==== Mandatory elements for plugins
|
||||
|
||||
|
||||
[cols="<,<,<",options="header",]
|
||||
|
@ -56,23 +40,6 @@ https://github.com/elastic/elasticsearch/blob/master/plugins/site-example/build.
|
|||
|
||||
|`name` |String | the plugin name
|
||||
|
||||
|=======================================================================
|
||||
|
||||
|
||||
|
||||
[float]
|
||||
==== Mandatory elements for Java plugins
|
||||
|
||||
|
||||
[cols="<,<,<",options="header",]
|
||||
|=======================================================================
|
||||
|Element | Type | Description
|
||||
|
||||
|`jvm` |Boolean | true if the `classname` class should be loaded
|
||||
from jar files in the root directory of the plugin.
|
||||
Note that only jar files in the root directory are added to the classpath for the plugin!
|
||||
If you need other resources, package them into a resources jar.
|
||||
|
||||
|`classname` |String | the name of the class to load, fully-qualified.
|
||||
|
||||
|`java.version` |String | version of java the code is built against.
|
||||
|
@ -83,6 +50,9 @@ of nonnegative decimal integers separated by "."'s and may have leading zeros.
|
|||
|
||||
|=======================================================================
|
||||
|
||||
Note that only jar files in the root directory are added to the classpath for the plugin!
|
||||
If you need other resources, package them into a resources jar.
|
||||
|
||||
[IMPORTANT]
|
||||
.Plugin release lifecycle
|
||||
==============================================
|
||||
|
@ -94,20 +64,6 @@ in the presence of plugins with the incorrect `elasticsearch.version`.
|
|||
==============================================
|
||||
|
||||
|
||||
[float]
|
||||
==== Mandatory elements for Site plugins
|
||||
|
||||
|
||||
[cols="<,<,<",options="header",]
|
||||
|=======================================================================
|
||||
|Element | Type | Description
|
||||
|
||||
|`site` |Boolean | true to indicate contents of the `_site/`
|
||||
directory in the root of the plugin should be served.
|
||||
|
||||
|=======================================================================
|
||||
|
||||
|
||||
[float]
|
||||
=== Testing your plugin
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ consult this table:
|
|||
|2.x |3.x |<<restart-upgrade,Full cluster restart>>
|
||||
|=======================================================================
|
||||
|
||||
TIP: Take plugins into consideration as well when upgrading. Most plugins will have to be upgraded alongside Elasticsearch, although some plugins accessed primarily through the browser (`_site` plugins) may continue to work given that API changes are compatible.
|
||||
TIP: Take plugins into consideration as well when upgrading. Plugins must be upgraded alongside Elasticsearch.
|
||||
|
||||
include::backup.asciidoc[]
|
||||
|
||||
|
|
|
@ -39,8 +39,5 @@ subprojects {
|
|||
if (esplugin.isolated == false) {
|
||||
throw new InvalidModelException("Modules cannot disable isolation")
|
||||
}
|
||||
if (esplugin.jvm == false) {
|
||||
throw new InvalidModelException("Modules must be jvm plugins")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.modules.0.name: lang-expression }
|
||||
- match: { nodes.$master.modules.0.jvm: true }
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.modules.0.name: lang-groovy }
|
||||
- match: { nodes.$master.modules.0.jvm: true }
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.modules.0.name: lang-mustache }
|
||||
- match: { nodes.$master.modules.0.jvm: true }
|
||||
|
||||
---
|
||||
"Indexed template":
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: discovery-azure }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: discovery-ec2 }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: discovery-gce }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: discovery-multicast }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: jvm-example }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: lang-plan-a }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: mapper-attachments }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: repository-azure }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: repository-hdfs }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
---
|
||||
#
|
||||
# Check that we can't use file:// repositories or anything like that
|
||||
|
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: repository-s3 }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -1,27 +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.
|
||||
*/
|
||||
|
||||
esplugin {
|
||||
description 'Demonstrates how to serve resources via elasticsearch.'
|
||||
jvm false
|
||||
site true
|
||||
}
|
||||
|
||||
// no unit tests
|
||||
test.enabled = false
|
|
@ -1,6 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Page title</title>
|
||||
</head>
|
||||
<body>Page body</body>
|
||||
</html>
|
|
@ -1,59 +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.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.elasticsearch.common.network.NetworkAddress;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ExternalTestCluster;
|
||||
import org.elasticsearch.test.TestCluster;
|
||||
import org.elasticsearch.test.rest.client.RestResponse;
|
||||
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* verifies content is actually served for the site plugin
|
||||
*/
|
||||
public class SiteContentsIT extends ESIntegTestCase {
|
||||
|
||||
// TODO: probably a better way to test, but we don't want to really
|
||||
// define a fake rest spec or anything?
|
||||
public void test() throws Exception {
|
||||
TestCluster cluster = cluster();
|
||||
assumeTrue("this test will not work from an IDE unless you pass tests.cluster pointing to a running instance", cluster instanceof ExternalTestCluster);
|
||||
ExternalTestCluster externalCluster = (ExternalTestCluster) cluster;
|
||||
try (CloseableHttpClient httpClient = HttpClients.createMinimal(new PoolingHttpClientConnectionManager(15, TimeUnit.SECONDS))) {
|
||||
for (InetSocketAddress address : externalCluster.httpAddresses()) {
|
||||
RestResponse restResponse = new RestResponse(
|
||||
new HttpRequestBuilder(httpClient)
|
||||
.host(NetworkAddress.formatAddress(address.getAddress())).port(address.getPort())
|
||||
.path("/_plugin/site-example/")
|
||||
.method("GET").execute());
|
||||
assertEquals(200, restResponse.getStatusCode());
|
||||
String body = restResponse.getBodyAsString();
|
||||
assertTrue("unexpected body contents: " + body, body.contains("<body>Page body</body>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,41 +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 com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SiteRestIT extends ESRestTestCase {
|
||||
|
||||
public SiteRestIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
# Integration tests for Example site plugin
|
||||
#
|
||||
"Example site loaded":
|
||||
- do:
|
||||
cluster.state: {}
|
||||
|
||||
# Get master node id
|
||||
- set: { master_node: master }
|
||||
|
||||
- do:
|
||||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: site-example }
|
||||
- match: { nodes.$master.plugins.0.jvm: false }
|
||||
- match: { nodes.$master.plugins.0.site: true }
|
|
@ -11,4 +11,3 @@
|
|||
nodes.info: {}
|
||||
|
||||
- match: { nodes.$master.plugins.0.name: store-smb }
|
||||
- match: { nodes.$master.plugins.0.jvm: true }
|
||||
|
|
|
@ -196,7 +196,6 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
assertStatus("install", USAGE);
|
||||
}
|
||||
|
@ -216,7 +215,6 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
|
||||
Path binDir = environment.binFile();
|
||||
|
@ -260,7 +258,6 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
|
||||
Path pluginConfigDir = environment.configFile().resolve(pluginName);
|
||||
|
@ -296,7 +293,6 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"version", "2.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
|
||||
assertStatusOk(String.format(Locale.ROOT, "install %s --verbose", pluginUrl));
|
||||
|
@ -361,7 +357,6 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
|
||||
Path binDir = environment.binFile();
|
||||
|
@ -392,16 +387,13 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
System.err.println("install " + pluginUrl + " --verbose");
|
||||
ExitStatus status = new PluginManagerCliParser(terminal).execute(args("install " + pluginUrl + " --verbose"));
|
||||
assertThat("Terminal output was: " + terminal.getTerminalOutput(), status, is(ExitStatus.OK));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("Name: fake-plugin")));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("Description: fake desc")));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("Site: false")));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("Version: 1.0")));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("JVM: true")));
|
||||
assertThatPluginIsListed(pluginName);
|
||||
}
|
||||
|
||||
|
@ -414,7 +406,6 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
ExitStatus status = new PluginManagerCliParser(terminal).execute(args("install " + pluginUrl));
|
||||
assertThat("Terminal output was: " + terminal.getTerminalOutput(), status, is(ExitStatus.OK));
|
||||
|
@ -447,7 +438,6 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"isolated", "false",
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
|
||||
// install
|
||||
|
@ -465,63 +455,20 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
assertTrue(foundExpectedMessage);
|
||||
}
|
||||
|
||||
public void testInstallSitePluginVerbose() throws IOException {
|
||||
String pluginName = "fake-plugin";
|
||||
Path pluginDir = createTempDir().resolve(pluginName);
|
||||
Files.createDirectories(pluginDir.resolve("_site"));
|
||||
Files.createFile(pluginDir.resolve("_site").resolve("somefile"));
|
||||
String pluginUrl = createPlugin(pluginDir,
|
||||
"description", "fake desc",
|
||||
"name", pluginName,
|
||||
"version", "1.0",
|
||||
"site", "true");
|
||||
ExitStatus status = new PluginManagerCliParser(terminal).execute(args("install " + pluginUrl + " --verbose"));
|
||||
assertThat("Terminal output was: " + terminal.getTerminalOutput(), status, is(ExitStatus.OK));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("Name: fake-plugin")));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("Description: fake desc")));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("Site: true")));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("Version: 1.0")));
|
||||
assertThat(terminal.getTerminalOutput(), hasItem(containsString("JVM: false")));
|
||||
assertThatPluginIsListed(pluginName);
|
||||
// We want to check that Plugin Manager moves content to _site
|
||||
assertFileExists(environment.pluginsFile().resolve(pluginName).resolve("_site"));
|
||||
}
|
||||
|
||||
public void testInstallSitePlugin() throws IOException {
|
||||
String pluginName = "fake-plugin";
|
||||
Path pluginDir = createTempDir().resolve(pluginName);
|
||||
Files.createDirectories(pluginDir.resolve("_site"));
|
||||
Files.createFile(pluginDir.resolve("_site").resolve("somefile"));
|
||||
String pluginUrl = createPlugin(pluginDir,
|
||||
"description", "fake desc",
|
||||
"name", pluginName,
|
||||
"version", "1.0",
|
||||
"site", "true");
|
||||
ExitStatus status = new PluginManagerCliParser(terminal).execute(args("install " + pluginUrl));
|
||||
assertThat("Terminal output was: " + terminal.getTerminalOutput(), status, is(ExitStatus.OK));
|
||||
assertThat(terminal.getTerminalOutput(), not(hasItem(containsString("Name: fake-plugin"))));
|
||||
assertThat(terminal.getTerminalOutput(), not(hasItem(containsString("Description:"))));
|
||||
assertThat(terminal.getTerminalOutput(), not(hasItem(containsString("Site:"))));
|
||||
assertThat(terminal.getTerminalOutput(), not(hasItem(containsString("Version:"))));
|
||||
assertThat(terminal.getTerminalOutput(), not(hasItem(containsString("JVM:"))));
|
||||
assertThatPluginIsListed(pluginName);
|
||||
// We want to check that Plugin Manager moves content to _site
|
||||
assertFileExists(environment.pluginsFile().resolve(pluginName).resolve("_site"));
|
||||
}
|
||||
|
||||
public void testInstallPluginWithBadChecksum() throws IOException {
|
||||
String pluginName = "fake-plugin";
|
||||
Path pluginDir = createTempDir().resolve(pluginName);
|
||||
Files.createDirectories(pluginDir.resolve("_site"));
|
||||
Files.createFile(pluginDir.resolve("_site").resolve("somefile"));
|
||||
String pluginUrl = createPluginWithBadChecksum(pluginDir,
|
||||
"description", "fake desc",
|
||||
"version", "1.0",
|
||||
"site", "true");
|
||||
"description", "fake desc",
|
||||
"name", pluginName,
|
||||
"version", "1.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"classname", "FakePlugin");
|
||||
assertStatus(String.format(Locale.ROOT, "install %s --verbose", pluginUrl),
|
||||
ExitStatus.IO_ERROR);
|
||||
assertThatPluginIsNotListed(pluginName);
|
||||
assertFileNotExists(environment.pluginsFile().resolve(pluginName).resolve("_site"));
|
||||
assertFileNotExists(environment.pluginsFile().resolve(pluginName));
|
||||
}
|
||||
|
||||
private void singlePluginInstallAndRemove(String pluginDescriptor, String pluginName, String pluginCoordinates) throws IOException {
|
||||
|
@ -606,7 +553,6 @@ public class PluginManagerTests extends ESIntegTestCase {
|
|||
"version", "1.0.0",
|
||||
"elasticsearch.version", Version.CURRENT.toString(),
|
||||
"java.version", System.getProperty("java.specification.version"),
|
||||
"jvm", "true",
|
||||
"classname", "FakePlugin");
|
||||
|
||||
// We want to remove plugin with plugin short name
|
||||
|
|
|
@ -263,12 +263,6 @@ fi
|
|||
install_and_check_plugin repository s3 aws-java-sdk-core-*.jar
|
||||
}
|
||||
|
||||
@test "[$GROUP] install site example" {
|
||||
# Doesn't use install_and_check_plugin because this is a site plugin
|
||||
install_plugin site-example $(readlink -m site-example-*.zip)
|
||||
assert_file_exist "$ESHOME/plugins/site-example/_site/index.html"
|
||||
}
|
||||
|
||||
@test "[$GROUP] install store-smb plugin" {
|
||||
install_and_check_plugin store smb
|
||||
}
|
||||
|
|
|
@ -10,7 +10,5 @@
|
|||
name .+ \n
|
||||
component .+ \n
|
||||
version .+ \n
|
||||
type .+ \n
|
||||
url .+ \n
|
||||
description .+ \n
|
||||
$/
|
||||
|
|
|
@ -34,7 +34,6 @@ List projects = [
|
|||
'plugins:repository-hdfs',
|
||||
'plugins:repository-s3',
|
||||
'plugins:jvm-example',
|
||||
'plugins:site-example',
|
||||
'plugins:store-smb',
|
||||
'qa:evil-tests',
|
||||
'qa:smoke-test-client',
|
||||
|
|
|
@ -154,11 +154,9 @@ public class BootstrapForTesting {
|
|||
try (InputStream stream = url.openStream()) {
|
||||
properties.load(stream);
|
||||
}
|
||||
if (Boolean.parseBoolean(properties.getProperty("jvm"))) {
|
||||
String clazz = properties.getProperty("classname");
|
||||
if (clazz != null) {
|
||||
Class.forName(clazz);
|
||||
}
|
||||
String clazz = properties.getProperty("classname");
|
||||
if (clazz != null) {
|
||||
Class.forName(clazz);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -731,82 +731,6 @@ public class ElasticsearchAssertions {
|
|||
return response;
|
||||
}
|
||||
|
||||
public static void assertNodeContainsPlugins(NodesInfoResponse response, String nodeId,
|
||||
List<String> expectedJvmPluginNames,
|
||||
List<String> expectedJvmPluginDescriptions,
|
||||
List<String> expectedJvmVersions,
|
||||
List<String> expectedSitePluginNames,
|
||||
List<String> expectedSitePluginDescriptions,
|
||||
List<String> expectedSiteVersions) {
|
||||
|
||||
Assert.assertThat(response.getNodesMap().get(nodeId), notNullValue());
|
||||
|
||||
PluginsAndModules plugins = response.getNodesMap().get(nodeId).getPlugins();
|
||||
Assert.assertThat(plugins, notNullValue());
|
||||
|
||||
List<String> pluginNames = filterAndMap(plugins, jvmPluginPredicate, nameFunction);
|
||||
for (String expectedJvmPluginName : expectedJvmPluginNames) {
|
||||
Assert.assertThat(pluginNames, hasItem(expectedJvmPluginName));
|
||||
}
|
||||
|
||||
List<String> pluginDescriptions = filterAndMap(plugins, jvmPluginPredicate, descriptionFunction);
|
||||
for (String expectedJvmPluginDescription : expectedJvmPluginDescriptions) {
|
||||
Assert.assertThat(pluginDescriptions, hasItem(expectedJvmPluginDescription));
|
||||
}
|
||||
|
||||
List<String> jvmPluginVersions = filterAndMap(plugins, jvmPluginPredicate, versionFunction);
|
||||
for (String pluginVersion : expectedJvmVersions) {
|
||||
Assert.assertThat(jvmPluginVersions, hasItem(pluginVersion));
|
||||
}
|
||||
|
||||
boolean anyHaveUrls =
|
||||
plugins
|
||||
.getPluginInfos()
|
||||
.stream()
|
||||
.filter(jvmPluginPredicate.and(sitePluginPredicate.negate()))
|
||||
.map(urlFunction)
|
||||
.anyMatch(p -> p != null);
|
||||
assertFalse(anyHaveUrls);
|
||||
|
||||
List<String> sitePluginNames = filterAndMap(plugins, sitePluginPredicate, nameFunction);
|
||||
|
||||
Assert.assertThat(sitePluginNames.isEmpty(), is(expectedSitePluginNames.isEmpty()));
|
||||
for (String expectedSitePluginName : expectedSitePluginNames) {
|
||||
Assert.assertThat(sitePluginNames, hasItem(expectedSitePluginName));
|
||||
}
|
||||
|
||||
List<String> sitePluginDescriptions = filterAndMap(plugins, sitePluginPredicate, descriptionFunction);
|
||||
Assert.assertThat(sitePluginDescriptions.isEmpty(), is(expectedSitePluginDescriptions.isEmpty()));
|
||||
for (String sitePluginDescription : expectedSitePluginDescriptions) {
|
||||
Assert.assertThat(sitePluginDescriptions, hasItem(sitePluginDescription));
|
||||
}
|
||||
|
||||
List<String> sitePluginUrls = filterAndMap(plugins, sitePluginPredicate, urlFunction);
|
||||
Assert.assertThat(sitePluginUrls, not(contains(nullValue())));
|
||||
|
||||
List<String> sitePluginVersions = filterAndMap(plugins, sitePluginPredicate, versionFunction);
|
||||
Assert.assertThat(sitePluginVersions.isEmpty(), is(expectedSiteVersions.isEmpty()));
|
||||
for (String pluginVersion : expectedSiteVersions) {
|
||||
Assert.assertThat(sitePluginVersions, hasItem(pluginVersion));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> filterAndMap(PluginsAndModules pluginsInfo, Predicate<PluginInfo> predicate, Function<PluginInfo, String> function) {
|
||||
return pluginsInfo.getPluginInfos().stream().filter(predicate).map(function).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Predicate<PluginInfo> jvmPluginPredicate = p -> p.isJvm();
|
||||
|
||||
private static Predicate<PluginInfo> sitePluginPredicate = p -> p.isSite();
|
||||
|
||||
private static Function<PluginInfo, String> nameFunction = p -> p.getName();
|
||||
|
||||
private static Function<PluginInfo, String> descriptionFunction = p -> p.getDescription();
|
||||
|
||||
private static Function<PluginInfo, String> urlFunction = p -> p.getUrl();
|
||||
|
||||
private static Function<PluginInfo, String> versionFunction = p -> p.getVersion();
|
||||
|
||||
/**
|
||||
* Check if a file exists
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue