Remove support for mulitple languages per scripting engine
This commit is contained in:
parent
a4060f7436
commit
efff3918d8
|
@ -40,8 +40,6 @@ 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
|
||||
|
@ -51,8 +49,8 @@ public class NativeScriptEngineService extends AbstractComponent implements Scri
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,33 +24,34 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.elasticsearch.common.Strings;
|
||||
|
||||
public class ScriptEngineRegistry {
|
||||
|
||||
private final Map<Class<? extends ScriptEngineService>, List<String>> registeredScriptEngineServices;
|
||||
private final Map<Class<? extends ScriptEngineService>, String> registeredScriptEngineServices;
|
||||
private final Map<String, Class<? extends ScriptEngineService>> registeredLanguages;
|
||||
private final Map<String, ScriptMode> defaultInlineScriptModes;
|
||||
|
||||
public ScriptEngineRegistry(Iterable<ScriptEngineRegistration> registrations) {
|
||||
Objects.requireNonNull(registrations);
|
||||
Map<Class<? extends ScriptEngineService>, List<String>> registeredScriptEngineServices = new HashMap<>();
|
||||
Map<Class<? extends ScriptEngineService>, String> registeredScriptEngineServices = new HashMap<>();
|
||||
Map<String, Class<? extends ScriptEngineService>> registeredLanguages = new HashMap<>();
|
||||
Map<String, ScriptMode> inlineScriptModes = 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) + "]");
|
||||
String oldLanguage = registeredScriptEngineServices.putIfAbsent(registration.getScriptEngineService(),
|
||||
registration.getScriptEngineLanguage());
|
||||
if (oldLanguage != null) {
|
||||
throw new IllegalArgumentException("script engine service [" + registration.getScriptEngineService() +
|
||||
"] already registered for language [" + oldLanguage + "]");
|
||||
}
|
||||
|
||||
for (String language : registration.getScriptEngineLanguages()) {
|
||||
Class<? extends ScriptEngineService> scriptEngineServiceClazz =
|
||||
String language = registration.getScriptEngineLanguage();
|
||||
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() + "]");
|
||||
}
|
||||
inlineScriptModes.put(language, registration.getDefaultInlineScriptMode());
|
||||
if (scriptEngineServiceClazz != null) {
|
||||
throw new IllegalArgumentException("scripting language [" + language + "] already registered for script engine service [" +
|
||||
scriptEngineServiceClazz.getCanonicalName() + "]");
|
||||
}
|
||||
inlineScriptModes.put(language, registration.getDefaultInlineScriptMode());
|
||||
}
|
||||
|
||||
this.registeredScriptEngineServices = Collections.unmodifiableMap(registeredScriptEngineServices);
|
||||
|
@ -62,7 +63,7 @@ public class ScriptEngineRegistry {
|
|||
return registeredScriptEngineServices.keySet();
|
||||
}
|
||||
|
||||
List<String> getLanguages(Class<? extends ScriptEngineService> scriptEngineService) {
|
||||
String getLanguage(Class<? extends ScriptEngineService> scriptEngineService) {
|
||||
Objects.requireNonNull(scriptEngineService);
|
||||
return registeredScriptEngineServices.get(scriptEngineService);
|
||||
}
|
||||
|
@ -77,23 +78,28 @@ public class ScriptEngineRegistry {
|
|||
|
||||
public static class ScriptEngineRegistration {
|
||||
private final Class<? extends ScriptEngineService> scriptEngineService;
|
||||
private final List<String> scriptEngineLanguages;
|
||||
private final String scriptEngineLanguage;
|
||||
private final ScriptMode defaultInlineScriptMode;
|
||||
|
||||
public ScriptEngineRegistration(Class<? extends ScriptEngineService> scriptEngineService, List<String> scriptEngineLanguages) {
|
||||
// Default to "off/disabled" if not specified
|
||||
this(scriptEngineService, scriptEngineLanguages, ScriptMode.OFF);
|
||||
/**
|
||||
* Register a script engine service with the default of inline scripts disabled
|
||||
*/
|
||||
public ScriptEngineRegistration(Class<? extends ScriptEngineService> scriptEngineService, String scriptEngineLanguage) {
|
||||
this(scriptEngineService, scriptEngineLanguage, ScriptMode.OFF);
|
||||
}
|
||||
|
||||
public ScriptEngineRegistration(Class<? extends ScriptEngineService> scriptEngineService, List<String> scriptEngineLanguages,
|
||||
/**
|
||||
* Register a script engine service with the given default mode for inline scripts
|
||||
*/
|
||||
public ScriptEngineRegistration(Class<? extends ScriptEngineService> scriptEngineService, String scriptEngineLanguage,
|
||||
ScriptMode defaultInlineScriptMode) {
|
||||
Objects.requireNonNull(scriptEngineService);
|
||||
Objects.requireNonNull(scriptEngineLanguages);
|
||||
if (scriptEngineLanguages.isEmpty()) {
|
||||
throw new IllegalArgumentException("languages for script engine service [" + scriptEngineService.getCanonicalName() + "] should be non-empty");
|
||||
if (Strings.hasText(scriptEngineLanguage) == false) {
|
||||
throw new IllegalArgumentException("languages for script engine service [" +
|
||||
scriptEngineService.getCanonicalName() + "] should be a non-empty string");
|
||||
}
|
||||
this.scriptEngineService = scriptEngineService;
|
||||
this.scriptEngineLanguages = scriptEngineLanguages;
|
||||
this.scriptEngineLanguage = scriptEngineLanguage;
|
||||
this.defaultInlineScriptMode = defaultInlineScriptMode;
|
||||
}
|
||||
|
||||
|
@ -101,8 +107,8 @@ public class ScriptEngineRegistry {
|
|||
return scriptEngineService;
|
||||
}
|
||||
|
||||
List<String> getScriptEngineLanguages() {
|
||||
return scriptEngineLanguages;
|
||||
String getScriptEngineLanguage() {
|
||||
return scriptEngineLanguage;
|
||||
}
|
||||
|
||||
ScriptMode getDefaultInlineScriptMode() {
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.Map;
|
|||
*/
|
||||
public interface ScriptEngineService extends Closeable {
|
||||
|
||||
List<String> getTypes();
|
||||
String getType();
|
||||
|
||||
List<String> getExtensions();
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ public class ScriptModule extends AbstractModule {
|
|||
|
||||
{
|
||||
scriptEngineRegistrations.add(new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class,
|
||||
NativeScriptEngineService.TYPES, ScriptMode.ON));
|
||||
NativeScriptEngineService.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
private final Map<String, Class<? extends NativeScriptFactory>> scripts = new HashMap<>();
|
||||
|
|
|
@ -168,9 +168,8 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
Map<String, ScriptEngineService> enginesByLangBuilder = new HashMap<>();
|
||||
Map<String, ScriptEngineService> enginesByExtBuilder = new HashMap<>();
|
||||
for (ScriptEngineService scriptEngine : scriptEngines) {
|
||||
for (String language : scriptEngineRegistry.getLanguages(scriptEngine.getClass())) {
|
||||
enginesByLangBuilder.put(language, scriptEngine);
|
||||
}
|
||||
String language = scriptEngineRegistry.getLanguage(scriptEngine.getClass());
|
||||
enginesByLangBuilder.put(language, scriptEngine);
|
||||
for (String ext : scriptEngine.getExtensions()) {
|
||||
enginesByExtBuilder.put(ext, scriptEngine);
|
||||
}
|
||||
|
@ -558,12 +557,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.getTypes().get(0), engineService, ScriptType.FILE)) {
|
||||
if (isAnyScriptContextEnabled(engineService.getType(), 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.getTypes().get(0), engineService.compile(script, Collections.emptyMap())));
|
||||
staticCache.put(cacheKey, new CompiledScript(ScriptType.FILE, scriptNameExt.v1(), engineService.getType(), engineService.compile(script, Collections.emptyMap())));
|
||||
scriptMetrics.onCompilation();
|
||||
}
|
||||
} else {
|
||||
|
@ -667,7 +666,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.getTypes().get(0);
|
||||
this.lang = service.getType();
|
||||
this.name = name;
|
||||
this.code = code;
|
||||
this.params = params;
|
||||
|
|
|
@ -83,79 +83,65 @@ public class ScriptSettings {
|
|||
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);
|
||||
private static List<Setting<ScriptMode>> languageSettings(Map<ScriptService.ScriptType, Setting<ScriptMode>> scriptTypeSettingMap,
|
||||
Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap,
|
||||
ScriptEngineRegistry scriptEngineRegistry,
|
||||
ScriptContextRegistry scriptContextRegistry) {
|
||||
final List<Setting<ScriptMode>> scriptModeSettings = new ArrayList<>();
|
||||
|
||||
for (String language : languages) {
|
||||
if (NativeScriptEngineService.TYPES.contains(language)) {
|
||||
// native scripts are always enabled, and their settings can not be changed
|
||||
continue;
|
||||
for (final Class<? extends ScriptEngineService> scriptEngineService : scriptEngineRegistry.getRegisteredScriptEngineServices()) {
|
||||
if (scriptEngineService == NativeScriptEngineService.class) {
|
||||
// native scripts are always enabled, and their settings can not be changed
|
||||
continue;
|
||||
}
|
||||
final String language = scriptEngineRegistry.getLanguage(scriptEngineService);
|
||||
for (final ScriptService.ScriptType scriptType : ScriptService.ScriptType.values()) {
|
||||
// Top level, like "script.engine.groovy.inline"
|
||||
final ScriptMode defaultNonFileScriptMode = scriptEngineRegistry.getDefaultInlineScriptModes().get(language);
|
||||
ScriptMode defaultLangAndType = defaultNonFileScriptMode;
|
||||
// Files are treated differently because they are never default-deny
|
||||
if (ScriptService.ScriptType.FILE == scriptType) {
|
||||
defaultLangAndType = ScriptService.ScriptType.FILE.getDefaultScriptMode();
|
||||
}
|
||||
ScriptMode defaultNonFileScriptMode = scriptEngineRegistry.getDefaultInlineScriptModes().get(language);
|
||||
for (final ScriptService.ScriptType scriptType : ScriptService.ScriptType.values()) {
|
||||
// This will be easier once ScriptMode is transitioned to booleans
|
||||
if (scriptType.getDefaultScriptMode() == ScriptMode.ON) {
|
||||
defaultNonFileScriptMode = ScriptMode.ON;
|
||||
}
|
||||
final ScriptMode defaultScriptMode = defaultNonFileScriptMode;
|
||||
// Like "script.engine.groovy.inline"
|
||||
final Setting<ScriptMode> langGlobalSetting = new Setting<>(ScriptModes.getGlobalKey(language, scriptType),
|
||||
defaultScriptMode.toString(), ScriptMode::parse, Property.NodeScope);
|
||||
scriptModeSettings.add(langGlobalSetting);
|
||||
final ScriptMode defaultIfNothingSet = defaultLangAndType;
|
||||
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
Function<Settings, String> defaultSetting = settings -> {
|
||||
// fallback logic for script mode settings
|
||||
// Setting for something like "script.engine.groovy.inline"
|
||||
final Setting<ScriptMode> langAndTypeSetting = new Setting<>(ScriptModes.getGlobalKey(language, scriptType),
|
||||
defaultLangAndType.toString(), ScriptMode::parse, Property.NodeScope);
|
||||
scriptModeSettings.add(langAndTypeSetting);
|
||||
|
||||
// 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();
|
||||
}
|
||||
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
|
||||
final String langAndTypeAndContextName = ScriptModes.getKey(language, scriptType, scriptContext);
|
||||
// A function that, given a setting, will return what the default should be. Since the fine-grained script settings
|
||||
// read from a bunch of different places this is implemented in this way.
|
||||
Function<Settings, String> defaultSettingFn = settings -> {
|
||||
final Setting<ScriptMode> globalOpSetting = scriptContextSettingMap.get(scriptContext);
|
||||
final Setting<ScriptMode> globalTypeSetting = scriptTypeSettingMap.get(scriptType);
|
||||
final Setting<ScriptMode> langAndTypeAndContextSetting = new Setting<>(langAndTypeAndContextName,
|
||||
defaultIfNothingSet.toString(), ScriptMode::parse, Property.NodeScope);
|
||||
|
||||
// the next fallback is settings configured for this engine and script type
|
||||
if (langGlobalSetting.exists(settings)) {
|
||||
return langGlobalSetting.get(settings).getMode();
|
||||
}
|
||||
|
||||
// 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 defaultScriptMode.toString();
|
||||
};
|
||||
Setting<ScriptMode> setting =
|
||||
new Setting<>(
|
||||
ScriptModes.getKey(language, scriptType, scriptContext),
|
||||
defaultSetting,
|
||||
ScriptMode::parse,
|
||||
Property.NodeScope);
|
||||
scriptModeSettings.add(setting);
|
||||
}
|
||||
// fallback logic for script mode settings
|
||||
if (langAndTypeAndContextSetting.exists(settings)) {
|
||||
// like: "script.engine.groovy.inline.aggs: true"
|
||||
return langAndTypeAndContextSetting.get(settings).getMode();
|
||||
} else if (langAndTypeSetting.exists(settings)) {
|
||||
// like: "script.engine.groovy.inline: true"
|
||||
return langAndTypeSetting.get(settings).getMode();
|
||||
} else if (globalOpSetting.exists(settings)) {
|
||||
// like: "script.aggs: true"
|
||||
return globalOpSetting.get(settings).getMode();
|
||||
} else if (globalTypeSetting.exists(settings)) {
|
||||
// like: "script.inline: true"
|
||||
return globalTypeSetting.get(settings).getMode();
|
||||
} else {
|
||||
// Nothing is set!
|
||||
return defaultIfNothingSet.getMode();
|
||||
}
|
||||
};
|
||||
// The actual setting for finest grained script settings
|
||||
Setting<ScriptMode> setting = new Setting<>(langAndTypeAndContextName, defaultSettingFn,
|
||||
ScriptMode::parse, Property.NodeScope);
|
||||
scriptModeSettings.add(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ public class BulkRequestTests extends ESTestCase {
|
|||
Script script = ((UpdateRequest) bulkRequest.requests().get(1)).script();
|
||||
assertThat(script, notNullValue());
|
||||
assertThat(script.getScript(), equalTo("counter += param1"));
|
||||
assertThat(script.getLang(), equalTo("js"));
|
||||
assertThat(script.getLang(), equalTo("javascript"));
|
||||
Map<String, Object> scriptParams = script.getParams();
|
||||
assertThat(scriptParams, notNullValue());
|
||||
assertThat(scriptParams.size(), equalTo(1));
|
||||
|
|
|
@ -241,7 +241,7 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
|
|||
ScriptEngineRegistry scriptEngineRegistry =
|
||||
new ScriptEngineRegistry(Collections
|
||||
.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class,
|
||||
MockScriptEngine.TYPES, ScriptMode.ON)));
|
||||
MockScriptEngine.NAME, ScriptMode.ON)));
|
||||
bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry);
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
|
||||
bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry);
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.script.ScriptMode;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.nio.file.Files;
|
||||
|
@ -44,7 +45,7 @@ public class FileScriptTests extends ESTestCase {
|
|||
.put(settings)
|
||||
.build();
|
||||
Set<ScriptEngineService> engines = new HashSet<>(Collections.singletonList(new MockScriptEngine()));
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES)));
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.NAME, ScriptMode.ON)));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
return new ScriptService(settings, new Environment(settings), engines, null, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.settings.SettingsModule;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.env.EnvironmentModule;
|
||||
import org.elasticsearch.script.ScriptMode;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
@ -85,7 +86,7 @@ public class NativeScriptTests extends ESTestCase {
|
|||
Map<String, NativeScriptFactory> nativeScriptFactoryMap = new HashMap<>();
|
||||
nativeScriptFactoryMap.put("my", new MyNativeScriptFactory());
|
||||
Set<ScriptEngineService> scriptEngineServices = singleton(new NativeScriptEngineService(settings, nativeScriptFactoryMap));
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.TYPES)));
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.NAME, ScriptMode.ON)));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(new ArrayList<>());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
ScriptService scriptService = new ScriptService(settings, environment, scriptEngineServices, resourceWatcherService, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
|
|
|
@ -45,10 +45,9 @@ public class ScriptContextTests extends ESTestCase {
|
|||
.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,
|
||||
ScriptMode.ON)));
|
||||
ScriptEngineRegistry.ScriptEngineRegistration registration =
|
||||
new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.NAME, ScriptMode.ON);
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(registration));
|
||||
List<ScriptContext.Plugin> customContexts = Arrays.asList(
|
||||
new ScriptContext.Plugin(PLUGIN_NAME, "custom_op"),
|
||||
new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"),
|
||||
|
|
|
@ -44,12 +44,6 @@ import static org.hamcrest.Matchers.containsString;
|
|||
|
||||
// TODO: this needs to be a base test class, and all scripting engines extend it
|
||||
public class ScriptModesTests extends ESTestCase {
|
||||
private static final Set<String> ALL_LANGS = unmodifiableSet(
|
||||
newHashSet("custom", "test"));
|
||||
|
||||
static final String[] ENABLE_VALUES = new String[]{"true"};
|
||||
static final String[] DISABLE_VALUES = new String[]{"false"};
|
||||
|
||||
ScriptSettings scriptSettings;
|
||||
ScriptContextRegistry scriptContextRegistry;
|
||||
private ScriptContext[] scriptContexts;
|
||||
|
@ -78,8 +72,8 @@ public class ScriptModesTests extends ESTestCase {
|
|||
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)));
|
||||
new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.NAME),
|
||||
new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.NAME)));
|
||||
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
checkedSettings = new HashSet<>();
|
||||
assertAllSettingsWereChecked = true;
|
||||
|
@ -97,9 +91,8 @@ public class ScriptModesTests extends ESTestCase {
|
|||
public void assertAllSettingsWereChecked() {
|
||||
if (assertScriptModesNonNull) {
|
||||
assertThat(scriptModes, notNullValue());
|
||||
//2 is the number of engines (native excluded), custom is counted twice though as it's associated with two different names
|
||||
int numberOfSettings = 2 * ScriptType.values().length * scriptContextRegistry.scriptContexts().size();
|
||||
numberOfSettings += 6; // for top-level inline/store/file settings
|
||||
int numberOfSettings = ScriptType.values().length * scriptContextRegistry.scriptContexts().size();
|
||||
numberOfSettings += 3; // for top-level inline/store/file settings
|
||||
assertThat(scriptModes.scriptModes.size(), equalTo(numberOfSettings));
|
||||
if (assertAllSettingsWereChecked) {
|
||||
assertThat(checkedSettings.size(), equalTo(numberOfSettings));
|
||||
|
@ -109,8 +102,8 @@ public class ScriptModesTests extends ESTestCase {
|
|||
|
||||
public void testDefaultSettings() {
|
||||
this.scriptModes = new ScriptModes(scriptSettings, Settings.EMPTY);
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ALL_LANGS, ScriptType.STORED, ScriptType.INLINE);
|
||||
assertScriptModesAllOps(ScriptMode.ON, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ScriptType.STORED, ScriptType.INLINE);
|
||||
}
|
||||
|
||||
public void testMissingSetting() {
|
||||
|
@ -143,16 +136,16 @@ public class ScriptModesTests extends ESTestCase {
|
|||
this.scriptModes = new ScriptModes(scriptSettings, builder.build());
|
||||
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
assertScriptModesAllOps(randomScriptModes[i], ALL_LANGS, randomScriptTypes[i]);
|
||||
assertScriptModesAllOps(randomScriptModes[i], randomScriptTypes[i]);
|
||||
}
|
||||
if (randomScriptTypesSet.contains(ScriptType.FILE) == false) {
|
||||
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
|
||||
assertScriptModesAllOps(ScriptMode.ON, ScriptType.FILE);
|
||||
}
|
||||
if (randomScriptTypesSet.contains(ScriptType.STORED) == false) {
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ALL_LANGS, ScriptType.STORED);
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ScriptType.STORED);
|
||||
}
|
||||
if (randomScriptTypesSet.contains(ScriptType.INLINE) == false) {
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ALL_LANGS, ScriptType.INLINE);
|
||||
assertScriptModesAllOps(ScriptMode.OFF, ScriptType.INLINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,46 +168,45 @@ public class ScriptModesTests extends ESTestCase {
|
|||
this.scriptModes = new ScriptModes(scriptSettings, builder.build());
|
||||
|
||||
for (int i = 0; i < randomInt; i++) {
|
||||
assertScriptModesAllTypes(randomScriptModes[i], ALL_LANGS, randomScriptContexts[i]);
|
||||
assertScriptModesAllTypes(randomScriptModes[i], randomScriptContexts[i]);
|
||||
}
|
||||
|
||||
ScriptContext[] complementOf = complementOf(randomScriptContexts);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE}, complementOf);
|
||||
assertScriptModes(ScriptMode.OFF, ALL_LANGS, new ScriptType[]{ScriptType.STORED, ScriptType.INLINE}, complementOf);
|
||||
assertScriptModes(ScriptMode.ON, new ScriptType[]{ScriptType.FILE}, complementOf);
|
||||
assertScriptModes(ScriptMode.OFF, new ScriptType[]{ScriptType.STORED, ScriptType.INLINE}, complementOf);
|
||||
}
|
||||
|
||||
public void testConflictingScriptTypeAndOpGenericSettings() {
|
||||
ScriptContext scriptContext = randomFrom(scriptContexts);
|
||||
Settings.Builder builder = Settings.builder().put("script" + "." + scriptContext.getKey(), randomFrom(DISABLE_VALUES))
|
||||
.put("script.stored", randomFrom(ENABLE_VALUES)).put("script.inline", "true");
|
||||
Settings.Builder builder = Settings.builder()
|
||||
.put("script." + scriptContext.getKey(), "false")
|
||||
.put("script.stored", "true")
|
||||
.put("script.inline", "true");
|
||||
//operations generic settings have precedence over script type generic settings
|
||||
this.scriptModes = new ScriptModes(scriptSettings, builder.build());
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, scriptContext);
|
||||
assertScriptModesAllTypes(ScriptMode.OFF, scriptContext);
|
||||
ScriptContext[] complementOf = complementOf(scriptContext);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE, ScriptType.STORED}, complementOf);
|
||||
assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.INLINE}, complementOf);
|
||||
assertScriptModes(ScriptMode.ON, new ScriptType[]{ScriptType.FILE, ScriptType.STORED}, complementOf);
|
||||
assertScriptModes(ScriptMode.ON, new ScriptType[]{ScriptType.INLINE}, complementOf);
|
||||
}
|
||||
|
||||
private void assertScriptModesAllOps(ScriptMode expectedScriptMode, Set<String> langs, ScriptType... scriptTypes) {
|
||||
assertScriptModes(expectedScriptMode, langs, scriptTypes, scriptContexts);
|
||||
private void assertScriptModesAllOps(ScriptMode expectedScriptMode, ScriptType... scriptTypes) {
|
||||
assertScriptModes(expectedScriptMode, scriptTypes, scriptContexts);
|
||||
}
|
||||
|
||||
private void assertScriptModesAllTypes(ScriptMode expectedScriptMode, Set<String> langs, ScriptContext... scriptContexts) {
|
||||
assertScriptModes(expectedScriptMode, langs, ScriptType.values(), scriptContexts);
|
||||
private void assertScriptModesAllTypes(ScriptMode expectedScriptMode, ScriptContext... scriptContexts) {
|
||||
assertScriptModes(expectedScriptMode, ScriptType.values(), scriptContexts);
|
||||
}
|
||||
|
||||
private void assertScriptModes(ScriptMode expectedScriptMode, Set<String> langs, ScriptType[] scriptTypes, ScriptContext... scriptContexts) {
|
||||
assert langs.size() > 0;
|
||||
private void assertScriptModes(ScriptMode expectedScriptMode, ScriptType[] scriptTypes, ScriptContext... scriptContexts) {
|
||||
assert scriptTypes.length > 0;
|
||||
assert scriptContexts.length > 0;
|
||||
for (String lang : langs) {
|
||||
for (ScriptType scriptType : scriptTypes) {
|
||||
checkedSettings.add("script.engine." + lang + "." + scriptType);
|
||||
for (ScriptContext scriptContext : scriptContexts) {
|
||||
assertThat(lang + "." + scriptType + "." + scriptContext.getKey() + " doesn't have the expected value",
|
||||
scriptModes.getScriptMode(lang, scriptType, scriptContext), equalTo(expectedScriptMode));
|
||||
checkedSettings.add(lang + "." + scriptType + "." + scriptContext);
|
||||
}
|
||||
for (ScriptType scriptType : scriptTypes) {
|
||||
checkedSettings.add("script.engine.custom." + scriptType);
|
||||
for (ScriptContext scriptContext : scriptContexts) {
|
||||
assertThat("custom." + scriptType + "." + scriptContext.getKey() + " doesn't have the expected value",
|
||||
scriptModes.getScriptMode("custom", scriptType, scriptContext), equalTo(expectedScriptMode));
|
||||
checkedSettings.add("custom." + scriptType + "." + scriptContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -233,25 +225,24 @@ public class ScriptModesTests extends ESTestCase {
|
|||
static Map<String, ScriptEngineService> buildScriptEnginesByLangMap(Set<ScriptEngineService> scriptEngines) {
|
||||
Map<String, ScriptEngineService> builder = new HashMap<>();
|
||||
for (ScriptEngineService scriptEngine : scriptEngines) {
|
||||
for (String type : scriptEngine.getTypes()) {
|
||||
builder.put(type, scriptEngine);
|
||||
}
|
||||
String type = scriptEngine.getType();
|
||||
builder.put(type, scriptEngine);
|
||||
}
|
||||
return unmodifiableMap(builder);
|
||||
}
|
||||
|
||||
private static class CustomScriptEngineService implements ScriptEngineService {
|
||||
|
||||
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("custom", "test"));
|
||||
public static final String NAME = "custom";
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExtensions() {
|
||||
return Collections.singletonList(TYPES.get(0));
|
||||
return Collections.unmodifiableList(Arrays.asList("custom", "test"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -110,8 +110,8 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
contexts.put(context, new ScriptContext.Plugin(plugin, operation));
|
||||
}
|
||||
List<ScriptEngineRegistry.ScriptEngineRegistration> registries = new ArrayList<>(2);
|
||||
registries.add(new ScriptEngineRegistry.ScriptEngineRegistration(TestEngineService.class, TestEngineService.TYPES, ScriptMode.ON));
|
||||
registries.add(new ScriptEngineRegistry.ScriptEngineRegistration(TestDangerousEngineService.class, TestDangerousEngineService.TYPES));
|
||||
registries.add(new ScriptEngineRegistry.ScriptEngineRegistration(TestEngineService.class, TestEngineService.NAME, ScriptMode.ON));
|
||||
registries.add(new ScriptEngineRegistry.ScriptEngineRegistration(TestDangerousEngineService.class, TestDangerousEngineService.NAME));
|
||||
scriptEngineRegistry = new ScriptEngineRegistry(registries);
|
||||
scriptContextRegistry = new ScriptContextRegistry(contexts.values());
|
||||
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
|
@ -195,30 +195,11 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
assertThat(compiledScript1.compiled(), sameInstance(compiledScript2.compiled()));
|
||||
}
|
||||
|
||||
public void testInlineScriptCompiledOnceMultipleLangAcronyms() throws IOException {
|
||||
buildScriptService(Settings.EMPTY);
|
||||
CompiledScript compiledScript1 = scriptService.compile(new Script("script", ScriptType.INLINE, "test", null),
|
||||
randomFrom(scriptContexts), Collections.emptyMap(), emptyClusterState());
|
||||
CompiledScript compiledScript2 = scriptService.compile(new Script("script", ScriptType.INLINE, "test2", null),
|
||||
randomFrom(scriptContexts), Collections.emptyMap(), emptyClusterState());
|
||||
assertThat(compiledScript1.compiled(), sameInstance(compiledScript2.compiled()));
|
||||
}
|
||||
|
||||
public void testFileScriptCompiledOnceMultipleLangAcronyms() throws IOException {
|
||||
buildScriptService(Settings.EMPTY);
|
||||
createFileScripts("test");
|
||||
CompiledScript compiledScript1 = scriptService.compile(new Script("file_script", ScriptType.FILE, "test", null),
|
||||
randomFrom(scriptContexts), Collections.emptyMap(), emptyClusterState());
|
||||
CompiledScript compiledScript2 = scriptService.compile(new Script("file_script", ScriptType.FILE, "test2", null),
|
||||
randomFrom(scriptContexts), Collections.emptyMap(), emptyClusterState());
|
||||
assertThat(compiledScript1.compiled(), sameInstance(compiledScript2.compiled()));
|
||||
}
|
||||
|
||||
public void testDefaultBehaviourFineGrainedSettings() throws IOException {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
//rarely inject the default settings, which have no effect
|
||||
if (rarely()) {
|
||||
builder.put("script.file", randomFrom(ScriptModesTests.ENABLE_VALUES));
|
||||
builder.put("script.file", "true");
|
||||
}
|
||||
buildScriptService(builder.build());
|
||||
createFileScripts("groovy", "mustache", "dtest");
|
||||
|
@ -258,7 +239,7 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
do {
|
||||
ScriptType scriptType = randomFrom(ScriptType.values());
|
||||
ScriptContext scriptContext = randomFrom(this.scriptContexts);
|
||||
settingKey = scriptEngineService.getTypes().get(0) + "." + scriptType + "." + scriptContext.getKey();
|
||||
settingKey = scriptEngineService.getType() + "." + scriptType + "." + scriptContext.getKey();
|
||||
} while (engineSettings.containsKey(settingKey));
|
||||
engineSettings.put(settingKey, randomFrom(ScriptMode.values()));
|
||||
}
|
||||
|
@ -289,7 +270,7 @@ 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).getTypes());
|
||||
String lang = randomFrom(scriptEnginesByLangMap.get(part1).getType());
|
||||
switch (entry.getValue()) {
|
||||
case ON:
|
||||
builder.put("script.engine" + "." + lang + "." + part2, "true");
|
||||
|
@ -309,7 +290,7 @@ 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(dangerousScriptEngineService.getTypes().get(0) + "." + scriptType + "." + scriptContext.getKey());
|
||||
ScriptMode scriptMode = engineSettings.get(dangerousScriptEngineService.getType() + "." + scriptType + "." + scriptContext.getKey());
|
||||
if (scriptMode == null) {
|
||||
scriptMode = scriptContextSettings.get(scriptContext);
|
||||
}
|
||||
|
@ -320,15 +301,14 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
scriptMode = DEFAULT_SCRIPT_MODES.get(scriptType);
|
||||
}
|
||||
|
||||
for (String lang : dangerousScriptEngineService.getTypes()) {
|
||||
switch (scriptMode) {
|
||||
case ON:
|
||||
assertCompileAccepted(lang, script, scriptType, scriptContext);
|
||||
break;
|
||||
case OFF:
|
||||
assertCompileRejected(lang, script, scriptType, scriptContext);
|
||||
break;
|
||||
}
|
||||
String lang = dangerousScriptEngineService.getType();
|
||||
switch (scriptMode) {
|
||||
case ON:
|
||||
assertCompileAccepted(lang, script, scriptType, scriptContext);
|
||||
break;
|
||||
case OFF:
|
||||
assertCompileRejected(lang, script, scriptType, scriptContext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,14 +323,13 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
unknownContext = randomAsciiOfLength(randomIntBetween(1, 30));
|
||||
} while(scriptContextRegistry.isSupportedContext(new ScriptContext.Plugin(pluginName, unknownContext)));
|
||||
|
||||
for (String type : scriptEngineService.getTypes()) {
|
||||
try {
|
||||
scriptService.compile(new Script("test", randomFrom(ScriptType.values()), type, null), new ScriptContext.Plugin(
|
||||
pluginName, unknownContext), Collections.emptyMap(), emptyClusterState());
|
||||
fail("script compilation should have been rejected");
|
||||
} catch(IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("script context [" + pluginName + "_" + unknownContext + "] not supported"));
|
||||
}
|
||||
String type = scriptEngineService.getType();
|
||||
try {
|
||||
scriptService.compile(new Script("test", randomFrom(ScriptType.values()), type, null), new ScriptContext.Plugin(
|
||||
pluginName, unknownContext), Collections.emptyMap(), emptyClusterState());
|
||||
fail("script compilation should have been rejected");
|
||||
} catch(IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("script context [" + pluginName + "_" + unknownContext + "] not supported"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -529,13 +508,13 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
|
||||
public static class TestEngineService implements ScriptEngineService {
|
||||
|
||||
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("test", "test2"));
|
||||
public static final String NAME = "test";
|
||||
|
||||
public static final List<String> EXTENSIONS = Collections.unmodifiableList(Arrays.asList("test", "tst"));
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -571,13 +550,13 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
|
||||
public static class TestDangerousEngineService implements ScriptEngineService {
|
||||
|
||||
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("dtest"));
|
||||
public static final String NAME = "dtest";
|
||||
|
||||
public static final List<String> EXTENSIONS = Collections.unmodifiableList(Arrays.asList("dtest"));
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.elasticsearch.script;
|
|||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.script.ScriptMode;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
|
@ -36,37 +37,9 @@ 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)));
|
||||
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.NAME, ScriptMode.ON)));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
assertThat(scriptSettings.getDefaultScriptLanguageSetting().get(Settings.EMPTY), equalTo("groovy"));
|
||||
|
@ -74,17 +47,17 @@ public class ScriptSettingsTests extends ESTestCase {
|
|||
|
||||
public void testCustomDefaultLanguage() {
|
||||
ScriptEngineRegistry scriptEngineRegistry =
|
||||
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.TYPES)));
|
||||
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.NAME, ScriptMode.ON)));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
String defaultLanguage = randomFrom(CustomScriptEngineService.TYPES);
|
||||
String defaultLanguage = CustomScriptEngineService.NAME;
|
||||
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)));
|
||||
new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.NAME, ScriptMode.ON)));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
Settings settings = Settings.builder().put("script.default_lang", "C++").build();
|
||||
|
@ -98,16 +71,18 @@ public class ScriptSettingsTests extends ESTestCase {
|
|||
|
||||
private static class CustomScriptEngineService implements ScriptEngineService {
|
||||
|
||||
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("test1", "test2", "test3"));
|
||||
public static final String NAME = "custom";
|
||||
|
||||
public static final List<String> TYPES = Collections.unmodifiableList(Arrays.asList("test"));
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExtensions() {
|
||||
return Collections.singletonList(TYPES.get(0));
|
||||
return Collections.unmodifiableList(Arrays.asList("test"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.elasticsearch.script.ScriptContext;
|
|||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptMode;
|
||||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
|
@ -130,8 +131,11 @@ public class AggregatorParsingTests extends ESTestCase {
|
|||
Set<ScriptEngineService> engines = new HashSet<>();
|
||||
engines.add(mockScriptEngine);
|
||||
List<ScriptContext.Plugin> customContexts = new ArrayList<>();
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections
|
||||
.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES)));
|
||||
ScriptEngineRegistry scriptEngineRegistry =
|
||||
new ScriptEngineRegistry(Collections
|
||||
.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class,
|
||||
MockScriptEngine.NAME,
|
||||
ScriptMode.ON)));
|
||||
bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry);
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
|
||||
bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry);
|
||||
|
|
|
@ -55,6 +55,7 @@ import org.elasticsearch.script.ScriptContext;
|
|||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptMode;
|
||||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
|
@ -143,8 +144,11 @@ public abstract class BaseAggregationTestCase<AB extends AggregatorBuilder<AB>>
|
|||
Set<ScriptEngineService> engines = new HashSet<>();
|
||||
engines.add(mockScriptEngine);
|
||||
List<ScriptContext.Plugin> customContexts = new ArrayList<>();
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections
|
||||
.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES)));
|
||||
ScriptEngineRegistry scriptEngineRegistry =
|
||||
new ScriptEngineRegistry(Collections
|
||||
.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class,
|
||||
MockScriptEngine.NAME,
|
||||
ScriptMode.ON)));
|
||||
bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry);
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
|
||||
bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry);
|
||||
|
|
|
@ -148,7 +148,7 @@ public abstract class BasePipelineAggregationTestCase<AF extends PipelineAggrega
|
|||
ScriptEngineRegistry scriptEngineRegistry =
|
||||
new ScriptEngineRegistry(Collections
|
||||
.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class,
|
||||
MockScriptEngine.TYPES, ScriptMode.ON)));
|
||||
MockScriptEngine.NAME, ScriptMode.ON)));
|
||||
bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry);
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
|
||||
bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry);
|
||||
|
|
|
@ -370,7 +370,7 @@ public class AvgIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -389,8 +389,8 @@ public class AvgIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -497,7 +497,7 @@ public class AvgIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -516,8 +516,8 @@ public class AvgIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -365,7 +365,7 @@ public class SumIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -385,8 +385,8 @@ public class SumIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -494,7 +494,7 @@ public class SumIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -514,8 +514,8 @@ public class SumIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -224,7 +224,7 @@ public class ValueCountIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -243,8 +243,8 @@ public class ValueCountIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -62,6 +62,7 @@ import org.elasticsearch.script.ScriptContext;
|
|||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptMode;
|
||||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
|
@ -151,7 +152,9 @@ public class SearchSourceBuilderTests extends ESTestCase {
|
|||
engines.add(mockScriptEngine);
|
||||
List<ScriptContext.Plugin> customContexts = new ArrayList<>();
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections
|
||||
.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES)));
|
||||
.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class,
|
||||
MockScriptEngine.NAME,
|
||||
ScriptMode.ON)));
|
||||
bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry);
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
|
||||
bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry);
|
||||
|
|
|
@ -96,7 +96,7 @@ public abstract class AbstractSortTestCase<T extends SortBuilder<T>> extends EST
|
|||
Environment environment = new Environment(baseSettings);
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry
|
||||
.ScriptEngineRegistration(TestEngineService.class, TestEngineService.TYPES)));
|
||||
.ScriptEngineRegistration(TestEngineService.class, TestEngineService.NAME)));
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
scriptService = new ScriptService(baseSettings, environment, Collections.singleton(new TestEngineService()),
|
||||
new ResourceWatcherService(baseSettings, null), scriptEngineRegistry, scriptContextRegistry, scriptSettings) {
|
||||
|
|
|
@ -94,7 +94,7 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PutFieldValuesScriptEngine.class, PutFieldValuesScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PutFieldValuesScriptEngine.class, PutFieldValuesScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -110,8 +110,8 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -183,7 +183,7 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldIncrementScriptEngine.class, FieldIncrementScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldIncrementScriptEngine.class, FieldIncrementScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -199,8 +199,8 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -265,7 +265,7 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ScriptedUpsertScriptEngine.class, ScriptedUpsertScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ScriptedUpsertScriptEngine.class, ScriptedUpsertScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -281,8 +281,8 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -347,7 +347,7 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractContextInSourceScriptEngine.class, ExtractContextInSourceScriptEngine.TYPES, ScriptMode.ON));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractContextInSourceScriptEngine.class, ExtractContextInSourceScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -363,8 +363,8 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ "update" : {"_id" : "1", "_retry_on_conflict" : 2} }
|
||||
{ "doc" : {"field" : "value"} }
|
||||
{ "update" : { "_id" : "0", "_type" : "type1", "_index" : "index1" } }
|
||||
{ "script" : "counter += param1", "lang" : "js", "params" : {"param1" : 1}, "upsert" : {"counter" : 1}}
|
||||
{ "script" : "counter += param1", "lang" : "javascript", "params" : {"param1" : 1}, "upsert" : {"counter" : 1}}
|
||||
{ "delete" : { "_id" : "2" } }
|
||||
{ "create" : { "_id" : "3" } }
|
||||
{ "field1" : "value3" }
|
||||
|
|
|
@ -36,7 +36,7 @@ The node must be stopped before removing the plugin.
|
|||
==== Using JavaScript in Elasticsearch
|
||||
|
||||
Once the plugin has been installed, JavaScript can be used at a scripting
|
||||
language by setting the `lang` parameter to `javascript` or `js`.
|
||||
language by setting the `lang` parameter to `javascript`.
|
||||
|
||||
Scripting is available in many APIs, but we will use an example with the
|
||||
`function_score` for demonstration purposes:
|
||||
|
|
|
@ -192,7 +192,7 @@ the options. Curl example with update actions:
|
|||
{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
|
||||
{ "doc" : {"field" : "value"} }
|
||||
{ "update" : { "_id" : "0", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
|
||||
{ "script" : { "inline": "ctx._source.counter += param1", "lang" : "js", "params" : {"param1" : 1}}, "upsert" : {"counter" : 1}}
|
||||
{ "script" : { "inline": "ctx._source.counter += param1", "lang" : "javascript", "params" : {"param1" : 1}}, "upsert" : {"counter" : 1}}
|
||||
{ "update" : {"_id" : "2", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
|
||||
{ "doc" : {"field" : "value"}, "doc_as_upsert" : true }
|
||||
{ "update" : {"_id" : "3", "_type" : "type1", "_index" : "index1", "fields" : ["_source"]} }
|
||||
|
|
|
@ -84,4 +84,12 @@ All the methods related to interacting with indexed scripts have been removed.
|
|||
The Java API methods for interacting with stored scripts have been added under `ClusterAdminClient` class.
|
||||
The sugar methods that used to exist on the indexed scripts API methods don't exist on the methods for
|
||||
stored scripts. The only way to provide scripts is by using `BytesReference` implementation, if a string needs to be
|
||||
provided the `BytesArray` class should be used.
|
||||
provided the `BytesArray` class should be used.
|
||||
|
||||
==== Scripting engines now register only a single language
|
||||
|
||||
Prior to 5.0.0, script engines could register multiple languages. The Javascript
|
||||
script engine in particular registered both `"lang": "js"` and `"lang":
|
||||
"javascript"`. Script engines can now only register a single language. All
|
||||
references to `"lang": "js"` should be changed to `"lang": "javascript"` for
|
||||
existing users of the lang-javascript plugin.
|
||||
|
|
|
@ -24,18 +24,23 @@ and give the most flexibility.
|
|||
[cols="<,<,<",options="header",]
|
||||
|=======================================================================
|
||||
|Language
|
||||
|Sandboxed
|
||||
|Required plugin
|
||||
|
||||
|<<modules-scripting-painless, `painless`>>
|
||||
|yes
|
||||
|built-in
|
||||
|
||||
|<<modules-scripting-groovy, `groovy`>>
|
||||
|<<modules-scripting-security, no>>
|
||||
|built-in
|
||||
|
||||
|{plugins}/lang-javascript.html[`javascript`]
|
||||
|<<modules-scripting-security, no>>
|
||||
|{plugins}/lang-javascript.html[`lang-javascript`]
|
||||
|
||||
|{plugins}/lang-python.html[`python`]
|
||||
|<<modules-scripting-security, no>>
|
||||
|{plugins}/lang-python.html[`lang-python`]
|
||||
|
||||
|=======================================================================
|
||||
|
@ -49,23 +54,35 @@ certain tasks.
|
|||
[cols="<,<,<,<",options="header",]
|
||||
|=======================================================================
|
||||
|Language
|
||||
|Sandboxed
|
||||
|Required plugin
|
||||
|Purpose
|
||||
|
||||
|<<modules-scripting-expression, `expression`>>
|
||||
|yes
|
||||
|built-in
|
||||
|fast custom ranking and sorting
|
||||
|
||||
|<<search-template, `mustache`>>
|
||||
|yes
|
||||
|built-in
|
||||
|templates
|
||||
|
||||
|<<modules-scripting-native, `java`>>
|
||||
|n/a
|
||||
|you write it!
|
||||
|expert API
|
||||
|
||||
|=======================================================================
|
||||
|
||||
[WARNING]
|
||||
.Scripts and security
|
||||
=================================================
|
||||
|
||||
Languages that are sandboxed are designed with security in mind. However, non-
|
||||
sandboxed languages can be a security issue, please read
|
||||
<<modules-scripting-security, Scripting and security>> for more details.
|
||||
|
||||
=================================================
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
[[modules-scripting-groovy]]
|
||||
=== Groovy Scripting Language
|
||||
|
||||
Groovy is the default scripting language available in Elasticsearch. Although
|
||||
limited by the <<java-security-manager,Java Security Manager>>, only `file`
|
||||
scripts may be used by default.
|
||||
Groovy is the default scripting language available in Elasticsearch. Although
|
||||
limited by the <<java-security-manager,Java Security Manager>>, it is not a
|
||||
sandboxed language and only `file` scripts may be used by default.
|
||||
|
||||
Enabling `inline` or `stored` Groovy scripting is a security risk and should
|
||||
only be considered if your Elasticsearch cluster is protected from the outside
|
||||
|
|
|
@ -64,9 +64,10 @@ script.file: true
|
|||
-----------------------------------
|
||||
|
||||
NOTE: Global scripting settings affect the `mustache` scripting language.
|
||||
<<search-template,Search templates>> internally use the `mustache` language, and
|
||||
will be disabled by default, but they can be enabled/disabled according to
|
||||
fine-grained settings specified in `elasticsearch.yml`.
|
||||
<<search-template,Search templates>> internally use the `mustache` language,
|
||||
and will still be enabled by default as the `mustache` engine is sandboxed,
|
||||
but they will be enabled/disabled according to fine-grained settings
|
||||
specified in `elasticsearch.yml`.
|
||||
|
||||
[[security-script-context]]
|
||||
[float]
|
||||
|
@ -86,9 +87,9 @@ of using the generic `plugin` category. Those operations can be referred to
|
|||
in the following form: `${pluginName}_${operation}`.
|
||||
|
||||
The following example disables scripting for `update` and `plugin` operations,
|
||||
regardless of the script source or language. Scripts can be executed from
|
||||
languages as part of `aggregations`, `search` and plugins execution though,
|
||||
assuming they are enabled in the scripting settings.
|
||||
regardless of the script source or language. Scripts can still be executed
|
||||
from sandboxed languages as part of `aggregations`, `search` and plugins
|
||||
execution though, as the above defaults still get applied.
|
||||
|
||||
[source,yaml]
|
||||
-----------------------------------
|
||||
|
|
|
@ -110,15 +110,15 @@ second version is only compiled once.
|
|||
[[modules-scripting-file-scripts]]
|
||||
=== File-based Scripts
|
||||
|
||||
To increase security, scripts for languages that are not deemed to be safe by
|
||||
default can only be specified in files stored on every node in the cluster. File
|
||||
scripts must be saved in the `scripts` directory whose default location depends
|
||||
on whether you use the <<zip-targz-layout,`zip`/`tar.gz`>>
|
||||
(`$ES_HOME/config/scripts/`), <<rpm-layout,RPM>>, or <<deb-layout,Debian>>
|
||||
package. The default may be changed with the `path.script` setting.
|
||||
To increase security, non-sandboxed languages can only be specified in script
|
||||
files stored on every node in the cluster. File scripts must be saved in the
|
||||
`scripts` directory whose default location depends on whether you use the
|
||||
<<zip-targz-layout,`zip`/`tar.gz`>> (`$ES_HOME/config/scripts/`),
|
||||
<<rpm-layout,RPM>>, or <<deb-layout,Debian>> package. The default may be
|
||||
changed with the `path.script` setting.
|
||||
|
||||
The languages which are assumed to be safe by default are: painless,
|
||||
expressions, and mustache (used for query templates).
|
||||
The languages which are assumed to be safe by default are: `painless`,
|
||||
`expression`, and `mustache` (used for search and query templates).
|
||||
|
||||
Any files placed in the `scripts` directory will be compiled automatically
|
||||
when the node starts up and then <<reload-scripts,every 60 seconds thereafter>>.
|
||||
|
|
|
@ -25,10 +25,10 @@ For more information on how Mustache templating and what kind of templating you
|
|||
can do with it check out the http://mustache.github.io/mustache.5.html[online
|
||||
documentation of the mustache project].
|
||||
|
||||
NOTE: The mustache language is implemented in elasticsearch as a scripting
|
||||
language, hence it obeys settings that may be used to enable or disable scripts
|
||||
per language, source and operation as described in <<enable-dynamic-scripting,
|
||||
scripting docs>>
|
||||
NOTE: The mustache language is implemented in elasticsearch as a sandboxed
|
||||
scripting language, hence it obeys settings that may be used to enable or
|
||||
disable scripts per language, source and operation as described in
|
||||
<<enable-dynamic-scripting, scripting docs>>
|
||||
|
||||
[float]
|
||||
==== More template examples
|
||||
|
|
|
@ -38,6 +38,6 @@ public class ExpressionPlugin extends Plugin {
|
|||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExpressionScriptEngineService.class,
|
||||
ExpressionScriptEngineService.TYPES, ScriptMode.ON));
|
||||
ExpressionScriptEngineService.NAME, ScriptMode.ON));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,8 +70,8 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -36,6 +36,6 @@ public class GroovyPlugin extends Plugin {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(GroovyScriptEngineService.class, GroovyScriptEngineService.TYPES));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(GroovyScriptEngineService.class, GroovyScriptEngineService.NAME));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,8 +161,8 @@ public class GroovyScriptEngineService extends AbstractComponent implements Scri
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -38,6 +38,6 @@ public class MustachePlugin extends Plugin {
|
|||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class,
|
||||
MustacheScriptEngineService.TYPES, ScriptMode.ON));
|
||||
MustacheScriptEngineService.NAME, ScriptMode.ON));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,8 +112,8 @@ public final class MustacheScriptEngineService extends AbstractComponent impleme
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,6 +59,7 @@ 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.ScriptMode;
|
||||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
|
@ -94,7 +95,6 @@ public class TemplateQueryParserTests extends ESTestCase {
|
|||
.put(Environment.PATH_CONF_SETTING.getKey(), this.getDataPath("config"))
|
||||
.put("node.name", getClass().getName())
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
|
||||
.put("script.inline", "true")
|
||||
.build();
|
||||
final Client proxy = (Client) Proxy.newProxyInstance(
|
||||
Client.class.getClassLoader(),
|
||||
|
@ -107,7 +107,7 @@ public class TemplateQueryParserTests extends ESTestCase {
|
|||
ScriptModule scriptModule = new ScriptModule();
|
||||
scriptModule.prepareSettings(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));
|
||||
scriptModule.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class, MustacheScriptEngineService.NAME, ScriptMode.ON));
|
||||
settingsModule.registerSetting(InternalSettingsPlugin.VERSION_CREATED);
|
||||
injector = new ModulesBuilder().add(
|
||||
new EnvironmentModule(new Environment(settings)),
|
||||
|
|
|
@ -41,6 +41,6 @@ public final class PainlessPlugin extends Plugin {
|
|||
|
||||
public void onModule(final ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(
|
||||
PainlessScriptEngineService.class, PainlessScriptEngineService.TYPES, ScriptMode.ON));
|
||||
PainlessScriptEngineService.class, PainlessScriptEngineService.NAME, ScriptMode.ON));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,8 +103,8 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme
|
|||
* @return Always contains only the single name of the language.
|
||||
*/
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,6 +45,6 @@ public class JavaScriptPlugin extends Plugin {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(JavaScriptScriptEngineService.class, JavaScriptScriptEngineService.TYPES));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(JavaScriptScriptEngineService.class, JavaScriptScriptEngineService.NAME));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,9 @@ 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"));
|
||||
public static final String NAME = "javascript";
|
||||
|
||||
public static final List<String> EXTENSIONS = Collections.unmodifiableList(Arrays.asList("js", "javascript"));
|
||||
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
|
||||
|
@ -159,13 +161,13 @@ public class JavaScriptScriptEngineService extends AbstractComponent implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExtensions() {
|
||||
return Collections.unmodifiableList(Arrays.asList("js"));
|
||||
return EXTENSIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
script:
|
||||
script:
|
||||
inline: "doc['num1'].value > 1"
|
||||
lang: js
|
||||
lang: javascript
|
||||
script_fields:
|
||||
sNum1:
|
||||
script:
|
||||
inline: "doc['num1'].value"
|
||||
lang: js
|
||||
lang: javascript
|
||||
sort:
|
||||
num1:
|
||||
order: asc
|
||||
|
@ -52,7 +52,7 @@
|
|||
script:
|
||||
script:
|
||||
inline: "doc['num1'].value > param1"
|
||||
lang: js
|
||||
lang: javascript
|
||||
params:
|
||||
param1: 1
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
|||
sNum1:
|
||||
script:
|
||||
inline: "doc['num1'].value"
|
||||
lang: js
|
||||
lang: javascript
|
||||
sort:
|
||||
num1:
|
||||
order: asc
|
||||
|
@ -77,7 +77,7 @@
|
|||
script:
|
||||
script:
|
||||
inline: "doc['num1'].value > param1"
|
||||
lang: js
|
||||
lang: javascript
|
||||
params:
|
||||
param1: -1
|
||||
|
||||
|
@ -85,7 +85,7 @@
|
|||
sNum1:
|
||||
script:
|
||||
inline: "doc['num1'].value"
|
||||
lang: js
|
||||
lang: javascript
|
||||
sort:
|
||||
num1:
|
||||
order: asc
|
||||
|
@ -123,19 +123,19 @@
|
|||
s_obj1:
|
||||
script:
|
||||
inline: "_source.obj1"
|
||||
lang: js
|
||||
lang: javascript
|
||||
s_obj1_test:
|
||||
script:
|
||||
inline: "_source.obj1.test"
|
||||
lang: js
|
||||
lang: javascript
|
||||
s_obj2:
|
||||
script:
|
||||
inline: "_source.obj2"
|
||||
lang: js
|
||||
lang: javascript
|
||||
s_obj2_arr2:
|
||||
script:
|
||||
inline: "_source.obj2.arr2"
|
||||
lang: js
|
||||
lang: javascript
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0.fields.s_obj1.0.test: something }
|
||||
|
@ -175,7 +175,7 @@
|
|||
"functions": [{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "doc['num1'].value"
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +197,7 @@
|
|||
"functions": [{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "-doc['num1'].value"
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@
|
|||
"functions": [{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "Math.pow(doc['num1'].value, 2)"
|
||||
}
|
||||
}
|
||||
|
@ -241,7 +241,7 @@
|
|||
"functions": [{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "Math.max(doc['num1'].value, 1)"
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +263,7 @@
|
|||
"functions": [{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "doc['num1'].value * _score"
|
||||
}
|
||||
}
|
||||
|
@ -285,7 +285,7 @@
|
|||
"functions": [{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "param1 * param2 * _score",
|
||||
"params": {
|
||||
"param1": 2,
|
||||
|
@ -322,14 +322,14 @@
|
|||
{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "1"
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "_score.doubleValue()"
|
||||
}
|
||||
}
|
||||
|
@ -338,7 +338,7 @@
|
|||
"functions": [{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "_score.doubleValue()"
|
||||
}
|
||||
}
|
||||
|
@ -370,7 +370,7 @@
|
|||
"functions": [{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "js",
|
||||
"lang": "javascript",
|
||||
"inline": "_score.doubleValue()"
|
||||
}
|
||||
}
|
||||
|
@ -379,7 +379,7 @@
|
|||
score_agg:
|
||||
terms:
|
||||
script:
|
||||
lang: js
|
||||
lang: javascript
|
||||
inline: "_score.doubleValue()"
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
@ -408,7 +408,7 @@
|
|||
foobar:
|
||||
script:
|
||||
inline: "doc['f'].values.length"
|
||||
lang: js
|
||||
lang: javascript
|
||||
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
|
|
@ -40,6 +40,6 @@ public class PythonPlugin extends Plugin {
|
|||
}
|
||||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PythonScriptEngineService.class, PythonScriptEngineService.TYPES));
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PythonScriptEngineService.class, PythonScriptEngineService.TYPE));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ 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"));
|
||||
public static final String TYPE = "python";
|
||||
|
||||
private final PythonInterpreter interp;
|
||||
|
||||
|
@ -96,8 +96,8 @@ public class PythonScriptEngineService extends AbstractComponent implements Scri
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.elasticsearch.env.Environment;
|
|||
import org.elasticsearch.ingest.core.TemplateService;
|
||||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptMode;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
|
@ -43,8 +44,11 @@ public abstract class AbstractMustacheTestCase extends ESTestCase {
|
|||
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), false)
|
||||
.build();
|
||||
MustacheScriptEngineService mustache = new MustacheScriptEngineService(settings);
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(
|
||||
new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class, MustacheScriptEngineService.TYPES)));
|
||||
ScriptEngineRegistry scriptEngineRegistry =
|
||||
new ScriptEngineRegistry(Collections.singletonList(
|
||||
new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class,
|
||||
MustacheScriptEngineService.NAME,
|
||||
ScriptMode.ON)));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
ScriptService scriptService = new ScriptService(settings, new Environment(settings), Collections.singleton(mustache), null,
|
||||
|
|
|
@ -57,14 +57,14 @@ public class MockScriptEngine implements ScriptEngineService {
|
|||
|
||||
public void onModule(ScriptModule module) {
|
||||
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class,
|
||||
MockScriptEngine.TYPES, ScriptMode.ON));
|
||||
MockScriptEngine.NAME, ScriptMode.ON));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypes() {
|
||||
return TYPES;
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1622,7 +1622,9 @@ 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")
|
||||
// wait short time for other active shards before actually deleting, default 30s not needed in tests
|
||||
.put("script.stored", "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();
|
||||
}
|
||||
|
|
|
@ -178,6 +178,9 @@ public abstract class ESSingleNodeTestCase extends ESTestCase {
|
|||
// This needs to tie into the ESIntegTestCase#indexSettings() method
|
||||
.put(Environment.PATH_SHARED_DATA_SETTING.getKey(), createTempDir().getParent())
|
||||
.put("node.name", nodeName())
|
||||
|
||||
.put("script.inline", "true")
|
||||
.put("script.stored", "true")
|
||||
.put(EsExecutors.PROCESSORS_SETTING.getKey(), 1) // limit the number of threads created
|
||||
.put("http.enabled", false)
|
||||
.put(Node.NODE_LOCAL_SETTING.getKey(), true)
|
||||
|
|
Loading…
Reference in New Issue