Remove Deprecated Script Settings (#24756)
Removes all fine-grained script settings replaced by scripts.types_allowed and scripts.contexts_allowed.
This commit is contained in:
parent
fe83df2a50
commit
1196dfb6bb
|
@ -19,8 +19,6 @@
|
|||
package org.elasticsearch.common.settings;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.close.TransportCloseIndexAction;
|
||||
import org.elasticsearch.transport.RemoteClusterService;
|
||||
import org.elasticsearch.transport.RemoteClusterAware;
|
||||
import org.elasticsearch.action.search.TransportSearchAction;
|
||||
import org.elasticsearch.action.support.AutoCreateIndex;
|
||||
import org.elasticsearch.action.support.DestructiveOperations;
|
||||
|
@ -88,6 +86,8 @@ import org.elasticsearch.search.SearchModule;
|
|||
import org.elasticsearch.search.SearchService;
|
||||
import org.elasticsearch.search.fetch.subphase.highlight.FastVectorHighlighter;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.RemoteClusterAware;
|
||||
import org.elasticsearch.transport.RemoteClusterService;
|
||||
import org.elasticsearch.transport.TcpTransport;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
@ -304,6 +304,8 @@ public final class ClusterSettings extends AbstractScopedSettings {
|
|||
ScriptService.SCRIPT_CACHE_EXPIRE_SETTING,
|
||||
ScriptService.SCRIPT_MAX_SIZE_IN_BYTES,
|
||||
ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE,
|
||||
ScriptService.TYPES_ALLOWED_SETTING,
|
||||
ScriptService.CONTEXTS_ALLOWED_SETTING,
|
||||
IndicesService.INDICES_CACHE_CLEAN_INTERVAL_SETTING,
|
||||
IndicesFieldDataCache.INDICES_FIELDDATA_CACHE_SIZE_KEY,
|
||||
IndicesRequestCache.INDICES_CACHE_QUERY_SIZE,
|
||||
|
|
|
@ -327,7 +327,6 @@ public class Node implements Closeable {
|
|||
final ResourceWatcherService resourceWatcherService = new ResourceWatcherService(settings, threadPool);
|
||||
final ScriptModule scriptModule = ScriptModule.create(settings, pluginsService.filterPlugins(ScriptPlugin.class));
|
||||
AnalysisModule analysisModule = new AnalysisModule(this.environment, pluginsService.filterPlugins(AnalysisPlugin.class));
|
||||
additionalSettings.addAll(scriptModule.getSettings());
|
||||
// this is as early as we can validate settings at this point. we already pass them to ScriptModule as well as ThreadPool
|
||||
// so we might be late here already
|
||||
final SettingsModule settingsModule = new SettingsModule(this.settings, additionalSettings, additionalSettingsFilter);
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.script;
|
||||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Holds the boolean indicating the enabled mode for each of the different scripting languages available, each script source and each
|
||||
* scripted operation.
|
||||
*/
|
||||
public class ScriptModes {
|
||||
|
||||
private static final String SCRIPT_SETTINGS_PREFIX = "script";
|
||||
private static final String ENGINE_SETTINGS_PREFIX = "script.engine";
|
||||
|
||||
final Map<String, Boolean> scriptEnabled;
|
||||
|
||||
private static final Setting<List<String>> TYPES_ALLOWED_SETTING =
|
||||
Setting.listSetting("script.types_allowed", Collections.emptyList(), Function.identity(), Setting.Property.NodeScope);
|
||||
private static final Setting<List<String>> CONTEXTS_ALLOWED_SETTING =
|
||||
Setting.listSetting("script.contexts_allowed", Collections.emptyList(), Function.identity(), Setting.Property.NodeScope);
|
||||
|
||||
private final Set<String> typesAllowed;
|
||||
private final Set<String> contextsAllowed;
|
||||
|
||||
ScriptModes(ScriptContextRegistry scriptContextRegistry, ScriptSettings scriptSettings, Settings settings) {
|
||||
HashMap<String, Boolean> scriptModes = new HashMap<>();
|
||||
for (Setting<Boolean> scriptModeSetting : scriptSettings.getScriptLanguageSettings()) {
|
||||
scriptModes.put(scriptModeSetting.getKey(), scriptModeSetting.get(settings));
|
||||
}
|
||||
this.scriptEnabled = Collections.unmodifiableMap(scriptModes);
|
||||
|
||||
typesAllowed = TYPES_ALLOWED_SETTING.exists(settings) ? new HashSet<>() : null;
|
||||
|
||||
if (typesAllowed != null) {
|
||||
for (String settingType : TYPES_ALLOWED_SETTING.get(settings)) {
|
||||
boolean found = false;
|
||||
|
||||
for (ScriptType scriptType : ScriptType.values()) {
|
||||
if (scriptType.getName().equals(settingType)) {
|
||||
found = true;
|
||||
typesAllowed.add(settingType);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new IllegalArgumentException(
|
||||
"unknown script type [" + settingType + "] found in setting [" + TYPES_ALLOWED_SETTING.getKey() + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contextsAllowed = CONTEXTS_ALLOWED_SETTING.exists(settings) ? new HashSet<>() : null;
|
||||
|
||||
if (contextsAllowed != null) {
|
||||
for (String settingContext : CONTEXTS_ALLOWED_SETTING.get(settings)) {
|
||||
if (scriptContextRegistry.isSupportedContext(settingContext)) {
|
||||
contextsAllowed.add(settingContext);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"unknown script context [" + settingContext + "] found in setting [" + CONTEXTS_ALLOWED_SETTING.getKey() + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the script mode for a script of a certain written in a certain language,
|
||||
* of a certain type and executing as part of a specific operation/api.
|
||||
*
|
||||
* @param lang the language that the script is written in
|
||||
* @param scriptType the type of the script
|
||||
* @param scriptContext the operation that requires the execution of the script
|
||||
* @return whether scripts are enabled (true) or disabled (false)
|
||||
*/
|
||||
public boolean getScriptEnabled(String lang, ScriptType scriptType, ScriptContext scriptContext) {
|
||||
if (typesAllowed != null && typesAllowed.contains(scriptType.getName()) == false) {
|
||||
throw new IllegalArgumentException("[" + scriptType.getName() + "] scripts cannot be executed");
|
||||
}
|
||||
|
||||
if (contextsAllowed != null && contextsAllowed.contains(scriptContext.getKey()) == false) {
|
||||
throw new IllegalArgumentException("[" + scriptContext.getKey() + "] scripts cannot be executed");
|
||||
}
|
||||
|
||||
Boolean scriptMode = scriptEnabled.get(getKey(lang, scriptType, scriptContext));
|
||||
if (scriptMode == null) {
|
||||
throw new IllegalArgumentException("script mode not found for lang [" + lang + "], script_type [" + scriptType + "], operation [" + scriptContext.getKey() + "]");
|
||||
}
|
||||
return scriptMode;
|
||||
}
|
||||
|
||||
static String operationKey(ScriptContext scriptContext) {
|
||||
return SCRIPT_SETTINGS_PREFIX + "." + scriptContext.getKey();
|
||||
}
|
||||
|
||||
static String sourceKey(ScriptType scriptType) {
|
||||
return SCRIPT_SETTINGS_PREFIX + "." + scriptType.getName();
|
||||
}
|
||||
|
||||
static String getGlobalKey(String lang, ScriptType scriptType) {
|
||||
return ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType;
|
||||
}
|
||||
|
||||
static String getKey(String lang, ScriptType scriptType, ScriptContext scriptContext) {
|
||||
return ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
//order settings by key before printing them out, for readability
|
||||
TreeMap<String, Boolean> scriptModesTreeMap = new TreeMap<>();
|
||||
scriptModesTreeMap.putAll(scriptEnabled);
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Map.Entry<String, Boolean> stringScriptModeEntry : scriptModesTreeMap.entrySet()) {
|
||||
stringBuilder.append(stringScriptModeEntry.getKey()).append(": ").append(stringScriptModeEntry.getValue()).append("\n");
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
|
@ -20,24 +20,18 @@
|
|||
package org.elasticsearch.script;
|
||||
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.plugins.ScriptPlugin;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Manages building {@link ScriptService} and {@link ScriptSettings} from a list of plugins.
|
||||
* Manages building {@link ScriptService}.
|
||||
*/
|
||||
public class ScriptModule {
|
||||
private final ScriptSettings scriptSettings;
|
||||
private final ScriptService scriptService;
|
||||
|
||||
/**
|
||||
|
@ -59,21 +53,13 @@ public class ScriptModule {
|
|||
List<ScriptContext.Plugin> customScriptContexts) {
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customScriptContexts);
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(scriptEngines);
|
||||
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
try {
|
||||
scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Couldn't setup ScriptService", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra settings for scripts.
|
||||
*/
|
||||
public List<Setting<?>> getSettings() {
|
||||
return scriptSettings.getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Service responsible for managing scripts.
|
||||
*/
|
||||
|
|
|
@ -19,12 +19,6 @@
|
|||
|
||||
package org.elasticsearch.script;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.elasticsearch.ResourceNotFoundException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
|
@ -41,7 +35,6 @@ import org.elasticsearch.cluster.metadata.MetaData;
|
|||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.breaker.CircuitBreakingException;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.cache.Cache;
|
||||
import org.elasticsearch.common.cache.CacheBuilder;
|
||||
import org.elasticsearch.common.cache.RemovalListener;
|
||||
|
@ -55,6 +48,16 @@ import org.elasticsearch.common.unit.TimeValue;
|
|||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
import org.elasticsearch.template.CompiledTemplate;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ScriptService extends AbstractComponent implements Closeable, ClusterStateListener {
|
||||
|
||||
static final String DISABLE_DYNAMIC_SCRIPTING_SETTING = "script.disable_dynamic";
|
||||
|
@ -68,11 +71,20 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
public static final Setting<Integer> SCRIPT_MAX_COMPILATIONS_PER_MINUTE =
|
||||
Setting.intSetting("script.max_compilations_per_minute", 15, 0, Property.Dynamic, Property.NodeScope);
|
||||
|
||||
public static final String ALLOW_NONE = "none";
|
||||
|
||||
public static final Setting<List<String>> TYPES_ALLOWED_SETTING =
|
||||
Setting.listSetting("script.types_allowed", Collections.emptyList(), Function.identity(), Setting.Property.NodeScope);
|
||||
public static final Setting<List<String>> CONTEXTS_ALLOWED_SETTING =
|
||||
Setting.listSetting("script.contexts_allowed", Collections.emptyList(), Function.identity(), Setting.Property.NodeScope);
|
||||
|
||||
private final Set<String> typesAllowed;
|
||||
private final Set<String> contextsAllowed;
|
||||
|
||||
private final Map<String, ScriptEngine> engines;
|
||||
|
||||
private final Cache<CacheKey, CompiledScript> cache;
|
||||
|
||||
private final ScriptModes scriptModes;
|
||||
private final ScriptContextRegistry scriptContextRegistry;
|
||||
|
||||
private final ScriptMetrics scriptMetrics = new ScriptMetrics();
|
||||
|
@ -84,18 +96,87 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
private double scriptsPerMinCounter;
|
||||
private double compilesAllowedPerNano;
|
||||
|
||||
public ScriptService(Settings settings, ScriptEngineRegistry scriptEngineRegistry,
|
||||
ScriptContextRegistry scriptContextRegistry, ScriptSettings scriptSettings) throws IOException {
|
||||
public ScriptService(Settings settings, ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry) throws IOException {
|
||||
super(settings);
|
||||
|
||||
Objects.requireNonNull(settings);
|
||||
Objects.requireNonNull(scriptEngineRegistry);
|
||||
Objects.requireNonNull(scriptContextRegistry);
|
||||
Objects.requireNonNull(scriptSettings);
|
||||
|
||||
if (Strings.hasLength(settings.get(DISABLE_DYNAMIC_SCRIPTING_SETTING))) {
|
||||
throw new IllegalArgumentException(DISABLE_DYNAMIC_SCRIPTING_SETTING + " is not a supported setting, replace with fine-grained script settings. \n" +
|
||||
"Dynamic scripts can be enabled for all languages and all operations by replacing `script.disable_dynamic: false` with `script.inline: true` and `script.stored: true` in elasticsearch.yml");
|
||||
"Dynamic scripts can be enabled for all languages and all operations not using `script.disable_dynamic: false` in elasticsearch.yml");
|
||||
}
|
||||
|
||||
this.typesAllowed = TYPES_ALLOWED_SETTING.exists(settings) ? new HashSet<>() : null;
|
||||
|
||||
if (this.typesAllowed != null) {
|
||||
List<String> typesAllowedList = TYPES_ALLOWED_SETTING.get(settings);
|
||||
|
||||
if (typesAllowedList.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"must specify at least one script type or none for setting [" + TYPES_ALLOWED_SETTING.getKey() + "].");
|
||||
}
|
||||
|
||||
for (String settingType : typesAllowedList) {
|
||||
if (ALLOW_NONE.equals(settingType)) {
|
||||
if (typesAllowedList.size() != 1) {
|
||||
throw new IllegalArgumentException("cannot specify both [" + ALLOW_NONE + "]" +
|
||||
" and other script types for setting [" + TYPES_ALLOWED_SETTING.getKey() + "].");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (ScriptType scriptType : ScriptType.values()) {
|
||||
if (scriptType.getName().equals(settingType)) {
|
||||
found = true;
|
||||
this.typesAllowed.add(settingType);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
throw new IllegalArgumentException(
|
||||
"unknown script type [" + settingType + "] found in setting [" + TYPES_ALLOWED_SETTING.getKey() + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.contextsAllowed = CONTEXTS_ALLOWED_SETTING.exists(settings) ? new HashSet<>() : null;
|
||||
|
||||
if (this.contextsAllowed != null) {
|
||||
List<String> contextsAllowedList = CONTEXTS_ALLOWED_SETTING.get(settings);
|
||||
|
||||
if (contextsAllowedList.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"must specify at least one script context or none for setting [" + CONTEXTS_ALLOWED_SETTING.getKey() + "].");
|
||||
}
|
||||
|
||||
for (String settingContext : contextsAllowedList) {
|
||||
if (ALLOW_NONE.equals(settingContext)) {
|
||||
if (contextsAllowedList.size() != 1) {
|
||||
throw new IllegalArgumentException("cannot specify both [" + ALLOW_NONE + "]" +
|
||||
" and other script contexts for setting [" + CONTEXTS_ALLOWED_SETTING.getKey() + "].");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (scriptContextRegistry.isSupportedContext(settingContext)) {
|
||||
this.contextsAllowed.add(settingContext);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"unknown script context [" + settingContext + "] found in setting [" + CONTEXTS_ALLOWED_SETTING.getKey() + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.scriptContextRegistry = scriptContextRegistry;
|
||||
|
||||
int cacheMaxSize = SCRIPT_CACHE_SIZE_SETTING.get(settings);
|
||||
|
||||
CacheBuilder<CacheKey, CompiledScript> cacheBuilder = CacheBuilder.builder();
|
||||
|
@ -110,8 +191,9 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
|
||||
logger.debug("using script cache with max_size [{}], expire [{}]", cacheMaxSize, cacheExpire);
|
||||
this.cache = cacheBuilder.removalListener(new ScriptCacheRemovalListener()).build();
|
||||
|
||||
this.engines = scriptEngineRegistry.getRegisteredLanguages();
|
||||
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, settings);
|
||||
|
||||
this.lastInlineCompileTime = System.nanoTime();
|
||||
this.setMaxCompilationsPerMinute(SCRIPT_MAX_COMPILATIONS_PER_MINUTE.get(settings));
|
||||
}
|
||||
|
@ -194,9 +276,16 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
|
||||
ScriptEngine scriptEngine = getEngine(lang);
|
||||
|
||||
if (canExecuteScript(lang, type, scriptContext) == false) {
|
||||
throw new IllegalStateException("scripts of type [" + script.getType() + "]," +
|
||||
" operation [" + scriptContext.getKey() + "] and lang [" + lang + "] are disabled");
|
||||
if (isTypeEnabled(type) == false) {
|
||||
throw new IllegalArgumentException("cannot execute [" + type + "] scripts");
|
||||
}
|
||||
|
||||
if (scriptContextRegistry.isSupportedContext(scriptContext.getKey()) == false) {
|
||||
throw new IllegalArgumentException("script context [" + scriptContext.getKey() + "] not supported");
|
||||
}
|
||||
|
||||
if (isContextEnabled(scriptContext) == false) {
|
||||
throw new IllegalArgumentException("cannot execute scripts using [" + scriptContext.getKey() + "] context");
|
||||
}
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
@ -288,6 +377,18 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
return engines.containsKey(lang);
|
||||
}
|
||||
|
||||
public boolean isTypeEnabled(ScriptType scriptType) {
|
||||
return typesAllowed == null || typesAllowed.contains(scriptType.getName());
|
||||
}
|
||||
|
||||
public boolean isContextEnabled(ScriptContext scriptContext) {
|
||||
return contextsAllowed == null || contextsAllowed.contains(scriptContext.getKey());
|
||||
}
|
||||
|
||||
public boolean isAnyContextEnabled() {
|
||||
return contextsAllowed == null || contextsAllowed.isEmpty() == false;
|
||||
}
|
||||
|
||||
StoredScriptSource getScriptFromClusterState(String id, String lang) {
|
||||
if (lang != null && isLangSupported(lang) == false) {
|
||||
throw new IllegalArgumentException("unable to get stored script with unsupported lang [" + lang + "]");
|
||||
|
@ -328,16 +429,19 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
try {
|
||||
ScriptEngine scriptEngine = getEngine(source.getLang());
|
||||
|
||||
if (isAnyScriptContextEnabled(source.getLang(), ScriptType.STORED)) {
|
||||
if (isTypeEnabled(ScriptType.STORED) == false) {
|
||||
throw new IllegalArgumentException(
|
||||
"cannot put [" + ScriptType.STORED + "] script, [" + ScriptType.STORED + "] scripts are not enabled");
|
||||
} else if (isAnyContextEnabled() == false) {
|
||||
throw new IllegalArgumentException(
|
||||
"cannot put [" + ScriptType.STORED + "] script, no script contexts are enabled");
|
||||
} else {
|
||||
Object compiled = scriptEngine.compile(request.id(), source.getCode(), Collections.emptyMap());
|
||||
|
||||
if (compiled == null) {
|
||||
throw new IllegalArgumentException("failed to parse/compile stored script [" + request.id() + "]" +
|
||||
(source.getCode() == null ? "" : " using code [" + source.getCode() + "]"));
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"cannot put stored script [" + request.id() + "], stored scripts cannot be run under any context");
|
||||
}
|
||||
} catch (ScriptException good) {
|
||||
throw good;
|
||||
|
@ -422,23 +526,6 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
return getEngine(compiledScript.lang()).search(compiledScript, lookup, params);
|
||||
}
|
||||
|
||||
private boolean isAnyScriptContextEnabled(String lang, ScriptType scriptType) {
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
if (canExecuteScript(lang, scriptType, scriptContext)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean canExecuteScript(String lang, ScriptType scriptType, ScriptContext scriptContext) {
|
||||
assert lang != null;
|
||||
if (scriptContextRegistry.isSupportedContext(scriptContext.getKey()) == false) {
|
||||
throw new IllegalArgumentException("script context [" + scriptContext.getKey() + "] not supported");
|
||||
}
|
||||
return scriptModes.getScriptEnabled(lang, scriptType, scriptContext);
|
||||
}
|
||||
|
||||
public ScriptStats stats() {
|
||||
return scriptMetrics.stats();
|
||||
}
|
||||
|
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.script;
|
||||
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Setting.Property;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ScriptSettings {
|
||||
|
||||
private static final Map<ScriptType, Setting<Boolean>> SCRIPT_TYPE_SETTING_MAP;
|
||||
|
||||
static {
|
||||
Map<ScriptType, Setting<Boolean>> scriptTypeSettingMap = new EnumMap<>(ScriptType.class);
|
||||
for (ScriptType scriptType : ScriptType.values()) {
|
||||
scriptTypeSettingMap.put(scriptType, Setting.boolSetting(
|
||||
ScriptModes.sourceKey(scriptType),
|
||||
scriptType.isDefaultEnabled(),
|
||||
Property.NodeScope,
|
||||
Property.Deprecated));
|
||||
}
|
||||
SCRIPT_TYPE_SETTING_MAP = Collections.unmodifiableMap(scriptTypeSettingMap);
|
||||
}
|
||||
|
||||
private final Map<ScriptContext, Setting<Boolean>> scriptContextSettingMap;
|
||||
private final List<Setting<Boolean>> scriptLanguageSettings;
|
||||
|
||||
public ScriptSettings(ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry) {
|
||||
Map<ScriptContext, Setting<Boolean>> scriptContextSettingMap = contextSettings(scriptContextRegistry);
|
||||
this.scriptContextSettingMap = Collections.unmodifiableMap(scriptContextSettingMap);
|
||||
|
||||
List<Setting<Boolean>> scriptLanguageSettings = languageSettings(SCRIPT_TYPE_SETTING_MAP, scriptContextSettingMap, scriptEngineRegistry, scriptContextRegistry);
|
||||
this.scriptLanguageSettings = Collections.unmodifiableList(scriptLanguageSettings);
|
||||
}
|
||||
|
||||
private static Map<ScriptContext, Setting<Boolean>> contextSettings(ScriptContextRegistry scriptContextRegistry) {
|
||||
Map<ScriptContext, Setting<Boolean>> scriptContextSettingMap = new HashMap<>();
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
scriptContextSettingMap.put(scriptContext,
|
||||
Setting.boolSetting(ScriptModes.operationKey(scriptContext), false, Property.NodeScope, Property.Deprecated));
|
||||
}
|
||||
return scriptContextSettingMap;
|
||||
}
|
||||
|
||||
private static List<Setting<Boolean>> languageSettings(Map<ScriptType, Setting<Boolean>> scriptTypeSettingMap,
|
||||
Map<ScriptContext, Setting<Boolean>> scriptContextSettingMap,
|
||||
ScriptEngineRegistry scriptEngineRegistry,
|
||||
ScriptContextRegistry scriptContextRegistry) {
|
||||
final List<Setting<Boolean>> scriptModeSettings = new ArrayList<>();
|
||||
|
||||
for (final Class<? extends ScriptEngine> scriptEngineService : scriptEngineRegistry.getRegisteredScriptEngineServices()) {
|
||||
final String language = scriptEngineRegistry.getLanguage(scriptEngineService);
|
||||
for (final ScriptType scriptType : ScriptType.values()) {
|
||||
// Top level, like "script.engine.groovy.inline"
|
||||
final boolean defaultNonFileScriptMode = scriptEngineRegistry.getDefaultInlineScriptEnableds().get(language);
|
||||
boolean defaultLangAndType = defaultNonFileScriptMode;
|
||||
// Files are treated differently because they are never default-deny
|
||||
final boolean defaultIfNothingSet = defaultLangAndType;
|
||||
|
||||
Function<Settings, String> defaultLangAndTypeFn = settings -> {
|
||||
final Setting<Boolean> globalTypeSetting = scriptTypeSettingMap.get(scriptType);
|
||||
final Setting<Boolean> langAndTypeSetting = Setting.boolSetting(ScriptModes.getGlobalKey(language, scriptType),
|
||||
defaultIfNothingSet, Property.NodeScope, Property.Deprecated);
|
||||
|
||||
if (langAndTypeSetting.exists(settings)) {
|
||||
// fine-grained e.g. script.engine.groovy.inline
|
||||
return langAndTypeSetting.get(settings).toString();
|
||||
} else if (globalTypeSetting.exists(settings)) {
|
||||
// global type - script.inline
|
||||
return globalTypeSetting.get(settings).toString();
|
||||
} else {
|
||||
return Boolean.toString(defaultIfNothingSet);
|
||||
}
|
||||
};
|
||||
|
||||
// Setting for something like "script.engine.groovy.inline"
|
||||
final Setting<Boolean> langAndTypeSetting = Setting.boolSetting(ScriptModes.getGlobalKey(language, scriptType),
|
||||
defaultLangAndTypeFn, Property.NodeScope, Property.Deprecated);
|
||||
scriptModeSettings.add(langAndTypeSetting);
|
||||
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
final String langAndTypeAndContextName = ScriptModes.getKey(language, scriptType, scriptContext);
|
||||
// A function that, given a setting, will return what the default should be. Since the fine-grained script settings
|
||||
// read from a bunch of different places this is implemented in this way.
|
||||
Function<Settings, String> defaultSettingFn = settings -> {
|
||||
final Setting<Boolean> globalOpSetting = scriptContextSettingMap.get(scriptContext);
|
||||
final Setting<Boolean> globalTypeSetting = scriptTypeSettingMap.get(scriptType);
|
||||
final Setting<Boolean> langAndTypeAndContextSetting = Setting.boolSetting(langAndTypeAndContextName,
|
||||
defaultIfNothingSet, Property.NodeScope, Property.Deprecated);
|
||||
|
||||
// fallback logic for script mode settings
|
||||
if (langAndTypeAndContextSetting.exists(settings)) {
|
||||
// like: "script.engine.groovy.inline.aggs: true"
|
||||
return langAndTypeAndContextSetting.get(settings).toString();
|
||||
} else if (langAndTypeSetting.exists(settings)) {
|
||||
// like: "script.engine.groovy.inline: true"
|
||||
return langAndTypeSetting.get(settings).toString();
|
||||
} else if (globalOpSetting.exists(settings)) {
|
||||
// like: "script.aggs: true"
|
||||
return globalOpSetting.get(settings).toString();
|
||||
} else if (globalTypeSetting.exists(settings)) {
|
||||
// like: "script.inline: true"
|
||||
return globalTypeSetting.get(settings).toString();
|
||||
} else {
|
||||
// Nothing is set!
|
||||
return Boolean.toString(defaultIfNothingSet);
|
||||
}
|
||||
};
|
||||
// The actual setting for finest grained script settings
|
||||
Setting<Boolean> setting =
|
||||
Setting.boolSetting(langAndTypeAndContextName, defaultSettingFn, Property.NodeScope, Property.Deprecated);
|
||||
scriptModeSettings.add(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
return scriptModeSettings;
|
||||
}
|
||||
|
||||
public List<Setting<?>> getSettings() {
|
||||
List<Setting<?>> settings = new ArrayList<>();
|
||||
settings.addAll(SCRIPT_TYPE_SETTING_MAP.values());
|
||||
settings.addAll(scriptContextSettingMap.values());
|
||||
settings.addAll(scriptLanguageSettings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
public Iterable<Setting<Boolean>> getScriptLanguageSettings() {
|
||||
return scriptLanguageSettings;
|
||||
}
|
||||
}
|
|
@ -28,8 +28,8 @@ import java.io.IOException;
|
|||
|
||||
/**
|
||||
* ScriptType represents the way a script is stored and retrieved from the {@link ScriptService}.
|
||||
* It's also used to by {@link ScriptSettings} and {@link ScriptModes} to determine whether or not
|
||||
* a {@link Script} is allowed to be executed based on both default and user-defined settings.
|
||||
* It's also used to by {@link ScriptService} to determine whether or not a {@link Script} is
|
||||
* allowed to be executed based on both default and user-defined settings.
|
||||
*/
|
||||
public enum ScriptType implements Writeable {
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ import org.elasticsearch.script.Script;
|
|||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.RandomObjects;
|
||||
|
@ -64,7 +63,6 @@ import static java.util.Collections.emptyMap;
|
|||
import static java.util.Collections.singletonList;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
|
||||
import static org.elasticsearch.common.xcontent.XContentHelper.update;
|
||||
import static org.elasticsearch.script.MockScriptEngine.mockInlineScript;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
|
@ -145,15 +143,12 @@ public class UpdateRequestTests extends ESTestCase {
|
|||
final ScriptEngineRegistry scriptEngineRegistry =
|
||||
new ScriptEngineRegistry(singletonList(engine));
|
||||
|
||||
final ScriptSettings scriptSettings =
|
||||
new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
final ResourceWatcherService watcherService =
|
||||
new ResourceWatcherService(baseSettings, null);
|
||||
ScriptService scriptService = new ScriptService(
|
||||
baseSettings,
|
||||
scriptEngineRegistry,
|
||||
scriptContextRegistry,
|
||||
scriptSettings);
|
||||
scriptContextRegistry);
|
||||
final Settings settings = settings(Version.CURRENT).build();
|
||||
|
||||
updateHelper = new UpdateHelper(settings, scriptService);
|
||||
|
|
|
@ -70,7 +70,6 @@ import org.elasticsearch.indices.mapper.MapperRegistry;
|
|||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.test.ClusterServiceUtils;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
@ -130,8 +129,7 @@ public class IndexModuleTests extends ESTestCase {
|
|||
bigArrays = new BigArrays(settings, circuitBreakerService);
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(emptyList());
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry);
|
||||
clusterService = ClusterServiceUtils.createClusterService(threadPool);
|
||||
nodeEnvironment = new NodeEnvironment(settings, environment);
|
||||
mapperRegistry = new IndicesModule(Collections.emptyList()).getMapperRegistry();
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.elasticsearch.cluster.ClusterChangedEvent;
|
|||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
@ -32,21 +31,14 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class ScriptContextTests extends ESTestCase {
|
||||
|
||||
private static final String PLUGIN_NAME = "testplugin";
|
||||
private static final String SCRIPT_PLUGIN_CUSTOM_SETTING = "script." + PLUGIN_NAME + "_custom_globally_disabled_op";
|
||||
private static final String SCRIPT_ENGINE_CUSTOM_SETTING = "script.engine." + MockScriptEngine.NAME + ".inline." + PLUGIN_NAME + "_custom_exp_disabled_op";
|
||||
|
||||
private ScriptSettings scriptSettings;
|
||||
|
||||
ScriptService makeScriptService() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
|
||||
.put(SCRIPT_PLUGIN_CUSTOM_SETTING, "false")
|
||||
.put(SCRIPT_ENGINE_CUSTOM_SETTING, "false")
|
||||
.put("script.contexts_allowed", "search, aggs, testplugin_custom_op")
|
||||
.build();
|
||||
|
||||
MockScriptEngine scriptEngine = new MockScriptEngine(MockScriptEngine.NAME, Collections.singletonMap("1", script -> "1"));
|
||||
|
@ -56,8 +48,7 @@ public class ScriptContextTests extends ESTestCase {
|
|||
new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"),
|
||||
new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op"));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
|
||||
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
ScriptService scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
ScriptService scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry);
|
||||
|
||||
ClusterState empty = ClusterState.builder(new ClusterName("_name")).build();
|
||||
ScriptMetaData smd = empty.metaData().custom(ScriptMetaData.TYPE);
|
||||
|
@ -69,8 +60,6 @@ public class ScriptContextTests extends ESTestCase {
|
|||
return scriptService;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void testCustomGlobalScriptContextSettings() throws Exception {
|
||||
ScriptService scriptService = makeScriptService();
|
||||
for (ScriptType scriptType : ScriptType.values()) {
|
||||
|
@ -78,12 +67,10 @@ public class ScriptContextTests extends ESTestCase {
|
|||
Script script = new Script(scriptType, MockScriptEngine.NAME, "1", Collections.emptyMap());
|
||||
scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op"));
|
||||
fail("script compilation should have been rejected");
|
||||
} catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage(), containsString("scripts of type [" + scriptType + "], operation [" + PLUGIN_NAME + "_custom_globally_disabled_op] and lang [" + MockScriptEngine.NAME + "] are disabled"));
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("cannot execute scripts using [" + PLUGIN_NAME + "_custom_globally_disabled_op] context"));
|
||||
}
|
||||
}
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, SCRIPT_PLUGIN_CUSTOM_SETTING, SCRIPT_ENGINE_CUSTOM_SETTING));
|
||||
}
|
||||
|
||||
public void testCustomScriptContextSettings() throws Exception {
|
||||
|
@ -92,16 +79,14 @@ public class ScriptContextTests extends ESTestCase {
|
|||
try {
|
||||
scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"));
|
||||
fail("script compilation should have been rejected");
|
||||
} catch (IllegalStateException e) {
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("scripts of type [inline], operation [" + PLUGIN_NAME + "_custom_exp_disabled_op] and lang [" + MockScriptEngine.NAME + "] are disabled"));
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("cannot execute scripts using [" + PLUGIN_NAME + "_custom_exp_disabled_op] context"));
|
||||
}
|
||||
|
||||
// still works for other script contexts
|
||||
assertNotNull(scriptService.compile(script, ScriptContext.Standard.AGGS));
|
||||
assertNotNull(scriptService.compile(script, ScriptContext.Standard.SEARCH));
|
||||
assertNotNull(scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_op")));
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, SCRIPT_PLUGIN_CUSTOM_SETTING, SCRIPT_ENGINE_CUSTOM_SETTING));
|
||||
}
|
||||
|
||||
public void testUnknownPluginScriptContext() throws Exception {
|
||||
|
@ -115,8 +100,6 @@ public class ScriptContextTests extends ESTestCase {
|
|||
assertTrue(e.getMessage(), e.getMessage().contains("script context [" + PLUGIN_NAME + "_unknown] not supported"));
|
||||
}
|
||||
}
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, SCRIPT_PLUGIN_CUSTOM_SETTING, SCRIPT_ENGINE_CUSTOM_SETTING));
|
||||
}
|
||||
|
||||
public void testUnknownCustomScriptContext() throws Exception {
|
||||
|
@ -136,7 +119,5 @@ public class ScriptContextTests extends ESTestCase {
|
|||
assertTrue(e.getMessage(), e.getMessage().contains("script context [test] not supported"));
|
||||
}
|
||||
}
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, SCRIPT_PLUGIN_CUSTOM_SETTING, SCRIPT_ENGINE_CUSTOM_SETTING));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,254 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.script;
|
||||
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static org.elasticsearch.common.util.set.Sets.newHashSet;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
// TODO: this needs to be a base test class, and all scripting engines extend it
|
||||
public class ScriptModesTests extends ESTestCase {
|
||||
ScriptSettings scriptSettings;
|
||||
ScriptContextRegistry scriptContextRegistry;
|
||||
private ScriptContext[] scriptContexts;
|
||||
private Map<String, ScriptEngine> scriptEngines;
|
||||
private ScriptModes scriptModes;
|
||||
private Set<String> checkedSettings;
|
||||
private boolean assertAllSettingsWereChecked;
|
||||
private boolean assertScriptModesNonNull;
|
||||
|
||||
@Before
|
||||
public void setupScriptEngines() {
|
||||
//randomly register custom script contexts
|
||||
int randomInt = randomIntBetween(0, 3);
|
||||
//prevent duplicates using map
|
||||
Map<String, ScriptContext.Plugin> contexts = new HashMap<>();
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
String plugin = randomAlphaOfLength(randomIntBetween(1, 10));
|
||||
String operation = randomAlphaOfLength(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(newHashSet(new CustomScriptEngine()));
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(scriptEngines.values());
|
||||
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
checkedSettings = new HashSet<>();
|
||||
assertAllSettingsWereChecked = true;
|
||||
assertScriptModesNonNull = true;
|
||||
}
|
||||
|
||||
@After
|
||||
public void assertAllSettingsWereChecked() {
|
||||
if (assertScriptModesNonNull) {
|
||||
assertThat(scriptModes, notNullValue());
|
||||
int numberOfSettings = ScriptType.values().length * scriptContextRegistry.scriptContexts().size();
|
||||
numberOfSettings += 2; // for top-level inline/store settings
|
||||
assertThat(scriptModes.scriptEnabled.size(), equalTo(numberOfSettings));
|
||||
if (assertAllSettingsWereChecked) {
|
||||
assertThat(checkedSettings.size(), equalTo(numberOfSettings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testDefaultSettings() {
|
||||
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, Settings.EMPTY);
|
||||
assertScriptModesAllOps(false, ScriptType.STORED, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
public void testMissingSetting() {
|
||||
assertAllSettingsWereChecked = false;
|
||||
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, Settings.EMPTY);
|
||||
try {
|
||||
scriptModes.getScriptEnabled("non_existing", randomFrom(ScriptType.values()), randomFrom(scriptContexts));
|
||||
fail("Expected IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("not found for lang [non_existing]"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testScriptTypeGenericSettings() {
|
||||
int randomInt = randomIntBetween(1, ScriptType.values().length - 1);
|
||||
Set<ScriptType> randomScriptTypesSet = new HashSet<>();
|
||||
boolean[] randomScriptModes = new boolean[randomInt];
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
boolean added = false;
|
||||
while (added == false) {
|
||||
added = randomScriptTypesSet.add(randomFrom(ScriptType.values()));
|
||||
}
|
||||
randomScriptModes[i] = randomBoolean();
|
||||
}
|
||||
ScriptType[] randomScriptTypes = randomScriptTypesSet.toArray(new ScriptType[randomScriptTypesSet.size()]);
|
||||
List<String> deprecated = new ArrayList<>();
|
||||
Settings.Builder builder = Settings.builder();
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
builder.put("script" + "." + randomScriptTypes[i].getName(), randomScriptModes[i]);
|
||||
deprecated.add("script" + "." + randomScriptTypes[i].getName());
|
||||
}
|
||||
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, builder.build());
|
||||
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
assertScriptModesAllOps(randomScriptModes[i], randomScriptTypes[i]);
|
||||
}
|
||||
if (randomScriptTypesSet.contains(ScriptType.STORED) == false) {
|
||||
assertScriptModesAllOps(false, ScriptType.STORED);
|
||||
}
|
||||
if (randomScriptTypesSet.contains(ScriptType.INLINE) == false) {
|
||||
assertScriptModesAllOps(false, ScriptType.INLINE);
|
||||
}
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, deprecated.toArray(new String[] {})));
|
||||
}
|
||||
|
||||
public void testScriptContextGenericSettings() {
|
||||
int randomInt = randomIntBetween(1, scriptContexts.length - 1);
|
||||
Set<ScriptContext> randomScriptContextsSet = new HashSet<>();
|
||||
boolean[] randomScriptModes = new boolean[randomInt];
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
boolean added = false;
|
||||
while (added == false) {
|
||||
added = randomScriptContextsSet.add(randomFrom(scriptContexts));
|
||||
}
|
||||
randomScriptModes[i] = randomBoolean();
|
||||
}
|
||||
ScriptContext[] randomScriptContexts = randomScriptContextsSet.toArray(new ScriptContext[randomScriptContextsSet.size()]);
|
||||
List<String> deprecated = new ArrayList<>();
|
||||
Settings.Builder builder = Settings.builder();
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
builder.put("script" + "." + randomScriptContexts[i].getKey(), randomScriptModes[i]);
|
||||
deprecated.add("script" + "." + randomScriptContexts[i].getKey());
|
||||
}
|
||||
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, builder.build());
|
||||
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
assertScriptModesAllTypes(randomScriptModes[i], randomScriptContexts[i]);
|
||||
}
|
||||
|
||||
ScriptContext[] complementOf = complementOf(randomScriptContexts);
|
||||
assertScriptModes(false, new ScriptType[]{ScriptType.STORED, ScriptType.INLINE}, complementOf);
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, deprecated.toArray(new String[] {})));
|
||||
}
|
||||
|
||||
public void testConflictingScriptTypeAndOpGenericSettings() {
|
||||
ScriptContext scriptContext = randomFrom(scriptContexts);
|
||||
Settings.Builder builder = Settings.builder()
|
||||
.put("script." + scriptContext.getKey(), "false")
|
||||
.put("script.stored", "true")
|
||||
.put("script.inline", "true");
|
||||
//operations generic settings have precedence over script type generic settings
|
||||
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, builder.build());
|
||||
assertScriptModesAllTypes(false, scriptContext);
|
||||
ScriptContext[] complementOf = complementOf(scriptContext);
|
||||
assertScriptModes(true, new ScriptType[]{ScriptType.STORED}, complementOf);
|
||||
assertScriptModes(true, new ScriptType[]{ScriptType.INLINE}, complementOf);
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(
|
||||
scriptSettings, "script." + scriptContext.getKey(), "script.stored", "script.inline"));
|
||||
}
|
||||
|
||||
private void assertScriptModesAllOps(boolean expectedScriptEnabled, ScriptType... scriptTypes) {
|
||||
assertScriptModes(expectedScriptEnabled, scriptTypes, scriptContexts);
|
||||
}
|
||||
|
||||
private void assertScriptModesAllTypes(boolean expectedScriptEnabled, ScriptContext... scriptContexts) {
|
||||
assertScriptModes(expectedScriptEnabled, ScriptType.values(), scriptContexts);
|
||||
}
|
||||
|
||||
private void assertScriptModes(boolean expectedScriptEnabled, ScriptType[] scriptTypes, ScriptContext... scriptContexts) {
|
||||
assert scriptTypes.length > 0;
|
||||
assert scriptContexts.length > 0;
|
||||
for (ScriptType scriptType : scriptTypes) {
|
||||
checkedSettings.add("script.engine.custom." + scriptType);
|
||||
for (ScriptContext scriptContext : scriptContexts) {
|
||||
assertThat("custom." + scriptType + "." + scriptContext.getKey() + " doesn't have the expected value",
|
||||
scriptModes.getScriptEnabled("custom", scriptType, scriptContext), equalTo(expectedScriptEnabled));
|
||||
checkedSettings.add("custom." + scriptType + "." + scriptContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ScriptContext[] complementOf(ScriptContext... scriptContexts) {
|
||||
Map<String, ScriptContext> copy = new HashMap<>();
|
||||
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()]);
|
||||
}
|
||||
|
||||
static Map<String, ScriptEngine> buildScriptEnginesByLangMap(Set<ScriptEngine> scriptEngines) {
|
||||
Map<String, ScriptEngine> builder = new HashMap<>();
|
||||
for (ScriptEngine scriptEngine : scriptEngines) {
|
||||
String type = scriptEngine.getType();
|
||||
builder.put(type, scriptEngine);
|
||||
}
|
||||
return unmodifiableMap(builder);
|
||||
}
|
||||
|
||||
private static class CustomScriptEngine implements ScriptEngine {
|
||||
|
||||
public static final String NAME = "custom";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,7 +57,6 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
private Map<String, ScriptEngine> scriptEnginesByLangMap;
|
||||
private ScriptEngineRegistry scriptEngineRegistry;
|
||||
private ScriptContextRegistry scriptContextRegistry;
|
||||
private ScriptSettings scriptSettings;
|
||||
private ScriptContext[] scriptContexts;
|
||||
private ScriptService scriptService;
|
||||
private Settings baseSettings;
|
||||
|
@ -80,8 +79,6 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
scriptEngine = new TestEngine();
|
||||
dangerousScriptEngine = new TestDangerousEngine();
|
||||
TestEngine defaultScriptServiceEngine = new TestEngine(Script.DEFAULT_SCRIPT_LANG) {};
|
||||
scriptEnginesByLangMap = ScriptModesTests.buildScriptEnginesByLangMap(
|
||||
new HashSet<>(Arrays.asList(scriptEngine, defaultScriptServiceEngine)));
|
||||
//randomly register custom script contexts
|
||||
int randomInt = randomIntBetween(0, 3);
|
||||
//prevent duplicates using map
|
||||
|
@ -101,15 +98,13 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
scriptEngineRegistry = new ScriptEngineRegistry(Arrays.asList(scriptEngine, dangerousScriptEngine,
|
||||
defaultScriptServiceEngine));
|
||||
scriptContextRegistry = new ScriptContextRegistry(contexts.values());
|
||||
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]);
|
||||
logger.info("--> setup script service");
|
||||
}
|
||||
|
||||
private void buildScriptService(Settings additionalSettings) throws IOException {
|
||||
Settings finalSettings = Settings.builder().put(baseSettings).put(additionalSettings).build();
|
||||
// TODO:
|
||||
scriptService = new ScriptService(finalSettings, scriptEngineRegistry, scriptContextRegistry, scriptSettings) {
|
||||
scriptService = new ScriptService(finalSettings, scriptEngineRegistry, scriptContextRegistry) {
|
||||
@Override
|
||||
StoredScriptSource getScriptFromClusterState(String id, String lang) {
|
||||
//mock the script that gets retrieved from an index
|
||||
|
@ -179,33 +174,25 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
public void testAllowSomeScriptTypeSettings() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
builder.put("script.types_allowed", "inline");
|
||||
builder.put("script.engine.painless.stored", false);
|
||||
buildScriptService(builder.build());
|
||||
|
||||
assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH);
|
||||
assertCompileRejected("painless", "script", ScriptType.STORED, ScriptContext.Standard.SEARCH);
|
||||
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.engine.painless.stored"));
|
||||
}
|
||||
|
||||
public void testAllowSomeScriptContextSettings() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
builder.put("script.contexts_allowed", "search, aggs");
|
||||
builder.put("script.update", false);
|
||||
buildScriptService(builder.build());
|
||||
|
||||
assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH);
|
||||
assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.AGGS);
|
||||
assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.UPDATE);
|
||||
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.update"));
|
||||
}
|
||||
|
||||
public void testAllowNoScriptTypeSettings() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
builder.put("script.types_allowed", "");
|
||||
builder.put("script.types_allowed", "none");
|
||||
buildScriptService(builder.build());
|
||||
|
||||
assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH);
|
||||
|
@ -214,7 +201,7 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
|
||||
public void testAllowNoScriptContextSettings() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
builder.put("script.contexts_allowed", "");
|
||||
builder.put("script.contexts_allowed", "none");
|
||||
buildScriptService(builder.build());
|
||||
|
||||
assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH);
|
||||
|
@ -223,109 +210,6 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.INGEST);
|
||||
}
|
||||
|
||||
public void testDefaultBehaviourFineGrainedSettings() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
buildScriptService(builder.build());
|
||||
|
||||
for (ScriptContext scriptContext : scriptContexts) {
|
||||
assertCompileRejected("dtest", "script", ScriptType.INLINE, scriptContext);
|
||||
assertCompileRejected("dtest", "script", ScriptType.STORED, scriptContext);
|
||||
}
|
||||
}
|
||||
|
||||
public void testFineGrainedSettings() throws IOException {
|
||||
//collect the fine-grained settings to set for this run
|
||||
int numScriptSettings = randomIntBetween(0, ScriptType.values().length);
|
||||
Map<ScriptType, Boolean> scriptSourceSettings = new HashMap<>();
|
||||
for (int i = 0; i < numScriptSettings; i++) {
|
||||
ScriptType scriptType;
|
||||
do {
|
||||
scriptType = randomFrom(ScriptType.values());
|
||||
} while (scriptSourceSettings.containsKey(scriptType));
|
||||
scriptSourceSettings.put(scriptType, randomBoolean());
|
||||
}
|
||||
int numScriptContextSettings = randomIntBetween(0, this.scriptContextRegistry.scriptContexts().size());
|
||||
Map<ScriptContext, Boolean> scriptContextSettings = new HashMap<>();
|
||||
for (int i = 0; i < numScriptContextSettings; i++) {
|
||||
ScriptContext scriptContext;
|
||||
do {
|
||||
scriptContext = randomFrom(this.scriptContexts);
|
||||
} while (scriptContextSettings.containsKey(scriptContext));
|
||||
scriptContextSettings.put(scriptContext, randomBoolean());
|
||||
}
|
||||
int numEngineSettings = randomIntBetween(0, ScriptType.values().length * scriptContexts.length);
|
||||
Map<String, Boolean> engineSettings = new HashMap<>();
|
||||
for (int i = 0; i < numEngineSettings; i++) {
|
||||
String settingKey;
|
||||
do {
|
||||
ScriptType scriptType = randomFrom(ScriptType.values());
|
||||
ScriptContext scriptContext = randomFrom(this.scriptContexts);
|
||||
settingKey = scriptEngine.getType() + "." + scriptType + "." + scriptContext.getKey();
|
||||
} while (engineSettings.containsKey(settingKey));
|
||||
engineSettings.put(settingKey, randomBoolean());
|
||||
}
|
||||
List<String> deprecated = new ArrayList<>();
|
||||
//set the selected fine-grained settings
|
||||
Settings.Builder builder = Settings.builder();
|
||||
for (Map.Entry<ScriptType, Boolean> entry : scriptSourceSettings.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
builder.put("script" + "." + entry.getKey().getName(), "true");
|
||||
} else {
|
||||
builder.put("script" + "." + entry.getKey().getName(), "false");
|
||||
}
|
||||
deprecated.add("script" + "." + entry.getKey().getName());
|
||||
}
|
||||
for (Map.Entry<ScriptContext, Boolean> entry : scriptContextSettings.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
builder.put("script" + "." + entry.getKey().getKey(), "true");
|
||||
} else {
|
||||
builder.put("script" + "." + entry.getKey().getKey(), "false");
|
||||
}
|
||||
deprecated.add("script" + "." + entry.getKey().getKey());
|
||||
}
|
||||
for (Map.Entry<String, Boolean> entry : engineSettings.entrySet()) {
|
||||
int delimiter = entry.getKey().indexOf('.');
|
||||
String part1 = entry.getKey().substring(0, delimiter);
|
||||
String part2 = entry.getKey().substring(delimiter + 1);
|
||||
|
||||
String lang = randomFrom(scriptEnginesByLangMap.get(part1).getType());
|
||||
if (entry.getValue()) {
|
||||
builder.put("script.engine" + "." + lang + "." + part2, "true");
|
||||
} else {
|
||||
builder.put("script.engine" + "." + lang + "." + part2, "false");
|
||||
}
|
||||
deprecated.add("script.engine" + "." + lang + "." + part2);
|
||||
}
|
||||
|
||||
buildScriptService(builder.build());
|
||||
|
||||
for (ScriptType scriptType : ScriptType.values()) {
|
||||
String script = "script";
|
||||
for (ScriptContext scriptContext : this.scriptContexts) {
|
||||
//fallback mechanism: 1) engine specific settings 2) op based settings 3) source based settings
|
||||
Boolean scriptEnabled = engineSettings.get(dangerousScriptEngine.getType() + "." + scriptType + "." + scriptContext.getKey());
|
||||
if (scriptEnabled == null) {
|
||||
scriptEnabled = scriptContextSettings.get(scriptContext);
|
||||
}
|
||||
if (scriptEnabled == null) {
|
||||
scriptEnabled = scriptSourceSettings.get(scriptType);
|
||||
}
|
||||
if (scriptEnabled == null) {
|
||||
scriptEnabled = DEFAULT_SCRIPT_ENABLED.get(scriptType);
|
||||
}
|
||||
|
||||
String lang = dangerousScriptEngine.getType();
|
||||
if (scriptEnabled) {
|
||||
assertCompileAccepted(lang, script, scriptType, scriptContext);
|
||||
} else {
|
||||
assertCompileRejected(lang, script, scriptType, scriptContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, deprecated.toArray(new String[] {})));
|
||||
}
|
||||
|
||||
public void testCompileNonRegisteredContext() throws IOException {
|
||||
buildScriptService(Settings.EMPTY);
|
||||
String pluginName;
|
||||
|
@ -378,14 +262,11 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
public void testCompilationStatsOnCacheHit() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getKey(), 1);
|
||||
builder.put("script.inline", "true");
|
||||
buildScriptService(builder.build());
|
||||
Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap());
|
||||
scriptService.compile(script, randomFrom(scriptContexts));
|
||||
scriptService.compile(script, randomFrom(scriptContexts));
|
||||
assertEquals(1L, scriptService.stats().getCompilations());
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.inline"));
|
||||
}
|
||||
|
||||
public void testIndexedScriptCountedInCompilationStats() throws IOException {
|
||||
|
@ -397,25 +278,19 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
public void testCacheEvictionCountedInCacheEvictionsStats() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getKey(), 1);
|
||||
builder.put("script.inline", "true");
|
||||
buildScriptService(builder.build());
|
||||
scriptService.compile(new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()), randomFrom(scriptContexts));
|
||||
scriptService.compile(new Script(ScriptType.INLINE, "test", "2+2", Collections.emptyMap()), randomFrom(scriptContexts));
|
||||
assertEquals(2L, scriptService.stats().getCompilations());
|
||||
assertEquals(1L, scriptService.stats().getCacheEvictions());
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.inline"));
|
||||
}
|
||||
|
||||
public void testDefaultLanguage() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
builder.put("script.inline", "true");
|
||||
buildScriptService(builder.build());
|
||||
CompiledScript script = scriptService.compile(
|
||||
new Script(ScriptType.INLINE, Script.DEFAULT_SCRIPT_LANG, "1 + 1", Collections.emptyMap()), randomFrom(scriptContexts));
|
||||
assertEquals(script.lang(), Script.DEFAULT_SCRIPT_LANG);
|
||||
assertSettingDeprecationsAndWarnings(
|
||||
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.inline"));
|
||||
}
|
||||
|
||||
public void testStoreScript() throws Exception {
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.script;
|
||||
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class ScriptSettingsTests extends ESTestCase {
|
||||
|
||||
|
||||
public static Setting<?>[] buildDeprecatedSettingsArray(ScriptSettings scriptSettings, String... keys) {
|
||||
Setting<?>[] settings = new Setting[keys.length];
|
||||
int count = 0;
|
||||
|
||||
for (Setting<?> setting : scriptSettings.getSettings()) {
|
||||
for (String key : keys) {
|
||||
if (setting.getKey().equals(key)) {
|
||||
settings[count++] = setting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
public void testSettingsAreProperlyPropogated() {
|
||||
ScriptEngineRegistry scriptEngineRegistry =
|
||||
new ScriptEngineRegistry(Collections.singletonList(new CustomScriptEngine()));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
boolean enabled = randomBoolean();
|
||||
Settings s = Settings.builder().put("script.inline", enabled).build();
|
||||
for (Iterator<Setting<Boolean>> iter = scriptSettings.getScriptLanguageSettings().iterator(); iter.hasNext();) {
|
||||
Setting<Boolean> setting = iter.next();
|
||||
if (setting.getKey().endsWith(".inline")) {
|
||||
assertThat("inline settings should have propagated", setting.get(s), equalTo(enabled));
|
||||
assertThat(setting.getDefaultRaw(s), equalTo(Boolean.toString(enabled)));
|
||||
}
|
||||
}
|
||||
assertSettingDeprecationsAndWarnings(buildDeprecatedSettingsArray(scriptSettings, "script.inline"));
|
||||
}
|
||||
|
||||
private static class CustomScriptEngine implements ScriptEngine {
|
||||
|
||||
public static final String NAME = "custom";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -28,7 +28,6 @@ import org.elasticsearch.script.Script;
|
|||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
import org.elasticsearch.test.InternalAggregationTestCase;
|
||||
|
@ -75,10 +74,8 @@ public class InternalScriptedMetricTests extends InternalAggregationTestCase<Int
|
|||
}));
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(scriptEngine));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
try {
|
||||
return new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry,
|
||||
scriptSettings);
|
||||
return new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException(e);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.elasticsearch.script.Script;
|
|||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.search.aggregations.AggregatorTestCase;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -201,10 +200,9 @@ public class ScriptedMetricAggregatorTests extends AggregatorTestCase {
|
|||
MockScriptEngine scriptEngine = new MockScriptEngine(MockScriptEngine.NAME, SCRIPTS);
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(scriptEngine));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
ScriptService scriptService;
|
||||
try {
|
||||
scriptService = new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
scriptService = new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException(e);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ import org.elasticsearch.script.ScriptContextRegistry;
|
|||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptServiceTests.TestEngine;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.search.DocValueFormat;
|
||||
import org.elasticsearch.search.SearchModule;
|
||||
|
@ -89,11 +88,9 @@ public abstract class AbstractSortTestCase<T extends SortBuilder<T>> extends EST
|
|||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
|
||||
.put(Environment.PATH_CONF_SETTING.getKey(), genericConfigFolder)
|
||||
.build();
|
||||
Environment environment = new Environment(baseSettings);
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new TestEngine()));
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
scriptService = new ScriptService(baseSettings, scriptEngineRegistry, scriptContextRegistry, scriptSettings) {
|
||||
scriptService = new ScriptService(baseSettings, scriptEngineRegistry, scriptContextRegistry) {
|
||||
@Override
|
||||
public CompiledScript compile(Script script, ScriptContext scriptContext) {
|
||||
return new CompiledScript(ScriptType.INLINE, "mockName", "test", script);
|
||||
|
|
|
@ -200,7 +200,7 @@ def smoke_test_release(release, files, hash, plugins):
|
|||
headers = {}
|
||||
print(' Starting elasticsearch deamon from [%s]' % es_dir)
|
||||
try:
|
||||
run('%s; %s -Enode.name=smoke_tester -Ecluster.name=prepare_release -Escript.inline=true -Escript.stored=true -Erepositories.url.allowed_urls=http://snapshot.test* %s -Epidfile=%s -Enode.portsfile=true'
|
||||
run('%s; %s -Enode.name=smoke_tester -Ecluster.name=prepare_release -Erepositories.url.allowed_urls=http://snapshot.test* %s -Epidfile=%s -Enode.portsfile=true'
|
||||
% (java_exe(), es_run_path, '-d', os.path.join(es_dir, 'es-smoke.pid')))
|
||||
if not wait_for_node_startup(es_dir, header=headers):
|
||||
print("elasticsearch logs:")
|
||||
|
|
|
@ -57,8 +57,6 @@ buildRestTests.expectedUnconvertedCandidates = [
|
|||
]
|
||||
|
||||
integTestCluster {
|
||||
setting 'script.inline', 'true'
|
||||
setting 'script.stored', 'true'
|
||||
setting 'script.max_compilations_per_minute', '1000'
|
||||
/* Enable regexes in painless so our tests don't complain about example
|
||||
* snippets that use them. */
|
||||
|
|
|
@ -24,5 +24,5 @@ The `_index` variable has been removed. If you used it for advanced scoring, con
|
|||
|
||||
==== Script Settings
|
||||
|
||||
All of the existing scripting security settings have been deprecated. Instead
|
||||
All of the existing scripting security settings have been removed. Instead
|
||||
they are replaced with `script.allowed_types` and `script.allowed_contexts`.
|
||||
|
|
|
@ -74,5 +74,5 @@ deprecation warning.
|
|||
|
||||
==== Script Settings
|
||||
|
||||
All of the existing scripting security settings have been deprecated. Instead
|
||||
All of the existing scripting security settings have been removed. Instead
|
||||
they are replaced with `script.allowed_types` and `script.allowed_contexts`.
|
|
@ -93,7 +93,8 @@ security of the Elasticsearch deployment.
|
|||
|
||||
By default all script types are allowed to be executed. This can be modified using the
|
||||
setting `script.allowed_types`. Only the types specified as part of the setting will be
|
||||
allowed to be executed.
|
||||
allowed to be executed. To specify no types are allowed, set `scripts.allowed_types` to
|
||||
be `none`.
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
|
@ -108,7 +109,8 @@ script.allowed_types: inline <1>
|
|||
|
||||
By default all script contexts are allowed to be executed. This can be modified using the
|
||||
setting `script.allowed_contexts`. Only the contexts specified as part of the setting will
|
||||
be allowed to be executed.
|
||||
be allowed to be executed. To specify no contexts are allowed, set `scripts.allowed_contexts`
|
||||
to be `none`.
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
|
@ -116,105 +118,3 @@ script.allowed_contexts: search, update <1>
|
|||
----
|
||||
<1> This will allow only search and update scripts to be executed but not
|
||||
aggs or plugin scripts (or any other contexts).
|
||||
|
||||
[[deprecated-script=settings]]
|
||||
[float]
|
||||
=== Deprecated script settings
|
||||
|
||||
The following settings have all been deprecated and will be removed in 6.0:
|
||||
|
||||
* <<security-script-source>>
|
||||
* <<security-script-context>>
|
||||
* <<security-script-fine>>
|
||||
|
||||
Use the following instead:
|
||||
|
||||
* <<allowed-script-types-setting>>
|
||||
* <<allowed-script-contexts-setting>>
|
||||
|
||||
[[security-script-source]]
|
||||
[float]
|
||||
=== Script source settings
|
||||
|
||||
Which scripts Elasticsearch will execute where is controlled by settings
|
||||
starting with `scripts.`. The simplest settings allow scripts to be enabled
|
||||
or disabled based on where they are stored. For example:
|
||||
|
||||
[source,yaml]
|
||||
-----------------------------------
|
||||
script.inline: false <1>
|
||||
script.stored: false <2>
|
||||
-----------------------------------
|
||||
<1> Refuse to run scripts provided inline in the API.
|
||||
<2> Refuse to run scripts stored using the API.
|
||||
|
||||
NOTE: These settings override the defaults mentioned
|
||||
<<modules-scripting-security-do-no-weaken, above>>. Recreating the defaults
|
||||
requires more fine grained settings described <<security-script-fine, below>>.
|
||||
|
||||
[[security-script-context]]
|
||||
[float]
|
||||
=== Script context settings
|
||||
|
||||
Scripting may also be enabled or disabled in different contexts in the
|
||||
Elasticsearch API. The supported contexts are:
|
||||
|
||||
[horizontal]
|
||||
`aggs`:: Aggregations
|
||||
`search`:: Search api, Percolator API and Suggester API
|
||||
`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 `plugin` operations,
|
||||
regardless of the script source or language. Scripts can still be executed
|
||||
as part of `aggregations`, `search` and plugins execution though, as the above
|
||||
defaults still get applied.
|
||||
|
||||
[source,yaml]
|
||||
-----------------------------------
|
||||
script.update: false
|
||||
script.plugin: false
|
||||
-----------------------------------
|
||||
|
||||
[[security-script-fine]]
|
||||
[float]
|
||||
=== Fine-grained script settings
|
||||
|
||||
First, the high-level script settings described above are applied in order
|
||||
(context settings have precedence over source settings). Then fine-grained
|
||||
settings which include the script language take precedence over any high-level
|
||||
settings. They have two forms:
|
||||
|
||||
[source,yaml]
|
||||
------------------------
|
||||
script.engine.{lang}.{inline|stored}.{context}: true|false
|
||||
------------------------
|
||||
|
||||
And
|
||||
|
||||
[source,yaml]
|
||||
------------------------
|
||||
script.engine.{lang}.{inline|stored}: true|false
|
||||
------------------------
|
||||
|
||||
For example:
|
||||
|
||||
[source,yaml]
|
||||
-----------------------------------
|
||||
script.inline: false <1>
|
||||
script.stored: false <1>
|
||||
|
||||
script.engine.painless.inline: true <2>
|
||||
script.engine.painless.stored.search: true <3>
|
||||
script.engine.painless.stored.aggs: true <3>
|
||||
|
||||
script.engine.mustache.stored.search: true <4>
|
||||
-----------------------------------
|
||||
<1> Disable all scripting from any source.
|
||||
<2> Allow inline Painless scripts for all operations.
|
||||
<3> Allow stored Painless scripts to be used for search and aggregations.
|
||||
<4> Allow stored Mustache templates to be used for search.
|
||||
|
|
|
@ -40,8 +40,7 @@ public class StoredExpressionTests extends ESIntegTestCase {
|
|||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
Settings.Builder builder = Settings.builder().put(super.nodeSettings(nodeOrdinal));
|
||||
builder.put("script.engine.expression.stored.update", "false");
|
||||
builder.put("script.engine.expression.stored.search", "false");
|
||||
builder.put("script.contexts_allowed", "update");
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -72,7 +71,7 @@ public class StoredExpressionTests extends ESIntegTestCase {
|
|||
.setIndices("test").setTypes("scriptTest").get();
|
||||
fail("search script should have been rejected");
|
||||
} catch(Exception e) {
|
||||
assertThat(e.toString(), containsString("scripts of type [stored], operation [search] and lang [expression] are disabled"));
|
||||
assertThat(e.toString(), containsString("cannot execute scripts using [search] context"));
|
||||
}
|
||||
try {
|
||||
client().prepareSearch("test")
|
||||
|
@ -80,7 +79,7 @@ public class StoredExpressionTests extends ESIntegTestCase {
|
|||
new SearchSourceBuilder().aggregation(AggregationBuilders.terms("test").script(
|
||||
new Script(ScriptType.STORED, "expression", "script1", Collections.emptyMap())))).get();
|
||||
} catch (Exception e) {
|
||||
assertThat(e.toString(), containsString("scripts of type [stored], operation [aggs] and lang [expression] are disabled"));
|
||||
assertThat(e.toString(), containsString("cannot execute scripts using [aggs] context"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,5 @@ dependencies {
|
|||
}
|
||||
|
||||
integTestCluster {
|
||||
setting 'script.inline', 'true'
|
||||
setting 'script.stored', 'true'
|
||||
setting 'script.max_compilations_per_minute', '1000'
|
||||
}
|
||||
|
|
|
@ -45,5 +45,4 @@ thirdPartyAudit.excludes = [
|
|||
integTestCluster {
|
||||
setting 'cloud.azure.storage.my_account_test.account', 'cloudazureresource'
|
||||
setting 'cloud.azure.storage.my_account_test.key', 'abcdefgh'
|
||||
setting 'script.stored', 'true'
|
||||
}
|
||||
|
|
|
@ -30,6 +30,5 @@ dependencies {
|
|||
|
||||
integTestCluster {
|
||||
plugin ':plugins:ingest-geoip'
|
||||
setting 'script.inline', 'true'
|
||||
setting 'script.max_compilations_per_minute', '1000'
|
||||
}
|
||||
|
|
|
@ -19,30 +19,25 @@
|
|||
|
||||
package org.elasticsearch.ingest;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngine;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public abstract class AbstractScriptTestCase extends ESTestCase {
|
||||
|
||||
protected TemplateService templateService;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Arrays.asList(new MustacheScriptEngine()));
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new MustacheScriptEngine()));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
|
||||
ScriptService scriptService = new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
ScriptService scriptService = new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry);
|
||||
templateService = new InternalTemplateService(scriptService);
|
||||
}
|
||||
|
||||
|
|
|
@ -1013,10 +1013,9 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
|
|||
new Class[]{Client.class},
|
||||
clientInvocationHandler);
|
||||
ScriptModule scriptModule = createScriptModule(pluginsService.filterPlugins(ScriptPlugin.class));
|
||||
List<Setting<?>> scriptSettings = scriptModule.getSettings();
|
||||
scriptSettings.addAll(pluginsService.getPluginSettings());
|
||||
scriptSettings.add(InternalSettingsPlugin.VERSION_CREATED);
|
||||
SettingsModule settingsModule = new SettingsModule(nodeSettings, scriptSettings, pluginsService.getPluginSettingsFilter());
|
||||
List<Setting<?>> additionalSettings = pluginsService.getPluginSettings();
|
||||
additionalSettings.add(InternalSettingsPlugin.VERSION_CREATED);
|
||||
SettingsModule settingsModule = new SettingsModule(nodeSettings, additionalSettings, pluginsService.getPluginSettingsFilter());
|
||||
searchModule = new SearchModule(nodeSettings, false, pluginsService.filterPlugins(SearchPlugin.class));
|
||||
IndicesModule indicesModule = new IndicesModule(pluginsService.filterPlugins(MapperPlugin.class));
|
||||
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
|
||||
|
|
|
@ -1722,8 +1722,6 @@ public abstract class ESIntegTestCase extends ESTestCase {
|
|||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b")
|
||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b")
|
||||
.put(ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE.getKey(), 1000)
|
||||
.put("script.stored", "true")
|
||||
.put("script.inline", "true")
|
||||
// by default we never cache below 10k docs in a segment,
|
||||
// bypass this limit so that caching gets some testing in
|
||||
// integration tests that usually create few documents
|
||||
|
|
Loading…
Reference in New Issue