Scripting: Add watcher script contexts (#34059)
This commit removes the use of ExecutableScript from watcher in favor of custom script contexts for both watcher condition scripts and transform scripts.
This commit is contained in:
parent
0c3846d3d5
commit
95977f4db9
|
@ -19,11 +19,12 @@
|
|||
|
||||
package org.elasticsearch.script;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||
|
||||
public final class ParameterMap implements Map<String, Object> {
|
||||
|
||||
|
@ -34,7 +35,7 @@ public final class ParameterMap implements Map<String, Object> {
|
|||
|
||||
private final Map<String, String> deprecations;
|
||||
|
||||
ParameterMap(Map<String, Object> params, Map<String, String> deprecations) {
|
||||
public ParameterMap(Map<String, Object> params, Map<String, String> deprecations) {
|
||||
this.params = params;
|
||||
this.deprecations = deprecations;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.elasticsearch.plugins.ReloadablePlugin;
|
|||
import org.elasticsearch.plugins.ScriptPlugin;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
|
@ -106,6 +105,7 @@ import org.elasticsearch.xpack.watcher.condition.CompareCondition;
|
|||
import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.NeverCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.WatcherConditionScript;
|
||||
import org.elasticsearch.xpack.watcher.execution.AsyncTriggerEventConsumer;
|
||||
import org.elasticsearch.xpack.watcher.execution.ExecutionService;
|
||||
import org.elasticsearch.xpack.watcher.execution.InternalWatchExecutor;
|
||||
|
@ -152,6 +152,7 @@ import org.elasticsearch.xpack.watcher.support.WatcherIndexTemplateRegistry;
|
|||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||
import org.elasticsearch.xpack.watcher.transform.script.ScriptTransform;
|
||||
import org.elasticsearch.xpack.watcher.transform.script.ScriptTransformFactory;
|
||||
import org.elasticsearch.xpack.watcher.transform.script.WatcherTransformScript;
|
||||
import org.elasticsearch.xpack.watcher.transform.search.SearchTransform;
|
||||
import org.elasticsearch.xpack.watcher.transform.search.SearchTransformFactory;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.ack.TransportAckWatchAction;
|
||||
|
@ -225,9 +226,6 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
|
|||
|
||||
public static final ScriptContext<SearchScript.Factory> SCRIPT_SEARCH_CONTEXT =
|
||||
new ScriptContext<>("xpack", SearchScript.Factory.class);
|
||||
// TODO: remove this context when each xpack script use case has their own contexts
|
||||
public static final ScriptContext<ExecutableScript.Factory> SCRIPT_EXECUTABLE_CONTEXT
|
||||
= new ScriptContext<>("xpack_executable", ExecutableScript.Factory.class);
|
||||
public static final ScriptContext<TemplateScript.Factory> SCRIPT_TEMPLATE_CONTEXT
|
||||
= new ScriptContext<>("xpack_template", TemplateScript.Factory.class);
|
||||
|
||||
|
@ -673,7 +671,8 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
|
|||
|
||||
@Override
|
||||
public List<ScriptContext<?>> getContexts() {
|
||||
return Arrays.asList(Watcher.SCRIPT_SEARCH_CONTEXT, Watcher.SCRIPT_EXECUTABLE_CONTEXT, Watcher.SCRIPT_TEMPLATE_CONTEXT);
|
||||
return Arrays.asList(Watcher.SCRIPT_SEARCH_CONTEXT, WatcherTransformScript.CONTEXT,
|
||||
WatcherConditionScript.CONTEXT, Watcher.SCRIPT_TEMPLATE_CONTEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -41,7 +41,7 @@ public class ExecutableEmailAction extends ExecutableAction<EmailAction> {
|
|||
}
|
||||
|
||||
public Action.Result execute(String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
|
||||
Map<String, Attachment> attachments = new HashMap<>();
|
||||
DataAttachment dataAttachment = action.getDataAttachment();
|
||||
|
|
|
@ -39,7 +39,7 @@ public class ExecutableHipChatAction extends ExecutableAction<HipChatAction> {
|
|||
// watch/action were created.
|
||||
account.validateParsedTemplate(ctx.id().watchId(), actionId, action.message);
|
||||
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
HipChatMessage message = account.render(ctx.id().watchId(), actionId, templateEngine, action.message, model);
|
||||
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
|
|
|
@ -42,7 +42,7 @@ public class ExecutableJiraAction extends ExecutableAction<JiraAction> {
|
|||
throw new IllegalStateException("account [" + action.account + "] was not found. perhaps it was deleted");
|
||||
}
|
||||
|
||||
final Function<String, String> render = s -> engine.render(new TextTemplate(s), Variables.createCtxModel(ctx, payload));
|
||||
final Function<String, String> render = s -> engine.render(new TextTemplate(s), Variables.createCtxParamsMap(ctx, payload));
|
||||
|
||||
Map<String, Object> fields = new HashMap<>();
|
||||
// Apply action fields
|
||||
|
|
|
@ -40,7 +40,7 @@ public class ExecutableLoggingAction extends ExecutableAction<LoggingAction> {
|
|||
|
||||
@Override
|
||||
public Action.Result execute(String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
|
||||
String loggedText = templateEngine.render(action.text, model);
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
|
|
|
@ -40,7 +40,7 @@ public class ExecutablePagerDutyAction extends ExecutableAction<PagerDutyAction>
|
|||
throw new IllegalStateException("account [" + action.event.account + "] was not found. perhaps it was deleted");
|
||||
}
|
||||
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
IncidentEvent event = action.event.render(ctx.watch().id(), actionId, templateEngine, model, account.getDefaults());
|
||||
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
|
|
|
@ -40,7 +40,7 @@ public class ExecutableSlackAction extends ExecutableAction<SlackAction> {
|
|||
throw new IllegalStateException("account [" + action.account + "] was not found. perhaps it was deleted");
|
||||
}
|
||||
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
SlackMessage message = action.message.render(ctx.id().watchId(), actionId, templateEngine, model, account.getMessageDefaults());
|
||||
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ExecutableWebhookAction extends ExecutableAction<WebhookAction> {
|
|||
|
||||
@Override
|
||||
public Action.Result execute(String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
|
||||
HttpRequest request = action.requestTemplate.render(templateEngine, model);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ abstract class AbstractCompareCondition implements ExecutableCondition {
|
|||
@Override
|
||||
public final Result execute(WatchExecutionContext ctx) {
|
||||
Map<String, Object> resolvedValues = new HashMap<>();
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, ctx.payload());
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, ctx.payload());
|
||||
return doExecute(model, resolvedValues);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,19 +8,15 @@ package org.elasticsearch.xpack.watcher.condition;
|
|||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.xpack.core.watcher.condition.ExecutableCondition;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.Watcher;
|
||||
import org.elasticsearch.xpack.watcher.support.Variables;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.xpack.core.watcher.support.Exceptions.illegalState;
|
||||
|
||||
/**
|
||||
* This class executes a script against the ctx payload and returns a boolean
|
||||
*/
|
||||
|
@ -30,16 +26,16 @@ public final class ScriptCondition implements ExecutableCondition {
|
|||
private static final Result UNMET = new Result(null, TYPE, false);
|
||||
|
||||
private final Script script;
|
||||
private final ExecutableScript.Factory scriptFactory;
|
||||
private final WatcherConditionScript.Factory scriptFactory;
|
||||
|
||||
public ScriptCondition(Script script) {
|
||||
this.script = script;
|
||||
scriptFactory = null;
|
||||
this.scriptFactory = null;
|
||||
}
|
||||
|
||||
ScriptCondition(Script script, ExecutableScript.Factory scriptFactory) {
|
||||
ScriptCondition(Script script, ScriptService scriptService) {
|
||||
this.script = script;
|
||||
this.scriptFactory = scriptFactory;
|
||||
this.scriptFactory = scriptService.compile(script, WatcherConditionScript.CONTEXT);
|
||||
}
|
||||
|
||||
public Script getScript() {
|
||||
|
@ -49,7 +45,7 @@ public final class ScriptCondition implements ExecutableCondition {
|
|||
public static ScriptCondition parse(ScriptService scriptService, String watchId, XContentParser parser) throws IOException {
|
||||
try {
|
||||
Script script = Script.parse(parser);
|
||||
return new ScriptCondition(script, scriptService.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT));
|
||||
return new ScriptCondition(script, scriptService);
|
||||
} catch (ElasticsearchParseException pe) {
|
||||
throw new ElasticsearchParseException("could not parse [{}] condition for watch [{}]. failed to parse script", pe, TYPE,
|
||||
watchId);
|
||||
|
@ -62,17 +58,12 @@ public final class ScriptCondition implements ExecutableCondition {
|
|||
}
|
||||
|
||||
public Result doExecute(WatchExecutionContext ctx) {
|
||||
Map<String, Object> parameters = Variables.createCtxModel(ctx, ctx.payload());
|
||||
Map<String, Object> parameters = Variables.createCtxParamsMap(ctx, ctx.payload());
|
||||
if (script.getParams() != null && !script.getParams().isEmpty()) {
|
||||
parameters.putAll(script.getParams());
|
||||
}
|
||||
ExecutableScript executable = scriptFactory.newInstance(parameters);
|
||||
Object value = executable.run();
|
||||
if (value instanceof Boolean) {
|
||||
return (Boolean) value ? MET : UNMET;
|
||||
}
|
||||
throw illegalState("condition [{}] must return a boolean value (true|false) but instead returned [{}]", type(), ctx.watch().id(),
|
||||
script, value);
|
||||
WatcherConditionScript conditionScript = scriptFactory.newInstance(script.getParams(), ctx);
|
||||
return conditionScript.execute() ? MET : UNMET;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.xpack.watcher.condition;
|
||||
|
||||
import org.elasticsearch.script.ParameterMap;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.support.Variables;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A script to determine whether a watch should be run.
|
||||
*/
|
||||
public abstract class WatcherConditionScript {
|
||||
public static final String[] PARAMETERS = {};
|
||||
|
||||
private static final Map<String, String> DEPRECATIONS;
|
||||
|
||||
static {
|
||||
Map<String, String> deprecations = new HashMap<>();
|
||||
deprecations.put(
|
||||
"ctx",
|
||||
"Accessing variable [ctx] via [params.ctx] from within a watcher_condition script " +
|
||||
"is deprecated in favor of directly accessing [ctx]."
|
||||
);
|
||||
DEPRECATIONS = Collections.unmodifiableMap(deprecations);
|
||||
}
|
||||
|
||||
private final Map<String, Object> params;
|
||||
// TODO: ctx should have its members extracted into execute parameters, but it needs to be a member for bwc access in params
|
||||
private final Map<String, Object> ctx;
|
||||
|
||||
public WatcherConditionScript(Map<String, Object> params, WatchExecutionContext watcherContext) {
|
||||
Map<String, Object> paramsWithCtx = new HashMap<>(params);
|
||||
Map<String, Object> ctx = Variables.createCtx(watcherContext, watcherContext.payload());
|
||||
paramsWithCtx.put("ctx", ctx);
|
||||
this.params = new ParameterMap(Collections.unmodifiableMap(paramsWithCtx), DEPRECATIONS);
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public abstract boolean execute();
|
||||
|
||||
public Map<String, Object> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public Map<String, Object> getCtx() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
WatcherConditionScript newInstance(Map<String, Object> params, WatchExecutionContext watcherContext);
|
||||
}
|
||||
|
||||
public static ScriptContext<Factory> CONTEXT = new ScriptContext<>("watcher_condition", Factory.class);
|
||||
}
|
|
@ -44,7 +44,7 @@ public class ExecutableHttpInput extends ExecutableInput<HttpInput, HttpInput.Re
|
|||
public HttpInput.Result execute(WatchExecutionContext ctx, Payload payload) {
|
||||
HttpRequest request = null;
|
||||
try {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
request = input.getRequest().render(templateEngine, model);
|
||||
return doExecute(ctx, request);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -57,7 +57,7 @@ public class DataAttachmentParser implements EmailAttachmentParser<DataAttachmen
|
|||
|
||||
@Override
|
||||
public Attachment toAttachment(WatchExecutionContext ctx, Payload payload, DataAttachment attachment) throws IOException {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
return attachment.getDataAttachment().create(attachment.id(), model);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ public class HttpEmailAttachementParser implements EmailAttachmentParser<HttpReq
|
|||
@Override
|
||||
public Attachment toAttachment(WatchExecutionContext context, Payload payload,
|
||||
HttpRequestAttachment attachment) throws IOException {
|
||||
Map<String, Object> model = Variables.createCtxModel(context, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(context, payload);
|
||||
HttpRequest httpRequest = attachment.getRequestTemplate().render(templateEngine, model);
|
||||
|
||||
HttpResponse response = httpClient.execute(httpRequest);
|
||||
|
|
|
@ -91,7 +91,7 @@ public class ReportingAttachmentParser implements EmailAttachmentParser<Reportin
|
|||
|
||||
@Override
|
||||
public Attachment toAttachment(WatchExecutionContext context, Payload payload, ReportingAttachment attachment) throws IOException {
|
||||
Map<String, Object> model = Variables.createCtxModel(context, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(context, payload);
|
||||
|
||||
String initialUrl = templateEngine.render(new TextTemplate(attachment.url()), model);
|
||||
|
||||
|
|
|
@ -22,7 +22,15 @@ public final class Variables {
|
|||
public static final String METADATA = "metadata";
|
||||
public static final String VARS = "vars";
|
||||
|
||||
public static Map<String, Object> createCtxModel(WatchExecutionContext ctx, Payload payload) {
|
||||
/** Creates a ctx map and puts it into the returned map as "ctx". */
|
||||
public static Map<String, Object> createCtxParamsMap(WatchExecutionContext ctx, Payload payload) {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
model.put(CTX, createCtx(ctx, payload));
|
||||
return model;
|
||||
}
|
||||
|
||||
/** Creates a ctx map. */
|
||||
public static Map<String, Object> createCtx(WatchExecutionContext ctx, Payload payload) {
|
||||
Map<String, Object> ctxModel = new HashMap<>();
|
||||
ctxModel.put(ID, ctx.id().value());
|
||||
ctxModel.put(WATCH_ID, ctx.id().watchId());
|
||||
|
@ -33,10 +41,6 @@ public final class Variables {
|
|||
}
|
||||
ctxModel.put(METADATA, ctx.watch().metadata());
|
||||
ctxModel.put(VARS, ctx.vars());
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
model.put(CTX, ctxModel);
|
||||
return model;
|
||||
return ctxModel;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class WatcherSearchTemplateService extends AbstractComponent {
|
|||
public String renderTemplate(Script source, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
// Due the inconsistency with templates in ES 1.x, we maintain our own template format.
|
||||
// This template format we use now, will become the template structure in ES 2.0
|
||||
Map<String, Object> watcherContextParams = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> watcherContextParams = Variables.createCtxParamsMap(ctx, payload);
|
||||
// Here we convert watcher template into a ES core templates. Due to the different format we use, we
|
||||
// convert to the template format used in ES core
|
||||
if (source.getParams() != null) {
|
||||
|
|
|
@ -8,19 +8,16 @@ package org.elasticsearch.xpack.watcher.transform.script;
|
|||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||
import org.apache.logging.log4j.util.Supplier;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.core.watcher.transform.ExecutableTransform;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Payload;
|
||||
import org.elasticsearch.xpack.watcher.Watcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.xpack.watcher.support.Variables.createCtxModel;
|
||||
import static org.elasticsearch.xpack.watcher.transform.script.ScriptTransform.TYPE;
|
||||
|
||||
public class ExecutableScriptTransform extends ExecutableTransform<ScriptTransform, ScriptTransform.Result> {
|
||||
|
@ -32,7 +29,7 @@ public class ExecutableScriptTransform extends ExecutableTransform<ScriptTransfo
|
|||
this.scriptService = scriptService;
|
||||
Script script = transform.getScript();
|
||||
// try to compile so we catch syntax errors early
|
||||
scriptService.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT);
|
||||
scriptService.compile(script, WatcherTransformScript.CONTEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,14 +44,9 @@ public class ExecutableScriptTransform extends ExecutableTransform<ScriptTransfo
|
|||
|
||||
ScriptTransform.Result doExecute(WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
Script script = transform.getScript();
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
if (script.getParams() != null) {
|
||||
model.putAll(script.getParams());
|
||||
}
|
||||
model.putAll(createCtxModel(ctx, payload));
|
||||
ExecutableScript.Factory factory = scriptService.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT);
|
||||
ExecutableScript executable = factory.newInstance(model);
|
||||
Object value = executable.run();
|
||||
WatcherTransformScript.Factory factory = scriptService.compile(script, WatcherTransformScript.CONTEXT);
|
||||
WatcherTransformScript transformScript = factory.newInstance(script.getParams(), ctx, payload);
|
||||
Object value = transformScript.execute();
|
||||
// TODO: deprecate one of these styles (returning a map or returning an opaque value below)
|
||||
if (value instanceof Map) {
|
||||
return new ScriptTransform.Result(new Payload.Simple((Map<String, Object>) value));
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.xpack.watcher.transform.script;
|
||||
|
||||
import org.elasticsearch.script.ParameterMap;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Payload;
|
||||
import org.elasticsearch.xpack.watcher.support.Variables;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A script to transform the results of a watch execution.
|
||||
*/
|
||||
public abstract class WatcherTransformScript {
|
||||
public static final String[] PARAMETERS = {};
|
||||
|
||||
private static final Map<String, String> DEPRECATIONS;
|
||||
|
||||
static {
|
||||
Map<String, String> deprecations = new HashMap<>();
|
||||
deprecations.put(
|
||||
"ctx",
|
||||
"Accessing variable [ctx] via [params.ctx] from within a watcher_transform script " +
|
||||
"is deprecated in favor of directly accessing [ctx]."
|
||||
);
|
||||
DEPRECATIONS = Collections.unmodifiableMap(deprecations);
|
||||
}
|
||||
|
||||
private final Map<String, Object> params;
|
||||
// TODO: ctx should have its members extracted into execute parameters, but it needs to be a member bwc access in params
|
||||
private final Map<String, Object> ctx;
|
||||
|
||||
public WatcherTransformScript(Map<String, Object> params, WatchExecutionContext watcherContext, Payload payload) {
|
||||
Map<String, Object> paramsWithCtx = new HashMap<>(params);
|
||||
Map<String, Object> ctx = Variables.createCtx(watcherContext, payload);
|
||||
paramsWithCtx.put("ctx", ctx);
|
||||
this.params = new ParameterMap(Collections.unmodifiableMap(paramsWithCtx), DEPRECATIONS);
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public abstract Object execute();
|
||||
|
||||
public Map<String, Object> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public Map<String, Object> getCtx() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
WatcherTransformScript newInstance(Map<String, Object> params, WatchExecutionContext watcherContext, Payload payload);
|
||||
}
|
||||
|
||||
public static ScriptContext<Factory> CONTEXT = new ScriptContext<>("watcher_transform", Factory.class);
|
||||
}
|
|
@ -12,7 +12,6 @@ import org.elasticsearch.script.Script;
|
|||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.watcher.condition.ExecutableCondition;
|
||||
import org.elasticsearch.xpack.watcher.Watcher;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
|
@ -56,7 +55,7 @@ public class AlwaysConditionTests extends ESTestCase {
|
|||
switch (type) {
|
||||
case ScriptCondition.TYPE:
|
||||
Script mockScript = mockScript("_script");
|
||||
return new ScriptCondition(mockScript, scriptService.compile(mockScript, Watcher.SCRIPT_EXECUTABLE_CONTEXT));
|
||||
return new ScriptCondition(mockScript, scriptService);
|
||||
case CompareCondition.TYPE:
|
||||
return new CompareCondition("_path", randomFrom(CompareCondition.Op.values()), randomFrom(5, "3"),
|
||||
Clock.systemUTC());
|
||||
|
|
|
@ -13,15 +13,12 @@ import org.elasticsearch.cluster.ClusterChangedEvent;
|
|||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.script.GeneralScriptException;
|
||||
import org.elasticsearch.script.MockScriptEngine;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptEngine;
|
||||
import org.elasticsearch.script.ScriptException;
|
||||
import org.elasticsearch.script.ScriptMetaData;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
|
@ -30,9 +27,12 @@ import org.elasticsearch.search.internal.InternalSearchResponse;
|
|||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.watcher.condition.ExecutableCondition;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.Wid;
|
||||
import org.elasticsearch.xpack.core.watcher.trigger.TriggerEvent;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Payload;
|
||||
import org.elasticsearch.xpack.watcher.Watcher;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Watch;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherMockScriptPlugin;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.junit.Before;
|
||||
|
@ -51,6 +51,8 @@ import static org.elasticsearch.xpack.core.watcher.support.Exceptions.illegalArg
|
|||
import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.mockExecutionContext;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class ScriptConditionTests extends ESTestCase {
|
||||
|
||||
|
@ -77,15 +79,13 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
return total > 1;
|
||||
});
|
||||
|
||||
scripts.put("ctx.payload.hits.total > threshold", vars -> {
|
||||
scripts.put("ctx.payload.hits.total > params.threshold", vars -> {
|
||||
int total = (int) XContentMapValues.extractValue("ctx.payload.hits.total", vars);
|
||||
int threshold = (int) XContentMapValues.extractValue("threshold", vars);
|
||||
int threshold = (int) XContentMapValues.extractValue("params.threshold", vars);
|
||||
return total > threshold;
|
||||
});
|
||||
|
||||
ScriptEngine engine = new MockScriptEngine(MockScriptEngine.NAME, scripts, Collections.emptyMap());
|
||||
scriptService = new ScriptService(Settings.EMPTY, Collections.singletonMap(engine.getType(), engine),
|
||||
Collections.singletonMap(Watcher.SCRIPT_EXECUTABLE_CONTEXT.name, Watcher.SCRIPT_EXECUTABLE_CONTEXT));
|
||||
scriptService = WatcherMockScriptPlugin.newMockScriptService(scripts);
|
||||
|
||||
ClusterState.Builder clusterState = new ClusterState.Builder(new ClusterName("_name"));
|
||||
clusterState.metaData(MetaData.builder().putCustom(ScriptMetaData.TYPE, new ScriptMetaData.Builder(null).build()));
|
||||
|
@ -94,8 +94,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testExecute() throws Exception {
|
||||
Script script = mockScript("ctx.payload.hits.total > 1");
|
||||
ScriptCondition condition = new ScriptCondition(script, scriptService.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT));
|
||||
ScriptCondition condition = new ScriptCondition(mockScript("ctx.payload.hits.total > 1"), scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 0, 500L, ShardSearchFailure.EMPTY_ARRAY,
|
||||
SearchResponse.Clusters.EMPTY);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
|
@ -103,8 +102,9 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testExecuteMergedParams() throws Exception {
|
||||
Script script = new Script(ScriptType.INLINE, "mockscript", "ctx.payload.hits.total > threshold", singletonMap("threshold", 1));
|
||||
ScriptCondition executable = new ScriptCondition(script, scriptService.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT));
|
||||
Script script = new Script(ScriptType.INLINE, "mockscript",
|
||||
"ctx.payload.hits.total > params.threshold", singletonMap("threshold", 1));
|
||||
ScriptCondition executable = new ScriptCondition(script, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 0, 500L, ShardSearchFailure.EMPTY_ARRAY,
|
||||
SearchResponse.Clusters.EMPTY);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
|
@ -182,9 +182,8 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testScriptConditionThrowException() throws Exception {
|
||||
Script script = mockScript("null.foo");
|
||||
ScriptCondition condition = new ScriptCondition(
|
||||
script, scriptService.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT));
|
||||
mockScript("null.foo"), scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 0, 500L, ShardSearchFailure.EMPTY_ARRAY,
|
||||
SearchResponse.Clusters.EMPTY);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
|
@ -192,20 +191,9 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
assertThat(exception.getMessage(), containsString("Error evaluating null.foo"));
|
||||
}
|
||||
|
||||
public void testScriptConditionReturnObjectThrowsException() throws Exception {
|
||||
Script script = mockScript("return new Object()");
|
||||
ScriptCondition condition = new ScriptCondition(script, scriptService.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT));
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 0, 500L, ShardSearchFailure.EMPTY_ARRAY,
|
||||
SearchResponse.Clusters.EMPTY);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
Exception exception = expectThrows(IllegalStateException.class, () -> condition.execute(ctx));
|
||||
assertThat(exception.getMessage(),
|
||||
containsString("condition [script] must return a boolean value (true|false) but instead returned [_name]"));
|
||||
}
|
||||
|
||||
public void testScriptConditionAccessCtx() throws Exception {
|
||||
Script script = mockScript("ctx.trigger.scheduled_time.getMillis() < new Date().time");
|
||||
ScriptCondition condition = new ScriptCondition(script, scriptService.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT));
|
||||
ScriptCondition condition = new ScriptCondition(mockScript("ctx.trigger.scheduled_time.getMillis() < new Date().time"),
|
||||
scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 0, 500L, ShardSearchFailure.EMPTY_ARRAY,
|
||||
SearchResponse.Clusters.EMPTY);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new DateTime(DateTimeZone.UTC), new Payload.XContent(response));
|
||||
|
@ -213,6 +201,23 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
assertThat(condition.execute(ctx).met(), is(true));
|
||||
}
|
||||
|
||||
public void testParamsCtxDeprecated() throws Exception {
|
||||
WatchExecutionContext watcherContext = mock(WatchExecutionContext.class);
|
||||
when(watcherContext.id()).thenReturn(mock(Wid.class));
|
||||
when(watcherContext.watch()).thenReturn(mock(Watch.class));
|
||||
when(watcherContext.triggerEvent()).thenReturn(mock(TriggerEvent.class));
|
||||
WatcherConditionScript watcherScript = new WatcherConditionScript(Collections.emptyMap(), watcherContext) {
|
||||
@Override
|
||||
public boolean execute() {
|
||||
assertThat(getParams().get("ctx"), is(getCtx()));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
watcherScript.execute();
|
||||
assertWarnings("Accessing variable [ctx] via [params.ctx] from within a watcher_condition script " +
|
||||
"is deprecated in favor of directly accessing [ctx].");
|
||||
}
|
||||
|
||||
private static XContentBuilder createConditionContent(String script, String scriptLang, ScriptType scriptType) throws IOException {
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
if (scriptType == null) {
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
|
|||
import org.elasticsearch.xpack.watcher.condition.NeverCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherMockScriptPlugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -66,7 +67,7 @@ public class HistoryActionConditionTests extends AbstractWatcherIntegrationTestC
|
|||
return types;
|
||||
}
|
||||
|
||||
public static class CustomScriptPlugin extends MockScriptPlugin {
|
||||
public static class CustomScriptPlugin extends WatcherMockScriptPlugin {
|
||||
|
||||
@Override
|
||||
protected Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
|
||||
|
|
|
@ -13,8 +13,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.MockScriptEngine;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptEngine;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
@ -25,7 +23,7 @@ import org.elasticsearch.xpack.core.watcher.transform.ExecutableTransform;
|
|||
import org.elasticsearch.xpack.core.watcher.transform.TransformFactory;
|
||||
import org.elasticsearch.xpack.core.watcher.transform.TransformRegistry;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Payload;
|
||||
import org.elasticsearch.xpack.watcher.Watcher;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherMockScriptPlugin;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherTestUtils;
|
||||
import org.elasticsearch.xpack.watcher.transform.script.ExecutableScriptTransform;
|
||||
import org.elasticsearch.xpack.watcher.transform.script.ScriptTransform;
|
||||
|
@ -33,7 +31,6 @@ import org.elasticsearch.xpack.watcher.transform.script.ScriptTransformFactory;
|
|||
import org.junit.Before;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
|
@ -46,14 +43,7 @@ public class TransformInputTests extends ESTestCase {
|
|||
|
||||
@Before
|
||||
public void setupScriptService() {
|
||||
Map<String, ScriptEngine> engines = new HashMap<>();
|
||||
engines.put(MockScriptEngine.NAME,
|
||||
new MockScriptEngine(MockScriptEngine.NAME, Collections.singletonMap("1", s -> "2"), Collections.emptyMap()));
|
||||
Map<String, ScriptContext<?>> contexts = new HashMap<>();
|
||||
contexts.put(Watcher.SCRIPT_TEMPLATE_CONTEXT.name, Watcher.SCRIPT_TEMPLATE_CONTEXT);
|
||||
contexts.put(Watcher.SCRIPT_SEARCH_CONTEXT.name, Watcher.SCRIPT_SEARCH_CONTEXT);
|
||||
contexts.put(Watcher.SCRIPT_EXECUTABLE_CONTEXT.name, Watcher.SCRIPT_EXECUTABLE_CONTEXT);
|
||||
scriptService = new ScriptService(Settings.EMPTY, engines, contexts);
|
||||
scriptService = WatcherMockScriptPlugin.newMockScriptService(Collections.singletonMap("1", s -> "2"));
|
||||
}
|
||||
|
||||
public void testExecute() {
|
||||
|
|
|
@ -40,7 +40,7 @@ public class VariablesTests extends ESTestCase {
|
|||
.metadata(metatdata)
|
||||
.buildMock();
|
||||
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
assertThat(model, notNullValue());
|
||||
assertThat(model.size(), is(1));
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.xpack.watcher.test;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.script.MockScriptEngine;
|
||||
import org.elasticsearch.script.MockScriptPlugin;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptEngine;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.xpack.watcher.Watcher;
|
||||
import org.elasticsearch.xpack.watcher.condition.WatcherConditionScript;
|
||||
import org.elasticsearch.xpack.watcher.transform.script.WatcherTransformScript;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Provides a mock script engine with mock versions of watcher scripts.
|
||||
*/
|
||||
public abstract class WatcherMockScriptPlugin extends MockScriptPlugin {
|
||||
public static final Map<ScriptContext<?>, MockScriptEngine.ContextCompiler> CONTEXT_COMPILERS;
|
||||
static {
|
||||
Map<ScriptContext<?>, MockScriptEngine.ContextCompiler> compilers = new HashMap<>();
|
||||
compilers.put(WatcherConditionScript.CONTEXT, (script, options) ->
|
||||
(WatcherConditionScript.Factory) (params, watcherContext) ->
|
||||
new WatcherConditionScript(params, watcherContext) {
|
||||
@Override
|
||||
public boolean execute() {
|
||||
Map<String, Object> vars = new HashMap<>();
|
||||
vars.put("params", getParams());
|
||||
vars.put("ctx", getCtx());
|
||||
return (boolean) script.apply(vars);
|
||||
}
|
||||
});
|
||||
compilers.put(WatcherTransformScript.CONTEXT, (script, options) ->
|
||||
(WatcherTransformScript.Factory) (params, watcherContext, payload) ->
|
||||
new WatcherTransformScript(params, watcherContext, payload) {
|
||||
@Override
|
||||
public Object execute() {
|
||||
Map<String, Object> vars = new HashMap<>();
|
||||
vars.put("params", getParams());
|
||||
vars.put("ctx", getCtx());
|
||||
return script.apply(vars);
|
||||
}
|
||||
});
|
||||
CONTEXT_COMPILERS = Collections.unmodifiableMap(compilers);
|
||||
}
|
||||
|
||||
public static final List<ScriptContext<?>> CONTEXTS = Collections.unmodifiableList(Arrays.asList(
|
||||
WatcherConditionScript.CONTEXT, WatcherTransformScript.CONTEXT, Watcher.SCRIPT_TEMPLATE_CONTEXT, Watcher.SCRIPT_SEARCH_CONTEXT
|
||||
));
|
||||
|
||||
@Override
|
||||
protected Map<ScriptContext<?>, MockScriptEngine.ContextCompiler> pluginContextCompilers() {
|
||||
return CONTEXT_COMPILERS;
|
||||
}
|
||||
|
||||
public static ScriptService newMockScriptService(Map<String, Function<Map<String, Object>, Object>> scripts) {
|
||||
Map<String, ScriptEngine> engines = new HashMap<>();
|
||||
engines.put(MockScriptEngine.NAME,
|
||||
new MockScriptEngine(MockScriptEngine.NAME, scripts, CONTEXT_COMPILERS));
|
||||
Map<String, ScriptContext<?>> contexts = CONTEXTS.stream().collect(Collectors.toMap(o -> o.name, Function.identity()));
|
||||
return new ScriptService(Settings.EMPTY, engines, contexts);
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@ import org.elasticsearch.action.search.SearchResponse;
|
|||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.protocol.xpack.watcher.PutWatchResponse;
|
||||
import org.elasticsearch.script.MockScriptPlugin;
|
||||
import org.elasticsearch.xpack.core.watcher.client.WatcherClient;
|
||||
import org.elasticsearch.xpack.core.watcher.support.xcontent.ObjectPath;
|
||||
import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource;
|
||||
import org.elasticsearch.xpack.core.watcher.transport.actions.execute.ExecuteWatchResponse;
|
||||
import org.elasticsearch.xpack.watcher.condition.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherMockScriptPlugin;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -46,7 +46,7 @@ public class ExecutionVarsIntegrationTests extends AbstractWatcherIntegrationTes
|
|||
return types;
|
||||
}
|
||||
|
||||
public static class CustomScriptPlugin extends MockScriptPlugin {
|
||||
public static class CustomScriptPlugin extends WatcherMockScriptPlugin {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.elasticsearch.xpack.watcher.input.search.SearchInputFactory;
|
|||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherTestUtils;
|
||||
import org.elasticsearch.xpack.watcher.transform.script.WatcherTransformScript;
|
||||
import org.junit.Before;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
|
@ -76,7 +77,7 @@ public class SearchInputTests extends ESTestCase {
|
|||
Map<String, ScriptContext<?>> contexts = new HashMap<>();
|
||||
contexts.put(Watcher.SCRIPT_TEMPLATE_CONTEXT.name, Watcher.SCRIPT_TEMPLATE_CONTEXT);
|
||||
contexts.put(Watcher.SCRIPT_SEARCH_CONTEXT.name, Watcher.SCRIPT_SEARCH_CONTEXT);
|
||||
contexts.put(Watcher.SCRIPT_EXECUTABLE_CONTEXT.name, Watcher.SCRIPT_EXECUTABLE_CONTEXT);
|
||||
contexts.put(WatcherTransformScript.CONTEXT.name, WatcherTransformScript.CONTEXT);
|
||||
scriptService = new ScriptService(Settings.EMPTY, engines, contexts);
|
||||
|
||||
ThreadPool threadPool = mock(ThreadPool.class);
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.elasticsearch.script.ScriptType;
|
|||
import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherMockScriptPlugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
|
@ -78,7 +79,7 @@ public class TransformIntegrationTests extends AbstractWatcherIntegrationTestCas
|
|||
return config;
|
||||
}
|
||||
|
||||
public static class CustomScriptPlugin extends MockScriptPlugin {
|
||||
public static class CustomScriptPlugin extends WatcherMockScriptPlugin {
|
||||
|
||||
@Override
|
||||
protected Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.elasticsearch.xpack.watcher.transform.script;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptException;
|
||||
|
@ -17,10 +16,12 @@ import org.elasticsearch.script.ScriptService;
|
|||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.Wid;
|
||||
import org.elasticsearch.xpack.core.watcher.transform.Transform;
|
||||
import org.elasticsearch.xpack.core.watcher.trigger.TriggerEvent;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Payload;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Watch;
|
||||
import org.elasticsearch.xpack.watcher.Watcher;
|
||||
import org.elasticsearch.xpack.watcher.support.Variables;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -49,21 +50,19 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
ScriptType type = randomFrom(ScriptType.values());
|
||||
Map<String, Object> params = Collections.emptyMap();
|
||||
Script script = new Script(type, type == ScriptType.STORED ? null : "_lang", "_script", params);
|
||||
ExecutableScript.Factory factory = mock(ExecutableScript.Factory.class);
|
||||
when(service.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT)).thenReturn(factory);
|
||||
WatcherTransformScript.Factory factory = mock(WatcherTransformScript.Factory.class);
|
||||
when(service.compile(script, WatcherTransformScript.CONTEXT)).thenReturn(factory);
|
||||
ExecutableScriptTransform transform = new ExecutableScriptTransform(new ScriptTransform(script), logger, service);
|
||||
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", Payload.EMPTY);
|
||||
|
||||
Payload payload = new Payload.Simple("key", "value");
|
||||
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
Map<String, Object> transformed = singletonMap("key", "value");
|
||||
|
||||
ExecutableScript executable = mock(ExecutableScript.class);
|
||||
when(executable.run()).thenReturn(transformed);
|
||||
when(factory.newInstance(model)).thenReturn(executable);
|
||||
WatcherTransformScript executable = mock(WatcherTransformScript.class);
|
||||
when(executable.execute()).thenReturn(transformed);
|
||||
when(factory.newInstance(params, ctx, payload)).thenReturn(executable);
|
||||
|
||||
Transform.Result result = transform.execute(ctx, payload);
|
||||
assertThat(result, notNullValue());
|
||||
|
@ -77,19 +76,17 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
ScriptType type = randomFrom(ScriptType.values());
|
||||
Map<String, Object> params = Collections.emptyMap();
|
||||
Script script = new Script(type, type == ScriptType.STORED ? null : "_lang", "_script", params);
|
||||
ExecutableScript.Factory factory = mock(ExecutableScript.Factory.class);
|
||||
when(service.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT)).thenReturn(factory);
|
||||
WatcherTransformScript.Factory factory = mock(WatcherTransformScript.Factory.class);
|
||||
when(service.compile(script, WatcherTransformScript.CONTEXT)).thenReturn(factory);
|
||||
ExecutableScriptTransform transform = new ExecutableScriptTransform(new ScriptTransform(script), logger, service);
|
||||
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", Payload.EMPTY);
|
||||
|
||||
Payload payload = new Payload.Simple("key", "value");
|
||||
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
ExecutableScript executable = mock(ExecutableScript.class);
|
||||
when(executable.run()).thenThrow(new RuntimeException("_error"));
|
||||
when(factory.newInstance(model)).thenReturn(executable);
|
||||
WatcherTransformScript executable = mock(WatcherTransformScript.class);
|
||||
when(executable.execute()).thenThrow(new RuntimeException("_error"));
|
||||
when(factory.newInstance(params, ctx, payload)).thenReturn(executable);
|
||||
|
||||
Transform.Result result = transform.execute(ctx, payload);
|
||||
assertThat(result, notNullValue());
|
||||
|
@ -103,20 +100,18 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
ScriptType type = randomFrom(ScriptType.values());
|
||||
Map<String, Object> params = Collections.emptyMap();
|
||||
Script script = new Script(type, type == ScriptType.STORED ? null : "_lang", "_script", params);
|
||||
ExecutableScript.Factory factory = mock(ExecutableScript.Factory.class);
|
||||
when(service.compile(script, Watcher.SCRIPT_EXECUTABLE_CONTEXT)).thenReturn(factory);
|
||||
WatcherTransformScript.Factory factory = mock(WatcherTransformScript.Factory.class);
|
||||
when(service.compile(script, WatcherTransformScript.CONTEXT)).thenReturn(factory);
|
||||
ExecutableScriptTransform transform = new ExecutableScriptTransform(new ScriptTransform(script), logger, service);
|
||||
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", Payload.EMPTY);
|
||||
|
||||
Payload payload = new Payload.Simple("key", "value");
|
||||
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
ExecutableScript executable = mock(ExecutableScript.class);
|
||||
WatcherTransformScript executable = mock(WatcherTransformScript.class);
|
||||
Object value = randomFrom("value", 1, new String[] { "value" }, Collections.singletonList("value"), singleton("value"));
|
||||
when(executable.run()).thenReturn(value);
|
||||
when(factory.newInstance(model)).thenReturn(executable);
|
||||
when(executable.execute()).thenReturn(value);
|
||||
when(factory.newInstance(params, ctx, payload)).thenReturn(executable);
|
||||
|
||||
Transform.Result result = transform.execute(ctx, payload);
|
||||
assertThat(result, notNullValue());
|
||||
|
@ -158,7 +153,7 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
String errorMessage = "expected error message";
|
||||
ScriptException scriptException = new ScriptException(errorMessage, new RuntimeException("foo"),
|
||||
Collections.emptyList(), "whatever", "whatever");
|
||||
when(scriptService.compile(anyObject(), eq(Watcher.SCRIPT_EXECUTABLE_CONTEXT))).thenThrow(scriptException);
|
||||
when(scriptService.compile(anyObject(), eq(WatcherTransformScript.CONTEXT))).thenThrow(scriptException);
|
||||
|
||||
ScriptTransformFactory transformFactory = new ScriptTransformFactory(Settings.builder().build(), scriptService);
|
||||
|
||||
|
@ -191,6 +186,23 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
assertThat(e.getMessage(), containsString("script_lang not supported [not_a_valid_lang]"));
|
||||
}
|
||||
|
||||
public void testParamsCtxDeprecated() throws Exception {
|
||||
WatchExecutionContext watcherContext = mock(WatchExecutionContext.class);
|
||||
when(watcherContext.id()).thenReturn(mock(Wid.class));
|
||||
when(watcherContext.watch()).thenReturn(mock(Watch.class));
|
||||
when(watcherContext.triggerEvent()).thenReturn(mock(TriggerEvent.class));
|
||||
Payload payload = mock(Payload.class);
|
||||
WatcherTransformScript watcherScript = new WatcherTransformScript(Collections.emptyMap(), watcherContext, payload) {
|
||||
@Override
|
||||
public Object execute() {
|
||||
return getParams().get("ctx");
|
||||
}
|
||||
};
|
||||
assertThat(watcherScript.execute(), is(watcherScript.getCtx()));
|
||||
assertWarnings("Accessing variable [ctx] via [params.ctx] from within a watcher_transform script " +
|
||||
"is deprecated in favor of directly accessing [ctx].");
|
||||
}
|
||||
|
||||
static String scriptTypeField(ScriptType type) {
|
||||
switch (type) {
|
||||
case INLINE: return "source";
|
||||
|
@ -205,7 +217,7 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
.put("path.home", createTempDir())
|
||||
.build();
|
||||
Map<String, ScriptContext> contexts = new HashMap<>(ScriptModule.CORE_CONTEXTS);
|
||||
contexts.put(Watcher.SCRIPT_EXECUTABLE_CONTEXT.name, Watcher.SCRIPT_EXECUTABLE_CONTEXT);
|
||||
contexts.put(WatcherTransformScript.CONTEXT.name, WatcherTransformScript.CONTEXT);
|
||||
contexts.put(Watcher.SCRIPT_TEMPLATE_CONTEXT.name, Watcher.SCRIPT_TEMPLATE_CONTEXT);
|
||||
return new ScriptService(settings, Collections.emptyMap(), Collections.emptyMap());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue