Merge pull request #16197 from jasontedor/script-settings

Script settings
This commit is contained in:
Jason Tedor 2016-01-27 06:54:13 -05:00
commit 651b9bff7d
52 changed files with 963 additions and 466 deletions

View File

@ -188,11 +188,12 @@ public class Node implements Releasable {
modules.add(pluginModule);
}
modules.add(new PluginsModule(pluginsService));
modules.add(new SettingsModule(this.settings, settingsFilter));
SettingsModule settingsModule = new SettingsModule(this.settings, settingsFilter);
modules.add(settingsModule);
modules.add(new EnvironmentModule(environment));
modules.add(new NodeModule(this, monitorService));
modules.add(new NetworkModule(networkService, settings, false, namedWriteableRegistry));
modules.add(new ScriptModule(this.settings));
modules.add(new ScriptModule(settingsModule));
modules.add(new NodeEnvironmentModule(nodeEnvironment));
modules.add(new ClusterNameModule(this.settings));
modules.add(new ThreadPoolModule(threadPool));

View File

@ -27,6 +27,8 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.search.lookup.SearchLookup;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static java.util.Collections.unmodifiableMap;
@ -38,6 +40,8 @@ public class NativeScriptEngineService extends AbstractComponent implements Scri
public static final String NAME = "native";
public static final List<String> TYPES = Collections.singletonList(NAME);
private final Map<String, NativeScriptFactory> scripts;
@Inject
@ -47,17 +51,17 @@ public class NativeScriptEngineService extends AbstractComponent implements Scri
}
@Override
public String[] types() {
return new String[]{NAME};
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return new String[0];
public List<String> getExtensions() {
return Collections.emptyList();
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return false;
}

View File

@ -0,0 +1,93 @@
/*
* 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 java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class ScriptEngineRegistry {
private final Map<Class<? extends ScriptEngineService>, List<String>> registeredScriptEngineServices;
private final Map<String, Class<? extends ScriptEngineService>> registeredLanguages;
public ScriptEngineRegistry(Iterable<ScriptEngineRegistration> registrations) {
Objects.requireNonNull(registrations);
Map<Class<? extends ScriptEngineService>, List<String>> registeredScriptEngineServices = new HashMap<>();
Map<String, Class<? extends ScriptEngineService>> registeredLanguages = new HashMap<>();
for (ScriptEngineRegistration registration : registrations) {
List<String> languages =
registeredScriptEngineServices.putIfAbsent(registration.getScriptEngineService(), Collections.unmodifiableList(registration.getScriptEngineLanguages()));
if (languages != null) {
throw new IllegalArgumentException("script engine service [" + registration.getScriptEngineService() + "] already registered for languages [" + String.join(",", languages) + "]");
}
for (String language : registration.getScriptEngineLanguages()) {
Class<? extends ScriptEngineService> scriptEngineServiceClazz =
registeredLanguages.putIfAbsent(language, registration.getScriptEngineService());
if (scriptEngineServiceClazz != null) {
throw new IllegalArgumentException("scripting language [" + language + "] already registered for script engine service [" + scriptEngineServiceClazz.getCanonicalName() + "]");
}
}
}
this.registeredScriptEngineServices = Collections.unmodifiableMap(registeredScriptEngineServices);
this.registeredLanguages = Collections.unmodifiableMap(registeredLanguages);
}
Iterable<Class<? extends ScriptEngineService>> getRegisteredScriptEngineServices() {
return registeredScriptEngineServices.keySet();
}
List<String> getLanguages(Class<? extends ScriptEngineService> scriptEngineService) {
Objects.requireNonNull(scriptEngineService);
return registeredScriptEngineServices.get(scriptEngineService);
}
Map<String, Class<? extends ScriptEngineService>> getRegisteredLanguages() {
return registeredLanguages;
}
public static class ScriptEngineRegistration {
private final Class<? extends ScriptEngineService> scriptEngineService;
private final List<String> scriptEngineLanguages;
public ScriptEngineRegistration(Class<? extends ScriptEngineService> scriptEngineService, List<String> scriptEngineLanguages) {
Objects.requireNonNull(scriptEngineService);
Objects.requireNonNull(scriptEngineLanguages);
if (scriptEngineLanguages.isEmpty()) {
throw new IllegalArgumentException("languages for script engine service [" + scriptEngineService.getCanonicalName() + "] should be non-empty");
}
this.scriptEngineService = scriptEngineService;
this.scriptEngineLanguages = scriptEngineLanguages;
}
Class<? extends ScriptEngineService> getScriptEngineService() {
return scriptEngineService;
}
List<String> getScriptEngineLanguages() {
return scriptEngineLanguages;
}
}
}

View File

@ -23,6 +23,7 @@ import org.elasticsearch.common.Nullable;
import org.elasticsearch.search.lookup.SearchLookup;
import java.io.Closeable;
import java.util.List;
import java.util.Map;
/**
@ -30,11 +31,11 @@ import java.util.Map;
*/
public interface ScriptEngineService extends Closeable {
String[] types();
List<String> getTypes();
String[] extensions();
List<String> getExtensions();
boolean sandboxed();
boolean isSandboxed();
Object compile(String script, Map<String, String> params);

View File

@ -19,37 +19,48 @@
package org.elasticsearch.script;
import org.elasticsearch.common.Booleans;
import java.util.Locale;
import java.util.HashMap;
import java.util.Map;
/**
* Mode for a specific script, used for script settings.
* Defines whether a certain script or catefory of scripts can be executed or not, or whether it can
* Defines whether a certain script or category of scripts can be executed or not, or whether it can
* only be executed by a sandboxed scripting language.
*/
enum ScriptMode {
ON,
OFF,
SANDBOX;
ON("true"),
OFF("false"),
SANDBOX("sandbox");
static ScriptMode parse(String input) {
input = input.toLowerCase(Locale.ROOT);
if (Booleans.isExplicitTrue(input)) {
return ON;
}
if (Booleans.isExplicitFalse(input)) {
return OFF;
}
if (SANDBOX.toString().equals(input)) {
return SANDBOX;
}
throw new IllegalArgumentException("script mode [" + input + "] not supported");
private final String mode;
ScriptMode(String mode) {
this.mode = mode;
}
private static final Map<String, ScriptMode> SCRIPT_MODES;
static {
SCRIPT_MODES = new HashMap<>();
for (ScriptMode scriptMode : ScriptMode.values()) {
SCRIPT_MODES.put(scriptMode.mode, scriptMode);
}
}
static ScriptMode parse(String input) {
ScriptMode scriptMode = SCRIPT_MODES.get(input);
if (scriptMode == null) {
throw new IllegalArgumentException("script mode [" + input + "] not supported");
}
return scriptMode;
}
public String getMode() {
return mode;
}
@Override
public String toString() {
return name().toLowerCase(Locale.ROOT);
return mode;
}
}

View File

@ -19,127 +19,32 @@
package org.elasticsearch.script;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.ScriptService.ScriptType;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import static java.util.Collections.unmodifiableMap;
/**
* Holds the {@link org.elasticsearch.script.ScriptMode}s for each of the different scripting languages available,
* each script source and each scripted operation.
*/
public class ScriptModes {
static final String SCRIPT_SETTINGS_PREFIX = "script.";
static final String ENGINE_SETTINGS_PREFIX = "script.engine";
private static final String SCRIPT_SETTINGS_PREFIX = "script";
private static final String ENGINE_SETTINGS_PREFIX = "script.engine";
final Map<String, ScriptMode> scriptModes;
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 = new HashMap<>(scriptEngines);
filteredEngines.remove(NativeScriptEngineService.NAME);
this.scriptModes = buildScriptModeSettingsMap(settings, filteredEngines, scriptContextRegistry);
}
private static Map<String, ScriptMode> buildScriptModeSettingsMap(Settings settings, Map<String, ScriptEngineService> scriptEngines, ScriptContextRegistry scriptContextRegistry) {
HashMap<String, ScriptMode> scriptModesMap = new HashMap<>();
//file scripts are enabled by default, for any language
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.FILE, ScriptMode.ON, scriptModesMap);
//indexed scripts are enabled by default only for sandboxed languages
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.INDEXED, ScriptMode.SANDBOX, scriptModesMap);
//dynamic scripts are enabled by default only for sandboxed languages
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.INLINE, ScriptMode.SANDBOX, scriptModesMap);
processSourceBasedGlobalSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap);
processOperationBasedGlobalSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap);
processEngineSpecificSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap);
return unmodifiableMap(scriptModesMap);
}
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(), scriptContextRegistry, scriptType, scriptTypeMode, scriptModes);
}
ScriptModes(ScriptSettings scriptSettings, Settings settings) {
HashMap<String, ScriptMode> scriptModes = new HashMap<>();
for (Setting<ScriptMode> scriptModeSetting : scriptSettings.getScriptLanguageSettings()) {
scriptModes.put(scriptModeSetting.getKey(), scriptModeSetting.get(settings));
}
}
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 : scriptContextRegistry.scriptContexts()) {
ScriptMode scriptMode = getScriptContextMode(settings, SCRIPT_SETTINGS_PREFIX, scriptContext);
if (scriptMode != null) {
addGlobalScriptContextModes(scriptEngines.keySet(), scriptContext, 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) {
for (ScriptType scriptType : ScriptType.values()) {
String scriptTypePrefix = scriptType + ".";
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
ScriptMode scriptMode = getScriptContextMode(langSettings.getValue(), scriptTypePrefix, scriptContext);
if (scriptMode != null) {
addScriptMode(scriptEngineService, scriptType, scriptContext, scriptMode, scriptModes);
}
}
}
}
}
}
private static ScriptMode getScriptContextMode(Settings settings, String prefix, ScriptContext 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, ScriptContextRegistry scriptContextRegistry, ScriptType scriptType, ScriptMode scriptMode, Map<String, ScriptMode> scriptModes) {
for (String lang : langs) {
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
addScriptMode(lang, scriptType, scriptContext, scriptMode, scriptModes);
}
}
}
private static void addGlobalScriptContextModes(Set<String> langs, ScriptContext scriptContext, ScriptMode scriptMode, Map<String, ScriptMode> scriptModes) {
for (String lang : langs) {
for (ScriptType scriptType : ScriptType.values()) {
addScriptMode(lang, scriptType, scriptContext, scriptMode, scriptModes);
}
}
}
private static void addScriptMode(ScriptEngineService scriptEngineService, ScriptType scriptType, ScriptContext scriptContext,
ScriptMode scriptMode, Map<String, ScriptMode> scriptModes) {
//expand the lang specific settings to all of the different names given to each scripting language
for (String scriptEngineName : scriptEngineService.types()) {
addScriptMode(scriptEngineName, scriptType, scriptContext, scriptMode, 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.getKey(), scriptMode);
this.scriptModes = Collections.unmodifiableMap(scriptModes);
}
/**
@ -156,13 +61,25 @@ public class ScriptModes {
if (NativeScriptEngineService.NAME.equals(lang)) {
return ScriptMode.ON;
}
ScriptMode scriptMode = scriptModes.get(ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey());
ScriptMode scriptMode = scriptModes.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.getScriptType();
}
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

View File

@ -22,12 +22,14 @@ package org.elasticsearch.script;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.multibindings.MapBinder;
import org.elasticsearch.common.inject.multibindings.Multibinder;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.SettingsModule;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* An {@link org.elasticsearch.common.inject.Module} which manages {@link ScriptEngineService}s, as well
@ -35,20 +37,25 @@ import java.util.Map;
*/
public class ScriptModule extends AbstractModule {
private final Settings settings;
private final SettingsModule settingsModule;
private final List<Class<? extends ScriptEngineService>> scriptEngines = new ArrayList<>();
private final List<ScriptEngineRegistry.ScriptEngineRegistration> scriptEngineRegistrations = new ArrayList<>();
{
scriptEngineRegistrations.add(new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.TYPES));
}
private final Map<String, Class<? extends NativeScriptFactory>> scripts = new HashMap<>();
private final List<ScriptContext.Plugin> customScriptContexts = new ArrayList<>();
public ScriptModule(Settings settings) {
this.settings = settings;
public ScriptModule(SettingsModule settingsModule) {
this.settingsModule = settingsModule;
}
public void addScriptEngine(Class<? extends ScriptEngineService> scriptEngine) {
scriptEngines.add(scriptEngine);
public void addScriptEngine(ScriptEngineRegistry.ScriptEngineRegistration scriptEngineRegistration) {
Objects.requireNonNull(scriptEngineRegistration);
scriptEngineRegistrations.add(scriptEngineRegistration);
}
public void registerScript(String name, Class<? extends NativeScriptFactory> script) {
@ -74,11 +81,23 @@ public class ScriptModule extends AbstractModule {
Multibinder<ScriptEngineService> multibinder = Multibinder.newSetBinder(binder(), ScriptEngineService.class);
multibinder.addBinding().to(NativeScriptEngineService.class);
for (Class<? extends ScriptEngineService> scriptEngine : scriptEngines) {
multibinder.addBinding().to(scriptEngine).asEagerSingleton();
for (ScriptEngineRegistry.ScriptEngineRegistration scriptEngineRegistration : scriptEngineRegistrations) {
multibinder.addBinding().to(scriptEngineRegistration.getScriptEngineService()).asEagerSingleton();
}
bind(ScriptContextRegistry.class).toInstance(new ScriptContextRegistry(customScriptContexts));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customScriptContexts);
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(scriptEngineRegistrations);
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
scriptSettings.getScriptTypeSettings().forEach(settingsModule::registerSetting);
scriptSettings.getScriptContextSettings().forEach(settingsModule::registerSetting);
scriptSettings.getScriptLanguageSettings().forEach(settingsModule::registerSetting);
settingsModule.registerSetting(scriptSettings.getDefaultScriptLanguageSetting());
bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry);
bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry);
bind(ScriptSettings.class).toInstance(scriptSettings);
bind(ScriptService.class).asEagerSingleton();
}
}

View File

@ -72,6 +72,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
@ -84,12 +85,10 @@ public class ScriptService extends AbstractComponent implements Closeable {
static final String DISABLE_DYNAMIC_SCRIPTING_SETTING = "script.disable_dynamic";
public static final String DEFAULT_SCRIPTING_LANGUAGE_SETTING = "script.default_lang";
public static final Setting<Integer> SCRIPT_CACHE_SIZE_SETTING = Setting.intSetting("script.cache.max_size", 100, 0, false, Setting.Scope.CLUSTER);
public static final String SCRIPT_CACHE_EXPIRE_SETTING = "script.cache.expire";
public static final Setting<TimeValue> SCRIPT_CACHE_EXPIRE_SETTING = Setting.positiveTimeSetting("script.cache.expire", TimeValue.timeValueMillis(0), false, Setting.Scope.CLUSTER);
public static final String SCRIPT_INDEX = ".scripts";
public static final String DEFAULT_LANG = "groovy";
public static final String SCRIPT_AUTO_RELOAD_ENABLED_SETTING = "script.auto_reload_enabled";
public static final Setting<Boolean> SCRIPT_AUTO_RELOAD_ENABLED_SETTING = Setting.boolSetting("script.auto_reload_enabled", true, false, Setting.Scope.CLUSTER);
private final String defaultLang;
@ -138,45 +137,50 @@ public class ScriptService extends AbstractComponent implements Closeable {
@Inject
public ScriptService(Settings settings, Environment env, Set<ScriptEngineService> scriptEngines,
ResourceWatcherService resourceWatcherService, ScriptContextRegistry scriptContextRegistry) throws IOException {
ResourceWatcherService resourceWatcherService, ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry, ScriptSettings scriptSettings) throws IOException {
super(settings);
Objects.requireNonNull(scriptEngineRegistry);
Objects.requireNonNull(scriptContextRegistry);
Objects.requireNonNull(scriptSettings);
this.parseFieldMatcher = new ParseFieldMatcher(settings);
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: on` and `script.indexed: on` in elasticsearch.yml");
"Dynamic scripts can be enabled for all languages and all operations by replacing `script.disable_dynamic: false` with `script.inline: true` and `script.indexed: true` in elasticsearch.yml");
}
this.scriptEngines = scriptEngines;
this.scriptContextRegistry = scriptContextRegistry;
int cacheMaxSize = SCRIPT_CACHE_SIZE_SETTING.get(settings);
TimeValue cacheExpire = settings.getAsTime(SCRIPT_CACHE_EXPIRE_SETTING, null);
logger.debug("using script cache with max_size [{}], expire [{}]", cacheMaxSize, cacheExpire);
this.defaultLang = settings.get(DEFAULT_SCRIPTING_LANGUAGE_SETTING, DEFAULT_LANG);
this.defaultLang = scriptSettings.getDefaultScriptLanguageSetting().get(settings);
CacheBuilder<CacheKey, CompiledScript> cacheBuilder = CacheBuilder.builder();
if (cacheMaxSize >= 0) {
cacheBuilder.setMaximumWeight(cacheMaxSize);
}
if (cacheExpire != null) {
TimeValue cacheExpire = SCRIPT_CACHE_EXPIRE_SETTING.get(settings);
if (cacheExpire.getNanos() != 0) {
cacheBuilder.setExpireAfterAccess(cacheExpire.nanos());
}
logger.debug("using script cache with max_size [{}], expire [{}]", cacheMaxSize, cacheExpire);
this.cache = cacheBuilder.removalListener(new ScriptCacheRemovalListener()).build();
Map<String, ScriptEngineService> enginesByLangBuilder = new HashMap<>();
Map<String, ScriptEngineService> enginesByExtBuilder = new HashMap<>();
for (ScriptEngineService scriptEngine : scriptEngines) {
for (String type : scriptEngine.types()) {
enginesByLangBuilder.put(type, scriptEngine);
for (String language : scriptEngineRegistry.getLanguages(scriptEngine.getClass())) {
enginesByLangBuilder.put(language, scriptEngine);
}
for (String ext : scriptEngine.extensions()) {
for (String ext : scriptEngine.getExtensions()) {
enginesByExtBuilder.put(ext, scriptEngine);
}
}
this.scriptEnginesByLang = unmodifiableMap(enginesByLangBuilder);
this.scriptEnginesByExt = unmodifiableMap(enginesByExtBuilder);
this.scriptModes = new ScriptModes(this.scriptEnginesByLang, scriptContextRegistry, settings);
this.scriptModes = new ScriptModes(scriptSettings, settings);
// add file watcher for static scripts
scriptsDirectory = env.scriptsFile();
@ -186,7 +190,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
FileWatcher fileWatcher = new FileWatcher(scriptsDirectory);
fileWatcher.addListener(new ScriptChangesListener());
if (settings.getAsBoolean(SCRIPT_AUTO_RELOAD_ENABLED_SETTING, true)) {
if (SCRIPT_AUTO_RELOAD_ENABLED_SETTING.get(settings)) {
// automatic reload is enabled - register scripts
resourceWatcherService.add(fileWatcher);
} else {
@ -477,7 +481,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
case OFF:
return false;
case SANDBOX:
return scriptEngineService.sandboxed();
return scriptEngineService.isSandboxed();
default:
throw new IllegalArgumentException("script mode [" + mode + "] not supported");
}
@ -536,12 +540,12 @@ public class ScriptService extends AbstractComponent implements Closeable {
try {
//we don't know yet what the script will be used for, but if all of the operations for this lang
// with file scripts are disabled, it makes no sense to even compile it and cache it.
if (isAnyScriptContextEnabled(engineService.types()[0], engineService, ScriptType.FILE)) {
if (isAnyScriptContextEnabled(engineService.getTypes().get(0), engineService, ScriptType.FILE)) {
logger.info("compiling script file [{}]", file.toAbsolutePath());
try(InputStreamReader reader = new InputStreamReader(Files.newInputStream(file), StandardCharsets.UTF_8)) {
String script = Streams.copyToString(reader);
CacheKey cacheKey = new CacheKey(engineService, scriptNameExt.v1(), null, Collections.emptyMap());
staticCache.put(cacheKey, new CompiledScript(ScriptType.FILE, scriptNameExt.v1(), engineService.types()[0], engineService.compile(script, Collections.emptyMap())));
staticCache.put(cacheKey, new CompiledScript(ScriptType.FILE, scriptNameExt.v1(), engineService.getTypes().get(0), engineService.compile(script, Collections.emptyMap())));
scriptMetrics.onCompilation();
}
} else {
@ -583,14 +587,16 @@ public class ScriptService extends AbstractComponent implements Closeable {
* - loaded from an index
* - loaded from file
*/
public static enum ScriptType {
public enum ScriptType {
INLINE(0, "inline"),
INDEXED(1, "id"),
FILE(2, "file");
INLINE(0, "inline", "inline", ScriptMode.SANDBOX),
INDEXED(1, "id", "indexed", ScriptMode.SANDBOX),
FILE(2, "file", "file", ScriptMode.ON);
private final int val;
private final ParseField parseField;
private final String scriptType;
private final ScriptMode defaultScriptMode;
public static ScriptType readFrom(StreamInput in) throws IOException {
int scriptTypeVal = in.readVInt();
@ -611,19 +617,30 @@ public class ScriptService extends AbstractComponent implements Closeable {
}
}
private ScriptType(int val, String name) {
ScriptType(int val, String name, String scriptType, ScriptMode defaultScriptMode) {
this.val = val;
this.parseField = new ParseField(name);
this.scriptType = scriptType;
this.defaultScriptMode = defaultScriptMode;
}
public ParseField getParseField() {
return parseField;
}
public ScriptMode getDefaultScriptMode() {
return defaultScriptMode;
}
public String getScriptType() {
return scriptType;
}
@Override
public String toString() {
return name().toLowerCase(Locale.ROOT);
}
}
private static final class CacheKey {
@ -633,7 +650,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
final Map<String, String> params;
private CacheKey(final ScriptEngineService service, final String name, final String code, final Map<String, String> params) {
this.lang = service.types()[0];
this.lang = service.getTypes().get(0);
this.name = name;
this.code = code;
this.params = params;

View File

@ -0,0 +1,165 @@
/*
* 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.collect.Tuple;
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.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ScriptSettings {
public final static String DEFAULT_LANG = "groovy";
private final static Map<ScriptService.ScriptType, Setting<ScriptMode>> SCRIPT_TYPE_SETTING_MAP;
static {
Map<ScriptService.ScriptType, Setting<ScriptMode>> scriptTypeSettingMap = new HashMap<>();
for (ScriptService.ScriptType scriptType : ScriptService.ScriptType.values()) {
scriptTypeSettingMap.put(scriptType, new Setting<>(
ScriptModes.sourceKey(scriptType),
scriptType.getDefaultScriptMode().getMode(),
ScriptMode::parse,
false,
Setting.Scope.CLUSTER));
}
SCRIPT_TYPE_SETTING_MAP = Collections.unmodifiableMap(scriptTypeSettingMap);
}
private final Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap;
private final List<Setting<ScriptMode>> scriptLanguageSettings;
private final Setting<String> defaultScriptLanguageSetting;
public ScriptSettings(ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry) {
Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap = contextSettings(scriptContextRegistry);
this.scriptContextSettingMap = Collections.unmodifiableMap(scriptContextSettingMap);
List<Setting<ScriptMode>> scriptLanguageSettings = languageSettings(SCRIPT_TYPE_SETTING_MAP, scriptContextSettingMap, scriptEngineRegistry, scriptContextRegistry);
this.scriptLanguageSettings = Collections.unmodifiableList(scriptLanguageSettings);
this.defaultScriptLanguageSetting = new Setting<>("script.default_lang", DEFAULT_LANG, setting -> {
if (!"groovy".equals(setting) && !scriptEngineRegistry.getRegisteredLanguages().containsKey(setting)) {
throw new IllegalArgumentException("unregistered default language [" + setting + "]");
}
return setting;
}, false, Setting.Scope.CLUSTER);
}
private static Map<ScriptContext, Setting<ScriptMode>> contextSettings(ScriptContextRegistry scriptContextRegistry) {
Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap = new HashMap<>();
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
scriptContextSettingMap.put(scriptContext, new Setting<>(
ScriptModes.operationKey(scriptContext),
ScriptMode.OFF.getMode(),
ScriptMode::parse,
false,
Setting.Scope.CLUSTER
));
}
return scriptContextSettingMap;
}
private static List<Setting<ScriptMode>> languageSettings(
Map<ScriptService.ScriptType, Setting<ScriptMode>> scriptTypeSettingMap,
Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap,
ScriptEngineRegistry scriptEngineRegistry,
ScriptContextRegistry scriptContextRegistry) {
List<Setting<ScriptMode>> scriptModeSettings = new ArrayList<>();
for (Class<? extends ScriptEngineService> scriptEngineService : scriptEngineRegistry.getRegisteredScriptEngineServices()) {
List<String> languages = scriptEngineRegistry.getLanguages(scriptEngineService);
for (String language : languages) {
if (NativeScriptEngineService.TYPES.contains(language)) {
// native scripts are always enabled, and their settings can not be changed
continue;
}
for (ScriptService.ScriptType scriptType : ScriptService.ScriptType.values()) {
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
Function<Settings, String> defaultSetting = settings -> {
// fallback logic for script mode settings
// the first fallback is other types registered by the same script engine service
// e.g., "py.inline.aggs" is in the settings but a script with lang "python" is executed
Map<String, List<String>> languageSettings =
languages
.stream()
.map(lang -> Tuple.tuple(lang, settings.get(ScriptModes.getKey(lang, scriptType, scriptContext))))
.filter(tuple -> tuple.v2() != null)
.collect(Collectors.groupingBy(Tuple::v2, Collectors.mapping(Tuple::v1, Collectors.toList())));
if (!languageSettings.isEmpty()) {
if (languageSettings.size() > 1) {
throw new IllegalArgumentException("conflicting settings [" + languageSettings.toString() + "] for language [" + language + "]");
}
return languageSettings.keySet().iterator().next();
}
// the next fallback is global operation-based settings (e.g., "script.aggs: false")
Setting<ScriptMode> setting = scriptContextSettingMap.get(scriptContext);
if (setting.exists(settings)) {
return setting.get(settings).getMode();
}
// the next fallback is global source-based settings (e.g., "script.inline: false")
Setting<ScriptMode> scriptTypeSetting = scriptTypeSettingMap.get(scriptType);
if (scriptTypeSetting.exists(settings)) {
return scriptTypeSetting.get(settings).getMode();
}
// the final fallback is the default for the type
return scriptType.getDefaultScriptMode().toString();
};
Setting<ScriptMode> setting =
new Setting<>(
ScriptModes.getKey(language, scriptType, scriptContext),
defaultSetting,
ScriptMode::parse,
false,
Setting.Scope.CLUSTER);
scriptModeSettings.add(setting);
}
}
}
}
return scriptModeSettings;
}
public Iterable<Setting<ScriptMode>> getScriptTypeSettings() {
return Collections.unmodifiableCollection(SCRIPT_TYPE_SETTING_MAP.values());
}
public Iterable<Setting<ScriptMode>> getScriptContextSettings() {
return Collections.unmodifiableCollection(scriptContextSettingMap.values());
}
public Iterable<Setting<ScriptMode>> getScriptLanguageSettings() {
return scriptLanguageSettings;
}
public Setting<String> getDefaultScriptLanguageSetting() {
return defaultScriptLanguageSetting;
}
}

View File

@ -18,15 +18,6 @@
*/
package org.elasticsearch.index;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import org.apache.lucene.index.AssertingDirectoryReader;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.FieldInvertState;
@ -70,7 +61,9 @@ import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCacheListener;
import org.elasticsearch.indices.mapper.MapperRegistry;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.IndexSettingsModule;
@ -78,6 +71,14 @@ import org.elasticsearch.test.engine.MockEngineFactory;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.ResourceWatcherService;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import static java.util.Collections.emptyMap;
public class IndexModuleTests extends ESTestCase {
@ -106,9 +107,12 @@ public class IndexModuleTests extends ESTestCase {
PageCacheRecycler recycler = new PageCacheRecycler(settings, threadPool);
BigArrays bigArrays = new BigArrays(recycler, circuitBreakerService);
IndicesFieldDataCache indicesFieldDataCache = new IndicesFieldDataCache(settings, new IndicesFieldDataCacheListener(circuitBreakerService), threadPool);
Set<ScriptEngineService> scriptEngines = new HashSet<>();
Set<ScriptEngineService> scriptEngines = Collections.emptySet();
scriptEngines.addAll(Arrays.asList(scriptEngineServices));
ScriptService scriptService = new ScriptService(settings, environment, scriptEngines, new ResourceWatcherService(settings, threadPool), new ScriptContextRegistry(Collections.emptyList()));
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.emptyList());
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
ScriptService scriptService = new ScriptService(settings, environment, scriptEngines, new ResourceWatcherService(settings, threadPool), scriptEngineRegistry, scriptContextRegistry, scriptSettings);
IndicesQueriesRegistry indicesQueriesRegistry = new IndicesQueriesRegistry(settings, emptyMap());
return new NodeServicesProvider(threadPool, indicesQueryCache, null, warmer, bigArrays, client, scriptService, indicesQueriesRegistry, indicesFieldDataCache, circuitBreakerService);
}

View File

@ -22,7 +22,6 @@ package org.elasticsearch.index.query;
import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
@ -88,7 +87,9 @@ import org.elasticsearch.script.MockScriptEngine;
import org.elasticsearch.script.Script.ScriptParseException;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchModule;
@ -187,7 +188,7 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
Settings settings = Settings.settingsBuilder()
.put("name", AbstractQueryTestCase.class.toString())
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING, false)
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), false)
.build();
Settings indexSettings = Settings.settingsBuilder()
.put(IndexMetaData.SETTING_VERSION_CREATED, version).build();
@ -214,13 +215,13 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
bindMapperExtension();
}
},
new ScriptModule(settings) {
new ScriptModule(settingsModule) {
@Override
protected void configure() {
Settings settings = Settings.builder()
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
// no file watching, so we don't need a ResourceWatcherService
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING, false)
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), false)
.build();
MockScriptEngine mockScriptEngine = new MockScriptEngine();
Multibinder<ScriptEngineService> multibinder = Multibinder.newSetBinder(binder(), ScriptEngineService.class);
@ -228,9 +229,14 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
Set<ScriptEngineService> engines = new HashSet<>();
engines.add(mockScriptEngine);
List<ScriptContext.Plugin> customContexts = new ArrayList<>();
bind(ScriptContextRegistry.class).toInstance(new ScriptContextRegistry(customContexts));
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES)));
bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry);
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry);
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
bind(ScriptSettings.class).toInstance(scriptSettings);
try {
ScriptService scriptService = new ScriptService(settings, new Environment(settings), engines, null, new ScriptContextRegistry(customContexts));
ScriptService scriptService = new ScriptService(settings, new Environment(settings), engines, null, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
bind(ScriptService.class).toInstance(scriptService);
} catch(IOException e) {
throw new IllegalStateException("error while binding ScriptService", e);

View File

@ -41,17 +41,20 @@ public class FileScriptTests extends ESTestCase {
settings = Settings.builder()
.put(Environment.PATH_HOME_SETTING.getKey(), homeDir)
// no file watching, so we don't need a ResourceWatcherService
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING, false)
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), false)
.put(settings)
.build();
Set<ScriptEngineService> engines = new HashSet<>(Collections.singletonList(new MockScriptEngine()));
return new ScriptService(settings, new Environment(settings), engines, null, new ScriptContextRegistry(Collections.emptyList()));
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES)));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
return new ScriptService(settings, new Environment(settings), engines, null, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
}
public void testFileScriptFound() throws Exception {
ContextAndHeaderHolder contextAndHeaders = new ContextAndHeaderHolder();
Settings settings = Settings.builder()
.put("script.engine." + MockScriptEngine.NAME + ".file.aggs", false).build();
.put("script.engine." + MockScriptEngine.NAME + ".file.aggs", "false").build();
ScriptService scriptService = makeScriptService(settings);
Script script = new Script("script1", ScriptService.ScriptType.FILE, MockScriptEngine.NAME, null);
assertNotNull(scriptService.compile(script, ScriptContext.Standard.SEARCH, contextAndHeaders, Collections.emptyMap()));
@ -60,11 +63,11 @@ public class FileScriptTests extends ESTestCase {
public void testAllOpsDisabled() throws Exception {
ContextAndHeaderHolder contextAndHeaders = new ContextAndHeaderHolder();
Settings settings = Settings.builder()
.put("script.engine." + MockScriptEngine.NAME + ".file.aggs", false)
.put("script.engine." + MockScriptEngine.NAME + ".file.search", false)
.put("script.engine." + MockScriptEngine.NAME + ".file.mapping", false)
.put("script.engine." + MockScriptEngine.NAME + ".file.update", false)
.put("script.engine." + MockScriptEngine.NAME + ".file.ingest", false).build();
.put("script.engine." + MockScriptEngine.NAME + ".file.aggs", "false")
.put("script.engine." + MockScriptEngine.NAME + ".file.search", "false")
.put("script.engine." + MockScriptEngine.NAME + ".file.mapping", "false")
.put("script.engine." + MockScriptEngine.NAME + ".file.update", "false")
.put("script.engine." + MockScriptEngine.NAME + ".file.ingest", "false").build();
ScriptService scriptService = makeScriptService(settings);
Script script = new Script("script1", ScriptService.ScriptType.FILE, MockScriptEngine.NAME, null);
for (ScriptContext context : ScriptContext.Standard.values()) {

View File

@ -52,7 +52,8 @@ public class NativeScriptTests extends ESTestCase {
.put("name", "testNativeScript")
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
.build();
ScriptModule scriptModule = new ScriptModule(settings);
SettingsModule settingsModule = new SettingsModule(settings, new SettingsFilter(settings));
ScriptModule scriptModule = new ScriptModule(settingsModule);
scriptModule.registerScript("my", MyNativeScriptFactory.class);
Injector injector = new ModulesBuilder().add(
new EnvironmentModule(new Environment(settings)),
@ -73,10 +74,10 @@ public class NativeScriptTests extends ESTestCase {
Settings.Builder builder = Settings.settingsBuilder();
if (randomBoolean()) {
ScriptType scriptType = randomFrom(ScriptType.values());
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptType, randomFrom(ScriptMode.values()));
builder.put("script" + "." + scriptType.getScriptType(), randomFrom(ScriptMode.values()));
} else {
String scriptContext = randomFrom(ScriptContext.Standard.values()).getKey();
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptContext, randomFrom(ScriptMode.values()));
ScriptContext scriptContext = randomFrom(ScriptContext.Standard.values());
builder.put("script" + "." + scriptContext.getKey(), randomFrom(ScriptMode.values()));
}
Settings settings = builder.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir()).build();
Environment environment = new Environment(settings);
@ -84,8 +85,10 @@ public class NativeScriptTests extends ESTestCase {
Map<String, NativeScriptFactory> nativeScriptFactoryMap = new HashMap<>();
nativeScriptFactoryMap.put("my", new MyNativeScriptFactory());
Set<ScriptEngineService> scriptEngineServices = singleton(new NativeScriptEngineService(settings, nativeScriptFactoryMap));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(new ArrayList<ScriptContext.Plugin>());
ScriptService scriptService = new ScriptService(settings, environment, scriptEngineServices, resourceWatcherService, scriptContextRegistry);
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.TYPES)));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(new ArrayList<>());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
ScriptService scriptService = new ScriptService(settings, environment, scriptEngineServices, resourceWatcherService, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
assertThat(scriptService.compile(new Script("my", ScriptType.INLINE, NativeScriptEngineService.NAME, null), scriptContext,

View File

@ -40,16 +40,20 @@ public class ScriptContextTests extends ESTestCase {
Settings settings = Settings.builder()
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
// no file watching, so we don't need a ResourceWatcherService
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING, false)
.put("script." + PLUGIN_NAME + "_custom_globally_disabled_op", false)
.put("script.engine." + MockScriptEngine.NAME + ".inline." + PLUGIN_NAME + "_custom_exp_disabled_op", false)
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), "off")
.put("script." + PLUGIN_NAME + "_custom_globally_disabled_op", "false")
.put("script.engine." + MockScriptEngine.NAME + ".inline." + PLUGIN_NAME + "_custom_exp_disabled_op", "false")
.build();
Set<ScriptEngineService> engines = new HashSet<>(Collections.singletonList(new MockScriptEngine()));
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES)));
List<ScriptContext.Plugin> customContexts = Arrays.asList(
new ScriptContext.Plugin(PLUGIN_NAME, "custom_op"),
new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"),
new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op"));
return new ScriptService(settings, new Environment(settings), engines, null, new ScriptContextRegistry(customContexts));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
return new ScriptService(settings, new Environment(settings), engines, null, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
}
public void testCustomGlobalScriptContextSettings() throws Exception {

View File

@ -27,9 +27,11 @@ import org.elasticsearch.test.ESTestCase;
import org.junit.After;
import org.junit.Before;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -45,9 +47,10 @@ public class ScriptModesTests extends ESTestCase {
private static final Set<String> ALL_LANGS = unmodifiableSet(
newHashSet("custom", "test"));
static final String[] ENABLE_VALUES = new String[]{"on", "true", "yes", "1"};
static final String[] DISABLE_VALUES = new String[]{"off", "false", "no", "0"};
static final String[] ENABLE_VALUES = new String[]{"true"};
static final String[] DISABLE_VALUES = new String[]{"false"};
ScriptSettings scriptSettings;
ScriptContextRegistry scriptContextRegistry;
private ScriptContext[] scriptContexts;
private Map<String, ScriptEngineService> scriptEngines;
@ -74,6 +77,10 @@ public class ScriptModesTests extends ESTestCase {
//add the native engine just to make sure it gets filtered out
new NativeScriptEngineService(Settings.EMPTY, Collections.<String, NativeScriptFactory>emptyMap()),
new CustomScriptEngineService()));
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Arrays.asList(
new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.TYPES),
new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.TYPES)));
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
checkedSettings = new HashSet<>();
assertAllSettingsWereChecked = true;
assertScriptModesNonNull = true;
@ -100,14 +107,14 @@ public class ScriptModesTests extends ESTestCase {
}
public void testDefaultSettings() {
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, Settings.EMPTY);
this.scriptModes = new ScriptModes(scriptSettings, Settings.EMPTY);
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED, ScriptType.INLINE);
}
public void testMissingSetting() {
assertAllSettingsWereChecked = false;
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, Settings.EMPTY);
this.scriptModes = new ScriptModes(scriptSettings, Settings.EMPTY);
try {
scriptModes.getScriptMode("non_existing", randomFrom(ScriptType.values()), randomFrom(scriptContexts));
fail("Expected IllegalArgumentException");
@ -130,9 +137,9 @@ public class ScriptModesTests extends ESTestCase {
ScriptType[] randomScriptTypes = randomScriptTypesSet.toArray(new ScriptType[randomScriptTypesSet.size()]);
Settings.Builder builder = Settings.builder();
for (int i = 0; i < randomInt; i++) {
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + randomScriptTypes[i], randomScriptModes[i]);
builder.put("script" + "." + randomScriptTypes[i].getScriptType(), randomScriptModes[i]);
}
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
this.scriptModes = new ScriptModes(scriptSettings, builder.build());
for (int i = 0; i < randomInt; i++) {
assertScriptModesAllOps(randomScriptModes[i], ALL_LANGS, randomScriptTypes[i]);
@ -162,9 +169,9 @@ public class ScriptModesTests extends ESTestCase {
ScriptContext[] randomScriptContexts = randomScriptContextsSet.toArray(new ScriptContext[randomScriptContextsSet.size()]);
Settings.Builder builder = Settings.builder();
for (int i = 0; i < randomInt; i++) {
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + randomScriptContexts[i].getKey(), randomScriptModes[i]);
builder.put("script" + "." + randomScriptContexts[i].getKey(), randomScriptModes[i]);
}
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
this.scriptModes = new ScriptModes(scriptSettings, builder.build());
for (int i = 0; i < randomInt; i++) {
assertScriptModesAllTypes(randomScriptModes[i], ALL_LANGS, randomScriptContexts[i]);
@ -177,10 +184,10 @@ public class ScriptModesTests extends ESTestCase {
public void testConflictingScriptTypeAndOpGenericSettings() {
ScriptContext scriptContext = randomFrom(scriptContexts);
Settings.Builder builder = Settings.builder().put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptContext.getKey(), randomFrom(DISABLE_VALUES))
.put("script.indexed", randomFrom(ENABLE_VALUES)).put("script.inline", ScriptMode.SANDBOX);
Settings.Builder builder = Settings.builder().put("script" + "." + scriptContext.getKey(), randomFrom(DISABLE_VALUES))
.put("script.indexed", randomFrom(ENABLE_VALUES)).put("script.inline", "sandbox");
//operations generic settings have precedence over script type generic settings
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
this.scriptModes = new ScriptModes(scriptSettings, builder.build());
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, scriptContext);
ScriptContext[] complementOf = complementOf(scriptContext);
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE, ScriptType.INDEXED}, complementOf);
@ -220,14 +227,10 @@ public class ScriptModesTests extends ESTestCase {
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.getKey();
}
static Map<String, ScriptEngineService> buildScriptEnginesByLangMap(Set<ScriptEngineService> scriptEngines) {
Map<String, ScriptEngineService> builder = new HashMap<>();
for (ScriptEngineService scriptEngine : scriptEngines) {
for (String type : scriptEngine.types()) {
for (String type : scriptEngine.getTypes()) {
builder.put(type, scriptEngine);
}
}
@ -235,18 +238,21 @@ public class ScriptModesTests extends ESTestCase {
}
private static class CustomScriptEngineService implements ScriptEngineService {
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("custom", "test"));
@Override
public String[] types() {
return new String[]{"custom", "test"};
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return new String[0];
public List<String> getExtensions() {
return Collections.singletonList(TYPES.get(0));
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return false;
}

View File

@ -33,8 +33,10 @@ import org.junit.Before;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
@ -49,7 +51,9 @@ public class ScriptServiceTests extends ESTestCase {
private ResourceWatcherService resourceWatcherService;
private ScriptEngineService scriptEngineService;
private Map<String, ScriptEngineService> scriptEnginesByLangMap;
private ScriptEngineRegistry scriptEngineRegistry;
private ScriptContextRegistry scriptContextRegistry;
private ScriptSettings scriptSettings;
private ScriptContext[] scriptContexts;
private ScriptService scriptService;
private Path scriptsFilePath;
@ -89,7 +93,9 @@ public class ScriptServiceTests extends ESTestCase {
String context = plugin + "_" + operation;
contexts.put(context, new ScriptContext.Plugin(plugin, operation));
}
scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(TestEngineService.class, TestEngineService.TYPES)));
scriptContextRegistry = new ScriptContextRegistry(contexts.values());
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]);
logger.info("--> setup script service");
scriptsFilePath = genericConfigFolder.resolve("scripts");
@ -99,7 +105,7 @@ public class ScriptServiceTests extends ESTestCase {
private void buildScriptService(Settings additionalSettings) throws IOException {
Settings finalSettings = Settings.builder().put(baseSettings).put(additionalSettings).build();
Environment environment = new Environment(finalSettings);
scriptService = new ScriptService(finalSettings, environment, Collections.singleton(scriptEngineService), resourceWatcherService, scriptContextRegistry) {
scriptService = new ScriptService(finalSettings, environment, Collections.singleton(scriptEngineService), resourceWatcherService, scriptEngineRegistry, scriptContextRegistry, scriptSettings) {
@Override
String getScriptFromIndex(String scriptLang, String id, HasContextAndHeaders headersContext) {
//mock the script that gets retrieved from an index
@ -187,10 +193,10 @@ public class ScriptServiceTests extends ESTestCase {
builder.put("script.file", randomFrom(ScriptModesTests.ENABLE_VALUES));
}
if (rarely()) {
builder.put("script.indexed", ScriptMode.SANDBOX);
builder.put("script.indexed", "sandbox");
}
if (rarely()) {
builder.put("script.inline", ScriptMode.SANDBOX);
builder.put("script.inline", "sandbox");
}
buildScriptService(builder.build());
createFileScripts("groovy", "mustache", "test");
@ -216,11 +222,11 @@ public class ScriptServiceTests extends ESTestCase {
scriptSourceSettings.put(scriptType, randomFrom(ScriptMode.values()));
}
int numScriptContextSettings = randomIntBetween(0, this.scriptContextRegistry.scriptContexts().size());
Map<String, ScriptMode> scriptContextSettings = new HashMap<>();
Map<ScriptContext, ScriptMode> scriptContextSettings = new HashMap<>();
for (int i = 0; i < numScriptContextSettings; i++) {
String scriptContext;
ScriptContext scriptContext;
do {
scriptContext = randomFrom(this.scriptContexts).getKey();
scriptContext = randomFrom(this.scriptContexts);
} while (scriptContextSettings.containsKey(scriptContext));
scriptContextSettings.put(scriptContext, randomFrom(ScriptMode.values()));
}
@ -231,7 +237,7 @@ public class ScriptServiceTests extends ESTestCase {
do {
ScriptType scriptType = randomFrom(ScriptType.values());
ScriptContext scriptContext = randomFrom(this.scriptContexts);
settingKey = scriptEngineService.types()[0] + "." + scriptType + "." + scriptContext.getKey();
settingKey = scriptEngineService.getTypes().get(0) + "." + scriptType + "." + scriptContext.getKey();
} while (engineSettings.containsKey(settingKey));
engineSettings.put(settingKey, randomFrom(ScriptMode.values()));
}
@ -240,26 +246,27 @@ public class ScriptServiceTests extends ESTestCase {
for (Map.Entry<ScriptType, ScriptMode> entry : scriptSourceSettings.entrySet()) {
switch (entry.getValue()) {
case ON:
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.ENABLE_VALUES));
builder.put("script" + "." + entry.getKey().getScriptType(), "true");
break;
case OFF:
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.DISABLE_VALUES));
builder.put("script" + "." + entry.getKey().getScriptType(), "false");
break;
case SANDBOX:
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), ScriptMode.SANDBOX);
builder.put("script" + "." + entry.getKey().getScriptType(), "sandbox");
break;
}
}
for (Map.Entry<String, ScriptMode> entry : scriptContextSettings.entrySet()) {
for (Map.Entry<ScriptContext, ScriptMode> entry : scriptContextSettings.entrySet()) {
switch (entry.getValue()) {
case ON:
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.ENABLE_VALUES));
builder.put("script" + "." + entry.getKey().getKey(), "true");
break;
case OFF:
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.DISABLE_VALUES));
builder.put("script" + "." + entry.getKey().getKey(), "false");
break;
case SANDBOX:
builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), ScriptMode.SANDBOX);
builder.put("script" + "." + entry.getKey().getKey(), "sandbox");
break;
}
}
@ -268,16 +275,16 @@ public class ScriptServiceTests extends ESTestCase {
String part1 = entry.getKey().substring(0, delimiter);
String part2 = entry.getKey().substring(delimiter + 1);
String lang = randomFrom(scriptEnginesByLangMap.get(part1).types());
String lang = randomFrom(scriptEnginesByLangMap.get(part1).getTypes());
switch (entry.getValue()) {
case ON:
builder.put(ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + part2, randomFrom(ScriptModesTests.ENABLE_VALUES));
builder.put("script.engine" + "." + lang + "." + part2, "true");
break;
case OFF:
builder.put(ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + part2, randomFrom(ScriptModesTests.DISABLE_VALUES));
builder.put("script.engine" + "." + lang + "." + part2, "false");
break;
case SANDBOX:
builder.put(ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + part2, ScriptMode.SANDBOX);
builder.put("script.engine" + "." + lang + "." + part2, "sandbox");
break;
}
}
@ -291,9 +298,9 @@ public class ScriptServiceTests extends ESTestCase {
String script = scriptType == ScriptType.FILE ? "file_script" : "script";
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.getKey());
ScriptMode scriptMode = engineSettings.get(scriptEngineService.getTypes().get(0) + "." + scriptType + "." + scriptContext.getKey());
if (scriptMode == null) {
scriptMode = scriptContextSettings.get(scriptContext.getKey());
scriptMode = scriptContextSettings.get(scriptContext);
}
if (scriptMode == null) {
scriptMode = scriptSourceSettings.get(scriptType);
@ -302,19 +309,19 @@ public class ScriptServiceTests extends ESTestCase {
scriptMode = DEFAULT_SCRIPT_MODES.get(scriptType);
}
for (String lang : scriptEngineService.types()) {
for (String lang : scriptEngineService.getTypes()) {
switch (scriptMode) {
case ON:
assertCompileAccepted(lang, script, scriptType, scriptContext, contextAndHeaders);
assertCompileAccepted(lang, script, scriptType, scriptContext, contextAndHeaders);
break;
case OFF:
assertCompileRejected(lang, script, scriptType, scriptContext, contextAndHeaders);
assertCompileRejected(lang, script, scriptType, scriptContext, contextAndHeaders);
break;
case SANDBOX:
if (scriptEngineService.sandboxed()) {
assertCompileAccepted(lang, script, scriptType, scriptContext, contextAndHeaders);
if (scriptEngineService.isSandboxed()) {
assertCompileAccepted(lang, script, scriptType, scriptContext, contextAndHeaders);
} else {
assertCompileRejected(lang, script, scriptType, scriptContext, contextAndHeaders);
assertCompileRejected(lang, script, scriptType, scriptContext, contextAndHeaders);
}
break;
}
@ -333,7 +340,7 @@ public class ScriptServiceTests extends ESTestCase {
unknownContext = randomAsciiOfLength(randomIntBetween(1, 30));
} while(scriptContextRegistry.isSupportedContext(new ScriptContext.Plugin(pluginName, unknownContext)));
for (String type : scriptEngineService.types()) {
for (String type : scriptEngineService.getTypes()) {
try {
scriptService.compile(new Script("test", randomFrom(ScriptType.values()), type, null), new ScriptContext.Plugin(
pluginName, unknownContext), contextAndHeaders, Collections.emptyMap());
@ -411,6 +418,16 @@ public class ScriptServiceTests extends ESTestCase {
assertEquals(1L, scriptService.stats().getCacheEvictions());
}
public void testDefaultLanguage() throws IOException {
ContextAndHeaderHolder contextAndHeaderHolder = new ContextAndHeaderHolder();
Settings.Builder builder = Settings.builder();
builder.put("script.default_lang", "test");
buildScriptService(builder.build());
CompiledScript script =
scriptService.compile(new Script("1 + 1", ScriptType.INLINE, null, null), randomFrom(scriptContexts), contextAndHeaderHolder, Collections.emptyMap());
assertEquals(script.lang(), "test");
}
private void createFileScripts(String... langs) throws IOException {
for (String lang : langs) {
Path scriptPath = scriptsFilePath.resolve("file_script." + lang);
@ -429,25 +446,28 @@ public class ScriptServiceTests extends ESTestCase {
}
}
private void assertCompileAccepted(String lang, String script, ScriptType scriptType, ScriptContext scriptContext,
HasContextAndHeaders contextAndHeaders) {
private void assertCompileAccepted(String lang, String script, ScriptType scriptType, ScriptContext scriptContext, HasContextAndHeaders contextAndHeaders) {
assertThat(scriptService.compile(new Script(script, scriptType, lang, null), scriptContext, contextAndHeaders, Collections.emptyMap()), notNullValue());
}
public static class TestEngineService implements ScriptEngineService {
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("test", "test2"));
public static final List<String> EXTENSIONS = Collections.unmodifiableList(Arrays.asList("test", "tst"));
@Override
public String[] types() {
return new String[] {"test", "test2"};
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return new String[] {"test", "tst"};
public List<String> getExtensions() {
return EXTENSIONS;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -0,0 +1,144 @@
/*
* 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.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
public class ScriptSettingsTests extends ESTestCase {
public void testConflictingModesForLanguage() {
ScriptEngineRegistry scriptEngineRegistry =
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.TYPES)));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
ScriptService.ScriptType scriptType = randomFrom(ScriptService.ScriptType.values());
ScriptContext scriptContext = randomFrom(ScriptContext.Standard.values());
Settings settings =
Settings
.builder()
.put(ScriptModes.getKey("test1", scriptType, scriptContext), "off")
.put(ScriptModes.getKey("test2", scriptType, scriptContext), "on")
.build();
boolean sawConflictingSettings = false;
for (Setting<ScriptMode> scriptModeSetting : scriptSettings.getScriptLanguageSettings()) {
if (scriptModeSetting.getKey().startsWith(ScriptModes.getKey("test3", scriptType, scriptContext))) {
try {
scriptModeSetting.get(settings);
fail("should have seen conflicting settings");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), anyOf(containsString("conflicting settings [{off=[test1], on=[test2]}] for language [test3]"), containsString("conflicting settings [{on=[test2], on=[test1]}] for language [test3]")));
sawConflictingSettings = true;
}
}
}
assertTrue(sawConflictingSettings);
}
public void testDefaultLanguageIsGroovy() {
ScriptEngineRegistry scriptEngineRegistry =
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.TYPES)));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
assertThat(scriptSettings.getDefaultScriptLanguageSetting().get(Settings.EMPTY), equalTo("groovy"));
}
public void testCustomDefaultLanguage() {
ScriptEngineRegistry scriptEngineRegistry =
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.TYPES)));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
String defaultLanguage = randomFrom(CustomScriptEngineService.TYPES);
Settings settings = Settings.builder().put("script.default_lang", defaultLanguage).build();
assertThat(scriptSettings.getDefaultScriptLanguageSetting().get(settings), equalTo(defaultLanguage));
}
public void testInvalidDefaultLanguage() {
ScriptEngineRegistry scriptEngineRegistry =
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.TYPES)));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
Settings settings = Settings.builder().put("script.default_lang", "C++").build();
try {
scriptSettings.getDefaultScriptLanguageSetting().get(settings);
fail("should have seen unregistered default language");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("unregistered default language [C++]"));
}
}
private static class CustomScriptEngineService implements ScriptEngineService {
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("test1", "test2", "test3"));
@Override
public List<String> getTypes() {
return TYPES;
}
@Override
public List<String> getExtensions() {
return Collections.singletonList(TYPES.get(0));
}
@Override
public boolean isSandboxed() {
return false;
}
@Override
public Object compile(String script, 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() {
}
@Override
public void scriptRemoved(@Nullable CompiledScript script) {
}
}
}

View File

@ -33,6 +33,7 @@ import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.LeafSearchScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService.ScriptType;
@ -55,6 +56,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -1397,7 +1399,7 @@ public class DateHistogramIT extends ESIntegTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(ExtractFieldScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.TYPES));
}
}
@ -1409,22 +1411,24 @@ public class DateHistogramIT extends ESIntegTestCase {
public static final String NAME = "extract_field";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}
@ -1517,7 +1521,7 @@ public class DateHistogramIT extends ESIntegTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(FieldValueScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES));
}
}
@ -1529,22 +1533,24 @@ public class DateHistogramIT extends ESIntegTestCase {
public static final String NAME = "field_value";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -26,6 +26,7 @@ import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.LeafSearchScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService.ScriptType;
@ -332,7 +333,7 @@ public class AvgIT extends AbstractNumericTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(ExtractFieldScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.TYPES));
}
}
@ -344,22 +345,24 @@ public class AvgIT extends AbstractNumericTestCase {
public static final String NAME = "extract_field";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}
@ -462,7 +465,7 @@ public class AvgIT extends AbstractNumericTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(FieldValueScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES));
}
}
@ -474,22 +477,24 @@ public class AvgIT extends AbstractNumericTestCase {
public static final String NAME = "field_value";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -26,6 +26,7 @@ import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.LeafSearchScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService.ScriptType;
@ -40,6 +41,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -326,7 +328,7 @@ public class SumIT extends AbstractNumericTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(ExtractFieldScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.TYPES));
}
}
@ -339,22 +341,24 @@ public class SumIT extends AbstractNumericTestCase {
public static final String NAME = "extract_field";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}
@ -458,7 +462,7 @@ public class SumIT extends AbstractNumericTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(FieldValueScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES));
}
}
@ -471,22 +475,24 @@ public class SumIT extends AbstractNumericTestCase {
public static final String NAME = "field_value";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -26,6 +26,7 @@ import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.LeafSearchScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService.ScriptType;
@ -40,6 +41,7 @@ import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@ -221,7 +223,7 @@ public class ValueCountIT extends ESIntegTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(FieldValueScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES));
}
}
@ -233,22 +235,24 @@ public class ValueCountIT extends ESIntegTestCase {
public static final String NAME = "field_value";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -104,7 +104,7 @@ public class FunctionScoreBackwardCompatibilityIT extends ESBackcompatTestCase {
@Override
protected Settings commonNodeSettings(int nodeOrdinal) {
return Settings.builder().put(super.commonNodeSettings(nodeOrdinal))
.put("script.inline", "on").build();
.put("script.inline", "true").build();
}
private void checkFunctionScoreStillWorks(String... ids) throws ExecutionException, InterruptedException, IOException {

View File

@ -41,6 +41,7 @@ import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService;
@ -92,7 +93,7 @@ public class UpdateIT extends ESIntegTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(PutFieldValuesScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PutFieldValuesScriptEngine.class, PutFieldValuesScriptEngine.TYPES));
}
}
@ -101,22 +102,24 @@ public class UpdateIT extends ESIntegTestCase {
public static final String NAME = "put_values";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}
@ -184,7 +187,7 @@ public class UpdateIT extends ESIntegTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(FieldIncrementScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldIncrementScriptEngine.class, FieldIncrementScriptEngine.TYPES));
}
}
@ -193,22 +196,24 @@ public class UpdateIT extends ESIntegTestCase {
public static final String NAME = "field_inc";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}
@ -269,7 +274,7 @@ public class UpdateIT extends ESIntegTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(ScriptedUpsertScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ScriptedUpsertScriptEngine.class, ScriptedUpsertScriptEngine.TYPES));
}
}
@ -278,22 +283,24 @@ public class UpdateIT extends ESIntegTestCase {
public static final String NAME = "scripted_upsert";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}
@ -354,7 +361,7 @@ public class UpdateIT extends ESIntegTestCase {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(ExtractContextInSourceScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractContextInSourceScriptEngine.class, ExtractContextInSourceScriptEngine.TYPES));
}
}
@ -363,22 +370,24 @@ public class UpdateIT extends ESIntegTestCase {
public static final String NAME = "extract_ctx";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -194,7 +194,7 @@ def smoke_test_release(release, files, expected_hash, plugins):
headers = {}
print(' Starting elasticsearch deamon from [%s]' % os.path.join(tmp_dir, 'elasticsearch-%s' % release))
try:
run('%s; %s -Des.node.name=smoke_tester -Des.cluster.name=prepare_release -Des.script.inline=on -Des.script.indexed=on -Des.repositories.url.allowed_urls=http://snapshot.test* %s -Des.pidfile=%s'
run('%s; %s -Des.node.name=smoke_tester -Des.cluster.name=prepare_release -Des.script.inline=true -Des.script.indexed=true -Des.repositories.url.allowed_urls=http://snapshot.test* %s -Des.pidfile=%s'
% (java_exe(), es_run_path, '-d', os.path.join(tmp_dir, 'elasticsearch-%s' % (release), 'es-smoke.pid')))
conn = HTTPConnection(host='127.0.0.1', port=9200, timeout=20)
if not wait_for_node_startup(header=headers):

View File

@ -17,6 +17,7 @@ your application to Elasticsearch 3.0.
* <<breaking_30_allocation>>
* <<breaking_30_percolator>>
* <<breaking_30_packaging>>
* <<breaking_30_scripting>>
[[breaking_30_search_changes]]
=== Warmers
@ -684,3 +685,15 @@ and these error messages would be lost to the nether. The default has
changed to now route standard output to the journal and standard error
to inherit this setting (these are the defaults for systemd). These
settings can be modified by editing the elasticsearch.service file.
[[breaking_30_scripting]]
=== Scripting
==== Script mode settings
Previously script mode settings (e.g., "script.inline: true",
"script.engine.groovy.inline.aggs: false", etc.) accepted the values
`on`, `true`, `1`, and `yes` for enabling a scripting mode, and the
values `off`, `false`, `0`, and `no` for disabling a scripting mode.
The variants `on`, `1`, and `yes ` for enabling and `off`, `0`,
and `no` for disabling are no longer supported.

View File

@ -244,8 +244,8 @@ every script engine, through the following settings that need to be added to the
[source,yaml]
-----------------------------------
script.inline: on
script.indexed: on
script.inline: true
script.indexed: true
-----------------------------------
@ -261,8 +261,8 @@ script settings:
[cols="<,<",options="header",]
|=======================================================================
|Value |Description
| `off` |scripting is turned off completely, in the context of the setting being set.
| `on` |scripting is turned on, in the context of the setting being set.
| `false` |scripting is turned off completely, in the context of the setting being set.
| `true` |scripting is turned on, in the context of the setting being set.
| `sandbox` |scripts may be executed only for languages that are sandboxed
|=======================================================================
@ -272,7 +272,7 @@ The default values are the following:
-----------------------------------
script.inline: sandbox
script.indexed: sandbox
script.file: on
script.file: true
-----------------------------------
@ -305,8 +305,8 @@ and plugins execution though, as the above defaults still get applied.
[source,yaml]
-----------------------------------
script.update: off
script.mapping: off
script.update: false
script.mapping: false
-----------------------------------
@ -317,21 +317,21 @@ precedence over any other generic settings.
[source,yaml]
-----------------------------------
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
script.engine.groovy.file.aggs: true
script.engine.groovy.file.mapping: true
script.engine.groovy.file.search: true
script.engine.groovy.file.update: true
script.engine.groovy.file.plugin: true
script.engine.groovy.indexed.aggs: true
script.engine.groovy.indexed.mapping: false
script.engine.groovy.indexed.search: true
script.engine.groovy.indexed.update: false
script.engine.groovy.indexed.plugin: false
script.engine.groovy.inline.aggs: true
script.engine.groovy.inline.mapping: false
script.engine.groovy.inline.search: false
script.engine.groovy.inline.update: false
script.engine.groovy.inline.plugin: false
-----------------------------------

View File

@ -20,10 +20,11 @@
package org.elasticsearch.script.expression;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptModule;
public class ExpressionPlugin extends Plugin {
@Override
public String name() {
return "lang-expression";
@ -35,6 +36,6 @@ public class ExpressionPlugin extends Plugin {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(ExpressionScriptEngineService.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExpressionScriptEngineService.class, ExpressionScriptEngineService.TYPES));
}
}

View File

@ -50,6 +50,8 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
@ -60,6 +62,8 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
public static final String NAME = "expression";
public static final List<String> TYPES = Collections.singletonList(NAME);
protected static final String GET_YEAR_METHOD = "getYear";
protected static final String GET_MONTH_METHOD = "getMonth";
protected static final String GET_DAY_OF_MONTH_METHOD = "getDayOfMonth";
@ -80,17 +84,17 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
}
@Override
public String[] types() {
return new String[]{NAME};
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return new String[]{NAME};
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -39,10 +39,9 @@ public class IndexedExpressionTests extends ESIntegTestCase {
@Override
protected Settings nodeSettings(int nodeOrdinal) {
Settings.Builder builder = Settings.builder().put(super.nodeSettings(nodeOrdinal));
builder.put("script.engine.expression.indexed.update", "off");
builder.put("script.engine.expression.indexed.search", "off");
builder.put("script.engine.expression.indexed.aggs", "off");
builder.put("script.engine.expression.indexed.mapping", "off");
builder.put("script.engine.expression.indexed.update", "false");
builder.put("script.engine.expression.indexed.search", "false");
builder.put("script.engine.expression.indexed.mapping", "false");
return builder.build();
}

View File

@ -28,8 +28,8 @@ dependencies {
integTest {
cluster {
systemProperty 'es.script.inline', 'on'
systemProperty 'es.script.indexed', 'on'
systemProperty 'es.script.inline', 'true'
systemProperty 'es.script.indexed', 'true'
}
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.script.groovy;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptModule;
public class GroovyPlugin extends Plugin {
@ -35,6 +36,6 @@ public class GroovyPlugin extends Plugin {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(GroovyScriptEngineService.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(GroovyScriptEngineService.class, GroovyScriptEngineService.TYPES));
}
}

View File

@ -19,15 +19,10 @@
package org.elasticsearch.script.groovy;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import groovy.lang.Script;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.Scorer;
import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
@ -60,10 +55,16 @@ import org.elasticsearch.script.SearchScript;
import org.elasticsearch.search.lookup.LeafSearchLookup;
import org.elasticsearch.search.lookup.SearchLookup;
import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import groovy.lang.Script;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Provides the infrastructure for Groovy as a scripting language for Elasticsearch
@ -74,6 +75,8 @@ public class GroovyScriptEngineService extends AbstractComponent implements Scri
* The name of the scripting engine/language.
*/
public static final String NAME = "groovy";
public static final List<String> TYPES = Collections.singletonList(NAME);
/**
* The name of the Groovy compiler setting to use associated with activating <code>invokedynamic</code> support.
*/
@ -158,17 +161,17 @@ public class GroovyScriptEngineService extends AbstractComponent implements Scri
}
@Override
public String[] types() {
return new String[]{NAME};
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return new String[]{NAME};
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return false;
}

View File

@ -91,7 +91,7 @@ public class ContextAndHeaderTransportTests extends ESIntegTestCase {
protected Settings nodeSettings(int nodeOrdinal) {
return settingsBuilder()
.put(super.nodeSettings(nodeOrdinal))
.put("script.indexed", "on")
.put("script.indexed", "true")
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
.build();
}

View File

@ -60,14 +60,13 @@ public class IndexedScriptTests extends ESIntegTestCase {
@Override
protected Settings nodeSettings(int nodeOrdinal) {
Settings.Builder builder = Settings.builder().put(super.nodeSettings(nodeOrdinal));
builder.put("script.engine.groovy.indexed.update", "off");
builder.put("script.engine.groovy.indexed.search", "on");
builder.put("script.engine.groovy.indexed.aggs", "on");
builder.put("script.engine.groovy.inline.aggs", "off");
builder.put("script.engine.expression.indexed.update", "off");
builder.put("script.engine.expression.indexed.search", "off");
builder.put("script.engine.expression.indexed.aggs", "off");
builder.put("script.engine.expression.indexed.mapping", "off");
builder.put("script.engine.groovy.indexed.update", "false");
builder.put("script.engine.groovy.indexed.search", "true");
builder.put("script.engine.groovy.indexed.aggs", "true");
builder.put("script.engine.groovy.inline.aggs", "false");
builder.put("script.engine.expression.indexed.update", "false");
builder.put("script.engine.expression.indexed.search", "false");
builder.put("script.engine.expression.indexed.mapping", "false");
return builder.build();
}

View File

@ -28,7 +28,7 @@ dependencies {
integTest {
cluster {
systemProperty 'es.script.inline', 'on'
systemProperty 'es.script.indexed', 'on'
systemProperty 'es.script.inline', 'true'
systemProperty 'es.script.indexed', 'true'
}
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.script.mustache;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptModule;
public class MustachePlugin extends Plugin {
@ -35,6 +36,6 @@ public class MustachePlugin extends Plugin {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(MustacheScriptEngineService.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class, MustacheScriptEngineService.TYPES));
}
}

View File

@ -18,13 +18,8 @@
*/
package org.elasticsearch.script.mustache;
import java.lang.ref.SoftReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.io.Reader;
import java.util.Map;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import org.elasticsearch.SpecialPermission;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.component.AbstractComponent;
@ -40,8 +35,13 @@ import org.elasticsearch.script.ScriptException;
import org.elasticsearch.script.SearchScript;
import org.elasticsearch.search.lookup.SearchLookup;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.DefaultMustacheFactory;
import java.io.Reader;
import java.lang.ref.SoftReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Main entry point handling template registration, compilation and
@ -54,6 +54,9 @@ import com.github.mustachejava.DefaultMustacheFactory;
public final class MustacheScriptEngineService extends AbstractComponent implements ScriptEngineService {
public static final String NAME = "mustache";
public static final List<String> TYPES = Collections.singletonList(NAME);
static final String CONTENT_TYPE_PARAM = "content_type";
static final String JSON_CONTENT_TYPE = "application/json";
static final String PLAIN_TEXT_CONTENT_TYPE = "text/plain";
@ -109,17 +112,17 @@ public final class MustacheScriptEngineService extends AbstractComponent impleme
}
@Override
public String[] types() {
return new String[] {NAME};
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return new String[] {NAME};
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -86,7 +86,7 @@ public class ContextAndHeaderTransportTests extends ESIntegTestCase {
protected Settings nodeSettings(int nodeOrdinal) {
return settingsBuilder()
.put(super.nodeSettings(nodeOrdinal))
.put("script.indexed", "on")
.put("script.indexed", "true")
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
.build();
}

View File

@ -18,10 +18,6 @@
*/
package org.elasticsearch.messy.tests;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.util.Collections;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.Accountable;
@ -62,6 +58,7 @@ import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache;
import org.elasticsearch.indices.mapper.MapperRegistry;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
@ -74,6 +71,10 @@ import org.elasticsearch.threadpool.ThreadPoolModule;
import org.junit.After;
import org.junit.Before;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.util.Collections;
import static org.hamcrest.Matchers.containsString;
/**
@ -100,10 +101,10 @@ public class TemplateQueryParserTests extends ESTestCase {
});
Index index = new Index("test");
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(index, settings);
ScriptModule scriptModule = new ScriptModule(settings);
// TODO: make this use a mock engine instead of mustache and it will no longer be messy!
scriptModule.addScriptEngine(MustacheScriptEngineService.class);
SettingsModule settingsModule = new SettingsModule(settings, new SettingsFilter(settings));
ScriptModule scriptModule = new ScriptModule(settingsModule);
// TODO: make this use a mock engine instead of mustache and it will no longer be messy!
scriptModule.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class, MustacheScriptEngineService.TYPES));
settingsModule.registerSetting(InternalSettingsPlugin.VERSION_CREATED);
injector = new ModulesBuilder().add(
new EnvironmentModule(new Environment(settings)),

View File

@ -28,7 +28,7 @@ dependencies {
integTest {
cluster {
systemProperty 'es.script.inline', 'on'
systemProperty 'es.script.indexed', 'on'
systemProperty 'es.script.inline', 'true'
systemProperty 'es.script.indexed', 'true'
}
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.plugin.javascript;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.javascript.JavaScriptScriptEngineService;
@ -44,6 +45,6 @@ public class JavaScriptPlugin extends Plugin {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(JavaScriptScriptEngineService.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(JavaScriptScriptEngineService.class, JavaScriptScriptEngineService.TYPES));
}
}

View File

@ -19,18 +19,6 @@
package org.elasticsearch.script.javascript;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.cert.Certificate;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.Scorer;
import org.elasticsearch.SpecialPermission;
@ -61,11 +49,27 @@ import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.SecurityController;
import org.mozilla.javascript.WrapFactory;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**
*
*/
public class JavaScriptScriptEngineService extends AbstractComponent implements ScriptEngineService {
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("js", "javascript"));
private final AtomicLong counter = new AtomicLong();
private static WrapFactory wrapFactory = new CustomWrapFactory();
@ -155,17 +159,17 @@ public class JavaScriptScriptEngineService extends AbstractComponent implements
}
@Override
public String[] types() {
return new String[]{"js", "javascript"};
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return new String[]{"js"};
public List<String> getExtensions() {
return Collections.unmodifiableList(Arrays.asList("js"));
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return false;
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.plan.a;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptModule;
public final class PlanAPlugin extends Plugin {
@ -35,6 +36,6 @@ public final class PlanAPlugin extends Plugin {
}
public void onModule(final ScriptModule module) {
module.addScriptEngine(PlanAScriptEngineService.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PlanAScriptEngineService.class, PlanAScriptEngineService.TYPES));
}
}

View File

@ -37,7 +37,9 @@ import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -50,6 +52,8 @@ public class PlanAScriptEngineService extends AbstractComponent implements Scrip
*/
public static final String NAME = "plan-a";
public static final List<String> TYPES = Collections.singletonList(NAME);
/**
* Default compiler settings to be used.
*/
@ -97,8 +101,8 @@ public class PlanAScriptEngineService extends AbstractComponent implements Scrip
* @return Always contains only the single name of the language.
*/
@Override
public String[] types() {
return new String[] { NAME };
public List<String> getTypes() {
return TYPES;
}
/**
@ -106,8 +110,8 @@ public class PlanAScriptEngineService extends AbstractComponent implements Scrip
* @return Always contains only the single extension of the language.
*/
@Override
public String[] extensions() {
return new String[] { NAME };
public List<String> getExtensions() {
return TYPES;
}
/**
@ -115,7 +119,7 @@ public class PlanAScriptEngineService extends AbstractComponent implements Scrip
* @return Always true as the engine should be secure at runtime.
*/
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -28,8 +28,8 @@ dependencies {
integTest {
cluster {
systemProperty 'es.script.inline', 'on'
systemProperty 'es.script.indexed', 'on'
systemProperty 'es.script.inline', 'true'
systemProperty 'es.script.indexed', 'true'
}
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.plugin.python;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.python.PythonScriptEngineService;
@ -39,6 +40,6 @@ public class PythonPlugin extends Plugin {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(PythonScriptEngineService.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PythonScriptEngineService.class, PythonScriptEngineService.TYPES));
}
}

View File

@ -47,6 +47,9 @@ import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
@ -55,6 +58,8 @@ import java.util.Map;
//TODO we can optimize the case for Map<String, Object> similar to PyStringMap
public class PythonScriptEngineService extends AbstractComponent implements ScriptEngineService {
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("py", "python"));
private final PythonInterpreter interp;
@Inject
@ -91,17 +96,17 @@ public class PythonScriptEngineService extends AbstractComponent implements Scri
}
@Override
public String[] types() {
return new String[]{"python", "py"};
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return new String[]{"py"};
public List<String> getExtensions() {
return Collections.unmodifiableList(Arrays.asList("py"));
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return false;
}

View File

@ -21,10 +21,11 @@ package org.elasticsearch.ingest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.ingest.InternalTemplateService;
import org.elasticsearch.ingest.core.TemplateService;
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.MustacheScriptEngineService;
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
@ -39,13 +40,15 @@ public abstract class AbstractMustacheTests extends ESTestCase {
public void init() throws Exception {
Settings settings = Settings.builder()
.put("path.home", createTempDir())
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING, false)
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), false)
.build();
MustacheScriptEngineService mustache = new MustacheScriptEngineService(settings);
ScriptContextRegistry registry = new ScriptContextRegistry(Collections.emptyList());
ScriptService scriptService = new ScriptService(
settings, new Environment(settings), Collections.singleton(mustache), null, registry
);
ScriptEngineRegistry scriptEngineRegistry =
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class, MustacheScriptEngineService.TYPES)));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
ScriptService scriptService =
new ScriptService(settings, new Environment(settings), Collections.singleton(mustache), null, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
templateService = new InternalTemplateService(scriptService);
}

View File

@ -26,14 +26,19 @@ import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.search.lookup.SearchLookup;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* A dummy script engine used for testing. Scripts must be a number. Running the script
*/
public class MockScriptEngine implements ScriptEngineService {
public static final String NAME = "mockscript";
public static final List<String> TYPES = Collections.singletonList(NAME);
public static class TestPlugin extends Plugin {
public TestPlugin() {
@ -50,23 +55,23 @@ public class MockScriptEngine implements ScriptEngineService {
}
public void onModule(ScriptModule module) {
module.addScriptEngine(MockScriptEngine.class);
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES));
}
}
@Override
public String[] types() {
return new String[]{ NAME };
public List<String> getTypes() {
return TYPES;
}
@Override
public String[] extensions() {
return types();
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean sandboxed() {
public boolean isSandboxed() {
return true;
}

View File

@ -1682,8 +1682,8 @@ public abstract class ESIntegTestCase extends ESTestCase {
// from failing on nodes without enough disk space
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b")
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b")
.put("script.indexed", "on")
.put("script.inline", "on")
.put("script.indexed", "true")
.put("script.inline", "true")
// wait short time for other active shards before actually deleting, default 30s not needed in tests
.put(IndicesStore.INDICES_STORE_DELETE_SHARD_TIMEOUT.getKey(), new TimeValue(1, TimeUnit.SECONDS));
return builder.build();

View File

@ -166,8 +166,8 @@ public abstract class ESSingleNodeTestCase extends ESTestCase {
.put("node.name", nodeName())
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
.put("script.inline", "on")
.put("script.indexed", "on")
.put("script.inline", "true")
.put("script.indexed", "true")
.put(EsExecutors.PROCESSORS_SETTING.getKey(), 1) // limit the number of threads created
.put("http.enabled", false)
.put(Node.NODE_LOCAL_SETTING.getKey(), true)

View File

@ -450,7 +450,7 @@ public final class InternalTestCluster extends TestCluster {
builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getKey(), RandomInts.randomIntBetween(random, 0, 2000));
}
if (random.nextBoolean()) {
builder.put(ScriptService.SCRIPT_CACHE_EXPIRE_SETTING, TimeValue.timeValueMillis(RandomInts.randomIntBetween(random, 750, 10000000)));
builder.put(ScriptService.SCRIPT_CACHE_EXPIRE_SETTING.getKey(), TimeValue.timeValueMillis(RandomInts.randomIntBetween(random, 750, 10000000)));
}
// always default delayed allocation to 0 to make sure we have tests are not delayed