Do script compilation validation at parse time.
This change will attempt to compile scripts at construction time and throw an exception if a script is bad or missing. With this change the script is compiled at Executable ctor and then the compiled script is used to get the executable. Fixes elastic/elasticsearch#262 Original commit: elastic/x-pack-elasticsearch@b49c9debf2
This commit is contained in:
parent
5c3d94076e
commit
274b01998c
|
@ -102,6 +102,7 @@ public class WatcherService extends AbstractComponent {
|
|||
}
|
||||
return result.indexResponse();
|
||||
} catch (Exception e) {
|
||||
logger.warn("failed to put watch [{}]", e, id);
|
||||
throw new WatcherException("failed to put watch [{}]", e, id);
|
||||
} finally {
|
||||
lock.release();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.watcher.condition.script;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.script.CompiledScript;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.groovy.GroovyScriptExecutionException;
|
||||
import org.elasticsearch.watcher.condition.ExecutableCondition;
|
||||
|
@ -14,6 +15,7 @@ import org.elasticsearch.watcher.support.Variables;
|
|||
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class executes a script against the ctx payload and returns a boolean
|
||||
|
@ -21,16 +23,26 @@ import java.io.IOException;
|
|||
public class ExecutableScriptCondition extends ExecutableCondition<ScriptCondition, ScriptCondition.Result> {
|
||||
|
||||
private final ScriptServiceProxy scriptService;
|
||||
private final CompiledScript compiledScript;
|
||||
|
||||
public ExecutableScriptCondition(ScriptCondition condition, ESLogger logger, ScriptServiceProxy scriptService) {
|
||||
super(condition, logger);
|
||||
this.scriptService = scriptService;
|
||||
try {
|
||||
compiledScript = scriptService.compile(condition.script);
|
||||
} catch (Exception e) {
|
||||
throw new ScriptConditionValidationException("failed to compile script [{}] with lang [{}] of type [{}]", e, condition.script.script(), condition.script.lang(), condition.script.type(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptCondition.Result execute(WatchExecutionContext ctx) throws IOException {
|
||||
try {
|
||||
ExecutableScript executable = scriptService.executable(condition.script, Variables.createCtxModel(ctx, ctx.payload()));
|
||||
Map<String, Object> parameters = Variables.createCtxModel(ctx, ctx.payload());
|
||||
if (condition.script.params() != null && !condition.script.params().isEmpty()) {
|
||||
parameters.putAll(condition.script.params());
|
||||
}
|
||||
ExecutableScript executable = scriptService.executable(compiledScript, parameters);
|
||||
Object value = executable.run();
|
||||
if (value instanceof Boolean) {
|
||||
return (Boolean) value ? ScriptCondition.Result.MET : ScriptCondition.Result.UNMET;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.watcher.condition.script;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ScriptConditionValidationException extends ScriptConditionException {
|
||||
|
||||
public ScriptConditionValidationException(String msg, Object... args) {
|
||||
super(msg, args);
|
||||
}
|
||||
|
||||
public ScriptConditionValidationException(String msg, Throwable cause, Object... args) {
|
||||
super(msg, cause, args);
|
||||
}
|
||||
}
|
|
@ -7,12 +7,12 @@ package org.elasticsearch.watcher.support.init.proxy;
|
|||
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.script.CompiledScript;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
import org.elasticsearch.watcher.support.Script;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.init.InitializingService;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -39,6 +39,18 @@ public class ScriptServiceProxy implements InitializingService.Initializable {
|
|||
this.service = injector.getInstance(ScriptService.class);
|
||||
}
|
||||
|
||||
public CompiledScript compile(String lang, String script, ScriptService.ScriptType scriptType) {
|
||||
return service.compile(lang, script, scriptType);
|
||||
}
|
||||
|
||||
public CompiledScript compile(Script script) {
|
||||
return compile(script.lang(), script.script(), script.type());
|
||||
}
|
||||
|
||||
public ExecutableScript executable(CompiledScript compiledScript, Map<String, Object> vars) {
|
||||
return service.executable(compiledScript, vars);
|
||||
}
|
||||
|
||||
public ExecutableScript executable(Script script, Map<String, Object> vars) {
|
||||
if (script.params() != null && !script.params().isEmpty()) {
|
||||
vars = ImmutableMap.<String, Object>builder()
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.watcher.transform.script;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.script.CompiledScript;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Script;
|
||||
|
@ -25,10 +26,17 @@ import static org.elasticsearch.watcher.support.Variables.createCtxModel;
|
|||
public class ExecutableScriptTransform extends ExecutableTransform<ScriptTransform, ScriptTransform.Result> {
|
||||
|
||||
private final ScriptServiceProxy scriptService;
|
||||
private final CompiledScript compiledScript;
|
||||
|
||||
public ExecutableScriptTransform(ScriptTransform transform, ESLogger logger, ScriptServiceProxy scriptService) {
|
||||
super(transform, logger);
|
||||
this.scriptService = scriptService;
|
||||
Script script = transform.getScript();
|
||||
try {
|
||||
compiledScript = scriptService.compile(script);
|
||||
} catch (Exception e) {
|
||||
throw new ScriptTransformValidationException("failed to compile script [{}] with lang [{}] of type [{}]", e, script.script(), script.lang(), script.type(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,7 +45,7 @@ public class ExecutableScriptTransform extends ExecutableTransform<ScriptTransfo
|
|||
Map<String, Object> model = new HashMap<>();
|
||||
model.putAll(script.params());
|
||||
model.putAll(createCtxModel(ctx, payload));
|
||||
ExecutableScript executable = scriptService.executable(script.lang(), script.script(), script.type(), model);
|
||||
ExecutableScript executable = scriptService.executable(compiledScript, model);
|
||||
Object value = executable.run();
|
||||
if (value instanceof Map) {
|
||||
return new ScriptTransform.Result(new Payload.Simple((Map<String, Object>) value));
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.watcher.transform.script;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ScriptTransformValidationException extends ScriptTransformException {
|
||||
|
||||
public ScriptTransformValidationException(String msg, Object... args) {
|
||||
super(msg, args);
|
||||
}
|
||||
|
||||
public ScriptTransformValidationException(String msg, Throwable cause, Object... args) {
|
||||
super(msg, cause, args);
|
||||
}
|
||||
}
|
|
@ -16,13 +16,8 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.node.settings.NodeSettingsService;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.watcher.actions.ActionException;
|
||||
import org.elasticsearch.watcher.actions.email.service.*;
|
||||
import org.elasticsearch.watcher.execution.TriggeredExecutionContext;
|
||||
|
@ -37,7 +32,6 @@ import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
|||
import org.elasticsearch.watcher.support.secret.SecretService;
|
||||
import org.elasticsearch.watcher.support.template.Template;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.support.template.xmustache.XMustacheScriptEngineService;
|
||||
import org.elasticsearch.watcher.support.template.xmustache.XMustacheTemplateEngine;
|
||||
import org.elasticsearch.watcher.test.WatcherTestUtils;
|
||||
import org.elasticsearch.watcher.trigger.schedule.ScheduleTriggerEvent;
|
||||
|
@ -51,9 +45,7 @@ import org.junit.Test;
|
|||
import javax.mail.internet.AddressException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.common.joda.time.DateTimeZone.UTC;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
|
@ -89,10 +81,7 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
|||
public void init() throws IOException {
|
||||
tp = new ThreadPool(ThreadPool.Names.SAME);
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
XMustacheScriptEngineService mustacheScriptEngineService = new XMustacheScriptEngineService(settings);
|
||||
Set<ScriptEngineService> engineServiceSet = new HashSet<>();
|
||||
engineServiceSet.add(mustacheScriptEngineService);
|
||||
scriptService = ScriptServiceProxy.of(new ScriptService(settings, new Environment(), engineServiceSet, new ResourceWatcherService(settings, tp), new NodeSettingsService(settings)));
|
||||
scriptService = WatcherTestUtils.getScriptServiceProxy(tp);
|
||||
templateEngine = new XMustacheTemplateEngine(settings, scriptService);
|
||||
secretService = mock(SecretService.class);
|
||||
testBody = new Template(TEST_BODY_STRING );
|
||||
|
|
|
@ -11,20 +11,14 @@ import org.elasticsearch.action.search.ShardSearchFailure;
|
|||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.node.settings.NodeSettingsService;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.groovy.GroovyScriptEngineService;
|
||||
import org.elasticsearch.search.internal.InternalSearchResponse;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Script;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
||||
|
@ -34,11 +28,10 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.common.joda.time.DateTimeZone.UTC;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.watcher.test.WatcherTestUtils.getScriptServiceProxy;
|
||||
import static org.elasticsearch.watcher.test.WatcherTestUtils.mockExecutionContext;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
|
@ -165,6 +158,42 @@ public class ScriptConditionTests extends ElasticsearchTestCase {
|
|||
fail("expected a condition exception trying to parse an invalid condition XContent");
|
||||
}
|
||||
|
||||
@Test(expected = ScriptConditionValidationException.class)
|
||||
@Repeat(iterations = 3)
|
||||
public void testScriptConditionParser_badScript() throws Exception {
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(ImmutableSettings.settingsBuilder().build(), getScriptServiceProxy(tp));
|
||||
ScriptService.ScriptType scriptType = randomFrom(ScriptService.ScriptType.values());
|
||||
String script;
|
||||
switch (scriptType) {
|
||||
case INDEXED:
|
||||
case FILE:
|
||||
script = "nonExisting_script";
|
||||
break;
|
||||
case INLINE:
|
||||
default:
|
||||
script = "foo = = 1";
|
||||
}
|
||||
XContentBuilder builder = createConditionContent(script, "groovy", scriptType);
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptCondition scriptCondition = conditionParser.parseCondition("_watch", parser);
|
||||
conditionParser.createExecutable(scriptCondition);
|
||||
fail("expected a condition validation exception trying to create an executable with a bad or missing script");
|
||||
}
|
||||
|
||||
@Test(expected = ScriptConditionValidationException.class)
|
||||
public void testScriptConditionParser_badLang() throws Exception {
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(ImmutableSettings.settingsBuilder().build(), getScriptServiceProxy(tp));
|
||||
ScriptService.ScriptType scriptType = ScriptService.ScriptType.INLINE;
|
||||
String script = "return true";
|
||||
XContentBuilder builder = createConditionContent(script, "not_a_valid_lang", scriptType);
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptCondition scriptCondition = conditionParser.parseCondition("_watch", parser);
|
||||
conditionParser.createExecutable(scriptCondition);
|
||||
fail("expected a condition validation exception trying to create an executable with an invalid language");
|
||||
}
|
||||
|
||||
@Test(expected = ScriptConditionException.class)
|
||||
public void testScriptCondition_throwException() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
|
@ -172,7 +201,7 @@ public class ScriptConditionTests extends ElasticsearchTestCase {
|
|||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500l, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
condition.execute(ctx);
|
||||
fail();
|
||||
fail("expected a ScriptConditionException trying to execute a script that throws an exception");
|
||||
}
|
||||
|
||||
@Test(expected = ScriptConditionException.class)
|
||||
|
@ -183,6 +212,7 @@ public class ScriptConditionTests extends ElasticsearchTestCase {
|
|||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
condition.execute(ctx);
|
||||
fail();
|
||||
fail("expected a ScriptConditionException trying to execute a script that returns an object");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -195,18 +225,6 @@ public class ScriptConditionTests extends ElasticsearchTestCase {
|
|||
assertThat(condition.execute(ctx).met(), is(true));
|
||||
}
|
||||
|
||||
|
||||
private static ScriptServiceProxy getScriptServiceProxy(ThreadPool tp) throws IOException {
|
||||
Settings settings = ImmutableSettings.settingsBuilder()
|
||||
.put(ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING, "none")
|
||||
.build();
|
||||
GroovyScriptEngineService groovyScriptEngineService = new GroovyScriptEngineService(settings);
|
||||
Set<ScriptEngineService> engineServiceSet = new HashSet<>();
|
||||
engineServiceSet.add(groovyScriptEngineService);
|
||||
NodeSettingsService nodeSettingsService = new NodeSettingsService(settings);
|
||||
return ScriptServiceProxy.of(new ScriptService(settings, new Environment(), engineServiceSet, new ResourceWatcherService(settings, tp), nodeSettingsService));
|
||||
}
|
||||
|
||||
private static XContentBuilder createConditionContent(String script, String scriptLang, ScriptService.ScriptType scriptType) throws IOException {
|
||||
XContentBuilder builder = jsonBuilder().startObject();
|
||||
builder.field("script", script);
|
||||
|
@ -219,5 +237,4 @@ public class ScriptConditionTests extends ElasticsearchTestCase {
|
|||
return builder.endObject();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,10 +12,18 @@ import org.elasticsearch.common.collect.ImmutableMap;
|
|||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.node.settings.NodeSettingsService;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.groovy.GroovyScriptEngineService;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.actions.email.EmailAction;
|
||||
|
@ -42,9 +50,10 @@ import org.elasticsearch.watcher.support.http.HttpRequestTemplate;
|
|||
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
||||
import org.elasticsearch.watcher.support.secret.Secret;
|
||||
import org.elasticsearch.watcher.support.template.xmustache.XMustacheTemplateEngine;
|
||||
import org.elasticsearch.watcher.support.template.Template;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.support.template.xmustache.XMustacheScriptEngineService;
|
||||
import org.elasticsearch.watcher.support.template.xmustache.XMustacheTemplateEngine;
|
||||
import org.elasticsearch.watcher.transform.search.ExecutableSearchTransform;
|
||||
import org.elasticsearch.watcher.transform.search.SearchTransform;
|
||||
import org.elasticsearch.watcher.trigger.TriggerEvent;
|
||||
|
@ -54,10 +63,8 @@ import org.elasticsearch.watcher.watch.Payload;
|
|||
import org.elasticsearch.watcher.watch.Watch;
|
||||
|
||||
import javax.mail.internet.AddressException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
|
||||
|
@ -190,4 +197,18 @@ public final class WatcherTestUtils {
|
|||
new Watch.Status());
|
||||
}
|
||||
|
||||
|
||||
public static ScriptServiceProxy getScriptServiceProxy(ThreadPool tp) throws IOException {
|
||||
Settings settings = ImmutableSettings.settingsBuilder()
|
||||
.put(ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING, "none")
|
||||
.build();
|
||||
GroovyScriptEngineService groovyScriptEngineService = new GroovyScriptEngineService(settings);
|
||||
XMustacheScriptEngineService mustacheScriptEngineService = new XMustacheScriptEngineService(settings);
|
||||
Set<ScriptEngineService> engineServiceSet = new HashSet<>();
|
||||
engineServiceSet.add(mustacheScriptEngineService);
|
||||
engineServiceSet.add(groovyScriptEngineService);
|
||||
NodeSettingsService nodeSettingsService = new NodeSettingsService(settings);
|
||||
return ScriptServiceProxy.of(new ScriptService(settings, new Environment(), engineServiceSet, new ResourceWatcherService(settings, tp), nodeSettingsService));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,29 +7,36 @@ package org.elasticsearch.watcher.transform;
|
|||
|
||||
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.collect.ImmutableList;
|
||||
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.collect.ImmutableSet;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.transform.script.ExecutableScriptTransform;
|
||||
import org.elasticsearch.watcher.transform.script.ScriptTransform;
|
||||
import org.elasticsearch.watcher.transform.script.ScriptTransformFactory;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
import org.elasticsearch.watcher.support.Script;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
||||
import com.carrotsearch.randomizedtesting.annotations.Repeat;
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.script.CompiledScript;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Script;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
||||
import org.elasticsearch.watcher.transform.script.ExecutableScriptTransform;
|
||||
import org.elasticsearch.watcher.transform.script.ScriptTransform;
|
||||
import org.elasticsearch.watcher.transform.script.ScriptTransformFactory;
|
||||
import org.elasticsearch.watcher.transform.script.ScriptTransformValidationException;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.watcher.test.WatcherTestUtils.*;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.watcher.test.WatcherTestUtils.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -39,12 +46,27 @@ import static org.mockito.Mockito.when;
|
|||
*/
|
||||
public class ScriptTransformTests extends ElasticsearchTestCase {
|
||||
|
||||
ThreadPool tp = null;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
tp = new ThreadPool(ThreadPool.Names.SAME);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
tp.shutdownNow();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testApply_MapValue() throws Exception {
|
||||
ScriptServiceProxy service = mock(ScriptServiceProxy.class);
|
||||
ScriptService.ScriptType type = randomFrom(ScriptService.ScriptType.values());
|
||||
Map<String, Object> params = Collections.emptyMap();
|
||||
Script script = new Script("_script", type, "_lang", params);
|
||||
CompiledScript compiledScript = mock(CompiledScript.class);
|
||||
when(service.compile(script)).thenReturn(compiledScript);
|
||||
ExecutableScriptTransform transform = new ExecutableScriptTransform(new ScriptTransform(script), logger, service);
|
||||
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", EMPTY_PAYLOAD);
|
||||
|
@ -59,7 +81,7 @@ public class ScriptTransformTests extends ElasticsearchTestCase {
|
|||
|
||||
ExecutableScript executable = mock(ExecutableScript.class);
|
||||
when(executable.run()).thenReturn(transformed);
|
||||
when(service.executable("_lang", "_script", type, model)).thenReturn(executable);
|
||||
when(service.executable(compiledScript, model)).thenReturn(executable);
|
||||
|
||||
Transform.Result result = transform.execute(ctx, payload);
|
||||
assertThat(result, notNullValue());
|
||||
|
@ -70,9 +92,12 @@ public class ScriptTransformTests extends ElasticsearchTestCase {
|
|||
@Test
|
||||
public void testApply_NonMapValue() throws Exception {
|
||||
ScriptServiceProxy service = mock(ScriptServiceProxy.class);
|
||||
|
||||
ScriptService.ScriptType type = randomFrom(ScriptService.ScriptType.values());
|
||||
Map<String, Object> params = Collections.emptyMap();
|
||||
Script script = new Script("_script", type, "_lang", params);
|
||||
CompiledScript compiledScript = mock(CompiledScript.class);
|
||||
when(service.compile(script)).thenReturn(compiledScript);
|
||||
ExecutableScriptTransform transform = new ExecutableScriptTransform(new ScriptTransform(script), logger, service);
|
||||
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", EMPTY_PAYLOAD);
|
||||
|
@ -82,9 +107,9 @@ public class ScriptTransformTests extends ElasticsearchTestCase {
|
|||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
ExecutableScript executable = mock(ExecutableScript.class);
|
||||
Object value = randomFrom("value", 1, new String[] { "value" }, ImmutableList.of("value"), ImmutableSet.of("value"));
|
||||
Object value = randomFrom("value", 1, new String[]{"value"}, ImmutableList.of("value"), ImmutableSet.of("value"));
|
||||
when(executable.run()).thenReturn(value);
|
||||
when(service.executable("_lang", "_script", type, model)).thenReturn(executable);
|
||||
when(service.executable(compiledScript, model)).thenReturn(executable);
|
||||
|
||||
Transform.Result result = transform.execute(ctx, payload);
|
||||
assertThat(result, notNullValue());
|
||||
|
@ -120,4 +145,56 @@ public class ScriptTransformTests extends ElasticsearchTestCase {
|
|||
ExecutableScriptTransform transform = new ScriptTransformFactory(ImmutableSettings.EMPTY, service).parseExecutable("_id", parser);
|
||||
assertThat(transform.transform().getScript(), equalTo(new Script("_script", ScriptService.ScriptType.INLINE, ScriptService.DEFAULT_LANG, ImmutableMap.<String, Object>of())));
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = ScriptTransformValidationException.class)
|
||||
@Repeat(iterations = 3)
|
||||
public void testScriptConditionParser_badScript() throws Exception {
|
||||
ScriptTransformFactory transformFactory = new ScriptTransformFactory(ImmutableSettings.settingsBuilder().build(), getScriptServiceProxy(tp));
|
||||
ScriptService.ScriptType scriptType = randomFrom(ScriptService.ScriptType.values());
|
||||
String script;
|
||||
switch (scriptType) {
|
||||
case INDEXED:
|
||||
case FILE:
|
||||
script = "nonExisting_script";
|
||||
break;
|
||||
case INLINE:
|
||||
default:
|
||||
script = "foo = = 1";
|
||||
}
|
||||
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.field("script", script)
|
||||
.field("lang", "groovy")
|
||||
.field("type", scriptType.name())
|
||||
.startObject("params").field("key", "value").endObject()
|
||||
.endObject();
|
||||
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptTransform scriptTransform = transformFactory.parseTransform("_watch", parser);
|
||||
transformFactory.createExecutable(scriptTransform);
|
||||
fail("expected a transform validation exception trying to create an executable with a bad or missing script");
|
||||
}
|
||||
|
||||
@Test(expected = ScriptTransformValidationException.class)
|
||||
public void testScriptConditionParser_badLang() throws Exception {
|
||||
ScriptTransformFactory transformFactory = new ScriptTransformFactory(ImmutableSettings.settingsBuilder().build(), getScriptServiceProxy(tp));
|
||||
ScriptService.ScriptType scriptType = ScriptService.ScriptType.INLINE;
|
||||
String script = "return true";
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.field("script", script)
|
||||
.field("lang", "not_a_valid_lang")
|
||||
.field("type", scriptType.name())
|
||||
.startObject("params").field("key", "value").endObject()
|
||||
.endObject();
|
||||
|
||||
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptTransform scriptCondition = transformFactory.parseTransform("_watch", parser);
|
||||
transformFactory.createExecutable(scriptCondition);
|
||||
fail("expected a transform validation exception trying to create an executable with an invalid language");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue