Scripting: allow plugins to define custom operations that they use scripts for
Plugins can now define multiple operations/contexts that they use scripts for. Fine-grained settings can then be used to enable/disable scripts based on each single registered context. Also added a new generic category called `plugin`, which will be used as a default when the context is not specified. This allows us to restore backwards compatibility for plugins on `ScriptService` by restoring the old methods that don't require the script context and making them internally use the `plugin` context, as they can only be called from plugins. Closes #10347 Closes #10419
This commit is contained in:
parent
5d4a4fc3ff
commit
7bd7ea8f13
|
@ -300,12 +300,17 @@ supported operations are:
|
|||
| `mapping` |Mappings (script transform feature)
|
||||
| `search` |Search api, Percolator api and Suggester api (e.g filters, script_fields)
|
||||
| `update` |Update api
|
||||
| `plugin` |Any plugin that makes use of scripts under the generic `plugin` category
|
||||
|=======================================================================
|
||||
|
||||
Plugins can also define custom operations that they use scripts for instead
|
||||
of using the generic `plugin` category. Those operations can be referred to
|
||||
in the following form: `${pluginName}_${operation}`.
|
||||
|
||||
The following example disables scripting for `update` and `mapping` operations,
|
||||
regardless of the script source, for any engine. Scripts can still be
|
||||
executed from sandboxed languages as part of `aggregations` and `search`
|
||||
operations though, as the above defaults still get applied.
|
||||
executed from sandboxed languages as part of `aggregations`, `search`
|
||||
and plugins execution though, as the above defaults still get applied.
|
||||
|
||||
[source,yaml]
|
||||
-----------------------------------
|
||||
|
@ -325,14 +330,17 @@ script.engine.groovy.file.aggs: on
|
|||
script.engine.groovy.file.mapping: on
|
||||
script.engine.groovy.file.search: on
|
||||
script.engine.groovy.file.update: on
|
||||
script.engine.groovy.file.plugin: on
|
||||
script.engine.groovy.indexed.aggs: on
|
||||
script.engine.groovy.indexed.mapping: off
|
||||
script.engine.groovy.indexed.search: on
|
||||
script.engine.groovy.indexed.update: off
|
||||
script.engine.groovy.indexed.plugin: off
|
||||
script.engine.groovy.inline.aggs: on
|
||||
script.engine.groovy.inline.mapping: off
|
||||
script.engine.groovy.inline.search: off
|
||||
script.engine.groovy.inline.update: off
|
||||
script.engine.groovy.inline.plugin: off
|
||||
|
||||
-----------------------------------
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ public class UpdateHelper extends AbstractComponent {
|
|||
ctx.put("op", "create");
|
||||
ctx.put("_source", upsertDoc);
|
||||
try {
|
||||
ExecutableScript script = scriptService.executable(request.scriptLang, request.script, request.scriptType, ScriptContext.UPDATE, request.scriptParams);
|
||||
ExecutableScript script = scriptService.executable(request.scriptLang, request.script, request.scriptType, ScriptContext.Standard.UPDATE, request.scriptParams);
|
||||
script.setNextVar("ctx", ctx);
|
||||
script.run();
|
||||
// we need to unwrap the ctx...
|
||||
|
@ -193,7 +193,7 @@ public class UpdateHelper extends AbstractComponent {
|
|||
ctx.put("_source", sourceAndContent.v2());
|
||||
|
||||
try {
|
||||
ExecutableScript script = scriptService.executable(request.scriptLang, request.script, request.scriptType, ScriptContext.UPDATE, request.scriptParams);
|
||||
ExecutableScript script = scriptService.executable(request.scriptLang, request.script, request.scriptType, ScriptContext.Standard.UPDATE, request.scriptParams);
|
||||
script.setNextVar("ctx", ctx);
|
||||
script.run();
|
||||
// we need to unwrap the ctx...
|
||||
|
|
|
@ -64,8 +64,9 @@ import org.elasticsearch.index.mapper.internal.VersionFieldMapper;
|
|||
import org.elasticsearch.index.mapper.object.ObjectMapper;
|
||||
import org.elasticsearch.index.mapper.object.RootObjectMapper;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -79,7 +80,6 @@ import java.util.Set;
|
|||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static org.elasticsearch.script.ScriptService.*;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -760,7 +760,7 @@ public class DocumentMapper implements ToXContent {
|
|||
public Map<String, Object> transformSourceAsMap(Map<String, Object> sourceAsMap) {
|
||||
try {
|
||||
// We use the ctx variable and the _source name to be consistent with the update api.
|
||||
ExecutableScript executable = scriptService.executable(language, script, scriptType, ScriptContext.MAPPING, parameters);
|
||||
ExecutableScript executable = scriptService.executable(language, script, scriptType, ScriptContext.Standard.MAPPING, parameters);
|
||||
Map<String, Object> ctx = new HashMap<>(1);
|
||||
ctx.put("_source", sourceAsMap);
|
||||
executable.setNextVar("ctx", ctx);
|
||||
|
|
|
@ -134,7 +134,7 @@ public class ScriptFilterParser implements FilterParser {
|
|||
public ScriptFilter(String scriptLang, String script, ScriptService.ScriptType scriptType, Map<String, Object> params, ScriptService scriptService, SearchLookup searchLookup) {
|
||||
this.script = script;
|
||||
this.params = params;
|
||||
this.searchScript = scriptService.search(searchLookup, scriptLang, script, scriptType, ScriptContext.SEARCH, newHashMap(params));
|
||||
this.searchScript = scriptService.search(searchLookup, scriptLang, script, scriptType, ScriptContext.Standard.SEARCH, newHashMap(params));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,8 +26,8 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -77,7 +77,7 @@ public class TemplateQueryParser implements QueryParser {
|
|||
public Query parse(QueryParseContext parseContext) throws IOException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
TemplateContext templateContext = parse(parser, PARAMS, parametersToTypes);
|
||||
ExecutableScript executable = this.scriptService.executable(MustacheScriptEngineService.NAME, templateContext.template(), templateContext.scriptType(), ScriptContext.SEARCH, templateContext.params());
|
||||
ExecutableScript executable = this.scriptService.executable(MustacheScriptEngineService.NAME, templateContext.template(), templateContext.scriptType(), ScriptContext.Standard.SEARCH, templateContext.params());
|
||||
|
||||
BytesReference querySource = (BytesReference) executable.run();
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ public class ScriptScoreFunctionParser implements ScoreFunctionParser {
|
|||
|
||||
SearchScript searchScript;
|
||||
try {
|
||||
searchScript = parseContext.scriptService().search(parseContext.lookup(), scriptParameterParser.lang(), script, scriptType, ScriptContext.SEARCH, vars);
|
||||
searchScript = parseContext.scriptService().search(parseContext.lookup(), scriptParameterParser.lang(), script, scriptType, ScriptContext.Standard.SEARCH, vars);
|
||||
return new ScriptScoreFunction(script, vars, searchScript);
|
||||
} catch (Exception e) {
|
||||
throw new QueryParsingException(parseContext.index(), NAMES[0] + " the script could not be loaded", e);
|
||||
|
|
|
@ -19,20 +19,95 @@
|
|||
|
||||
package org.elasticsearch.script;
|
||||
|
||||
import java.util.Locale;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
|
||||
/**
|
||||
* Operation/api that uses a script as part of its execution.
|
||||
* Note that the suggest api is considered part of search for simplicity, as well as the percolate api.
|
||||
* Context of an operation that uses scripts as part of its execution.
|
||||
*/
|
||||
public enum ScriptContext {
|
||||
MAPPING,
|
||||
UPDATE,
|
||||
SEARCH,
|
||||
AGGS;
|
||||
public interface ScriptContext {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
/**
|
||||
* @return the name of the operation
|
||||
*/
|
||||
String getKey();
|
||||
|
||||
/**
|
||||
* Standard operations that make use of scripts as part of their execution.
|
||||
* Note that the suggest api is considered part of search for simplicity, as well as the percolate api.
|
||||
*/
|
||||
enum Standard implements ScriptContext {
|
||||
|
||||
AGGS("aggs"), MAPPING("mapping"), SEARCH("search"), UPDATE("update"),
|
||||
/**
|
||||
* Generic custom operation exposed via plugin
|
||||
*
|
||||
* @deprecated create a new {@link org.elasticsearch.script.ScriptContext.Plugin} instance instead
|
||||
*/
|
||||
@Deprecated
|
||||
GENERIC_PLUGIN("plugin");
|
||||
|
||||
private final String key;
|
||||
|
||||
Standard(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom operation exposed via plugin, which makes use of scripts as part of its execution
|
||||
*/
|
||||
final class Plugin implements ScriptContext {
|
||||
|
||||
private final String pluginName;
|
||||
private final String operation;
|
||||
private final String key;
|
||||
|
||||
/**
|
||||
* Creates a new custom scripts based operation exposed via plugin.
|
||||
* The name of the plugin combined with the operation name can be used to enable/disable scripts via fine-grained settings.
|
||||
*
|
||||
* @param pluginName the name of the plugin
|
||||
* @param operation the name of the operation
|
||||
*/
|
||||
public Plugin(String pluginName, String operation) {
|
||||
if (Strings.hasLength(pluginName) == false) {
|
||||
throw new ElasticsearchIllegalArgumentException("plugin name cannot be empty when registering a custom script context");
|
||||
}
|
||||
if (Strings.hasLength(operation) == false) {
|
||||
throw new ElasticsearchIllegalArgumentException("operation name cannot be empty when registering a custom script context");
|
||||
}
|
||||
this.pluginName = pluginName;
|
||||
this.operation = operation;
|
||||
this.key = pluginName + "_" + operation;
|
||||
}
|
||||
|
||||
public final String getPluginName() {
|
||||
return pluginName;
|
||||
}
|
||||
|
||||
public final String getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Registry for operations that use scripts as part of their execution. Can be standard operations of custom defined ones (via plugin).
|
||||
* Allows plugins to register custom operations that they use scripts for, via {@link ScriptModule#registerScriptContext(org.elasticsearch.script.ScriptContext.Plugin)}.
|
||||
* Scripts can be enabled/disabled via fine-grained settings for each single registered operation.
|
||||
*/
|
||||
public final class ScriptContextRegistry {
|
||||
static final ImmutableSet<String> RESERVED_SCRIPT_CONTEXTS = reservedScriptContexts();
|
||||
|
||||
private final ImmutableMap<String, ScriptContext> scriptContexts;
|
||||
|
||||
ScriptContextRegistry(Iterable<ScriptContext.Plugin> customScriptContexts) {
|
||||
Map<String, ScriptContext> scriptContexts = Maps.newHashMap();
|
||||
for (ScriptContext.Standard scriptContext : ScriptContext.Standard.values()) {
|
||||
scriptContexts.put(scriptContext.getKey(), scriptContext);
|
||||
}
|
||||
for (ScriptContext.Plugin customScriptContext : customScriptContexts) {
|
||||
validateScriptContext(customScriptContext);
|
||||
ScriptContext previousContext = scriptContexts.put(customScriptContext.getKey(), customScriptContext);
|
||||
if (previousContext != null) {
|
||||
throw new ElasticsearchIllegalArgumentException("script context [" + customScriptContext.getKey() + "] cannot be registered twice");
|
||||
}
|
||||
}
|
||||
this.scriptContexts = ImmutableMap.copyOf(scriptContexts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a list that contains all the supported {@link ScriptContext}s, both standard ones and registered via plugins
|
||||
*/
|
||||
ImmutableCollection<ScriptContext> scriptContexts() {
|
||||
return scriptContexts.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <tt>true</tt> if the provided {@link ScriptContext} is supported, <tt>false</tt> otherwise
|
||||
*/
|
||||
boolean isSupportedContext(ScriptContext scriptContext) {
|
||||
return scriptContexts.containsKey(scriptContext.getKey());
|
||||
}
|
||||
|
||||
//script contexts can be used in fine-grained settings, we need to be careful with what we allow here
|
||||
private void validateScriptContext(ScriptContext.Plugin scriptContext) {
|
||||
if (RESERVED_SCRIPT_CONTEXTS.contains(scriptContext.getPluginName())) {
|
||||
throw new ElasticsearchIllegalArgumentException("[" + scriptContext.getPluginName() + "] is a reserved name, it cannot be registered as a custom script context");
|
||||
}
|
||||
if (RESERVED_SCRIPT_CONTEXTS.contains(scriptContext.getOperation())) {
|
||||
throw new ElasticsearchIllegalArgumentException("[" + scriptContext.getOperation() + "] is a reserved name, it cannot be registered as a custom script context");
|
||||
}
|
||||
}
|
||||
|
||||
private static ImmutableSet<String> reservedScriptContexts() {
|
||||
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
|
||||
for (ScriptService.ScriptType scriptType : ScriptService.ScriptType.values()) {
|
||||
builder.add(scriptType.toString());
|
||||
}
|
||||
for (ScriptContext.Standard scriptContext : ScriptContext.Standard.values()) {
|
||||
builder.add(scriptContext.getKey());
|
||||
}
|
||||
builder.add("script").add("engine");
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -42,45 +42,45 @@ public class ScriptModes {
|
|||
|
||||
final ImmutableMap<String, ScriptMode> scriptModes;
|
||||
|
||||
ScriptModes(Map<String, ScriptEngineService> scriptEngines, Settings settings) {
|
||||
ScriptModes(Map<String, ScriptEngineService> scriptEngines, ScriptContextRegistry scriptContextRegistry, Settings settings) {
|
||||
//filter out the native engine as we don't want to apply fine grained settings to it.
|
||||
//native scripts are always on as they are static by definition.
|
||||
Map<String, ScriptEngineService> filteredEngines = Maps.newHashMap(scriptEngines);
|
||||
filteredEngines.remove(NativeScriptEngineService.NAME);
|
||||
this.scriptModes = buildScriptModeSettingsMap(settings, filteredEngines);
|
||||
this.scriptModes = buildScriptModeSettingsMap(settings, filteredEngines, scriptContextRegistry);
|
||||
}
|
||||
|
||||
private ImmutableMap<String, ScriptMode> buildScriptModeSettingsMap(Settings settings, Map<String, ScriptEngineService> scriptEngines) {
|
||||
private static ImmutableMap<String, ScriptMode> buildScriptModeSettingsMap(Settings settings, Map<String, ScriptEngineService> scriptEngines, ScriptContextRegistry scriptContextRegistry) {
|
||||
HashMap<String, ScriptMode> scriptModesMap = Maps.newHashMap();
|
||||
|
||||
//file scripts are enabled by default, for any language
|
||||
addGlobalScriptTypeModes(scriptEngines.keySet(), ScriptType.FILE, ScriptMode.ON, scriptModesMap);
|
||||
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.FILE, ScriptMode.ON, scriptModesMap);
|
||||
//indexed scripts are enabled by default only for sandboxed languages
|
||||
addGlobalScriptTypeModes(scriptEngines.keySet(), ScriptType.INDEXED, ScriptMode.SANDBOX, scriptModesMap);
|
||||
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.INDEXED, ScriptMode.SANDBOX, scriptModesMap);
|
||||
//dynamic scripts are enabled by default only for sandboxed languages
|
||||
addGlobalScriptTypeModes(scriptEngines.keySet(), ScriptType.INLINE, ScriptMode.SANDBOX, scriptModesMap);
|
||||
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.INLINE, ScriptMode.SANDBOX, scriptModesMap);
|
||||
|
||||
processSourceBasedGlobalSettings(settings, scriptEngines, scriptModesMap);
|
||||
processOperationBasedGlobalSettings(settings, scriptEngines, scriptModesMap);
|
||||
processEngineSpecificSettings(settings, scriptEngines, scriptModesMap);
|
||||
processSourceBasedGlobalSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap);
|
||||
processOperationBasedGlobalSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap);
|
||||
processEngineSpecificSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap);
|
||||
return ImmutableMap.copyOf(scriptModesMap);
|
||||
}
|
||||
|
||||
private static void processSourceBasedGlobalSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, Map<String, ScriptMode> scriptModes) {
|
||||
private static void processSourceBasedGlobalSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, ScriptContextRegistry scriptContextRegistry, Map<String, ScriptMode> scriptModes) {
|
||||
//read custom source based settings for all operations (e.g. script.indexed: on)
|
||||
for (ScriptType scriptType : ScriptType.values()) {
|
||||
String scriptTypeSetting = settings.get(SCRIPT_SETTINGS_PREFIX + scriptType);
|
||||
if (Strings.hasLength(scriptTypeSetting)) {
|
||||
ScriptMode scriptTypeMode = ScriptMode.parse(scriptTypeSetting);
|
||||
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptType, scriptTypeMode, scriptModes);
|
||||
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, scriptType, scriptTypeMode, scriptModes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processOperationBasedGlobalSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, Map<String, ScriptMode> scriptModes) {
|
||||
private static void processOperationBasedGlobalSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, ScriptContextRegistry scriptContextRegistry, Map<String, ScriptMode> scriptModes) {
|
||||
//read custom op based settings for all sources (e.g. script.aggs: off)
|
||||
//op based settings take precedence over source based settings, hence they get expanded later
|
||||
for (ScriptContext scriptContext : ScriptContext.values()) {
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
ScriptMode scriptMode = getScriptContextMode(settings, SCRIPT_SETTINGS_PREFIX, scriptContext);
|
||||
if (scriptMode != null) {
|
||||
addGlobalScriptContextModes(scriptEngines.keySet(), scriptContext, scriptMode, scriptModes);
|
||||
|
@ -88,16 +88,15 @@ public class ScriptModes {
|
|||
}
|
||||
}
|
||||
|
||||
private static void processEngineSpecificSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, Map<String, ScriptMode> scriptModes) {
|
||||
private static void processEngineSpecificSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, ScriptContextRegistry scriptContextRegistry, Map<String, ScriptMode> scriptModes) {
|
||||
Map<String, Settings> langGroupedSettings = settings.getGroups(ENGINE_SETTINGS_PREFIX, true);
|
||||
for (Map.Entry<String, Settings> langSettings : langGroupedSettings.entrySet()) {
|
||||
//read engine specific settings that refer to a non existing script lang will be ignored
|
||||
ScriptEngineService scriptEngineService = scriptEngines.get(langSettings.getKey());
|
||||
if (scriptEngineService != null) {
|
||||
String enginePrefix = ScriptModes.ENGINE_SETTINGS_PREFIX + "." + langSettings.getKey() + ".";
|
||||
for (ScriptType scriptType : ScriptType.values()) {
|
||||
String scriptTypePrefix = scriptType + ".";
|
||||
for (ScriptContext scriptContext : ScriptContext.values()) {
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
ScriptMode scriptMode = getScriptContextMode(langSettings.getValue(), scriptTypePrefix, scriptContext);
|
||||
if (scriptMode != null) {
|
||||
addScriptMode(scriptEngineService, scriptType, scriptContext, scriptMode, scriptModes);
|
||||
|
@ -109,16 +108,16 @@ public class ScriptModes {
|
|||
}
|
||||
|
||||
private static ScriptMode getScriptContextMode(Settings settings, String prefix, ScriptContext scriptContext) {
|
||||
String settingValue = settings.get(prefix + scriptContext);
|
||||
String settingValue = settings.get(prefix + scriptContext.getKey());
|
||||
if (Strings.hasLength(settingValue)) {
|
||||
return ScriptMode.parse(settingValue);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void addGlobalScriptTypeModes(Set<String> langs, ScriptType scriptType, ScriptMode scriptMode, Map<String, ScriptMode> scriptModes) {
|
||||
private static void addGlobalScriptTypeModes(Set<String> langs, ScriptContextRegistry scriptContextRegistry, ScriptType scriptType, ScriptMode scriptMode, Map<String, ScriptMode> scriptModes) {
|
||||
for (String lang : langs) {
|
||||
for (ScriptContext scriptContext : ScriptContext.values()) {
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
addScriptMode(lang, scriptType, scriptContext, scriptMode, scriptModes);
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +140,7 @@ public class ScriptModes {
|
|||
}
|
||||
|
||||
private static void addScriptMode(String lang, ScriptType scriptType, ScriptContext scriptContext, ScriptMode scriptMode, Map<String, ScriptMode> scriptModes) {
|
||||
scriptModes.put(ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext, scriptMode);
|
||||
scriptModes.put(ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey(), scriptMode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,7 +149,7 @@ public class ScriptModes {
|
|||
*
|
||||
* @param lang the language that the script is written in
|
||||
* @param scriptType the type of the script
|
||||
* @param scriptContext the api that requires the execution of the script
|
||||
* @param scriptContext the operation that requires the execution of the script
|
||||
* @return whether scripts are on, off, or enabled only for sandboxed languages
|
||||
*/
|
||||
public ScriptMode getScriptMode(String lang, ScriptType scriptType, ScriptContext scriptContext) {
|
||||
|
@ -158,9 +157,9 @@ public class ScriptModes {
|
|||
if (NativeScriptEngineService.NAME.equals(lang)) {
|
||||
return ScriptMode.ON;
|
||||
}
|
||||
ScriptMode scriptMode = scriptModes.get(ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext);
|
||||
ScriptMode scriptMode = scriptModes.get(ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey());
|
||||
if (scriptMode == null) {
|
||||
throw new ElasticsearchIllegalArgumentException("script mode not found for lang [" + lang + "], script_type [" + scriptType + "], operation [" + scriptContext + "]");
|
||||
throw new ElasticsearchIllegalArgumentException("script mode not found for lang [" + lang + "], script_type [" + scriptType + "], operation [" + scriptContext.getKey() + "]");
|
||||
}
|
||||
return scriptMode;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ public class ScriptModule extends AbstractModule {
|
|||
|
||||
private final Map<String, Class<? extends NativeScriptFactory>> scripts = Maps.newHashMap();
|
||||
|
||||
private final List<ScriptContext.Plugin> customScriptContexts = Lists.newArrayList();
|
||||
|
||||
public ScriptModule(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
@ -58,6 +60,14 @@ public class ScriptModule extends AbstractModule {
|
|||
scripts.put(name, script);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom script context that can be used by plugins to categorize the different operations that they use scripts for.
|
||||
* Fine-grained settings allow to enable/disable scripts per context.
|
||||
*/
|
||||
public void registerScriptContext(ScriptContext.Plugin scriptContext) {
|
||||
customScriptContexts.add(scriptContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
MapBinder<String, NativeScriptFactory> scriptsBinder
|
||||
|
@ -105,6 +115,7 @@ public class ScriptModule extends AbstractModule {
|
|||
multibinder.addBinding().to(scriptEngine).asEagerSingleton();
|
||||
}
|
||||
|
||||
bind(ScriptContextRegistry.class).toInstance(new ScriptContextRegistry(customScriptContexts));
|
||||
bind(ScriptService.class).asEagerSingleton();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
private final FileWatcher fileWatcher;
|
||||
|
||||
private final ScriptModes scriptModes;
|
||||
private final ScriptContextRegistry scriptContextRegistry;
|
||||
|
||||
private Client client = null;
|
||||
|
||||
|
@ -113,7 +114,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
|
||||
@Inject
|
||||
public ScriptService(Settings settings, Environment env, Set<ScriptEngineService> scriptEngines,
|
||||
ResourceWatcherService resourceWatcherService, NodeSettingsService nodeSettingsService) throws IOException {
|
||||
ResourceWatcherService resourceWatcherService, NodeSettingsService nodeSettingsService, ScriptContextRegistry scriptContextRegistry) throws IOException {
|
||||
super(settings);
|
||||
|
||||
if (Strings.hasLength(settings.get(DISABLE_DYNAMIC_SCRIPTING_SETTING))) {
|
||||
|
@ -122,6 +123,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
}
|
||||
|
||||
this.scriptEngines = scriptEngines;
|
||||
this.scriptContextRegistry = scriptContextRegistry;
|
||||
int cacheMaxSize = settings.getAsInt(SCRIPT_CACHE_SIZE_SETTING, 100);
|
||||
TimeValue cacheExpire = settings.getAsTime(SCRIPT_CACHE_EXPIRE_SETTING, null);
|
||||
logger.debug("using script cache with max_size [{}], expire [{}]", cacheMaxSize, cacheExpire);
|
||||
|
@ -150,7 +152,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
this.scriptEnginesByLang = enginesByLangBuilder.build();
|
||||
this.scriptEnginesByExt = enginesByExtBuilder.build();
|
||||
|
||||
this.scriptModes = new ScriptModes(this.scriptEnginesByLang, settings);
|
||||
this.scriptModes = new ScriptModes(this.scriptEnginesByLang, scriptContextRegistry, settings);
|
||||
|
||||
// add file watcher for static scripts
|
||||
scriptsDirectory = env.configFile().resolve("scripts");
|
||||
|
@ -212,6 +214,18 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
return scriptEngineService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a script can be executed and compiles it if needed, or returns the previously compiled and cached script.
|
||||
* Doesn't require to specify a script context in order to maintain backwards compatibility, internally uses
|
||||
* the {@link org.elasticsearch.script.ScriptContext.Standard#GENERIC_PLUGIN} default context, assuming that it can only be called from plugins.
|
||||
*
|
||||
* @deprecated use the method variant that accepts the {@link ScriptContext} argument too: {@link #compile(String, String, ScriptType, ScriptContext)}
|
||||
*/
|
||||
@Deprecated
|
||||
public CompiledScript compile(String lang, String script, ScriptType scriptType) {
|
||||
return compile(lang, script, scriptType, ScriptContext.Standard.GENERIC_PLUGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a script can be executed and compiles it if needed, or returns the previously compiled and cached script.
|
||||
*/
|
||||
|
@ -226,7 +240,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
|
||||
ScriptEngineService scriptEngineService = getScriptEngineServiceForLang(lang);
|
||||
if (canExecuteScript(lang, scriptEngineService, scriptType, scriptContext) == false) {
|
||||
throw new ScriptException("scripts of type [" + scriptType + "], operation [" + scriptContext + "] and lang [" + lang + "] are disabled");
|
||||
throw new ScriptException("scripts of type [" + scriptType + "], operation [" + scriptContext.getKey() + "] and lang [" + lang + "] are disabled");
|
||||
}
|
||||
return compileInternal(lang, script, scriptType);
|
||||
}
|
||||
|
@ -380,6 +394,18 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles (or retrieves from cache) and executes the provided script.
|
||||
* Doesn't require to specify a script context in order to maintain backwards compatibility, internally uses
|
||||
* the {@link org.elasticsearch.script.ScriptContext.Standard#GENERIC_PLUGIN} default context, assuming that it can only be called from plugins.
|
||||
*
|
||||
* @deprecated use the method variant that accepts the {@link ScriptContext} argument too: {@link #executable(String, String, ScriptType, ScriptContext, Map)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ExecutableScript executable(String lang, String script, ScriptType scriptType, Map<String, Object> vars) {
|
||||
return executable(lang, script, scriptType, ScriptContext.Standard.GENERIC_PLUGIN, vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles (or retrieves from cache) and executes the provided script
|
||||
*/
|
||||
|
@ -394,6 +420,18 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
return getScriptEngineServiceForLang(compiledScript.lang()).executable(compiledScript.compiled(), vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles (or retrieves from cache) and executes the provided search script
|
||||
* Doesn't require to specify a script context in order to maintain backwards compatibility, internally uses
|
||||
* the {@link org.elasticsearch.script.ScriptContext.Standard#GENERIC_PLUGIN} default context, assuming that it can only be called from plugins.
|
||||
*
|
||||
* @deprecated use the method variant that accepts the {@link ScriptContext} argument too: {@link #search(SearchLookup, String, String, ScriptType, ScriptContext, Map)}
|
||||
*/
|
||||
@Deprecated
|
||||
public SearchScript search(SearchLookup lookup, String lang, String script, ScriptType scriptType, @Nullable Map<String, Object> vars) {
|
||||
return search(lookup, lang, script, scriptType, ScriptContext.Standard.GENERIC_PLUGIN, vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles (or retrieves from cache) and executes the provided search script
|
||||
*/
|
||||
|
@ -403,7 +441,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
}
|
||||
|
||||
private boolean isAnyScriptContextEnabled(String lang, ScriptEngineService scriptEngineService, ScriptType scriptType) {
|
||||
for (ScriptContext scriptContext : ScriptContext.values()) {
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
if (canExecuteScript(lang, scriptEngineService, scriptType, scriptContext)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -413,6 +451,9 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
|
||||
private boolean canExecuteScript(String lang, ScriptEngineService scriptEngineService, ScriptType scriptType, ScriptContext scriptContext) {
|
||||
assert lang != null;
|
||||
if (scriptContextRegistry.isSupportedContext(scriptContext) == false) {
|
||||
throw new ElasticsearchIllegalArgumentException("script context [" + scriptContext.getKey() + "] not supported");
|
||||
}
|
||||
ScriptMode mode = scriptModes.getScriptMode(lang, scriptType, scriptContext);
|
||||
switch (mode) {
|
||||
case ON:
|
||||
|
|
|
@ -71,8 +71,9 @@ import org.elasticsearch.indices.IndicesWarmer.TerminationHandle;
|
|||
import org.elasticsearch.indices.IndicesWarmer.WarmerContext;
|
||||
import org.elasticsearch.indices.cache.query.IndicesQueryCache;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
import org.elasticsearch.search.dfs.CachedDfSource;
|
||||
import org.elasticsearch.search.dfs.DfsPhase;
|
||||
|
@ -652,7 +653,7 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> {
|
|||
|
||||
final ExecutableScript executable;
|
||||
if (hasLength(request.templateName())) {
|
||||
executable = this.scriptService.executable(MustacheScriptEngineService.NAME, request.templateName(), request.templateType(), ScriptContext.SEARCH, request.templateParams());
|
||||
executable = this.scriptService.executable(MustacheScriptEngineService.NAME, request.templateName(), request.templateType(), ScriptContext.Standard.SEARCH, request.templateParams());
|
||||
} else {
|
||||
if (!hasLength(request.templateSource())) {
|
||||
return;
|
||||
|
@ -692,7 +693,7 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> {
|
|||
if (!hasLength(templateContext.template())) {
|
||||
throw new ElasticsearchParseException("Template must have [template] field configured");
|
||||
}
|
||||
executable = this.scriptService.executable(MustacheScriptEngineService.NAME, templateContext.template(), templateContext.scriptType(), ScriptContext.SEARCH, templateContext.params());
|
||||
executable = this.scriptService.executable(MustacheScriptEngineService.NAME, templateContext.template(), templateContext.scriptType(), ScriptContext.Standard.SEARCH, templateContext.params());
|
||||
}
|
||||
|
||||
BytesReference processedQuery = (BytesReference) executable.run();
|
||||
|
|
|
@ -30,10 +30,7 @@ import org.elasticsearch.common.logging.ESLoggerFactory;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParsingException;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.*;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -86,7 +83,7 @@ public class ScriptHeuristic extends SignificanceHeuristic {
|
|||
}
|
||||
|
||||
public void initialize(InternalAggregation.ReduceContext context) {
|
||||
script = context.scriptService().executable(scriptLang, scriptString, scriptType, ScriptContext.AGGS, params);
|
||||
script = context.scriptService().executable(scriptLang, scriptString, scriptType, ScriptContext.Standard.AGGS, params);
|
||||
script.setNextVar("_subset_freq", subsetDfHolder);
|
||||
script.setNextVar("_subset_size", subsetSizeHolder);
|
||||
script.setNextVar("_superset_freq", supersetDfHolder);
|
||||
|
@ -171,7 +168,7 @@ public class ScriptHeuristic extends SignificanceHeuristic {
|
|||
}
|
||||
ExecutableScript searchScript;
|
||||
try {
|
||||
searchScript = scriptService.executable(scriptLang, script, scriptType, ScriptContext.AGGS, params);
|
||||
searchScript = scriptService.executable(scriptLang, script, scriptType, ScriptContext.Standard.AGGS, params);
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchParseException("The script [" + script + "] could not be loaded", e);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ import org.elasticsearch.common.io.stream.StreamInput;
|
|||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.search.aggregations.AggregationStreams;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregation;
|
||||
import org.elasticsearch.search.aggregations.metrics.InternalMetricsAggregation;
|
||||
|
@ -99,7 +99,7 @@ public class InternalScriptedMetric extends InternalMetricsAggregation implement
|
|||
}
|
||||
params.put("_aggs", aggregationObjects);
|
||||
ExecutableScript script = reduceContext.scriptService().executable(firstAggregation.scriptLang, firstAggregation.reduceScript,
|
||||
firstAggregation.scriptType, ScriptContext.AGGS, params);
|
||||
firstAggregation.scriptType, ScriptContext.Standard.AGGS, params);
|
||||
aggregation = script.run();
|
||||
} else {
|
||||
aggregation = aggregationObjects;
|
||||
|
|
|
@ -23,9 +23,8 @@ import org.apache.lucene.index.LeafReaderContext;
|
|||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.LeafSearchScript;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.*;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
import org.elasticsearch.search.SearchParseException;
|
||||
import org.elasticsearch.search.aggregations.Aggregator;
|
||||
import org.elasticsearch.search.aggregations.AggregatorFactory;
|
||||
|
@ -75,11 +74,11 @@ public class ScriptedMetricAggregator extends MetricsAggregator {
|
|||
}
|
||||
ScriptService scriptService = context.searchContext().scriptService();
|
||||
if (initScript != null) {
|
||||
scriptService.executable(scriptLang, initScript, initScriptType, ScriptContext.AGGS, this.params).run();
|
||||
scriptService.executable(scriptLang, initScript, initScriptType, ScriptContext.Standard.AGGS, this.params).run();
|
||||
}
|
||||
this.mapScript = scriptService.search(context.searchContext().lookup(), scriptLang, mapScript, mapScriptType, ScriptContext.AGGS, this.params);
|
||||
this.mapScript = scriptService.search(context.searchContext().lookup(), scriptLang, mapScript, mapScriptType, ScriptContext.Standard.AGGS, this.params);
|
||||
if (combineScript != null) {
|
||||
this.combineScript = scriptService.executable(scriptLang, combineScript, combineScriptType, ScriptContext.AGGS, this.params);
|
||||
this.combineScript = scriptService.executable(scriptLang, combineScript, combineScriptType, ScriptContext.Standard.AGGS, this.params);
|
||||
} else {
|
||||
this.combineScript = null;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,8 @@ import org.elasticsearch.index.mapper.core.BooleanFieldMapper;
|
|||
import org.elasticsearch.index.mapper.core.DateFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.NumberFieldMapper;
|
||||
import org.elasticsearch.index.mapper.ip.IpFieldMapper;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.*;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
import org.elasticsearch.search.SearchParseException;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregation;
|
||||
import org.elasticsearch.search.aggregations.support.format.ValueFormat;
|
||||
|
@ -189,7 +186,7 @@ public class ValuesSourceParser<VS extends ValuesSource> {
|
|||
}
|
||||
|
||||
private SearchScript createScript() {
|
||||
return input.script == null ? null : context.scriptService().search(context.lookup(), input.lang, input.script, input.scriptType, ScriptContext.AGGS, input.params);
|
||||
return input.script == null ? null : context.scriptService().search(context.lookup(), input.lang, input.script, input.scriptType, ScriptContext.Standard.AGGS, input.params);
|
||||
}
|
||||
|
||||
private static ValueFormat resolveFormat(@Nullable String format, @Nullable ValueType valueType) {
|
||||
|
|
|
@ -20,11 +20,8 @@
|
|||
package org.elasticsearch.search.fetch.script;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.*;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
import org.elasticsearch.search.SearchParseElement;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
|
||||
|
@ -79,7 +76,7 @@ public class ScriptFieldsParseElement implements SearchParseElement {
|
|||
script = scriptValue.script();
|
||||
scriptType = scriptValue.scriptType();
|
||||
}
|
||||
SearchScript searchScript = context.scriptService().search(context.lookup(), scriptParameterParser.lang(), script, scriptType, ScriptContext.SEARCH, params);
|
||||
SearchScript searchScript = context.scriptService().search(context.lookup(), scriptParameterParser.lang(), script, scriptType, ScriptContext.Standard.SEARCH, params);
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(fieldName, searchScript, ignoreException));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ public class ScriptSortParser implements SortParser {
|
|||
if (type == null) {
|
||||
throw new SearchParseException(context, "_script sorting requires setting the type of the script");
|
||||
}
|
||||
final SearchScript searchScript = context.scriptService().search(context.lookup(), scriptLang, script, scriptType, ScriptContext.SEARCH, params);
|
||||
final SearchScript searchScript = context.scriptService().search(context.lookup(), scriptLang, script, scriptType, ScriptContext.Standard.SEARCH, params);
|
||||
|
||||
if (STRING_SORT_TYPE.equals(type) && (sortMode == MultiValueMode.SUM || sortMode == MultiValueMode.AVG)) {
|
||||
throw new SearchParseException(context, "type [string] doesn't support mode [" + sortMode + "]");
|
||||
|
|
|
@ -30,8 +30,8 @@ import org.elasticsearch.index.analysis.ShingleTokenFilterFactory;
|
|||
import org.elasticsearch.index.mapper.FieldMapper;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.script.CompiledScript;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
import org.elasticsearch.search.suggest.SuggestContextParser;
|
||||
import org.elasticsearch.search.suggest.SuggestUtils;
|
||||
|
@ -153,7 +153,7 @@ public final class PhraseSuggestParser implements SuggestContextParser {
|
|||
if (suggestion.getCollateQueryScript() != null) {
|
||||
throw new ElasticsearchIllegalArgumentException("suggester[phrase][collate] query already set, doesn't support additional [" + fieldName + "]");
|
||||
}
|
||||
CompiledScript compiledScript = suggester.scriptService().compile(MustacheScriptEngineService.NAME, templateNameOrTemplateContent, ScriptType.INLINE, ScriptContext.SEARCH);
|
||||
CompiledScript compiledScript = suggester.scriptService().compile(MustacheScriptEngineService.NAME, templateNameOrTemplateContent, ScriptType.INLINE, ScriptContext.Standard.SEARCH);
|
||||
if ("query".equals(fieldName)) {
|
||||
suggestion.setCollateQueryScript(compiledScript);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.AbstractPlugin;
|
||||
import org.elasticsearch.script.expression.ExpressionScriptEngineService;
|
||||
import org.elasticsearch.script.groovy.GroovyScriptEngineService;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
|
||||
public class CustomScriptContextTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
private static final ImmutableSet<String> LANG_SET = ImmutableSet.of(GroovyScriptEngineService.NAME, MustacheScriptEngineService.NAME, ExpressionScriptEngineService.NAME);
|
||||
|
||||
private static final String PLUGIN_NAME = "testplugin";
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return ImmutableSettings.builder().put(super.nodeSettings(nodeOrdinal))
|
||||
.put("plugin.types", CustomScriptContextPlugin.class.getName())
|
||||
.put("script." + PLUGIN_NAME + "_custom_globally_disabled_op", "off")
|
||||
.put("script.engine.expression.inline." + PLUGIN_NAME + "_custom_exp_disabled_op", "off")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomScriptContextsSettings() {
|
||||
ScriptService scriptService = internalCluster().getInstance(ScriptService.class);
|
||||
for (String lang : LANG_SET) {
|
||||
for (ScriptService.ScriptType scriptType : ScriptService.ScriptType.values()) {
|
||||
try {
|
||||
scriptService.compile(lang, "test", scriptType, new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op"));
|
||||
fail("script compilation should have been rejected");
|
||||
} catch(ScriptException e) {
|
||||
assertThat(e.getMessage(), containsString("scripts of type [" + scriptType + "], operation [" + PLUGIN_NAME + "_custom_globally_disabled_op] and lang [" + lang + "] are disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
scriptService.compile("expression", "1", ScriptService.ScriptType.INLINE, new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"));
|
||||
fail("script compilation should have been rejected");
|
||||
} catch(ScriptException e) {
|
||||
assertThat(e.getMessage(), containsString("scripts of type [inline], operation [" + PLUGIN_NAME + "_custom_exp_disabled_op] and lang [expression] are disabled"));
|
||||
}
|
||||
|
||||
CompiledScript compiledScript = scriptService.compile("expression", "1", ScriptService.ScriptType.INLINE, randomFrom(ScriptContext.Standard.values()));
|
||||
assertThat(compiledScript, notNullValue());
|
||||
|
||||
compiledScript = scriptService.compile("mustache", "1", ScriptService.ScriptType.INLINE, new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"));
|
||||
assertThat(compiledScript, notNullValue());
|
||||
|
||||
for (String lang : LANG_SET) {
|
||||
compiledScript = scriptService.compile(lang, "1", ScriptService.ScriptType.INLINE, new ScriptContext.Plugin(PLUGIN_NAME, "custom_op"));
|
||||
assertThat(compiledScript, notNullValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompileNonRegisteredPluginContext() {
|
||||
ScriptService scriptService = internalCluster().getInstance(ScriptService.class);
|
||||
try {
|
||||
scriptService.compile(randomFrom(LANG_SET.toArray(new String[LANG_SET.size()])), "test", randomFrom(ScriptService.ScriptType.values()), new ScriptContext.Plugin("test", "unknown"));
|
||||
fail("script compilation should have been rejected");
|
||||
} catch(ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("script context [test_unknown] not supported"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompileNonRegisteredScriptContext() {
|
||||
ScriptService scriptService = internalCluster().getInstance(ScriptService.class);
|
||||
try {
|
||||
scriptService.compile(randomFrom(LANG_SET.toArray(new String[LANG_SET.size()])), "test", randomFrom(ScriptService.ScriptType.values()), new ScriptContext() {
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "test";
|
||||
}
|
||||
});
|
||||
fail("script compilation should have been rejected");
|
||||
} catch(ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("script context [test] not supported"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomScriptContextPlugin extends AbstractPlugin {
|
||||
@Override
|
||||
public String name() {
|
||||
return "custom_script_context_plugin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Custom script context plugin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processModule(Module module) {
|
||||
if (module instanceof ScriptModule) {
|
||||
ScriptModule scriptModule = (ScriptModule) module;
|
||||
scriptModule.registerScriptContext(new ScriptContext.Plugin(PLUGIN_NAME, "custom_op"));
|
||||
scriptModule.registerScriptContext(new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"));
|
||||
scriptModule.registerScriptContext(new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch.script;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.inject.ModulesBuilder;
|
||||
|
@ -58,7 +59,7 @@ public class NativeScriptTests extends ElasticsearchTestCase {
|
|||
|
||||
ScriptService scriptService = injector.getInstance(ScriptService.class);
|
||||
|
||||
ExecutableScript executable = scriptService.executable(NativeScriptEngineService.NAME, "my", ScriptType.INLINE, ScriptContext.SEARCH, null);
|
||||
ExecutableScript executable = scriptService.executable(NativeScriptEngineService.NAME, "my", ScriptType.INLINE, ScriptContext.Standard.SEARCH, null);
|
||||
assertThat(executable.run().toString(), equalTo("test"));
|
||||
terminate(injector.getInstance(ThreadPool.class));
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ public class NativeScriptTests extends ElasticsearchTestCase {
|
|||
ScriptType scriptType = randomFrom(ScriptType.values());
|
||||
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptType, randomFrom(ScriptMode.values()));
|
||||
} else {
|
||||
ScriptContext scriptContext = randomFrom(ScriptContext.values());
|
||||
String scriptContext = randomFrom(ScriptContext.Standard.values()).getKey();
|
||||
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptContext, randomFrom(ScriptMode.values()));
|
||||
}
|
||||
Settings settings = builder.build();
|
||||
|
@ -79,9 +80,10 @@ public class NativeScriptTests extends ElasticsearchTestCase {
|
|||
Map<String, NativeScriptFactory> nativeScriptFactoryMap = new HashMap<>();
|
||||
nativeScriptFactoryMap.put("my", new MyNativeScriptFactory());
|
||||
Set<ScriptEngineService> scriptEngineServices = ImmutableSet.<ScriptEngineService>of(new NativeScriptEngineService(settings, nativeScriptFactoryMap));
|
||||
ScriptService scriptService = new ScriptService(settings, environment, scriptEngineServices, resourceWatcherService, new NodeSettingsService(settings));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Lists.<ScriptContext.Plugin>newArrayList());
|
||||
ScriptService scriptService = new ScriptService(settings, environment, scriptEngineServices, resourceWatcherService, new NodeSettingsService(settings), scriptContextRegistry);
|
||||
|
||||
for (ScriptContext scriptContext : ScriptContext.values()) {
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
assertThat(scriptService.compile(NativeScriptEngineService.NAME, "my", ScriptType.INLINE, scriptContext), notNullValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ScriptContextRegistryTests extends ElasticsearchTestCase {
|
||||
|
||||
@Test
|
||||
public void testValidateCustomScriptContextsOperation() throws IOException {
|
||||
for (final String rejectedContext : ScriptContextRegistry.RESERVED_SCRIPT_CONTEXTS) {
|
||||
try {
|
||||
//try to register a prohibited script context
|
||||
new ScriptContextRegistry(Lists.newArrayList(new ScriptContext.Plugin("test", rejectedContext)));
|
||||
fail("ScriptContextRegistry initialization should have failed");
|
||||
} catch(ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), Matchers.containsString("[" + rejectedContext + "] is a reserved name, it cannot be registered as a custom script context"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCustomScriptContextsPluginName() throws IOException {
|
||||
for (final String rejectedContext : ScriptContextRegistry.RESERVED_SCRIPT_CONTEXTS) {
|
||||
try {
|
||||
//try to register a prohibited script context
|
||||
new ScriptContextRegistry(Lists.newArrayList(new ScriptContext.Plugin(rejectedContext, "test")));
|
||||
fail("ScriptContextRegistry initialization should have failed");
|
||||
} catch(ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), Matchers.containsString("[" + rejectedContext + "] is a reserved name, it cannot be registered as a custom script context"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = ElasticsearchIllegalArgumentException.class)
|
||||
public void testValidateCustomScriptContextsEmptyPluginName() throws IOException {
|
||||
new ScriptContext.Plugin(randomBoolean() ? null : "", "test");
|
||||
}
|
||||
|
||||
@Test(expected = ElasticsearchIllegalArgumentException.class)
|
||||
public void testValidateCustomScriptContextsEmptyOperation() throws IOException {
|
||||
new ScriptContext.Plugin("test", randomBoolean() ? null : "");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicatedPluginScriptContexts() throws IOException {
|
||||
try {
|
||||
//try to register a prohibited script context
|
||||
new ScriptContextRegistry(Lists.newArrayList(new ScriptContext.Plugin("testplugin", "test"), new ScriptContext.Plugin("testplugin", "test")));
|
||||
fail("ScriptContextRegistry initialization should have failed");
|
||||
} catch(ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), Matchers.containsString("script context [testplugin_test] cannot be registered twice"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonDuplicatedPluginScriptContexts() throws IOException {
|
||||
new ScriptContextRegistry(Lists.newArrayList(new ScriptContext.Plugin("testplugin1", "test"), new ScriptContext.Plugin("testplugin2", "test")));
|
||||
}
|
||||
}
|
|
@ -19,8 +19,7 @@
|
|||
|
||||
package org.elasticsearch.script;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.*;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
|
@ -34,10 +33,7 @@ import org.junit.After;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
|
@ -49,6 +45,8 @@ public class ScriptModesTests extends ElasticsearchTestCase {
|
|||
static final String[] ENABLE_VALUES = new String[]{"on", "true", "yes", "1"};
|
||||
static final String[] DISABLE_VALUES = new String[]{"off", "false", "no", "0"};
|
||||
|
||||
ScriptContextRegistry scriptContextRegistry;
|
||||
private ScriptContext[] scriptContexts;
|
||||
private Map<String, ScriptEngineService> scriptEngines;
|
||||
private ScriptModes scriptModes;
|
||||
private Set<String> checkedSettings;
|
||||
|
@ -57,6 +55,18 @@ public class ScriptModesTests extends ElasticsearchTestCase {
|
|||
|
||||
@Before
|
||||
public void setupScriptEngines() {
|
||||
//randomly register custom script contexts
|
||||
int randomInt = randomIntBetween(0, 3);
|
||||
//prevent duplicates using map
|
||||
Map<String, ScriptContext.Plugin> contexts = Maps.newHashMap();
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
String plugin = randomAsciiOfLength(randomIntBetween(1, 10));
|
||||
String operation = randomAsciiOfLength(randomIntBetween(1, 30));
|
||||
String context = plugin + "-" + operation;
|
||||
contexts.put(context, new ScriptContext.Plugin(plugin, operation));
|
||||
}
|
||||
scriptContextRegistry = new ScriptContextRegistry(contexts.values());
|
||||
scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]);
|
||||
scriptEngines = buildScriptEnginesByLangMap(ImmutableSet.of(
|
||||
new GroovyScriptEngineService(ImmutableSettings.EMPTY),
|
||||
new MustacheScriptEngineService(ImmutableSettings.EMPTY),
|
||||
|
@ -72,7 +82,7 @@ public class ScriptModesTests extends ElasticsearchTestCase {
|
|||
@After
|
||||
public void assertNativeScriptsAreAlwaysAllowed() {
|
||||
if (assertScriptModesNonNull) {
|
||||
assertThat(scriptModes.getScriptMode(NativeScriptEngineService.NAME, randomFrom(ScriptType.values()), randomFrom(ScriptContext.values())), equalTo(ScriptMode.ON));
|
||||
assertThat(scriptModes.getScriptMode(NativeScriptEngineService.NAME, randomFrom(ScriptType.values()), randomFrom(scriptContexts)), equalTo(ScriptMode.ON));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +91,7 @@ public class ScriptModesTests extends ElasticsearchTestCase {
|
|||
if (assertScriptModesNonNull) {
|
||||
assertThat(scriptModes, notNullValue());
|
||||
//4 is the number of engines (native excluded), custom is counted twice though as it's associated with two different names
|
||||
int numberOfSettings = 5 * ScriptType.values().length * ScriptContext.values().length;
|
||||
int numberOfSettings = 5 * ScriptType.values().length * scriptContextRegistry.scriptContexts().size();
|
||||
assertThat(scriptModes.scriptModes.size(), equalTo(numberOfSettings));
|
||||
if (assertAllSettingsWereChecked) {
|
||||
assertThat(checkedSettings.size(), equalTo(numberOfSettings));
|
||||
|
@ -91,7 +101,7 @@ public class ScriptModesTests extends ElasticsearchTestCase {
|
|||
|
||||
@Test
|
||||
public void testDefaultSettings() {
|
||||
this.scriptModes = new ScriptModes(scriptEngines, ImmutableSettings.EMPTY);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, ImmutableSettings.EMPTY);
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED, ScriptType.INLINE);
|
||||
}
|
||||
|
@ -99,239 +109,95 @@ public class ScriptModesTests extends ElasticsearchTestCase {
|
|||
@Test(expected = ElasticsearchIllegalArgumentException.class)
|
||||
public void testMissingSetting() {
|
||||
assertAllSettingsWereChecked = false;
|
||||
this.scriptModes = new ScriptModes(scriptEngines, ImmutableSettings.EMPTY);
|
||||
scriptModes.getScriptMode("non_existing", randomFrom(ScriptType.values()), randomFrom(ScriptContext.values()));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, ImmutableSettings.EMPTY);
|
||||
scriptModes.getScriptMode("non_existing", randomFrom(ScriptType.values()), randomFrom(scriptContexts));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableInlineGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.inline", randomFrom(ENABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE, ScriptType.INLINE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED);
|
||||
public void testScriptTypeGenericSettings() {
|
||||
int randomInt = randomIntBetween(1, ScriptType.values().length - 1);
|
||||
Set<ScriptType> randomScriptTypesSet = Sets.newHashSet();
|
||||
ScriptMode[] randomScriptModes = new ScriptMode[randomInt];
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
boolean added = false;
|
||||
while (added == false) {
|
||||
added = randomScriptTypesSet.add(randomFrom(ScriptType.values()));
|
||||
}
|
||||
randomScriptModes[i] = randomFrom(ScriptMode.values());
|
||||
}
|
||||
ScriptType[] randomScriptTypes = randomScriptTypesSet.toArray(new ScriptType[randomScriptTypesSet.size()]);
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder();
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + randomScriptTypes[i], randomScriptModes[i]);
|
||||
}
|
||||
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
|
||||
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
assertScriptModesAllOps(randomScriptModes[i], ALL_LANGS, randomScriptTypes[i]);
|
||||
}
|
||||
if (randomScriptTypesSet.contains(ScriptType.FILE) == false) {
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
}
|
||||
if (randomScriptTypesSet.contains(ScriptType.INDEXED) == false) {
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED);
|
||||
}
|
||||
if (randomScriptTypesSet.contains(ScriptType.INLINE) == false) {
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableInlineGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.inline", randomFrom(DISABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED);
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ALL_LANGS, ScriptType.INLINE);
|
||||
}
|
||||
public void testScriptContextGenericSettings() {
|
||||
int randomInt = randomIntBetween(1, scriptContexts.length - 1);
|
||||
Set<ScriptContext> randomScriptContextsSet = Sets.newHashSet();
|
||||
ScriptMode[] randomScriptModes = new ScriptMode[randomInt];
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
boolean added = false;
|
||||
while (added == false) {
|
||||
added = randomScriptContextsSet.add(randomFrom(scriptContexts));
|
||||
}
|
||||
randomScriptModes[i] = randomFrom(ScriptMode.values());
|
||||
}
|
||||
ScriptContext[] randomScriptContexts = randomScriptContextsSet.toArray(new ScriptContext[randomScriptContextsSet.size()]);
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder();
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + randomScriptContexts[i].getKey(), randomScriptModes[i]);
|
||||
}
|
||||
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
|
||||
|
||||
@Test
|
||||
public void testSandboxInlineGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.inline", randomFrom(ScriptMode.SANDBOX));
|
||||
//nothing changes if setting set is same as default
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED, ScriptType.INLINE);
|
||||
}
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
assertScriptModesAllTypes(randomScriptModes[i], ALL_LANGS, randomScriptContexts[i]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableIndexedGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.indexed", randomFrom(ENABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE, ScriptType.INDEXED);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableIndexedGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.indexed", randomFrom(DISABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ALL_LANGS, ScriptType.INDEXED);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSandboxIndexedGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.indexed", ScriptMode.SANDBOX);
|
||||
//nothing changes if setting set is same as default
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableFileGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.file", randomFrom(ENABLE_VALUES));
|
||||
//nothing changes if setting set is same as default
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableFileGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.file", randomFrom(DISABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSandboxFileGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.file", ScriptMode.SANDBOX);
|
||||
//nothing changes if setting set is same as default
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.FILE, ScriptType.INDEXED, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleScriptTypeGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.file", ScriptMode.SANDBOX).put("script.inline", randomFrom(DISABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED);
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ALL_LANGS, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableMappingGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.mapping", randomFrom(ENABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.ON, ALL_LANGS, ScriptContext.MAPPING);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.AGGS, ScriptContext.SEARCH, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.AGGS, ScriptContext.SEARCH, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableMappingGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.mapping", randomFrom(DISABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, ScriptContext.MAPPING);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.AGGS, ScriptContext.SEARCH, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.AGGS, ScriptContext.SEARCH, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSandboxMappingGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.mapping", ScriptMode.SANDBOX);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.SANDBOX, ALL_LANGS, ScriptContext.MAPPING);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.AGGS, ScriptContext.SEARCH, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.AGGS, ScriptContext.SEARCH, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableSearchGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.search", randomFrom(ENABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.ON, ALL_LANGS, ScriptContext.SEARCH);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.AGGS, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.AGGS, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableSearchGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.search", randomFrom(DISABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, ScriptContext.SEARCH);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.AGGS, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.AGGS, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSandboxSearchGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.search", ScriptMode.SANDBOX);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.SANDBOX, ALL_LANGS, ScriptContext.SEARCH);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.AGGS, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.AGGS, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableAggsGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.aggs", randomFrom(ENABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.ON, ALL_LANGS, ScriptContext.AGGS);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableAggsGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.aggs", randomFrom(DISABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, ScriptContext.AGGS);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSandboxAggsGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.aggs", ScriptMode.SANDBOX);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.SANDBOX, ALL_LANGS, ScriptContext.AGGS);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableUpdateGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.update", randomFrom(ENABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.ON, ALL_LANGS, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.AGGS);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.AGGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableUpdateGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.update", randomFrom(DISABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.AGGS);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.AGGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSandboxUpdateGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.update", ScriptMode.SANDBOX);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.SANDBOX, ALL_LANGS, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.AGGS);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.SEARCH, ScriptContext.MAPPING, ScriptContext.AGGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleScriptContextGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.update", ScriptMode.SANDBOX)
|
||||
.put("script.aggs", randomFrom(DISABLE_VALUES))
|
||||
.put("script.search", randomFrom(ENABLE_VALUES));
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.SANDBOX, ALL_LANGS, ScriptContext.UPDATE);
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, ScriptContext.AGGS);
|
||||
assertScriptModesAllTypes(ScriptMode.ON, ALL_LANGS, ScriptContext.SEARCH);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, ScriptContext.MAPPING);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, ScriptContext.MAPPING);
|
||||
ScriptContext[] complementOf = complementOf(randomScriptContexts);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, complementOf);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INDEXED, ScriptType.INLINE}, complementOf);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConflictingScriptTypeAndOpGenericSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.update", randomFrom(DISABLE_VALUES))
|
||||
ScriptContext scriptContext = randomFrom(scriptContexts);
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptContext.getKey(), randomFrom(DISABLE_VALUES))
|
||||
.put("script.indexed", randomFrom(ENABLE_VALUES)).put("script.inline", ScriptMode.SANDBOX);
|
||||
//operations generic settings have precedence over script type generic settings
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE, ScriptType.INDEXED}, ScriptContext.MAPPING, ScriptContext.AGGS, ScriptContext.SEARCH);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INLINE}, ScriptContext.MAPPING, ScriptContext.AGGS, ScriptContext.SEARCH);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, scriptContext);
|
||||
ScriptContext[] complementOf = complementOf(scriptContext);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE, ScriptType.INDEXED}, complementOf);
|
||||
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INLINE}, complementOf);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEngineSpecificSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder()
|
||||
.put(specificEngineOpSettings(GroovyScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.MAPPING), randomFrom(DISABLE_VALUES))
|
||||
.put(specificEngineOpSettings(GroovyScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.UPDATE), randomFrom(DISABLE_VALUES));
|
||||
.put(specificEngineOpSettings(GroovyScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.Standard.MAPPING), randomFrom(DISABLE_VALUES))
|
||||
.put(specificEngineOpSettings(GroovyScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.Standard.UPDATE), randomFrom(DISABLE_VALUES));
|
||||
ImmutableSet<String> groovyLangSet = ImmutableSet.of(GroovyScriptEngineService.NAME);
|
||||
Set<String> allButGroovyLangSet = new HashSet<>(ALL_LANGS);
|
||||
allButGroovyLangSet.remove(GroovyScriptEngineService.NAME);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModes(ScriptMode.OFF, groovyLangSet, new ScriptType[]{ScriptType.INLINE}, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, groovyLangSet, new ScriptType[]{ScriptType.INLINE}, ScriptContext.SEARCH, ScriptContext.AGGS);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
|
||||
assertScriptModes(ScriptMode.OFF, groovyLangSet, new ScriptType[]{ScriptType.INLINE}, ScriptContext.Standard.MAPPING, ScriptContext.Standard.UPDATE);
|
||||
assertScriptModes(ScriptMode.SANDBOX, groovyLangSet, new ScriptType[]{ScriptType.INLINE}, complementOf(ScriptContext.Standard.MAPPING, ScriptContext.Standard.UPDATE));
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, allButGroovyLangSet, ScriptType.INLINE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED);
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
|
@ -340,88 +206,21 @@ public class ScriptModesTests extends ElasticsearchTestCase {
|
|||
@Test
|
||||
public void testInteractionBetweenGenericAndEngineSpecificSettings() {
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder().put("script.inline", randomFrom(DISABLE_VALUES))
|
||||
.put(specificEngineOpSettings(MustacheScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.AGGS), randomFrom(ENABLE_VALUES))
|
||||
.put(specificEngineOpSettings(MustacheScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.SEARCH), randomFrom(ENABLE_VALUES));
|
||||
.put(specificEngineOpSettings(MustacheScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.Standard.AGGS), randomFrom(ENABLE_VALUES))
|
||||
.put(specificEngineOpSettings(MustacheScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.Standard.SEARCH), randomFrom(ENABLE_VALUES));
|
||||
ImmutableSet<String> mustacheLangSet = ImmutableSet.of(MustacheScriptEngineService.NAME);
|
||||
Set<String> allButMustacheLangSet = new HashSet<>(ALL_LANGS);
|
||||
allButMustacheLangSet.remove(MustacheScriptEngineService.NAME);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, builder.build());
|
||||
assertScriptModes(ScriptMode.ON, mustacheLangSet, new ScriptType[]{ScriptType.INLINE}, ScriptContext.AGGS, ScriptContext.SEARCH);
|
||||
assertScriptModes(ScriptMode.OFF, mustacheLangSet, new ScriptType[]{ScriptType.INLINE}, ScriptContext.MAPPING, ScriptContext.UPDATE);
|
||||
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
|
||||
assertScriptModes(ScriptMode.ON, mustacheLangSet, new ScriptType[]{ScriptType.INLINE}, ScriptContext.Standard.AGGS, ScriptContext.Standard.SEARCH);
|
||||
assertScriptModes(ScriptMode.OFF, mustacheLangSet, new ScriptType[]{ScriptType.INLINE}, complementOf(ScriptContext.Standard.AGGS, ScriptContext.Standard.SEARCH));
|
||||
assertScriptModesAllOps(ScriptMode.OFF, allButMustacheLangSet, ScriptType.INLINE);
|
||||
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED);
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultSettingsToString() {
|
||||
assertAllSettingsWereChecked = false;
|
||||
this.scriptModes = new ScriptModes(scriptEngines, ImmutableSettings.EMPTY);
|
||||
assertThat(scriptModes.toString(), equalTo(
|
||||
"script.engine.custom.file.aggs: on\n" +
|
||||
"script.engine.custom.file.mapping: on\n" +
|
||||
"script.engine.custom.file.search: on\n" +
|
||||
"script.engine.custom.file.update: on\n" +
|
||||
"script.engine.custom.indexed.aggs: sandbox\n" +
|
||||
"script.engine.custom.indexed.mapping: sandbox\n" +
|
||||
"script.engine.custom.indexed.search: sandbox\n" +
|
||||
"script.engine.custom.indexed.update: sandbox\n" +
|
||||
"script.engine.custom.inline.aggs: sandbox\n" +
|
||||
"script.engine.custom.inline.mapping: sandbox\n" +
|
||||
"script.engine.custom.inline.search: sandbox\n" +
|
||||
"script.engine.custom.inline.update: sandbox\n" +
|
||||
"script.engine.expression.file.aggs: on\n" +
|
||||
"script.engine.expression.file.mapping: on\n" +
|
||||
"script.engine.expression.file.search: on\n" +
|
||||
"script.engine.expression.file.update: on\n" +
|
||||
"script.engine.expression.indexed.aggs: sandbox\n" +
|
||||
"script.engine.expression.indexed.mapping: sandbox\n" +
|
||||
"script.engine.expression.indexed.search: sandbox\n" +
|
||||
"script.engine.expression.indexed.update: sandbox\n" +
|
||||
"script.engine.expression.inline.aggs: sandbox\n" +
|
||||
"script.engine.expression.inline.mapping: sandbox\n" +
|
||||
"script.engine.expression.inline.search: sandbox\n" +
|
||||
"script.engine.expression.inline.update: sandbox\n" +
|
||||
"script.engine.groovy.file.aggs: on\n" +
|
||||
"script.engine.groovy.file.mapping: on\n" +
|
||||
"script.engine.groovy.file.search: on\n" +
|
||||
"script.engine.groovy.file.update: on\n" +
|
||||
"script.engine.groovy.indexed.aggs: sandbox\n" +
|
||||
"script.engine.groovy.indexed.mapping: sandbox\n" +
|
||||
"script.engine.groovy.indexed.search: sandbox\n" +
|
||||
"script.engine.groovy.indexed.update: sandbox\n" +
|
||||
"script.engine.groovy.inline.aggs: sandbox\n" +
|
||||
"script.engine.groovy.inline.mapping: sandbox\n" +
|
||||
"script.engine.groovy.inline.search: sandbox\n" +
|
||||
"script.engine.groovy.inline.update: sandbox\n" +
|
||||
"script.engine.mustache.file.aggs: on\n" +
|
||||
"script.engine.mustache.file.mapping: on\n" +
|
||||
"script.engine.mustache.file.search: on\n" +
|
||||
"script.engine.mustache.file.update: on\n" +
|
||||
"script.engine.mustache.indexed.aggs: sandbox\n" +
|
||||
"script.engine.mustache.indexed.mapping: sandbox\n" +
|
||||
"script.engine.mustache.indexed.search: sandbox\n" +
|
||||
"script.engine.mustache.indexed.update: sandbox\n" +
|
||||
"script.engine.mustache.inline.aggs: sandbox\n" +
|
||||
"script.engine.mustache.inline.mapping: sandbox\n" +
|
||||
"script.engine.mustache.inline.search: sandbox\n" +
|
||||
"script.engine.mustache.inline.update: sandbox\n" +
|
||||
"script.engine.test.file.aggs: on\n" +
|
||||
"script.engine.test.file.mapping: on\n" +
|
||||
"script.engine.test.file.search: on\n" +
|
||||
"script.engine.test.file.update: on\n" +
|
||||
"script.engine.test.indexed.aggs: sandbox\n" +
|
||||
"script.engine.test.indexed.mapping: sandbox\n" +
|
||||
"script.engine.test.indexed.search: sandbox\n" +
|
||||
"script.engine.test.indexed.update: sandbox\n" +
|
||||
"script.engine.test.inline.aggs: sandbox\n" +
|
||||
"script.engine.test.inline.mapping: sandbox\n" +
|
||||
"script.engine.test.inline.search: sandbox\n" +
|
||||
"script.engine.test.inline.update: sandbox\n"));
|
||||
}
|
||||
|
||||
private void assertScriptModesAllOps(ScriptMode expectedScriptMode, Set<String> langs, ScriptType... scriptTypes) {
|
||||
assertScriptModes(expectedScriptMode, langs, scriptTypes, ScriptContext.values());
|
||||
assertScriptModes(expectedScriptMode, langs, scriptTypes, scriptContexts);
|
||||
}
|
||||
|
||||
private void assertScriptModesAllTypes(ScriptMode expectedScriptMode, Set<String> langs, ScriptContext... scriptContexts) {
|
||||
|
@ -435,15 +234,26 @@ public class ScriptModesTests extends ElasticsearchTestCase {
|
|||
for (String lang : langs) {
|
||||
for (ScriptType scriptType : scriptTypes) {
|
||||
for (ScriptContext scriptContext : scriptContexts) {
|
||||
assertThat(lang + "." + scriptType + "." + scriptContext + " doesn't have the expected value", scriptModes.getScriptMode(lang, scriptType, scriptContext), equalTo(expectedScriptMode));
|
||||
assertThat(lang + "." + scriptType + "." + scriptContext.getKey() + " doesn't have the expected value", scriptModes.getScriptMode(lang, scriptType, scriptContext), equalTo(expectedScriptMode));
|
||||
checkedSettings.add(lang + "." + scriptType + "." + scriptContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ScriptContext[] complementOf(ScriptContext... scriptContexts) {
|
||||
Map<String, ScriptContext> copy = Maps.newHashMap();
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
copy.put(scriptContext.getKey(), scriptContext);
|
||||
}
|
||||
for (ScriptContext scriptContext : scriptContexts) {
|
||||
copy.remove(scriptContext.getKey());
|
||||
}
|
||||
return copy.values().toArray(new ScriptContext[copy.size()]);
|
||||
}
|
||||
|
||||
private static String specificEngineOpSettings(String lang, ScriptType scriptType, ScriptContext scriptContext) {
|
||||
return ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext;
|
||||
return ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey();
|
||||
}
|
||||
|
||||
static ImmutableMap<String, ScriptEngineService> buildScriptEnginesByLangMap(Set<ScriptEngineService> scriptEngines) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.elasticsearch.script;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
|
@ -44,16 +45,16 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ScriptServiceTests extends ElasticsearchTestCase {
|
||||
|
||||
private ResourceWatcherService resourceWatcherService;
|
||||
private Set<ScriptEngineService> scriptEngineServices;
|
||||
private Map<String, ScriptEngineService> scriptEnginesByLangMap;
|
||||
private ScriptContextRegistry scriptContextRegistry;
|
||||
private ScriptContext[] scriptContexts;
|
||||
private ScriptService scriptService;
|
||||
private Path scriptsFilePath;
|
||||
private Settings baseSettings;
|
||||
|
@ -76,6 +77,24 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
scriptEngineServices = ImmutableSet.of(new TestEngineService(), new GroovyScriptEngineService(baseSettings),
|
||||
new ExpressionScriptEngineService(baseSettings), new MustacheScriptEngineService(baseSettings));
|
||||
scriptEnginesByLangMap = ScriptModesTests.buildScriptEnginesByLangMap(scriptEngineServices);
|
||||
//randomly register custom script contexts
|
||||
int randomInt = randomIntBetween(0, 3);
|
||||
//prevent duplicates using map
|
||||
Map<String, ScriptContext.Plugin> contexts = Maps.newHashMap();
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
String plugin;
|
||||
do {
|
||||
plugin = randomAsciiOfLength(randomIntBetween(1, 10));
|
||||
} while (ScriptContextRegistry.RESERVED_SCRIPT_CONTEXTS.contains(plugin));
|
||||
String operation;
|
||||
do {
|
||||
operation = randomAsciiOfLength(randomIntBetween(1, 30));
|
||||
} while (ScriptContextRegistry.RESERVED_SCRIPT_CONTEXTS.contains(operation));
|
||||
String context = plugin + "_" + operation;
|
||||
contexts.put(context, new ScriptContext.Plugin(plugin, operation));
|
||||
}
|
||||
scriptContextRegistry = new ScriptContextRegistry(contexts.values());
|
||||
scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]);
|
||||
logger.info("--> setup script service");
|
||||
scriptsFilePath = genericConfigFolder.resolve("scripts");
|
||||
Files.createDirectories(scriptsFilePath);
|
||||
|
@ -84,7 +103,7 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
private void buildScriptService(Settings additionalSettings) throws IOException {
|
||||
Settings finalSettings = ImmutableSettings.builder().put(baseSettings).put(additionalSettings).build();
|
||||
Environment environment = new Environment(finalSettings);
|
||||
scriptService = new ScriptService(finalSettings, environment, scriptEngineServices, resourceWatcherService, new NodeSettingsService(finalSettings)) {
|
||||
scriptService = new ScriptService(finalSettings, environment, scriptEngineServices, resourceWatcherService, new NodeSettingsService(finalSettings), scriptContextRegistry) {
|
||||
@Override
|
||||
String getScriptFromIndex(String scriptLang, String id) {
|
||||
//mock the script that gets retrieved from an index
|
||||
|
@ -114,7 +133,7 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
resourceWatcherService.notifyNow();
|
||||
|
||||
logger.info("--> verify that file with extension was correctly processed");
|
||||
CompiledScript compiledScript = scriptService.compile("test", "test_script", ScriptType.FILE, ScriptContext.SEARCH);
|
||||
CompiledScript compiledScript = scriptService.compile("test", "test_script", ScriptType.FILE, ScriptContext.Standard.SEARCH);
|
||||
assertThat(compiledScript.compiled(), equalTo((Object) "compiled_test_file"));
|
||||
|
||||
logger.info("--> delete both files");
|
||||
|
@ -124,7 +143,7 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
|
||||
logger.info("--> verify that file with extension was correctly removed");
|
||||
try {
|
||||
scriptService.compile("test", "test_script", ScriptType.FILE, ScriptContext.SEARCH);
|
||||
scriptService.compile("test", "test_script", ScriptType.FILE, ScriptContext.Standard.SEARCH);
|
||||
fail("the script test_script should no longer exist");
|
||||
} catch (ElasticsearchIllegalArgumentException ex) {
|
||||
assertThat(ex.getMessage(), containsString("Unable to find on disk script test_script"));
|
||||
|
@ -135,17 +154,17 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
public void testScriptsSameNameDifferentLanguage() throws IOException {
|
||||
buildScriptService(ImmutableSettings.EMPTY);
|
||||
createFileScripts("groovy", "expression");
|
||||
CompiledScript groovyScript = scriptService.compile(GroovyScriptEngineService.NAME, "file_script", ScriptType.FILE, randomFrom(ScriptContext.values()));
|
||||
CompiledScript groovyScript = scriptService.compile(GroovyScriptEngineService.NAME, "file_script", ScriptType.FILE, randomFrom(scriptContexts));
|
||||
assertThat(groovyScript.lang(), equalTo(GroovyScriptEngineService.NAME));
|
||||
CompiledScript expressionScript = scriptService.compile(ExpressionScriptEngineService.NAME, "file_script", ScriptType.FILE, randomFrom(ScriptContext.values()));
|
||||
CompiledScript expressionScript = scriptService.compile(ExpressionScriptEngineService.NAME, "file_script", ScriptType.FILE, randomFrom(scriptContexts));
|
||||
assertThat(expressionScript.lang(), equalTo(ExpressionScriptEngineService.NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInlineScriptCompiledOnceMultipleLangAcronyms() throws IOException {
|
||||
buildScriptService(ImmutableSettings.EMPTY);
|
||||
CompiledScript compiledScript1 = scriptService.compile("test", "script", ScriptType.INLINE, randomFrom(ScriptContext.values()));
|
||||
CompiledScript compiledScript2 = scriptService.compile("test2", "script", ScriptType.INLINE, randomFrom(ScriptContext.values()));
|
||||
CompiledScript compiledScript1 = scriptService.compile("test", "script", ScriptType.INLINE, randomFrom(scriptContexts));
|
||||
CompiledScript compiledScript2 = scriptService.compile("test2", "script", ScriptType.INLINE, randomFrom(scriptContexts));
|
||||
assertThat(compiledScript1, sameInstance(compiledScript2));
|
||||
}
|
||||
|
||||
|
@ -153,8 +172,8 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
public void testFileScriptCompiledOnceMultipleLangAcronyms() throws IOException {
|
||||
buildScriptService(ImmutableSettings.EMPTY);
|
||||
createFileScripts("test");
|
||||
CompiledScript compiledScript1 = scriptService.compile("test", "file_script", ScriptType.FILE, randomFrom(ScriptContext.values()));
|
||||
CompiledScript compiledScript2 = scriptService.compile("test2", "file_script", ScriptType.FILE, randomFrom(ScriptContext.values()));
|
||||
CompiledScript compiledScript1 = scriptService.compile("test", "file_script", ScriptType.FILE, randomFrom(scriptContexts));
|
||||
CompiledScript compiledScript2 = scriptService.compile("test2", "file_script", ScriptType.FILE, randomFrom(scriptContexts));
|
||||
assertThat(compiledScript1, sameInstance(compiledScript2));
|
||||
}
|
||||
|
||||
|
@ -174,7 +193,7 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
buildScriptService(builder.build());
|
||||
createFileScripts("groovy", "expression", "mustache", "test");
|
||||
|
||||
for (ScriptContext scriptContext : ScriptContext.values()) {
|
||||
for (ScriptContext scriptContext : scriptContexts) {
|
||||
//groovy is not sandboxed, only file scripts are enabled by default
|
||||
assertCompileRejected(GroovyScriptEngineService.NAME, "script", ScriptType.INLINE, scriptContext);
|
||||
assertCompileRejected(GroovyScriptEngineService.NAME, "script", ScriptType.INDEXED, scriptContext);
|
||||
|
@ -206,12 +225,12 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
} while (scriptSourceSettings.containsKey(scriptType));
|
||||
scriptSourceSettings.put(scriptType, randomFrom(ScriptMode.values()));
|
||||
}
|
||||
int numScriptContextSettings = randomIntBetween(0, ScriptContext.values().length);
|
||||
Map<ScriptContext, ScriptMode> scriptContextSettings = new HashMap<>();
|
||||
int numScriptContextSettings = randomIntBetween(0, this.scriptContextRegistry.scriptContexts().size());
|
||||
Map<String, ScriptMode> scriptContextSettings = new HashMap<>();
|
||||
for (int i = 0; i < numScriptContextSettings; i++) {
|
||||
ScriptContext scriptContext;
|
||||
String scriptContext;
|
||||
do {
|
||||
scriptContext = randomFrom(ScriptContext.values());
|
||||
scriptContext = randomFrom(this.scriptContexts).getKey();
|
||||
} while (scriptContextSettings.containsKey(scriptContext));
|
||||
scriptContextSettings.put(scriptContext, randomFrom(ScriptMode.values()));
|
||||
}
|
||||
|
@ -223,9 +242,9 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
ScriptEngineService[] scriptEngineServices = this.scriptEngineServices.toArray(new ScriptEngineService[this.scriptEngineServices.size()]);
|
||||
ScriptEngineService scriptEngineService = randomFrom(scriptEngineServices);
|
||||
ScriptType scriptType = randomFrom(ScriptType.values());
|
||||
ScriptContext scriptContext = randomFrom(ScriptContext.values());
|
||||
settingKey = scriptEngineService.types()[0] + "." + scriptType + "." + scriptContext;
|
||||
} while(engineSettings.containsKey(settingKey));
|
||||
ScriptContext scriptContext = randomFrom(this.scriptContexts);
|
||||
settingKey = scriptEngineService.types()[0] + "." + scriptType + "." + scriptContext.getKey();
|
||||
} while (engineSettings.containsKey(settingKey));
|
||||
engineSettings.put(settingKey, randomFrom(ScriptMode.values()));
|
||||
}
|
||||
//set the selected fine-grained settings
|
||||
|
@ -243,7 +262,7 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
break;
|
||||
}
|
||||
}
|
||||
for (Map.Entry<ScriptContext, ScriptMode> entry : scriptContextSettings.entrySet()) {
|
||||
for (Map.Entry<String, ScriptMode> entry : scriptContextSettings.entrySet()) {
|
||||
switch (entry.getValue()) {
|
||||
case ON:
|
||||
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.ENABLE_VALUES));
|
||||
|
@ -283,11 +302,11 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
//make sure file scripts have a different name than inline ones.
|
||||
//Otherwise they are always considered file ones as they can be found in the static cache.
|
||||
String script = scriptType == ScriptType.FILE ? "file_script" : "script";
|
||||
for (ScriptContext scriptContext : ScriptContext.values()) {
|
||||
for (ScriptContext scriptContext : this.scriptContexts) {
|
||||
//fallback mechanism: 1) engine specific settings 2) op based settings 3) source based settings
|
||||
ScriptMode scriptMode = engineSettings.get(scriptEngineService.types()[0] + "." + scriptType + "." + scriptContext);
|
||||
ScriptMode scriptMode = engineSettings.get(scriptEngineService.types()[0] + "." + scriptType + "." + scriptContext.getKey());
|
||||
if (scriptMode == null) {
|
||||
scriptMode = scriptContextSettings.get(scriptContext);
|
||||
scriptMode = scriptContextSettings.get(scriptContext.getKey());
|
||||
}
|
||||
if (scriptMode == null) {
|
||||
scriptMode = scriptSourceSettings.get(scriptType);
|
||||
|
@ -318,6 +337,28 @@ public class ScriptServiceTests extends ElasticsearchTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompileNonRegisteredContext() throws IOException {
|
||||
buildScriptService(ImmutableSettings.EMPTY);
|
||||
String pluginName;
|
||||
String unknownContext;
|
||||
do {
|
||||
pluginName = randomAsciiOfLength(randomIntBetween(1, 10));
|
||||
unknownContext = randomAsciiOfLength(randomIntBetween(1, 30));
|
||||
} while(scriptContextRegistry.isSupportedContext(new ScriptContext.Plugin(pluginName, unknownContext)));
|
||||
|
||||
for (ScriptEngineService scriptEngineService : scriptEngineServices) {
|
||||
for (String type : scriptEngineService.types()) {
|
||||
try {
|
||||
scriptService.compile(type, "test", randomFrom(ScriptType.values()), new ScriptContext.Plugin(pluginName, unknownContext));
|
||||
fail("script compilation should have been rejected");
|
||||
} catch(ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("script context [" + pluginName + "_" + unknownContext + "] not supported"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createFileScripts(String... langs) throws IOException {
|
||||
for (String lang : langs) {
|
||||
Path scriptPath = scriptsFilePath.resolve("file_script." + lang);
|
||||
|
|
Loading…
Reference in New Issue