mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-24 05:44:59 +00:00
Cleanup and Refactoring of the actions
* Split the action into two constructs: `Action` and `ExecutableAction`. The former holds all the action configuration, the latter can execute the action based on that configuration (an executable action holds an action) - This the code clearer to understand and maintain. - This also enabled to pull some common implementation code into the `ExecutableAction` and by that reduce the implementation details of each executable to the minimum required. * Also, extracted teh `Action.Parser` to its own top level class, and renamed it to - `ActionFactory`. The main thing that the parser does is: 1) delegate to the parsing to the `Action` class, 2) construct & wire up the `ExecutableAction`. * Cleaned up and aligned the log messages across all actions. Introduced - introduced parameterized exceptions (now the exception messages are constructed exactly like that log messages - using `{}` params) - Introduced the notion of `Wid` - Watch (execution) ID`. Now the `WatchExecutionContext` and the `WatchRecord` hold this construct as their ID (instead of an opaque string). The Wid has a well defined structure where it's prefixed with the watch id. This is very helpful to provide context to parsing the different constructs (actions in our case) as when parsing error occurs we can point directly to the place were we found the error (ie. watch id, record id and action id). * With the introduction of `Action`, we no longer need the `SourceBuilder` for actions. Instead, we have `Action.Builder` that help you build actions. This is much more intuitive from the client perspective. Original commit: elastic/x-pack-elasticsearch@df22da4e1f
This commit is contained in:
parent
8c87cb0728
commit
13573d6c6d
@ -6,17 +6,18 @@
|
||||
package org.elasticsearch.watcher;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||
|
||||
/**
|
||||
* A base class for all watcher exceptions
|
||||
*/
|
||||
public class WatcherException extends ElasticsearchException {
|
||||
|
||||
public WatcherException(String msg) {
|
||||
super(msg);
|
||||
public WatcherException(String msg, Object... args) {
|
||||
super(LoggerMessageFormat.format(msg, args));
|
||||
}
|
||||
|
||||
public WatcherException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
public WatcherException(String msg, Throwable cause, Object... args) {
|
||||
super(LoggerMessageFormat.format(msg, args), cause);
|
||||
}
|
||||
}
|
||||
|
@ -5,56 +5,20 @@
|
||||
*/
|
||||
package org.elasticsearch.watcher.actions;
|
||||
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.transform.Transform;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public abstract class Action<R extends Action.Result> implements ToXContent {
|
||||
public interface Action extends ToXContent {
|
||||
|
||||
protected final ESLogger logger;
|
||||
String type();
|
||||
|
||||
protected Action(ESLogger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type of this action
|
||||
*/
|
||||
public abstract String type();
|
||||
|
||||
protected abstract R execute(String actionId, WatchExecutionContext context, Payload payload) throws IOException;
|
||||
|
||||
/**
|
||||
* Parses xcontent to a concrete action of the same type.
|
||||
*/
|
||||
public interface Parser<R extends Result, T extends Action<R>> {
|
||||
|
||||
/**
|
||||
* @return The type of the action
|
||||
*/
|
||||
String type();
|
||||
|
||||
/**
|
||||
* Parses the given xcontent and creates a concrete action
|
||||
*/
|
||||
T parse(XContentParser parser) throws IOException;
|
||||
|
||||
R parseResult(XContentParser parser) throws IOException;
|
||||
}
|
||||
|
||||
public static abstract class Result implements ToXContent {
|
||||
|
||||
public static final ParseField SUCCESS_FIELD = new ParseField("success");
|
||||
abstract class Result implements ToXContent {
|
||||
|
||||
protected final String type;
|
||||
protected final boolean success;
|
||||
@ -72,43 +36,30 @@ public abstract class Action<R extends Action.Result> implements ToXContent {
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(SUCCESS_FIELD.getPreferredName(), success);
|
||||
builder.field(Field.SUCCESS.getPreferredName(), success);
|
||||
xContentBody(builder, params);
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
protected abstract XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException;
|
||||
|
||||
public interface Failure extends ToXContent {
|
||||
|
||||
String reason();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class SourceBuilder<SB extends SourceBuilder<SB>> implements ToXContent {
|
||||
interface Builder<A extends Action> {
|
||||
|
||||
protected @Nullable Transform.SourceBuilder transform;
|
||||
A build();
|
||||
}
|
||||
|
||||
public SB transform(Transform.SourceBuilder transform) {
|
||||
this.transform = transform;
|
||||
return (SB) this;
|
||||
}
|
||||
|
||||
public abstract String type();
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
if (transform != null) {
|
||||
builder.startObject(Transform.Parser.TRANSFORM_FIELD.getPreferredName())
|
||||
.field(transform.type(), transform)
|
||||
.endObject();
|
||||
}
|
||||
builder.field(type());
|
||||
actionXContent(builder, params);
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
protected abstract XContentBuilder actionXContent(XContentBuilder builder, Params params) throws IOException;
|
||||
interface Field {
|
||||
ParseField SUCCESS = new ParseField("success");
|
||||
ParseField REASON = new ParseField("reason");
|
||||
}
|
||||
}
|
||||
|
@ -21,32 +21,32 @@ public final class ActionBuilders {
|
||||
private ActionBuilders() {
|
||||
}
|
||||
|
||||
public static EmailAction.SourceBuilder emailAction(EmailTemplate.Builder email) {
|
||||
public static EmailAction.Builder emailAction(EmailTemplate.Builder email) {
|
||||
return emailAction(email.build());
|
||||
}
|
||||
|
||||
public static EmailAction.SourceBuilder emailAction(EmailTemplate email) {
|
||||
return new EmailAction.SourceBuilder(email);
|
||||
public static EmailAction.Builder emailAction(EmailTemplate email) {
|
||||
return EmailAction.builder(email);
|
||||
}
|
||||
|
||||
public static IndexAction.SourceBuilder indexAction(String index, String type) {
|
||||
return new IndexAction.SourceBuilder(index, type);
|
||||
public static IndexAction.Builder indexAction(String index, String type) {
|
||||
return IndexAction.builder(index, type);
|
||||
}
|
||||
|
||||
public static WebhookAction.SourceBuilder webhookAction(HttpRequestTemplate.Builder httpRequest) {
|
||||
return new WebhookAction.SourceBuilder(httpRequest.build());
|
||||
public static WebhookAction.Builder webhookAction(HttpRequestTemplate.Builder httpRequest) {
|
||||
return webhookAction(httpRequest.build());
|
||||
}
|
||||
|
||||
public static WebhookAction.SourceBuilder webhookAction(HttpRequestTemplate httpRequest) {
|
||||
return new WebhookAction.SourceBuilder(httpRequest);
|
||||
public static WebhookAction.Builder webhookAction(HttpRequestTemplate httpRequest) {
|
||||
return WebhookAction.builder(httpRequest);
|
||||
}
|
||||
|
||||
public static LoggingAction.SourceBuilder loggingAction(String text) {
|
||||
public static LoggingAction.Builder loggingAction(String text) {
|
||||
return loggingAction(new Template(text));
|
||||
}
|
||||
|
||||
public static LoggingAction.SourceBuilder loggingAction(Template text) {
|
||||
return new LoggingAction.SourceBuilder(text);
|
||||
public static LoggingAction.Builder loggingAction(Template text) {
|
||||
return LoggingAction.builder(text);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.elasticsearch.watcher.actions;
|
||||
|
||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||
import org.elasticsearch.watcher.WatcherException;
|
||||
|
||||
/**
|
||||
@ -12,11 +13,12 @@ import org.elasticsearch.watcher.WatcherException;
|
||||
*/
|
||||
public class ActionException extends WatcherException {
|
||||
|
||||
public ActionException(String msg) {
|
||||
super(msg);
|
||||
public ActionException(String msg, Object... args) {
|
||||
super(LoggerMessageFormat.format(msg, args));
|
||||
}
|
||||
|
||||
public ActionException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
public ActionException(String msg, Throwable cause, Object... args) {
|
||||
super(LoggerMessageFormat.format(msg, args), cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.actions;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Parses xcontent to a concrete action of the same type.
|
||||
*/
|
||||
public abstract class ActionFactory<A extends Action, R extends Action.Result, E extends ExecutableAction<A, R>> {
|
||||
|
||||
protected final ESLogger actionLogger;
|
||||
|
||||
protected ActionFactory(ESLogger actionLogger) {
|
||||
this.actionLogger = actionLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type of the action
|
||||
*/
|
||||
public abstract String type();
|
||||
|
||||
public abstract A parseAction(String watchId, String actionId, XContentParser parser) throws IOException;
|
||||
|
||||
public abstract R parseResult(Wid wid, String actionId, XContentParser parser) throws IOException;
|
||||
|
||||
public abstract E createExecutable(A action);
|
||||
|
||||
/**
|
||||
* Parses the given xcontent and creates a concrete action
|
||||
*/
|
||||
public E parseExecutable(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
A action = parseAction(watchId, actionId, parser);
|
||||
return createExecutable(action);
|
||||
}
|
||||
}
|
@ -8,11 +8,15 @@ package org.elasticsearch.watcher.actions;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.multibindings.MapBinder;
|
||||
import org.elasticsearch.watcher.actions.email.EmailAction;
|
||||
import org.elasticsearch.watcher.actions.email.EmailActionFactory;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailService;
|
||||
import org.elasticsearch.watcher.actions.email.service.InternalEmailService;
|
||||
import org.elasticsearch.watcher.actions.index.IndexAction;
|
||||
import org.elasticsearch.watcher.actions.index.IndexActionFactory;
|
||||
import org.elasticsearch.watcher.actions.logging.LoggingAction;
|
||||
import org.elasticsearch.watcher.actions.logging.LoggingActionFactory;
|
||||
import org.elasticsearch.watcher.actions.webhook.WebhookAction;
|
||||
import org.elasticsearch.watcher.actions.webhook.WebhookActionFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -21,29 +25,30 @@ import java.util.Map;
|
||||
*/
|
||||
public class ActionModule extends AbstractModule {
|
||||
|
||||
private final Map<String, Class<? extends Action.Parser>> parsers = new HashMap<>();
|
||||
private final Map<String, Class<? extends ActionFactory>> parsers = new HashMap<>();
|
||||
|
||||
public void registerAction(String type, Class<? extends Action.Parser> parserType) {
|
||||
public void registerAction(String type, Class<? extends ActionFactory> parserType) {
|
||||
parsers.put(type, parserType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
MapBinder<String, Action.Parser> parsersBinder = MapBinder.newMapBinder(binder(), String.class, Action.Parser.class);
|
||||
bind(EmailAction.Parser.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(EmailAction.TYPE).to(EmailAction.Parser.class);
|
||||
MapBinder<String, ActionFactory> parsersBinder = MapBinder.newMapBinder(binder(), String.class, ActionFactory.class);
|
||||
|
||||
bind(WebhookAction.Parser.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(WebhookAction.TYPE).to(WebhookAction.Parser.class);
|
||||
bind(EmailActionFactory.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(EmailAction.TYPE).to(EmailActionFactory.class);
|
||||
|
||||
bind(IndexAction.Parser.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(IndexAction.TYPE).to(IndexAction.Parser.class);
|
||||
bind(WebhookActionFactory.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(WebhookAction.TYPE).to(WebhookActionFactory.class);
|
||||
|
||||
bind(LoggingAction.Parser.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(LoggingAction.TYPE).to(LoggingAction.Parser.class);
|
||||
bind(IndexActionFactory.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(IndexAction.TYPE).to(IndexActionFactory.class);
|
||||
|
||||
for (Map.Entry<String, Class<? extends Action.Parser>> entry : parsers.entrySet()) {
|
||||
bind(LoggingActionFactory.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(LoggingAction.TYPE).to(LoggingActionFactory.class);
|
||||
|
||||
for (Map.Entry<String, Class<? extends ActionFactory>> entry : parsers.entrySet()) {
|
||||
bind(entry.getValue()).asEagerSingleton();
|
||||
parsersBinder.addBinding(entry.getKey()).to(entry.getValue());
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ package org.elasticsearch.watcher.actions;
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.transform.TransformRegistry;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -20,36 +21,20 @@ import java.util.Map;
|
||||
*/
|
||||
public class ActionRegistry {
|
||||
|
||||
private final ImmutableMap<String, Action.Parser> parsers;
|
||||
private final ImmutableMap<String, ActionFactory> parsers;
|
||||
private final TransformRegistry transformRegistry;
|
||||
|
||||
@Inject
|
||||
public ActionRegistry(Map<String, Action.Parser> parsers, TransformRegistry transformRegistry) {
|
||||
public ActionRegistry(Map<String, ActionFactory> parsers, TransformRegistry transformRegistry) {
|
||||
this.parsers = ImmutableMap.copyOf(parsers);
|
||||
this.transformRegistry = transformRegistry;
|
||||
}
|
||||
|
||||
Action.Parser parser(String type) {
|
||||
ActionFactory factory(String type) {
|
||||
return parsers.get(type);
|
||||
}
|
||||
|
||||
public Actions.Results parseResults(XContentParser parser) throws IOException {
|
||||
Map<String, ActionWrapper.Result> results = new HashMap<>();
|
||||
|
||||
String id = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
id = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT && id != null) {
|
||||
ActionWrapper.Result result = ActionWrapper.Result.parse(parser, id, this, transformRegistry);
|
||||
results.put(id, result);
|
||||
}
|
||||
}
|
||||
return new Actions.Results(results);
|
||||
}
|
||||
|
||||
public Actions parseActions(XContentParser parser) throws IOException {
|
||||
public ExecutableActions parseActions(String watchId, XContentParser parser) throws IOException {
|
||||
List<ActionWrapper> actions = new ArrayList<>();
|
||||
|
||||
String id = null;
|
||||
@ -58,13 +43,27 @@ public class ActionRegistry {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
id = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT && id != null) {
|
||||
ActionWrapper action = ActionWrapper.parse(parser, id, this, transformRegistry);
|
||||
ActionWrapper action = ActionWrapper.parse(watchId, id, parser, this, transformRegistry);
|
||||
actions.add(action);
|
||||
}
|
||||
}
|
||||
return new Actions(actions);
|
||||
return new ExecutableActions(actions);
|
||||
}
|
||||
|
||||
public ExecutableActions.Results parseResults(Wid wid, XContentParser parser) throws IOException {
|
||||
Map<String, ActionWrapper.Result> results = new HashMap<>();
|
||||
|
||||
String id = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
id = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT && id != null) {
|
||||
ActionWrapper.Result result = ActionWrapper.Result.parse(wid, id, parser, this, transformRegistry);
|
||||
results.put(id, result);
|
||||
}
|
||||
}
|
||||
return new ExecutableActions.Results(results);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,10 +9,11 @@ import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.transform.Transform;
|
||||
import org.elasticsearch.watcher.transform.TransformRegistry;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -23,13 +24,13 @@ public class ActionWrapper implements ToXContent {
|
||||
|
||||
private String id;
|
||||
private final @Nullable Transform transform;
|
||||
private final Action action;
|
||||
private final ExecutableAction action;
|
||||
|
||||
public ActionWrapper(String id, Action action) {
|
||||
public ActionWrapper(String id, ExecutableAction action) {
|
||||
this(id, null, action);
|
||||
}
|
||||
|
||||
public ActionWrapper(String id, @Nullable Transform transform, Action action) {
|
||||
public ActionWrapper(String id, @Nullable Transform transform, ExecutableAction action) {
|
||||
this.id = id;
|
||||
this.transform = transform;
|
||||
this.action = action;
|
||||
@ -43,7 +44,7 @@ public class ActionWrapper implements ToXContent {
|
||||
return transform;
|
||||
}
|
||||
|
||||
public Action action() {
|
||||
public ExecutableAction action() {
|
||||
return action;
|
||||
}
|
||||
|
||||
@ -91,11 +92,11 @@ public class ActionWrapper implements ToXContent {
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
static ActionWrapper parse(XContentParser parser, String id, ActionRegistry actionRegistry, TransformRegistry transformRegistry) throws IOException {
|
||||
static ActionWrapper parse(String watchId, String actionId, XContentParser parser, ActionRegistry actionRegistry, TransformRegistry transformRegistry) throws IOException {
|
||||
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
|
||||
|
||||
Transform transform = null;
|
||||
Action action = null;
|
||||
ExecutableAction action = null;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
@ -107,18 +108,18 @@ public class ActionWrapper implements ToXContent {
|
||||
transform = transformRegistry.parse(parser);
|
||||
} else {
|
||||
// it's the type of the action
|
||||
Action.Parser actionParser = actionRegistry.parser(currentFieldName);
|
||||
if (actionParser == null) {
|
||||
throw new ActionException("could not parse action [" + id + "]. unknown action type [" + currentFieldName + "]");
|
||||
ActionFactory actionFactory = actionRegistry.factory(currentFieldName);
|
||||
if (actionFactory == null) {
|
||||
throw new ActionException("could not parse action [{}/{}]. unknown action type [{}]", watchId, actionId, currentFieldName);
|
||||
}
|
||||
action = actionParser.parse(parser);
|
||||
action = actionFactory.parseExecutable(watchId, actionId, parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (action == null) {
|
||||
throw new ActionException("could not parse watch action [" + id + "]. missing action type");
|
||||
throw new ActionException("could not parse watch action [{}/{}]. missing action type", watchId, actionId);
|
||||
}
|
||||
return new ActionWrapper(id, transform, action);
|
||||
return new ActionWrapper(actionId, transform, action);
|
||||
}
|
||||
|
||||
public static class Result implements ToXContent {
|
||||
@ -181,7 +182,7 @@ public class ActionWrapper implements ToXContent {
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
static Result parse(XContentParser parser, String id, ActionRegistry actionRegistry, TransformRegistry transformRegistry) throws IOException {
|
||||
static Result parse(Wid wid, String actionId, XContentParser parser, ActionRegistry actionRegistry, TransformRegistry transformRegistry) throws IOException {
|
||||
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
|
||||
|
||||
Transform.Result transformResult = null;
|
||||
@ -197,18 +198,18 @@ public class ActionWrapper implements ToXContent {
|
||||
transformResult = transformRegistry.parseResult(parser);
|
||||
} else {
|
||||
// it's the type of the action
|
||||
Action.Parser actionParser = actionRegistry.parser(currentFieldName);
|
||||
if (actionParser == null) {
|
||||
throw new ActionException("could not parse action result [" + id + "]. unknown action type [" + currentFieldName + "]");
|
||||
ActionFactory actionFactory = actionRegistry.factory(currentFieldName);
|
||||
if (actionFactory == null) {
|
||||
throw new ActionException("could not parse action result [{}/{}]. unknown action type [{}]", wid, actionId, currentFieldName);
|
||||
}
|
||||
actionResult = actionParser.parseResult(parser);
|
||||
actionResult = actionFactory.parseResult(wid, actionId, parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (actionResult == null) {
|
||||
throw new ActionException("could not parse watch action result [" + id + "]. missing action result type");
|
||||
throw new ActionException("could not parse watch action result [{}/{}]. missing action result type", wid, actionId);
|
||||
}
|
||||
return new Result(id, transformResult, actionResult);
|
||||
return new Result(actionId, transformResult, actionResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.actions;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*/
|
||||
public abstract class ExecutableAction<A extends Action, R extends Action.Result> implements ToXContent {
|
||||
|
||||
protected final A action;
|
||||
protected final ESLogger logger;
|
||||
|
||||
protected ExecutableAction(A action, ESLogger logger) {
|
||||
this.action = action;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type of this action
|
||||
*/
|
||||
public final String type() {
|
||||
return action.type();
|
||||
}
|
||||
|
||||
public A action() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public R execute(String actionId, WatchExecutionContext context, Payload payload) throws IOException {
|
||||
try {
|
||||
return doExecute(actionId, context, payload);
|
||||
} catch (Exception e){
|
||||
logger.error("failed to execute [{}] action [{}/{}]", e, type(), context.id().value(), actionId);
|
||||
return failure(LoggerMessageFormat.format("failed to execute [{}] action [{}/{}]. error: {}", (Object) type(), context.id().value(), actionId, e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the action. The implementation need not to worry about handling exception/errors as they're handled
|
||||
* here by default. Of course, if the implementation wants to do that, it can... nothing stops you.
|
||||
*/
|
||||
protected abstract R doExecute(String actionId, WatchExecutionContext context, Payload payload) throws Exception;
|
||||
|
||||
/**
|
||||
* Returns an appropriate failure result that contains the given failure reason.
|
||||
*/
|
||||
protected abstract R failure(String reason);
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ExecutableAction that = (ExecutableAction) o;
|
||||
|
||||
return action.equals(that.action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return action.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return action.toXContent(builder, params);
|
||||
}
|
||||
|
||||
}
|
@ -16,11 +16,11 @@ import java.util.Map;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Actions implements Iterable<ActionWrapper>, ToXContent {
|
||||
public class ExecutableActions implements Iterable<ActionWrapper>, ToXContent {
|
||||
|
||||
private final List<ActionWrapper> actions;
|
||||
|
||||
public Actions(List<ActionWrapper> actions) {
|
||||
public ExecutableActions(List<ActionWrapper> actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public class Actions implements Iterable<ActionWrapper>, ToXContent {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Actions actions1 = (Actions) o;
|
||||
ExecutableActions actions1 = (ExecutableActions) o;
|
||||
|
||||
if (!actions.equals(actions1.actions)) return false;
|
||||
|
@ -5,49 +5,58 @@
|
||||
*/
|
||||
package org.elasticsearch.watcher.actions.email;
|
||||
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.actions.Action;
|
||||
import org.elasticsearch.watcher.actions.email.service.*;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
import org.elasticsearch.watcher.actions.email.service.Authentication;
|
||||
import org.elasticsearch.watcher.actions.email.service.Email;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailTemplate;
|
||||
import org.elasticsearch.watcher.actions.email.service.Profile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class EmailAction extends Action<EmailAction.Result> {
|
||||
public class EmailAction implements Action {
|
||||
|
||||
public static final String TYPE = "email";
|
||||
|
||||
final EmailTemplate emailTemplate;
|
||||
final Authentication auth;
|
||||
final Profile profile;
|
||||
final String account;
|
||||
final boolean attachPayload;
|
||||
private final EmailTemplate email;
|
||||
private final @Nullable String account;
|
||||
private final @Nullable Authentication auth;
|
||||
private final @Nullable Profile profile;
|
||||
private final @Nullable Boolean attachPayload;
|
||||
|
||||
final EmailService emailService;
|
||||
final TemplateEngine templateEngine;
|
||||
|
||||
public EmailAction(ESLogger logger, EmailTemplate emailTemplate, Authentication auth, Profile profile, String account, boolean attachPayload,
|
||||
EmailService emailService, TemplateEngine templateEngine) {
|
||||
super(logger);
|
||||
this.emailTemplate = emailTemplate;
|
||||
public EmailAction(EmailTemplate email, @Nullable String account, @Nullable Authentication auth, @Nullable Profile profile, @Nullable Boolean attachPayload) {
|
||||
this.email = email;
|
||||
this.account = account;
|
||||
this.auth = auth;
|
||||
this.profile = profile;
|
||||
this.account = account;
|
||||
this.attachPayload = attachPayload;
|
||||
this.emailService = emailService;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
public EmailTemplate getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public Authentication getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public Profile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
public boolean isAttachPayload() {
|
||||
return attachPayload != null && attachPayload;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,222 +64,130 @@ public class EmailAction extends Action<EmailAction.Result> {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
protected Result execute(String actionId, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
try {
|
||||
return doExecute(actionId, ctx, payload);
|
||||
} catch (Exception e) {
|
||||
logger.error("could not send email [{}] for watch [{}]", e, actionId, ctx.watch().name());
|
||||
return new Result.Failure("could not execute email action. error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
protected Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
EmailAction action = (EmailAction) o;
|
||||
|
||||
Email.Builder email = emailTemplate.render(templateEngine, model);
|
||||
email.id(ctx.id());
|
||||
|
||||
if (attachPayload) {
|
||||
Attachment.Bytes attachment = new Attachment.XContent.Yaml("payload", "payload.yml", payload);
|
||||
email.attach(attachment);
|
||||
}
|
||||
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new Result.Simulated(email.build());
|
||||
}
|
||||
|
||||
EmailService.EmailSent sent = emailService.send(email.build(), auth, profile, account);
|
||||
return new Result.Success(sent);
|
||||
if (!email.equals(action.email)) return false;
|
||||
if (account != null ? !account.equals(action.account) : action.account != null) return false;
|
||||
if (auth != null ? !auth.equals(action.auth) : action.auth != null) return false;
|
||||
if (profile != action.profile) return false;
|
||||
return !(attachPayload != null ? !attachPayload.equals(action.attachPayload) : action.attachPayload != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(emailTemplate, auth, profile, account, attachPayload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final EmailAction other = (EmailAction) obj;
|
||||
return Objects.equals(this.emailTemplate, other.emailTemplate)
|
||||
&& Objects.equals(this.auth, other.auth)
|
||||
&& Objects.equals(this.profile, other.profile)
|
||||
&& Objects.equals(this.account, other.account)
|
||||
&& Objects.equals(this.attachPayload, other.attachPayload);
|
||||
int result = email.hashCode();
|
||||
result = 31 * result + (account != null ? account.hashCode() : 0);
|
||||
result = 31 * result + (auth != null ? auth.hashCode() : 0);
|
||||
result = 31 * result + (profile != null ? profile.hashCode() : 0);
|
||||
result = 31 * result + (attachPayload != null ? attachPayload.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
emailTemplate.xContentBody(builder, params);
|
||||
if (account != null) {
|
||||
builder.field(Parser.ACCOUNT_FIELD.getPreferredName(), account);
|
||||
}
|
||||
if (profile != null) {
|
||||
builder.field(Parser.PROFILE_FIELD.getPreferredName(), profile);
|
||||
builder.field(Field.ACCOUNT.getPreferredName(), account);
|
||||
}
|
||||
if (auth != null) {
|
||||
builder.field(Parser.USER_FIELD.getPreferredName(), auth.user());
|
||||
builder.field(Parser.PASSWORD_FIELD.getPreferredName(), new String(auth.password()));
|
||||
builder.field(Field.USER.getPreferredName(), auth.user());
|
||||
builder.field(Field.PASSWORD.getPreferredName(), new String(auth.password()));
|
||||
}
|
||||
builder.field(Parser.ATTACH_PAYLOAD_FIELD.getPreferredName(), attachPayload);
|
||||
if (profile != null) {
|
||||
builder.field(Field.PROFILE.getPreferredName(), profile.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
if (attachPayload != null) {
|
||||
builder.field(Field.ATTACH_PAYLOAD.getPreferredName(), attachPayload);
|
||||
}
|
||||
email.xContentBody(builder, params);
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
public static class Parser extends AbstractComponent implements Action.Parser<Result, EmailAction> {
|
||||
public static EmailAction parse(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
EmailTemplate.Parser emailParser = new EmailTemplate.Parser();
|
||||
String account = null;
|
||||
String user = null;
|
||||
String password = null;
|
||||
Profile profile = Profile.STANDARD;
|
||||
Boolean attachPayload = null;
|
||||
|
||||
public static final ParseField ACCOUNT_FIELD = new ParseField("account");
|
||||
public static final ParseField PROFILE_FIELD = new ParseField("profile");
|
||||
public static final ParseField USER_FIELD = new ParseField("user");
|
||||
public static final ParseField PASSWORD_FIELD = new ParseField("password");
|
||||
public static final ParseField ATTACH_PAYLOAD_FIELD = new ParseField("attach_payload");
|
||||
public static final ParseField EMAIL_FIELD = new ParseField("email");
|
||||
public static final ParseField REASON_FIELD = new ParseField("reason");
|
||||
public static final ParseField SIMULATED_EMAIL_FIELD = new ParseField("simulated_email");
|
||||
|
||||
private final EmailService emailService;
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
@Inject
|
||||
public Parser(Settings settings, EmailService emailService, TemplateEngine templateEngine) {
|
||||
super(settings);
|
||||
this.emailService = emailService;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailAction parse(XContentParser parser) throws IOException {
|
||||
EmailTemplate.Parser emailParser = EmailTemplate.parser();
|
||||
String user = null;
|
||||
String password = null;
|
||||
String account = null;
|
||||
Profile profile = null;
|
||||
boolean attachPayload = false;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (!emailParser.handle(currentFieldName, parser)) {
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (ACCOUNT_FIELD.match(currentFieldName)) {
|
||||
account = parser.text();
|
||||
} else if (USER_FIELD.match(currentFieldName)) {
|
||||
user = parser.text();
|
||||
} else if (PASSWORD_FIELD.match(currentFieldName)) {
|
||||
password = parser.text();
|
||||
} else if (PROFILE_FIELD.match(currentFieldName)) {
|
||||
profile = Profile.resolve(parser.text());
|
||||
} else {
|
||||
throw new EmailActionException("could not parse [email] action. unrecognized string field [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
if (ATTACH_PAYLOAD_FIELD.match(currentFieldName)) {
|
||||
attachPayload = parser.booleanValue();
|
||||
} else {
|
||||
throw new EmailActionException("could not parse [email] action. unrecognized boolean field [" + currentFieldName + "]");
|
||||
}
|
||||
} else {
|
||||
throw new EmailActionException("could not parse [email] action. unexpected token [" + token + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Authentication auth = user != null ? new Authentication(user, password.toCharArray()) : null;
|
||||
|
||||
return new EmailAction(logger, emailParser.parsedTemplate(), auth, profile, account, attachPayload, emailService, templateEngine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailAction.Result parseResult(XContentParser parser) throws IOException {
|
||||
Boolean success = null;
|
||||
Email email = null;
|
||||
Email simulatedEmail = null;
|
||||
String account = null;
|
||||
String reason = null;
|
||||
|
||||
XContentParser.Token token;
|
||||
String currentFieldName = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token.isValue()) {
|
||||
if (ACCOUNT_FIELD.match(currentFieldName)) {
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (!emailParser.handle(currentFieldName, parser)) {
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (Field.ACCOUNT.match(currentFieldName)) {
|
||||
account = parser.text();
|
||||
} else if (REASON_FIELD.match(currentFieldName)) {
|
||||
reason = parser.text();
|
||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
if (Action.Result.SUCCESS_FIELD.match(currentFieldName)) {
|
||||
success = parser.booleanValue();
|
||||
} else {
|
||||
throw new EmailException("could not parse email result. unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (Field.USER.match(currentFieldName)) {
|
||||
user = parser.text();
|
||||
} else if (Field.PASSWORD.match(currentFieldName)) {
|
||||
password = parser.text();
|
||||
} else if (Field.PROFILE.match(currentFieldName)) {
|
||||
profile = Profile.resolve(parser.text());
|
||||
} else {
|
||||
throw new EmailException("could not parse email result. unexpected field [" + currentFieldName + "]");
|
||||
throw new EmailActionException("could not parse [{}] action [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (EMAIL_FIELD.match(currentFieldName)) {
|
||||
email = Email.parse(parser);
|
||||
} else if (SIMULATED_EMAIL_FIELD.match(currentFieldName)) {
|
||||
simulatedEmail = Email.parse(parser);
|
||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
if (Field.ATTACH_PAYLOAD.match(currentFieldName)) {
|
||||
attachPayload = parser.booleanValue();
|
||||
} else {
|
||||
throw new EmailException("could not parse email result. unexpected field [" + currentFieldName + "]");
|
||||
throw new EmailActionException("could not parse [{}] action [{}/{}]. unexpected boolean field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else {
|
||||
throw new EmailException("could not parse email result. unexpected token [" + token + "]");
|
||||
throw new EmailActionException("could not parse [{}] action [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
||||
}
|
||||
}
|
||||
|
||||
if (simulatedEmail != null) {
|
||||
return new Result.Simulated(simulatedEmail);
|
||||
}
|
||||
|
||||
if (success == null) {
|
||||
throw new EmailException("could not parse email result. expected field [success]");
|
||||
}
|
||||
|
||||
return success ? new Result.Success(new EmailService.EmailSent(account, email)) : new Result.Failure(reason);
|
||||
}
|
||||
|
||||
Authentication auth = null;
|
||||
if (user != null) {
|
||||
char[] passwd = password != null ? password.toCharArray() : null;
|
||||
auth = new Authentication(user, passwd);
|
||||
}
|
||||
|
||||
return new EmailAction(emailParser.parsedTemplate(), account, auth, profile, attachPayload);
|
||||
}
|
||||
|
||||
public static Builder builder(EmailTemplate email) {
|
||||
return new Builder(email);
|
||||
}
|
||||
|
||||
public static abstract class Result extends Action.Result {
|
||||
|
||||
public Result(String type, boolean success) {
|
||||
super(type, success);
|
||||
protected Result(boolean success) {
|
||||
super(TYPE, success);
|
||||
}
|
||||
|
||||
public static class Success extends Result {
|
||||
|
||||
private final EmailService.EmailSent sent;
|
||||
private final String account;
|
||||
private final Email email;
|
||||
|
||||
private Success(EmailService.EmailSent sent) {
|
||||
super(TYPE, true);
|
||||
this.sent = sent;
|
||||
Success(String account, Email email) {
|
||||
super(true);
|
||||
this.account = account;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String account() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public Email email() {
|
||||
return email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.ACCOUNT_FIELD.getPreferredName(), sent.account())
|
||||
.field(Parser.EMAIL_FIELD.getPreferredName(), sent.email());
|
||||
}
|
||||
|
||||
public String account() {
|
||||
return sent.account();
|
||||
}
|
||||
|
||||
public Email email() {
|
||||
return sent.email();
|
||||
return builder.field(Field.ACCOUNT.getPreferredName(), account)
|
||||
.field(Field.EMAIL.getPreferredName(), email);
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,7 +196,7 @@ public class EmailAction extends Action<EmailAction.Result> {
|
||||
private final String reason;
|
||||
|
||||
public Failure(String reason) {
|
||||
super(TYPE, false);
|
||||
super(false);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
@ -289,7 +206,7 @@ public class EmailAction extends Action<EmailAction.Result> {
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.REASON_FIELD.getPreferredName(), reason);
|
||||
return builder.field(Action.Field.REASON.getPreferredName(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,74 +218,134 @@ public class EmailAction extends Action<EmailAction.Result> {
|
||||
return email;
|
||||
}
|
||||
|
||||
public Simulated(Email email) {
|
||||
super(TYPE, true);
|
||||
Simulated(Email email) {
|
||||
super(true);
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.SIMULATED_EMAIL_FIELD.getPreferredName(), email);
|
||||
return builder.field(Field.SIMULATED_EMAIL.getPreferredName(), email);
|
||||
}
|
||||
}
|
||||
|
||||
public static Result parse(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
Boolean success = null;
|
||||
Email email = null;
|
||||
Email simulatedEmail = null;
|
||||
String account = null;
|
||||
String reason = null;
|
||||
|
||||
XContentParser.Token token;
|
||||
String currentFieldName = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (Field.EMAIL.match(currentFieldName)) {
|
||||
try {
|
||||
email = Email.parse(parser);
|
||||
} catch (Email.ParseException pe) {
|
||||
throw new EmailActionException("could not parse [{}] action result [{}/{}]. failed parsing [{}] field", pe, TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (Field.SIMULATED_EMAIL.match(currentFieldName)) {
|
||||
try {
|
||||
simulatedEmail = Email.parse(parser);
|
||||
} catch (Email.ParseException pe) {
|
||||
throw new EmailActionException("could not parse [{}] action result [{}/{}]. failed parsing [{}] field", pe, TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (Field.ACCOUNT.match(currentFieldName)) {
|
||||
account = parser.text();
|
||||
} else if (Field.REASON.match(currentFieldName)) {
|
||||
reason = parser.text();
|
||||
} else {
|
||||
throw new EmailActionException("could not parse [{}] action result [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
if (Field.SUCCESS.match(currentFieldName)) {
|
||||
success = parser.booleanValue();
|
||||
} else {
|
||||
throw new EmailActionException("could not parse [{}] action result [{}/{}]. unexpected boolean field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else {
|
||||
throw new EmailActionException("could not parse [{}] action result [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
||||
}
|
||||
}
|
||||
|
||||
if (simulatedEmail != null) {
|
||||
return new Simulated(simulatedEmail);
|
||||
}
|
||||
|
||||
if (success == null) {
|
||||
throw new EmailActionException("could not parse [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.SUCCESS.getPreferredName());
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (account == null) {
|
||||
throw new EmailActionException("could not parse [{}] action successful result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.ACCOUNT.getPreferredName());
|
||||
}
|
||||
if (email == null) {
|
||||
throw new EmailActionException("could not parse [{}] action successful result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.EMAIL.getPreferredName());
|
||||
}
|
||||
return new Success(account, email);
|
||||
}
|
||||
if (reason == null) {
|
||||
throw new EmailActionException("could not parse [{}] action failure result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.REASON.getPreferredName());
|
||||
}
|
||||
return new Failure(reason);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SourceBuilder extends Action.SourceBuilder<SourceBuilder> {
|
||||
public static class Builder implements Action.Builder<EmailAction> {
|
||||
|
||||
private final EmailTemplate email;
|
||||
private Authentication auth = null;
|
||||
private Profile profile = null;
|
||||
private String account = null;
|
||||
private Boolean attachPayload;
|
||||
final EmailTemplate email;
|
||||
@Nullable String account;
|
||||
@Nullable Authentication auth;
|
||||
@Nullable Profile profile;
|
||||
@Nullable Boolean attachPayload;
|
||||
|
||||
public SourceBuilder(EmailTemplate email) {
|
||||
private Builder(EmailTemplate email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public SourceBuilder auth(String username, char[] password) {
|
||||
this.auth = new Authentication(username, password);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceBuilder profile(Profile profile) {
|
||||
this.profile = profile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceBuilder account(String account) {
|
||||
public Builder setAccount(String account) {
|
||||
this.account = account;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceBuilder attachPayload(boolean attachPayload) {
|
||||
public Builder setAuthentication(String username, char[] password) {
|
||||
this.auth = new Authentication(username, password);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setProfile(Profile profile) {
|
||||
this.profile = profile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAttachPayload(boolean attachPayload) {
|
||||
this.attachPayload = attachPayload;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder actionXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
email.xContentBody(builder, params);
|
||||
if (auth != null) {
|
||||
builder.field(Parser.USER_FIELD.getPreferredName(), auth.user());
|
||||
builder.field(Parser.PASSWORD_FIELD.getPreferredName(), auth.password());
|
||||
}
|
||||
if (profile != null) {
|
||||
builder.field(Parser.PROFILE_FIELD.getPreferredName(), profile);
|
||||
}
|
||||
if (account != null) {
|
||||
builder.field(Parser.ACCOUNT_FIELD.getPreferredName(), account);
|
||||
}
|
||||
if (attachPayload != null) {
|
||||
builder.field(Parser.ATTACH_PAYLOAD_FIELD.getPreferredName(), attachPayload);
|
||||
}
|
||||
return builder.endObject();
|
||||
public EmailAction build() {
|
||||
return new EmailAction(email, account, auth, profile, attachPayload);
|
||||
}
|
||||
}
|
||||
|
||||
interface Field extends Action.Field {
|
||||
|
||||
// common fields
|
||||
ParseField ACCOUNT = new ParseField("account");
|
||||
|
||||
// action fields
|
||||
ParseField PROFILE = new ParseField("profile");
|
||||
ParseField USER = new ParseField("user");
|
||||
ParseField PASSWORD = new ParseField("password");
|
||||
ParseField ATTACH_PAYLOAD = new ParseField("attach_payload");
|
||||
|
||||
// result fields
|
||||
ParseField EMAIL = new ParseField("email");
|
||||
ParseField SIMULATED_EMAIL = new ParseField("simulated_email");
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ import org.elasticsearch.watcher.actions.ActionException;
|
||||
*/
|
||||
public class EmailActionException extends ActionException {
|
||||
|
||||
public EmailActionException(String msg) {
|
||||
super(msg);
|
||||
public EmailActionException(String msg, Object... args) {
|
||||
super(msg, args);
|
||||
}
|
||||
|
||||
public EmailActionException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
public EmailActionException(String msg, Throwable cause, Object... args) {
|
||||
super(msg, cause, args);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.actions.email;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.actions.ActionFactory;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailService;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class EmailActionFactory extends ActionFactory<EmailAction, EmailAction.Result, ExecutableEmailAction> {
|
||||
|
||||
private final EmailService emailService;
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
@Inject
|
||||
public EmailActionFactory(Settings settings, EmailService emailService, TemplateEngine templateEngine) {
|
||||
super(Loggers.getLogger(ExecutableEmailAction.class, settings));
|
||||
this.emailService = emailService;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return EmailAction.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailAction parseAction(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
return EmailAction.parse(watchId, actionId, parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailAction.Result parseResult(Wid wid, String actionId, XContentParser parser) throws IOException {
|
||||
return EmailAction.Result.parse(wid.watchId(), actionId, parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableEmailAction createExecutable(EmailAction action) {
|
||||
return new ExecutableEmailAction(action, actionLogger, emailService, templateEngine);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.actions.email;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.watcher.actions.ExecutableAction;
|
||||
import org.elasticsearch.watcher.actions.email.service.Attachment;
|
||||
import org.elasticsearch.watcher.actions.email.service.Email;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailService;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ExecutableEmailAction extends ExecutableAction<EmailAction, EmailAction.Result> {
|
||||
|
||||
final EmailService emailService;
|
||||
final TemplateEngine templateEngine;
|
||||
|
||||
public ExecutableEmailAction(EmailAction action, ESLogger logger, EmailService emailService, TemplateEngine templateEngine) {
|
||||
super(action, logger);
|
||||
this.emailService = emailService;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
protected EmailAction.Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
Email.Builder email = action.getEmail().render(templateEngine, model);
|
||||
email.id(ctx.id().value());
|
||||
|
||||
if (action.isAttachPayload()) {
|
||||
Attachment.Bytes attachment = new Attachment.XContent.Yaml("payload", "payload.yml", payload);
|
||||
email.attach(attachment);
|
||||
}
|
||||
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new EmailAction.Result.Simulated(email.build());
|
||||
}
|
||||
|
||||
EmailService.EmailSent sent = emailService.send(email.build(), action.getAuth(), action.getProfile(), action.getAccount());
|
||||
return new EmailAction.Result.Success(sent.account(), sent.email());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EmailAction.Result failure(String reason) {
|
||||
return new EmailAction.Result.Failure(reason);
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -195,7 +196,7 @@ public class Email implements ToXContent {
|
||||
} else if (Field.HTML_BODY.match(currentFieldName)) {
|
||||
email.htmlBody(parser.text());
|
||||
} else {
|
||||
throw new EmailException("could not parse email. unrecognized field [" + currentFieldName + "]");
|
||||
throw new ParseException("could not parse email. unrecognized field [" + currentFieldName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -416,7 +417,7 @@ public class Email implements ToXContent {
|
||||
try {
|
||||
return new Email.Address(parser.text());
|
||||
} catch (AddressException ae) {
|
||||
throw new EmailException("could not parse [" + text + "] in field [" + field + "] as address. address must be RFC822 encoded", ae);
|
||||
throw new ParseException("could not parse [" + text + "] in field [" + field + "] as address. address must be RFC822 encoded", ae);
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,21 +434,21 @@ public class Email implements ToXContent {
|
||||
} else if (ADDRESS_NAME_FIELD.match(currentFieldName)) {
|
||||
name = parser.text();
|
||||
} else {
|
||||
throw new EmailException("could not parse [" + field + "] object as address. unknown address field [" + currentFieldName + "]");
|
||||
throw new ParseException("could not parse [" + field + "] object as address. unknown address field [" + currentFieldName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (email == null) {
|
||||
throw new EmailException("could not parse [" + field + "] as address. address object must define an [email] field");
|
||||
throw new ParseException("could not parse [" + field + "] as address. address object must define an [email] field");
|
||||
}
|
||||
try {
|
||||
return name != null ? new Email.Address(email, name) : new Email.Address(email);
|
||||
} catch (AddressException ae) {
|
||||
throw new EmailException("could not parse [" + field + "] as address", ae);
|
||||
throw new ParseException("could not parse [" + field + "] as address", ae);
|
||||
}
|
||||
|
||||
}
|
||||
throw new EmailException("could not parse [" + field + "] as address. address must either be a string (RFC822 encoded) or an object specifying the address [name] and [email]");
|
||||
throw new ParseException("could not parse [" + field + "] as address. address must either be a string (RFC822 encoded) or an object specifying the address [name] and [email]");
|
||||
}
|
||||
|
||||
public static Address parse(Settings settings, String name) {
|
||||
@ -527,7 +528,7 @@ public class Email implements ToXContent {
|
||||
try {
|
||||
return parse(parser.text());
|
||||
} catch (AddressException ae) {
|
||||
throw new EmailException("could not parse field [" + field + "] with value [" + text + "] as address list. address(es) must be RFC822 encoded", ae);
|
||||
throw new ParseException("could not parse field [" + field + "] with value [" + text + "] as address list. address(es) must be RFC822 encoded", ae);
|
||||
}
|
||||
}
|
||||
if (token == XContentParser.Token.START_ARRAY) {
|
||||
@ -537,7 +538,7 @@ public class Email implements ToXContent {
|
||||
}
|
||||
return new Email.AddressList(addresses);
|
||||
}
|
||||
throw new EmailException("could not parse [" + field + "] as address list. field must either be a string " +
|
||||
throw new ParseException("could not parse [" + field + "] as address list. field must either be a string " +
|
||||
"(comma-separated list of RFC822 encoded addresses) or an array of objects representing addresses");
|
||||
}
|
||||
|
||||
@ -559,6 +560,17 @@ public class Email implements ToXContent {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ParseException extends EmailException {
|
||||
|
||||
public ParseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public ParseException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
|
||||
interface Field {
|
||||
ParseField ID = new ParseField("id");
|
||||
ParseField FROM = new ParseField("from");
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.actions.index;
|
||||
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.watcher.actions.ExecutableAction;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExecutableIndexAction extends ExecutableAction<IndexAction, IndexAction.Result> {
|
||||
|
||||
private final ClientProxy client;
|
||||
|
||||
public ExecutableIndexAction(IndexAction action, ESLogger logger, ClientProxy client) {
|
||||
super(action, logger);
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndexAction.Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
IndexRequest indexRequest = new IndexRequest();
|
||||
indexRequest.index(action.index);
|
||||
indexRequest.type(action.docType);
|
||||
|
||||
XContentBuilder resultBuilder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
resultBuilder.startObject();
|
||||
resultBuilder.field("data", payload.data());
|
||||
resultBuilder.field("timestamp", ctx.executionTime());
|
||||
resultBuilder.endObject();
|
||||
indexRequest.source(resultBuilder);
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new IndexAction.Result.Simulated(action.index, action.docType, new Payload.Simple(indexRequest.sourceAsMap()));
|
||||
}
|
||||
|
||||
IndexResponse response = client.index(indexRequest);
|
||||
data.put("created", response.isCreated());
|
||||
data.put("id", response.getId());
|
||||
data.put("version", response.getVersion());
|
||||
data.put("type", response.getType());
|
||||
data.put("index", response.getIndex());
|
||||
return new IndexAction.Result.Executed(new Payload.Simple(data), response.isCreated());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndexAction.Result failure(String reason) {
|
||||
return new IndexAction.Result.Failure(reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,44 +5,27 @@
|
||||
*/
|
||||
package org.elasticsearch.watcher.actions.index;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
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.watcher.actions.Action;
|
||||
import org.elasticsearch.watcher.actions.ActionException;
|
||||
import org.elasticsearch.watcher.actions.ActionSettingsException;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexAction extends Action<IndexAction.Result> {
|
||||
public class IndexAction implements Action {
|
||||
|
||||
public static final String TYPE = "index";
|
||||
|
||||
private final ClientProxy client;
|
||||
|
||||
final String index;
|
||||
final String type;
|
||||
final String docType;
|
||||
|
||||
public IndexAction(ESLogger logger, ClientProxy client, String index, String type) {
|
||||
super(logger);
|
||||
this.client = client;
|
||||
public IndexAction(String index, String docType) {
|
||||
this.index = index;
|
||||
this.type = type;
|
||||
this.docType = docType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,49 +33,12 @@ public class IndexAction extends Action<IndexAction.Result> {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result execute(String actionId, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
IndexRequest indexRequest = new IndexRequest();
|
||||
indexRequest.index(index);
|
||||
indexRequest.type(type);
|
||||
try {
|
||||
XContentBuilder resultBuilder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
resultBuilder.startObject();
|
||||
resultBuilder.field("data", payload.data());
|
||||
resultBuilder.field("timestamp", ctx.executionTime());
|
||||
resultBuilder.endObject();
|
||||
indexRequest.source(resultBuilder);
|
||||
} catch (IOException ioe) {
|
||||
logger.error("failed to execute index action [{}] for watch [{}]", ioe, actionId, ctx.watch().name());
|
||||
return new Result.IndexResult(null, "failed to index payload. " + ioe.getMessage(), false);
|
||||
}
|
||||
|
||||
try {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new Result.Simulated(new Payload.Simple(indexRequest.sourceAsMap()));
|
||||
} else {
|
||||
IndexResponse response = client.index(indexRequest);
|
||||
data.put("created", response.isCreated());
|
||||
data.put("id", response.getId());
|
||||
data.put("version", response.getVersion());
|
||||
data.put("type", response.getType());
|
||||
data.put("index", response.getIndex());
|
||||
return new Result.IndexResult(new Payload.Simple(data), null, response.isCreated());
|
||||
}
|
||||
|
||||
} catch (ElasticsearchException e) {
|
||||
logger.error("failed to index result for watch [{}]", e, ctx.watch().name());
|
||||
return new Result.IndexResult(null, "failed to build index request. " + e.getMessage(), false);
|
||||
}
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.startObject()
|
||||
.field(Parser.INDEX_FIELD.getPreferredName(), index)
|
||||
.field(Parser.TYPE_FIELD.getPreferredName(), type)
|
||||
.endObject();
|
||||
public String getDocType() {
|
||||
return docType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,138 +46,77 @@ public class IndexAction extends Action<IndexAction.Result> {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
IndexAction that = (IndexAction) o;
|
||||
IndexAction action = (IndexAction) o;
|
||||
|
||||
if (index != null ? !index.equals(that.index) : that.index != null) return false;
|
||||
if (type != null ? !type.equals(that.type) : that.type != null) return false;
|
||||
|
||||
return true;
|
||||
if (!index.equals(action.index)) return false;
|
||||
return docType.equals(action.docType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = index != null ? index.hashCode() : 0;
|
||||
result = 31 * result + (type != null ? type.hashCode() : 0);
|
||||
int result = index.hashCode();
|
||||
result = 31 * result + docType.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class Parser extends AbstractComponent implements Action.Parser<Result, IndexAction> {
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.startObject()
|
||||
.field(Field.INDEX.getPreferredName(), index)
|
||||
.field(Field.DOC_TYPE.getPreferredName(), docType)
|
||||
.endObject();
|
||||
}
|
||||
|
||||
public static final ParseField INDEX_FIELD = new ParseField("index");
|
||||
public static final ParseField TYPE_FIELD = new ParseField("type");
|
||||
public static final ParseField REASON_FIELD = new ParseField("reason");
|
||||
public static final ParseField RESPONSE_FIELD = new ParseField("response");
|
||||
public static final ParseField SIMULATED_REQUEST_FIELD = new ParseField("simulated_request");
|
||||
public static IndexAction parse(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
String index = null;
|
||||
String docType = null;
|
||||
|
||||
private final ClientProxy client;
|
||||
|
||||
@Inject
|
||||
public Parser(Settings settings, ClientProxy client) {
|
||||
super(settings);
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexAction parse(XContentParser parser) throws IOException {
|
||||
String index = null;
|
||||
String type = null;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token.isValue()) {
|
||||
if (INDEX_FIELD.match(currentFieldName)) {
|
||||
index = parser.text();
|
||||
} else if (TYPE_FIELD.match(currentFieldName)) {
|
||||
type = parser.text();
|
||||
} else {
|
||||
throw new ActionSettingsException("could not parse index action. unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (Field.INDEX.match(currentFieldName)) {
|
||||
index = parser.text();
|
||||
} else if (Field.DOC_TYPE.match(currentFieldName)) {
|
||||
docType = parser.text();
|
||||
} else {
|
||||
throw new ActionSettingsException("could not parse index action. unexpected token [" + token + "]");
|
||||
throw new IndexActionException("could not parse [{}] action [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else {
|
||||
throw new IndexActionException("could not parse [{}] action [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
||||
}
|
||||
|
||||
if (index == null) {
|
||||
throw new ActionSettingsException("could not parse index action. [index] is required");
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
throw new ActionSettingsException("could not parse index action. [type] is required");
|
||||
}
|
||||
|
||||
return new IndexAction(logger, client, index, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result parseResult(XContentParser parser) throws IOException {
|
||||
Boolean success = null;
|
||||
Payload payload = null;
|
||||
String reason = null;
|
||||
Payload simulatedRequest = null;
|
||||
XContentParser.Token token;
|
||||
String currentFieldName = null;
|
||||
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token.isValue()) {
|
||||
if (REASON_FIELD.match(currentFieldName)) {
|
||||
reason = parser.text();
|
||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
if (Action.Result.SUCCESS_FIELD.match(currentFieldName)) {
|
||||
success = parser.booleanValue();
|
||||
} else {
|
||||
throw new ActionException("could not parse index result. unexpected boolean field [" + currentFieldName + "]");
|
||||
}
|
||||
} else {
|
||||
throw new ActionException("could not parse index result. unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (RESPONSE_FIELD.match(currentFieldName)) {
|
||||
payload = new Payload.Simple(parser.map());
|
||||
} else if (SIMULATED_REQUEST_FIELD.match(currentFieldName)) {
|
||||
simulatedRequest = new Payload.Simple(parser.map());
|
||||
} else {
|
||||
throw new ActionException("could not parse index result. unexpected object field [" + currentFieldName + "]");
|
||||
}
|
||||
} else {
|
||||
throw new ActionException("could not parse index result. unexpected token [" + token + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (simulatedRequest != null) {
|
||||
return new Result.Simulated(simulatedRequest);
|
||||
}
|
||||
if (success == null) {
|
||||
throw new ActionException("could not parse index result. expected boolean field [success]");
|
||||
}
|
||||
|
||||
return new Result.IndexResult(payload, reason, success);
|
||||
if (index == null) {
|
||||
throw new IndexActionException("could not parse [{}] action [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.INDEX.getPreferredName());
|
||||
}
|
||||
|
||||
if (docType == null) {
|
||||
throw new IndexActionException("could not parse [{}] action [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.DOC_TYPE.getPreferredName());
|
||||
}
|
||||
|
||||
return new IndexAction(index, docType);
|
||||
}
|
||||
|
||||
public static Builder builder(String index, String docType) {
|
||||
return new Builder(index, docType);
|
||||
}
|
||||
|
||||
public abstract static class Result extends Action.Result {
|
||||
|
||||
protected Result(String type, boolean success) {
|
||||
super(type, success);
|
||||
protected Result(boolean success) {
|
||||
super(TYPE, success);
|
||||
}
|
||||
|
||||
public static class IndexResult extends Result {
|
||||
final Payload response;
|
||||
final String reason;
|
||||
static class Executed extends Result {
|
||||
|
||||
public IndexResult(Payload response, String reason, boolean isCreated) {
|
||||
super(TYPE, isCreated);
|
||||
private final Payload response;
|
||||
|
||||
public Executed(Payload response, boolean isCreated) {
|
||||
super(isCreated);
|
||||
this.response = response;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Payload response() {
|
||||
@ -240,63 +125,169 @@ public class IndexAction extends Action<IndexAction.Result> {
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
if (reason != null) {
|
||||
builder.field(Parser.REASON_FIELD.getPreferredName(), reason);
|
||||
}
|
||||
if (response != null) {
|
||||
builder.field(Parser.RESPONSE_FIELD.getPreferredName(), response());
|
||||
builder.field(Field.RESPONSE.getPreferredName(), response());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Simulated extends Result {
|
||||
static class Failure extends Result {
|
||||
|
||||
private final Payload indexRequest;
|
||||
private final String reason;
|
||||
|
||||
protected Simulated(Payload indexRequest) {
|
||||
super(TYPE, true);
|
||||
this.indexRequest = indexRequest;
|
||||
public Failure(String reason) {
|
||||
super(false);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Payload indexRequest() {
|
||||
return indexRequest;
|
||||
public String reason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.SIMULATED_REQUEST_FIELD.getPreferredName(), indexRequest);
|
||||
return builder.field(Field.REASON.getPreferredName(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Simulated extends Result {
|
||||
|
||||
private final String index;
|
||||
private final String docType;
|
||||
private final Payload source;
|
||||
|
||||
protected Simulated(String index, String docType, Payload source) {
|
||||
super(true);
|
||||
this.index = index;
|
||||
this.docType = docType;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public String index() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public String docType() {
|
||||
return docType;
|
||||
}
|
||||
|
||||
public Payload source() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.startObject(Field.SIMULATED_REQUEST.getPreferredName())
|
||||
.field(Field.INDEX.getPreferredName(), index)
|
||||
.field(Field.DOC_TYPE.getPreferredName(), docType)
|
||||
.field(Field.SOURCE.getPreferredName(), source)
|
||||
.endObject();
|
||||
}
|
||||
}
|
||||
|
||||
public static Result parse(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
Boolean success = null;
|
||||
Payload response = null;
|
||||
String reason = null;
|
||||
Payload source = null;
|
||||
String index = null;
|
||||
String docType = null;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (Field.REASON.match(currentFieldName)) {
|
||||
reason = parser.text();
|
||||
} else {
|
||||
throw new IndexActionException("could not parse [{}] action result [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
if (Field.SUCCESS.match(currentFieldName)) {
|
||||
success = parser.booleanValue();
|
||||
} else {
|
||||
throw new IndexActionException("could not parse [{}] action result [{}/{}]. unexpected boolean field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (Field.RESPONSE.match(currentFieldName)) {
|
||||
response = new Payload.Simple(parser.map());
|
||||
} else if (Field.SIMULATED_REQUEST.match(currentFieldName)) {
|
||||
String context = currentFieldName;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (Field.INDEX.match(currentFieldName)) {
|
||||
index = parser.text();
|
||||
} else if (Field.DOC_TYPE.match(currentFieldName)) {
|
||||
docType = parser.text();
|
||||
} else {
|
||||
throw new IndexActionException("could not parse [{}] action result [{}/{}]. unexpected string field [{}.{}]", TYPE, watchId, actionId, context, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (Field.SOURCE.match(currentFieldName)) {
|
||||
source = new Payload.Simple(parser.map());
|
||||
} else {
|
||||
throw new IndexActionException("could not parse [{}] action result [{}/{}]. unexpected object field [{}.{}]", TYPE, watchId, actionId, context, currentFieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IndexActionException("could not parse [{}] action result [{}/{}]. unexpected object field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else {
|
||||
throw new IndexActionException("could not parse [{}] action result [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
||||
}
|
||||
}
|
||||
|
||||
if (index != null || docType != null || source != null) {
|
||||
assertNotNull(index, "could not parse simulated [{}] action result [{}/{}]. missing required [{}.{}] field", TYPE, watchId, actionId, Field.SIMULATED_REQUEST.getPreferredName(), Field.INDEX.getPreferredName());
|
||||
assertNotNull(docType, "could not parse simulated [{}] action result [{}/{}]. missing required [{}.{}] field", TYPE, watchId, actionId, Field.SIMULATED_REQUEST.getPreferredName(), Field.DOC_TYPE.getPreferredName());
|
||||
assertNotNull(source, "could not parse simulated [{}] action result [{}/{}]. missing required [{}.{}] field", TYPE, watchId, actionId, Field.SIMULATED_REQUEST.getPreferredName(), Field.SOURCE.getPreferredName());
|
||||
return new Simulated(index, docType, source);
|
||||
}
|
||||
|
||||
assertNotNull(success, "could not parse [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.SUCCESS.getPreferredName());
|
||||
|
||||
if (reason != null) {
|
||||
return new Failure(reason);
|
||||
}
|
||||
|
||||
assertNotNull(response, "could not parse executed [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.RESPONSE.getPreferredName());
|
||||
return new Executed(response, success);
|
||||
}
|
||||
|
||||
private static void assertNotNull(Object value, String message, Object... args) {
|
||||
if (value == null) {
|
||||
throw new IndexActionException(message, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder implements Action.Builder<IndexAction> {
|
||||
|
||||
final String index;
|
||||
final String docType;
|
||||
|
||||
public static class SourceBuilder extends Action.SourceBuilder<SourceBuilder> {
|
||||
|
||||
private final String index;
|
||||
private final String type;
|
||||
|
||||
public SourceBuilder(String index, String type) {
|
||||
private Builder(String index, String docType) {
|
||||
this.index = index;
|
||||
this.type = type;
|
||||
this.docType = docType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder actionXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.startObject()
|
||||
.field(Parser.INDEX_FIELD.getPreferredName(), index)
|
||||
.field(Parser.TYPE_FIELD.getPreferredName(), type)
|
||||
.endObject();
|
||||
public IndexAction build() {
|
||||
return new IndexAction(index, docType);
|
||||
}
|
||||
}
|
||||
|
||||
interface Field extends Action.Field {
|
||||
ParseField INDEX = new ParseField("index");
|
||||
ParseField DOC_TYPE = new ParseField("doc_type");
|
||||
ParseField SOURCE = new ParseField("source");
|
||||
ParseField RESPONSE = new ParseField("response");
|
||||
ParseField SIMULATED_REQUEST = new ParseField("simulated_request");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.actions.index;
|
||||
|
||||
import org.elasticsearch.watcher.actions.ActionException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexActionException extends ActionException {
|
||||
|
||||
public IndexActionException(String msg, Object... args) {
|
||||
super(msg, args);
|
||||
}
|
||||
|
||||
public IndexActionException(String msg, Throwable cause, Object... args) {
|
||||
super(msg, cause, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.actions.index;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.actions.ActionFactory;
|
||||
import org.elasticsearch.watcher.actions.email.ExecutableEmailAction;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexActionFactory extends ActionFactory<IndexAction, IndexAction.Result, ExecutableIndexAction> {
|
||||
|
||||
private final ClientProxy client;
|
||||
|
||||
@Inject
|
||||
public IndexActionFactory(Settings settings, ClientProxy client) {
|
||||
super(Loggers.getLogger(ExecutableEmailAction.class, settings));
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return IndexAction.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexAction parseAction(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
return IndexAction.parse(watchId, actionId, parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexAction.Result parseResult(Wid wid, String actionId, XContentParser parser) throws IOException {
|
||||
return IndexAction.Result.parse(wid.watchId(), actionId, parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableIndexAction createExecutable(IndexAction action) {
|
||||
return new ExecutableIndexAction(action, actionLogger, client);
|
||||
}
|
||||
}
|
@ -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.watcher.actions.logging;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.watcher.actions.ExecutableAction;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ExecutableLoggingAction extends ExecutableAction<LoggingAction, LoggingAction.Result> {
|
||||
|
||||
private final ESLogger textLogger;
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
ExecutableLoggingAction(LoggingAction action, ESLogger logger, Settings settings, TemplateEngine templateEngine) {
|
||||
super(action, logger);
|
||||
this.textLogger = action.category != null ? Loggers.getLogger(action.category, settings) : logger;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
// for tests
|
||||
ExecutableLoggingAction(LoggingAction action, ESLogger logger, ESLogger textLogger, TemplateEngine templateEngine) {
|
||||
super(action, logger);
|
||||
this.textLogger = textLogger;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
ESLogger textLogger() {
|
||||
return textLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggingAction.Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
String loggedText = templateEngine.render(action.text, model);
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new LoggingAction.Result.Simulated(loggedText);
|
||||
}
|
||||
|
||||
action.level.log(textLogger, loggedText);
|
||||
return new LoggingAction.Result.Success(loggedText);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggingAction.Result failure(String reason) {
|
||||
return new LoggingAction.Result.Failure(reason);
|
||||
}
|
||||
}
|
@ -7,56 +7,29 @@ package org.elasticsearch.watcher.actions.logging;
|
||||
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.actions.Action;
|
||||
import org.elasticsearch.watcher.actions.ActionException;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.template.Template;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class LoggingAction extends Action<LoggingAction.Result> {
|
||||
public class LoggingAction implements Action {
|
||||
|
||||
public static final String TYPE = "logging";
|
||||
|
||||
private final Template text;
|
||||
private final @Nullable String category;
|
||||
private final @Nullable LoggingLevel level;
|
||||
final Template text;
|
||||
final @Nullable LoggingLevel level;
|
||||
final @Nullable String category;
|
||||
|
||||
private final ESLogger actionLogger;
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
public LoggingAction(ESLogger logger, Template text, @Nullable String category, @Nullable LoggingLevel level, Settings settings, TemplateEngine templateEngine) {
|
||||
super(logger);
|
||||
public LoggingAction(Template text, @Nullable LoggingLevel level, @Nullable String category) {
|
||||
this.text = text;
|
||||
this.category = category;
|
||||
this.level = level != null ? level : LoggingLevel.INFO;
|
||||
this.actionLogger = category != null ? Loggers.getLogger(category, settings) : logger;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
// for tests
|
||||
LoggingAction(ESLogger logger, Template text, @Nullable String category, @Nullable LoggingLevel level, ESLogger actionLogger, TemplateEngine templateEngine) {
|
||||
super(logger);
|
||||
this.text = text;
|
||||
this.category = category;
|
||||
this.level = level != null ? level : LoggingLevel.INFO;
|
||||
this.actionLogger = actionLogger;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -64,68 +37,79 @@ public class LoggingAction extends Action<LoggingAction.Result> {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
Template text() {
|
||||
return text;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
String category() {
|
||||
return category;
|
||||
}
|
||||
LoggingAction action = (LoggingAction) o;
|
||||
|
||||
LoggingLevel level() {
|
||||
return level;
|
||||
}
|
||||
|
||||
ESLogger logger() {
|
||||
return actionLogger;
|
||||
if (!text.equals(action.text)) return false;
|
||||
if (level != action.level) return false;
|
||||
return !(category != null ? !category.equals(action.category) : action.category != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result execute(String actionId, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
try {
|
||||
return doExecute(actionId, ctx, payload);
|
||||
} catch (Exception e) {
|
||||
return new Result.Failure("failed to execute [logging] action. error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
String loggedText = templateEngine.render(text, model);
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new Result.Simulated(loggedText);
|
||||
}
|
||||
|
||||
level.log(actionLogger, loggedText);
|
||||
return new Result.Success(loggedText);
|
||||
|
||||
public int hashCode() {
|
||||
int result = text.hashCode();
|
||||
result = 31 * result + (level != null ? level.hashCode() : 0);
|
||||
result = 31 * result + (category != null ? category.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
if (category != null) {
|
||||
builder.field(Parser.CATEGORY_FIELD.getPreferredName(), category);
|
||||
builder.field(Field.CATEGORY.getPreferredName(), category);
|
||||
}
|
||||
builder.field(Parser.LEVEL_FIELD.getPreferredName(), level);
|
||||
builder.field(Parser.TEXT_FIELD.getPreferredName(), text);
|
||||
builder.field(Field.LEVEL.getPreferredName(), level);
|
||||
builder.field(Field.TEXT.getPreferredName(), text);
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
LoggingAction action = (LoggingAction) o;
|
||||
return Objects.equals(text, action.text) &&
|
||||
Objects.equals(category, action.category) &&
|
||||
Objects.equals(level, action.level);
|
||||
public static LoggingAction parse(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
String category = null;
|
||||
LoggingLevel level = null;
|
||||
Template text = null;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (Field.TEXT.match(currentFieldName)) {
|
||||
try {
|
||||
text = Template.parse(parser);
|
||||
} catch (Template.ParseException pe) {
|
||||
throw new LoggingActionException("failed to parse [{}] action [{}/{}]. failed to parse [{}] field", pe, TYPE, watchId, actionId, Field.TEXT.getPreferredName());
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (Field.CATEGORY.match(currentFieldName)) {
|
||||
category = parser.text();
|
||||
} else if (Field.LEVEL.match(currentFieldName)) {
|
||||
try {
|
||||
level = LoggingLevel.valueOf(parser.text().toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new LoggingActionException("failed to parse [{}] action [{}/{}]. unknown logging level [{}]", TYPE, watchId, actionId, parser.text());
|
||||
}
|
||||
} else {
|
||||
throw new LoggingActionException("failed to parse [{}] action [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else {
|
||||
throw new LoggingActionException("failed to parse [{}] action [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
||||
}
|
||||
}
|
||||
|
||||
if (text == null) {
|
||||
throw new LoggingActionException("failed to parse [{}] action [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.TEXT.getPreferredName());
|
||||
}
|
||||
|
||||
return new LoggingAction(text, level, category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(text, category, level);
|
||||
public static Builder builder(Template template) {
|
||||
return new Builder(template);
|
||||
}
|
||||
|
||||
public static abstract class Result extends Action.Result {
|
||||
@ -149,7 +133,7 @@ public class LoggingAction extends Action<LoggingAction.Result> {
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.LOGGED_TEXT_FIELD.getPreferredName(), loggedText);
|
||||
return builder.field(Field.LOGGED_TEXT.getPreferredName(), loggedText);
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,7 +152,7 @@ public class LoggingAction extends Action<LoggingAction.Result> {
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.REASON_FIELD.getPreferredName(), reason);
|
||||
return builder.field(Field.REASON.getPreferredName(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,81 +171,11 @@ public class LoggingAction extends Action<LoggingAction.Result> {
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.SIMULATED_LOGGED_TEXT_FIELD.getPreferredName(), loggedText);
|
||||
return builder.field(Field.SIMULATED_LOGGED_TEXT.getPreferredName(), loggedText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Parser implements Action.Parser<LoggingAction.Result, LoggingAction> {
|
||||
|
||||
static final ParseField CATEGORY_FIELD = new ParseField("category");
|
||||
static final ParseField LEVEL_FIELD = new ParseField("level");
|
||||
static final ParseField TEXT_FIELD = new ParseField("text");
|
||||
static final ParseField LOGGED_TEXT_FIELD = new ParseField("logged_text");
|
||||
static final ParseField SIMULATED_LOGGED_TEXT_FIELD = new ParseField("simulated_logged_text");
|
||||
static final ParseField REASON_FIELD = new ParseField("reason");
|
||||
|
||||
private final Settings settings;
|
||||
private final TemplateEngine templateEngine;
|
||||
private final ESLogger logger;
|
||||
|
||||
@Inject
|
||||
public Parser(Settings settings, TemplateEngine templateEngine) {
|
||||
this.settings = settings;
|
||||
this.logger = Loggers.getLogger(LoggingAction.class, settings);
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoggingAction parse(XContentParser parser) throws IOException {
|
||||
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
|
||||
|
||||
String category = null;
|
||||
LoggingLevel level = LoggingLevel.INFO;
|
||||
Template text = null;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (TEXT_FIELD.match(currentFieldName)) {
|
||||
try {
|
||||
text = Template.parse(parser);
|
||||
} catch (Template.ParseException pe) {
|
||||
throw new LoggingActionException("failed to parse [logging] action. failed to parse text template", pe);
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (CATEGORY_FIELD.match(currentFieldName)) {
|
||||
category = parser.text();
|
||||
} else if (LEVEL_FIELD.match(currentFieldName)) {
|
||||
try {
|
||||
level = LoggingLevel.valueOf(parser.text().toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new LoggingActionException("failed to parse [logging] action. unknown logging level [" + parser.text() + "]");
|
||||
}
|
||||
} else {
|
||||
throw new LoggingActionException("failed to parse [logging] action. unexpected string field [" + currentFieldName + "]");
|
||||
}
|
||||
} else {
|
||||
throw new LoggingActionException("failed to parse [logging] action. unexpected token [" + token + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (text == null) {
|
||||
throw new LoggingActionException("failed to parse [logging] action. missing [text] field");
|
||||
}
|
||||
|
||||
return new LoggingAction(logger, text, category, level, settings, templateEngine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoggingAction.Result parseResult(XContentParser parser) throws IOException {
|
||||
public static Result parse(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
Boolean success = null;
|
||||
String loggedText = null;
|
||||
String simulatedLoggedText = null;
|
||||
@ -273,88 +187,79 @@ public class LoggingAction extends Action<LoggingAction.Result> {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (LOGGED_TEXT_FIELD.match(currentFieldName)) {
|
||||
if (Field.LOGGED_TEXT.match(currentFieldName)) {
|
||||
loggedText = parser.text();
|
||||
} else if (SIMULATED_LOGGED_TEXT_FIELD.match(currentFieldName)) {
|
||||
} else if (Field.SIMULATED_LOGGED_TEXT.match(currentFieldName)) {
|
||||
simulatedLoggedText = parser.text();
|
||||
} else if (REASON_FIELD.match(currentFieldName)) {
|
||||
} else if (Field.REASON.match(currentFieldName)) {
|
||||
reason = parser.text();
|
||||
} else {
|
||||
throw new LoggingActionException("could not parse [logging] result. unexpected string field [" + currentFieldName + "]");
|
||||
throw new LoggingActionException("could not parse [{}] action result [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
if (Action.Result.SUCCESS_FIELD.match(currentFieldName)) {
|
||||
success = parser.booleanValue();
|
||||
}else {
|
||||
throw new LoggingActionException("could not parse [logging] result. unexpected boolean field [" + currentFieldName + "]");
|
||||
}
|
||||
if (Field.SUCCESS.match(currentFieldName)) {
|
||||
success = parser.booleanValue();
|
||||
} else {
|
||||
throw new LoggingActionException("could not parse [{}] action result [{}/{}]. unexpected boolean field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else {
|
||||
throw new LoggingActionException("could not parse [logging] result. unexpected token [" + token + "]");
|
||||
throw new LoggingActionException("could not parse [{}] action result [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
||||
}
|
||||
}
|
||||
|
||||
if (success == null) {
|
||||
throw new LoggingActionException("could not parse [logging] result. expected boolean field [success]");
|
||||
throw new LoggingActionException("could not parse [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.SUCCESS.getPreferredName());
|
||||
}
|
||||
|
||||
if (simulatedLoggedText != null) {
|
||||
return new Result.Simulated(simulatedLoggedText);
|
||||
return new LoggingAction.Result.Simulated(simulatedLoggedText);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (loggedText == null) {
|
||||
throw new LoggingActionException("could not parse successful [logging] result. expected string field [logged_text]");
|
||||
throw new LoggingActionException("could not parse successful [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.LOGGED_TEXT.getPreferredName());
|
||||
}
|
||||
return new Result.Success(loggedText);
|
||||
return new LoggingAction.Result.Success(loggedText);
|
||||
}
|
||||
|
||||
if (reason == null) {
|
||||
throw new LoggingActionException("could not parse failed [logging] result. expected string field [reason]");
|
||||
throw new LoggingActionException("could not parse failed [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, Field.REASON.getPreferredName());
|
||||
}
|
||||
|
||||
return new Result.Failure(reason);
|
||||
return new LoggingAction.Result.Failure(reason);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SourceBuilder extends Action.SourceBuilder<SourceBuilder> {
|
||||
public static class Builder implements Action.Builder<LoggingAction> {
|
||||
|
||||
private Template text;
|
||||
private String category;
|
||||
private LoggingLevel level;
|
||||
final Template text;
|
||||
LoggingLevel level;
|
||||
@Nullable String category;
|
||||
|
||||
public SourceBuilder(Template text) {
|
||||
private Builder(Template text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public SourceBuilder category(String category) {
|
||||
this.category = category;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceBuilder level(LoggingLevel level) {
|
||||
public Builder setLevel(LoggingLevel level) {
|
||||
this.level = level;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCategory(String category) {
|
||||
this.category = category;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XContentBuilder actionXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (text == null) {
|
||||
throw new ActionException("could not build logging action source. [text] must be defined");
|
||||
}
|
||||
builder.startObject();
|
||||
builder.field(Parser.TEXT_FIELD.getPreferredName(), text);
|
||||
if (category != null) {
|
||||
builder.field(Parser.CATEGORY_FIELD.getPreferredName(), category);
|
||||
}
|
||||
if (level != null) {
|
||||
builder.field(Parser.LEVEL_FIELD.getPreferredName(), level);
|
||||
}
|
||||
return builder.endObject();
|
||||
public LoggingAction build() {
|
||||
return new LoggingAction(text, level, category);
|
||||
}
|
||||
}
|
||||
|
||||
interface Field extends Action.Field {
|
||||
ParseField CATEGORY = new ParseField("category");
|
||||
ParseField LEVEL = new ParseField("level");
|
||||
ParseField TEXT = new ParseField("text");
|
||||
ParseField LOGGED_TEXT = new ParseField("logged_text");
|
||||
ParseField SIMULATED_LOGGED_TEXT = new ParseField("simulated_logged_text");
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ import org.elasticsearch.watcher.actions.ActionException;
|
||||
*/
|
||||
public class LoggingActionException extends ActionException {
|
||||
|
||||
public LoggingActionException(String msg) {
|
||||
super(msg);
|
||||
public LoggingActionException(String msg, Object... args) {
|
||||
super(msg, args);
|
||||
}
|
||||
|
||||
public LoggingActionException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
public LoggingActionException(String msg, Throwable cause, Object... args) {
|
||||
super(msg, cause, args);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.actions.logging;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.actions.ActionFactory;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class LoggingActionFactory extends ActionFactory<LoggingAction, LoggingAction.Result, ExecutableLoggingAction> {
|
||||
|
||||
private final Settings settings;
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
@Inject
|
||||
public LoggingActionFactory(Settings settings, TemplateEngine templateEngine) {
|
||||
super(Loggers.getLogger(ExecutableLoggingAction.class, settings));
|
||||
this.settings = settings;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return LoggingAction.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoggingAction parseAction(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
return LoggingAction.parse(watchId, actionId, parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoggingAction.Result parseResult(Wid wid, String actionId, XContentParser parser) throws IOException {
|
||||
return LoggingAction.Result.parse(wid.watchId(), actionId, parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableLoggingAction createExecutable(LoggingAction action) {
|
||||
return new ExecutableLoggingAction(action, actionLogger, settings, templateEngine);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.actions.webhook;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.watcher.actions.ExecutableAction;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.http.HttpClient;
|
||||
import org.elasticsearch.watcher.support.http.HttpRequest;
|
||||
import org.elasticsearch.watcher.support.http.HttpResponse;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ExecutableWebhookAction extends ExecutableAction<WebhookAction, WebhookAction.Result> {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
public ExecutableWebhookAction(WebhookAction action, ESLogger logger, HttpClient httpClient, TemplateEngine templateEngine) {
|
||||
super(action, logger);
|
||||
this.httpClient = httpClient;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WebhookAction.Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
HttpRequest request = action.requestTemplate.render(templateEngine, model);
|
||||
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new WebhookAction.Result.Simulated(request);
|
||||
}
|
||||
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
|
||||
int status = response.status();
|
||||
if (status >= 300) {
|
||||
logger.warn("received http status [{}] when connecting to watch action [{}/{}/{}]", status, ctx.watch().name(), type(), actionId);
|
||||
}
|
||||
return new WebhookAction.Result.Executed(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WebhookAction.Result failure(String reason) {
|
||||
return new WebhookAction.Result.Failure(reason);
|
||||
}
|
||||
}
|
@ -6,47 +6,27 @@
|
||||
package org.elasticsearch.watcher.actions.webhook;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.actions.Action;
|
||||
import org.elasticsearch.watcher.actions.ActionException;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.support.Variables;
|
||||
import org.elasticsearch.watcher.support.http.HttpClient;
|
||||
import org.elasticsearch.watcher.support.http.HttpRequest;
|
||||
import org.elasticsearch.watcher.support.http.HttpRequestTemplate;
|
||||
import org.elasticsearch.watcher.support.http.HttpResponse;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class WebhookAction extends Action<WebhookAction.Result> {
|
||||
public class WebhookAction implements Action {
|
||||
|
||||
public static final String TYPE = "webhook";
|
||||
|
||||
private final HttpClient httpClient;
|
||||
final HttpRequestTemplate requestTemplate;
|
||||
|
||||
private final HttpRequestTemplate requestTemplate;
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
public WebhookAction(ESLogger logger, HttpClient httpClient, HttpRequestTemplate requestTemplate, TemplateEngine templateEngine) {
|
||||
super(logger);
|
||||
this.httpClient = httpClient;
|
||||
public WebhookAction(HttpRequestTemplate requestTemplate) {
|
||||
this.requestTemplate = requestTemplate;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
public HttpRequestTemplate requestTemplate() {
|
||||
return requestTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -54,32 +34,8 @@ public class WebhookAction extends Action<WebhookAction.Result> {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result execute(String actionId, WatchExecutionContext ctx, Payload payload) throws IOException {
|
||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||
|
||||
HttpRequest request = requestTemplate.render(templateEngine, model);
|
||||
try {
|
||||
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new Result.Simulated(request);
|
||||
}
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
|
||||
int status = response.status();
|
||||
if (status >= 300) {
|
||||
logger.warn("received http status [{}] when connecting to [{}] [{}]", status, request.host(), request.path());
|
||||
}
|
||||
return new Result.Executed(request, response);
|
||||
} catch (IOException ioe) {
|
||||
logger.error("failed to execute webhook action [{}]. could not connect to [{}]", ioe, actionId, ctx.watch().name(), request.toString());
|
||||
return new Result.Failure("failed to send http request. " + ioe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return requestTemplate.toXContent(builder, params);
|
||||
public HttpRequestTemplate getRequest() {
|
||||
return requestTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -87,23 +43,38 @@ public class WebhookAction extends Action<WebhookAction.Result> {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
WebhookAction that = (WebhookAction) o;
|
||||
WebhookAction action = (WebhookAction) o;
|
||||
|
||||
if (requestTemplate != null ? !requestTemplate.equals(that.requestTemplate) : that.requestTemplate != null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return requestTemplate.equals(action.requestTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return requestTemplate != null ? requestTemplate.hashCode() : 0;
|
||||
return requestTemplate.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return requestTemplate.toXContent(builder, params);
|
||||
}
|
||||
|
||||
public static WebhookAction parse(String watchId, String actionId, XContentParser parser, HttpRequestTemplate.Parser requestParser) throws IOException {
|
||||
try {
|
||||
HttpRequestTemplate request = requestParser.parse(parser);
|
||||
return new WebhookAction(request);
|
||||
} catch (HttpRequestTemplate.ParseException pe) {
|
||||
throw new WebhookActionException("could not parse [{}] action [{}/{}]. failed parsing http request template", pe, TYPE, watchId, actionId);
|
||||
}
|
||||
}
|
||||
|
||||
public static Builder builder(HttpRequestTemplate requestTemplate) {
|
||||
return new Builder(requestTemplate);
|
||||
}
|
||||
|
||||
public abstract static class Result extends Action.Result {
|
||||
|
||||
public Result(String type, boolean success) {
|
||||
super(type, success);
|
||||
public Result(boolean success) {
|
||||
super(TYPE, success);
|
||||
}
|
||||
|
||||
public static class Executed extends Result {
|
||||
@ -112,7 +83,7 @@ public class WebhookAction extends Action<WebhookAction.Result> {
|
||||
private final HttpResponse response;
|
||||
|
||||
public Executed(HttpRequest request, HttpResponse response) {
|
||||
super(TYPE, response.status() < 400);
|
||||
super(response.status() < 400);
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
@ -127,18 +98,18 @@ public class WebhookAction extends Action<WebhookAction.Result> {
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.REQUEST_FIELD.getPreferredName(), request)
|
||||
.field(Parser.RESPONSE_FIELD.getPreferredName(), response);
|
||||
return builder.field(Field.REQUEST.getPreferredName(), request)
|
||||
.field(Field.RESPONSE.getPreferredName(), response);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Failure extends Result {
|
||||
static class Failure extends Result {
|
||||
|
||||
private final String reason;
|
||||
|
||||
public Failure(String reason) {
|
||||
super(TYPE, false);
|
||||
this.reason = reason;
|
||||
Failure(String reason, Object... args) {
|
||||
super(false);
|
||||
this.reason = LoggerMessageFormat.format(reason, args);
|
||||
}
|
||||
|
||||
public String reason() {
|
||||
@ -147,15 +118,16 @@ public class WebhookAction extends Action<WebhookAction.Result> {
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(WebhookAction.Parser.REASON_FIELD.getPreferredName(), reason);
|
||||
return builder.field(Field.REASON.getPreferredName(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Simulated extends Result {
|
||||
static class Simulated extends Result {
|
||||
|
||||
private final HttpRequest request;
|
||||
|
||||
public Simulated(HttpRequest request) {
|
||||
super(TYPE, true);
|
||||
super(true);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@ -165,53 +137,11 @@ public class WebhookAction extends Action<WebhookAction.Result> {
|
||||
|
||||
@Override
|
||||
protected XContentBuilder xContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(Parser.SIMULATED_REQUEST_FIELD.getPreferredName(), request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Parser extends AbstractComponent implements Action.Parser<Result, WebhookAction> {
|
||||
|
||||
public static final ParseField REQUEST_FIELD = new ParseField("request");
|
||||
public static final ParseField SIMULATED_REQUEST_FIELD = new ParseField("simulated_request");
|
||||
public static final ParseField RESPONSE_FIELD = new ParseField("response");
|
||||
public static final ParseField REASON_FIELD = new ParseField("reason");
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final HttpRequest.Parser requestParser;
|
||||
private final HttpRequestTemplate.Parser requestTemplateParser;
|
||||
private final TemplateEngine templateEngine;
|
||||
private final ESLogger actionLogger;
|
||||
|
||||
@Inject
|
||||
public Parser(Settings settings, HttpClient httpClient, HttpRequest.Parser requestParser,
|
||||
HttpRequestTemplate.Parser requestTemplateParser, TemplateEngine templateEngine) {
|
||||
super(settings);
|
||||
this.httpClient = httpClient;
|
||||
this.requestParser = requestParser;
|
||||
this.requestTemplateParser = requestTemplateParser;
|
||||
this.templateEngine = templateEngine;
|
||||
this.actionLogger = Loggers.getLogger(WebhookAction.class, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebhookAction parse(XContentParser parser) throws IOException {
|
||||
try {
|
||||
HttpRequestTemplate request = requestTemplateParser.parse(parser);
|
||||
return new WebhookAction(actionLogger, httpClient, request, templateEngine);
|
||||
} catch (HttpRequestTemplate.ParseException pe) {
|
||||
throw new ActionException("could not parse webhook action", pe);
|
||||
return builder.field(Field.SIMULATED_REQUEST.getPreferredName(), request);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result parseResult(XContentParser parser) throws IOException {
|
||||
public static Result parse(String watchId, String actionId, XContentParser parser, HttpRequest.Parser requestParser) throws IOException {
|
||||
Boolean success = null;
|
||||
String reason = null;
|
||||
HttpRequest request = null;
|
||||
@ -223,62 +153,82 @@ public class WebhookAction extends Action<WebhookAction.Result> {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (REQUEST_FIELD.match(currentFieldName)) {
|
||||
} else if (Field.REQUEST.match(currentFieldName)) {
|
||||
try {
|
||||
request = requestParser.parse(parser);
|
||||
} else if (SIMULATED_REQUEST_FIELD.match(currentFieldName)) {
|
||||
} catch (HttpRequest.Parser.ParseException pe) {
|
||||
throw new WebhookActionException("could not parse [{}] action result [{}/{}]. failed parsing [{}] field", pe, TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (Field.SIMULATED_REQUEST.match(currentFieldName)) {
|
||||
try {
|
||||
simulatedRequest = requestParser.parse(parser);
|
||||
} else if (RESPONSE_FIELD.match(currentFieldName)) {
|
||||
} catch (HttpRequest.Parser.ParseException pe) {
|
||||
throw new WebhookActionException("could not parse [{}] action result [{}/{}]. failed parsing [{}] field", pe, TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (Field.RESPONSE.match(currentFieldName)) {
|
||||
try {
|
||||
response = HttpResponse.parse(parser);
|
||||
} else {
|
||||
throw new ActionException("unable to parse webhook action result. unexpected object field [" + currentFieldName + "]");
|
||||
} catch (HttpResponse.ParseException pe) {
|
||||
throw new WebhookActionException("could not parse [{}] action result [{}/{}]. failed parsing [{}] field", pe, TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (REASON_FIELD.match(currentFieldName)) {
|
||||
if (Field.REASON.match(currentFieldName)) {
|
||||
reason = parser.text();
|
||||
} else {
|
||||
throw new ActionException("unable to parse webhook action result. unexpected string field [" + currentFieldName + "]");
|
||||
throw new WebhookActionException("could not parse [{}] action result [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
if (Action.Result.SUCCESS_FIELD.match(currentFieldName)) {
|
||||
if (Field.SUCCESS.match(currentFieldName)) {
|
||||
success = parser.booleanValue();
|
||||
} else {
|
||||
throw new ActionException("unable to parse webhook action result. unexpected boolean field [" + currentFieldName + "]");
|
||||
throw new WebhookActionException("could not parse [{}] action result [{}/{}]. unexpected boolean field [{}]", TYPE, watchId, actionId, watchId, currentFieldName);
|
||||
}
|
||||
} else {
|
||||
throw new ActionException("unable to parse webhook action result. unexpected token [" + token + "]" );
|
||||
throw new WebhookActionException("could not parse [{}] action result [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
||||
}
|
||||
}
|
||||
|
||||
if (success == null) {
|
||||
throw new ActionException("could not parse webhook result. expected boolean field [success]");
|
||||
throw new WebhookActionException("could not parse [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, currentFieldName, Field.SUCCESS.getPreferredName());
|
||||
}
|
||||
|
||||
if (simulatedRequest != null) {
|
||||
return new Result.Simulated(simulatedRequest);
|
||||
return new Simulated(simulatedRequest);
|
||||
}
|
||||
|
||||
return (reason == null) ? new Result.Executed(request, response) : new Result.Failure(reason);
|
||||
if (reason != null) {
|
||||
return new Failure(reason);
|
||||
}
|
||||
|
||||
if (request == null) {
|
||||
throw new WebhookActionException("could not parse executed [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, currentFieldName, Field.REQUEST.getPreferredName());
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
throw new WebhookActionException("could not parse executed [{}] action result [{}/{}]. missing required [{}] field", TYPE, watchId, actionId, currentFieldName, Field.RESPONSE.getPreferredName());
|
||||
}
|
||||
|
||||
return new Executed(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SourceBuilder extends Action.SourceBuilder<SourceBuilder> {
|
||||
public static class Builder implements Action.Builder<WebhookAction> {
|
||||
|
||||
private final HttpRequestTemplate requestTemplate;
|
||||
final HttpRequestTemplate requestTemplate;
|
||||
|
||||
public SourceBuilder(HttpRequestTemplate requestTemplate) {
|
||||
private Builder(HttpRequestTemplate requestTemplate) {
|
||||
this.requestTemplate = requestTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder actionXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return requestTemplate.toXContent(builder, params);
|
||||
|
||||
public WebhookAction build() {
|
||||
return new WebhookAction(requestTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
interface Field extends Action.Field {
|
||||
ParseField REQUEST = new ParseField("request");
|
||||
ParseField SIMULATED_REQUEST = new ParseField("simulated_request");
|
||||
ParseField RESPONSE = new ParseField("response");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.actions.webhook;
|
||||
|
||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||
import org.elasticsearch.watcher.actions.ActionException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class WebhookActionException extends ActionException {
|
||||
|
||||
public WebhookActionException(String msg, Object... args) {
|
||||
super(LoggerMessageFormat.format(msg, args));
|
||||
}
|
||||
|
||||
public WebhookActionException(String msg, Throwable cause, Object... args) {
|
||||
super(LoggerMessageFormat.format(msg, args), cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.actions.webhook;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.actions.ActionFactory;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.http.HttpClient;
|
||||
import org.elasticsearch.watcher.support.http.HttpRequest;
|
||||
import org.elasticsearch.watcher.support.http.HttpRequestTemplate;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class WebhookActionFactory extends ActionFactory<WebhookAction, WebhookAction.Result, ExecutableWebhookAction> {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final HttpRequest.Parser requestParser;
|
||||
private final HttpRequestTemplate.Parser requestTemplateParser;
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
@Inject
|
||||
public WebhookActionFactory(Settings settings, HttpClient httpClient, HttpRequest.Parser requestParser,
|
||||
HttpRequestTemplate.Parser requestTemplateParser, TemplateEngine templateEngine) {
|
||||
|
||||
super(Loggers.getLogger(ExecutableWebhookAction.class, settings));
|
||||
this.httpClient = httpClient;
|
||||
this.requestParser = requestParser;
|
||||
this.requestTemplateParser = requestTemplateParser;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return WebhookAction.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebhookAction parseAction(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
return WebhookAction.parse(watchId, actionId, parser, requestTemplateParser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebhookAction.Result parseResult(Wid wid, String actionId, XContentParser parser) throws IOException {
|
||||
return WebhookAction.Result.parse(wid.watchId(), actionId, parser, requestParser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableWebhookAction createExecutable(WebhookAction action) {
|
||||
return new ExecutableWebhookAction(action, actionLogger, httpClient, templateEngine);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.elasticsearch.watcher.client;
|
||||
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
@ -35,7 +36,7 @@ public class WatchSourceBuilder implements ToXContent {
|
||||
private Input.SourceBuilder input = NoneInput.SourceBuilder.INSTANCE;
|
||||
private Condition.SourceBuilder condition = ConditionBuilders.alwaysTrueCondition();
|
||||
private Transform.SourceBuilder transform = null;
|
||||
private Map<String, Action.SourceBuilder> actions = new HashMap<>();
|
||||
private Map<String, TransformedAction> actions = new HashMap<>();
|
||||
private TimeValue throttlePeriod = null;
|
||||
private Map<String, Object> metadata;
|
||||
|
||||
@ -64,11 +65,20 @@ public class WatchSourceBuilder implements ToXContent {
|
||||
return this;
|
||||
}
|
||||
|
||||
public WatchSourceBuilder addAction(String id, Action.SourceBuilder action) {
|
||||
actions.put(id, action);
|
||||
public WatchSourceBuilder addAction(String id, Transform.SourceBuilder transform, Action action) {
|
||||
actions.put(id, new TransformedAction(id, action, transform));
|
||||
return this;
|
||||
}
|
||||
|
||||
public WatchSourceBuilder addAction(String id, Action action) {
|
||||
actions.put(id, new TransformedAction(id, action));
|
||||
return this;
|
||||
}
|
||||
|
||||
public WatchSourceBuilder addAction(String id, Action.Builder action) {
|
||||
return addAction(id, action.build());
|
||||
}
|
||||
|
||||
public WatchSourceBuilder metadata(Map<String, Object> metadata) {
|
||||
this.metadata = metadata;
|
||||
return this;
|
||||
@ -104,7 +114,7 @@ public class WatchSourceBuilder implements ToXContent {
|
||||
}
|
||||
|
||||
builder.startObject(Watch.Parser.ACTIONS_FIELD.getPreferredName());
|
||||
for (Map.Entry<String, Action.SourceBuilder> entry : actions.entrySet()) {
|
||||
for (Map.Entry<String, TransformedAction> entry : actions.entrySet()) {
|
||||
builder.field(entry.getKey(), entry.getValue());
|
||||
}
|
||||
builder.endObject();
|
||||
@ -126,7 +136,36 @@ public class WatchSourceBuilder implements ToXContent {
|
||||
}
|
||||
}
|
||||
|
||||
public class BuilderException extends WatcherException {
|
||||
static class TransformedAction implements ToXContent {
|
||||
|
||||
private final String id;
|
||||
private final Action action;
|
||||
private final @Nullable Transform.SourceBuilder transform;
|
||||
|
||||
public TransformedAction(String id, Action action) {
|
||||
this(id, action, null);
|
||||
}
|
||||
|
||||
public TransformedAction(String id, Action action, @Nullable Transform.SourceBuilder transform) {
|
||||
this.id = id;
|
||||
this.transform = transform;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
if (transform != null) {
|
||||
builder.startObject(Transform.Parser.TRANSFORM_FIELD.getPreferredName())
|
||||
.field(transform.type(), transform)
|
||||
.endObject();
|
||||
}
|
||||
builder.field(action.type(), action);
|
||||
return builder.endObject();
|
||||
}
|
||||
}
|
||||
|
||||
public static class BuilderException extends WatcherException {
|
||||
|
||||
public BuilderException(String msg) {
|
||||
super(msg);
|
||||
@ -136,4 +175,5 @@ public class WatchSourceBuilder implements ToXContent {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
package org.elasticsearch.watcher.condition;
|
||||
|
||||
import org.elasticsearch.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysFalseCondition;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
|
||||
/**
|
||||
@ -20,6 +21,10 @@ public final class ConditionBuilders {
|
||||
return AlwaysTrueCondition.SourceBuilder.INSTANCE;
|
||||
}
|
||||
|
||||
public static AlwaysFalseCondition.SourceBuilder alwaysFalseCondition() {
|
||||
return AlwaysFalseCondition.SourceBuilder.INSTANCE;
|
||||
}
|
||||
|
||||
public static ScriptCondition.SourceBuilder scriptCondition() {
|
||||
return new ScriptCondition.SourceBuilder();
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
package org.elasticsearch.watcher.execution;
|
||||
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.condition.Condition;
|
||||
import org.elasticsearch.watcher.input.Input;
|
||||
@ -25,7 +25,7 @@ import java.util.Map;
|
||||
*/
|
||||
public abstract class WatchExecutionContext {
|
||||
|
||||
private final String id;
|
||||
private final Wid id;
|
||||
private final Watch watch;
|
||||
private final DateTime executionTime;
|
||||
private final TriggerEvent triggerEvent;
|
||||
@ -42,7 +42,7 @@ public abstract class WatchExecutionContext {
|
||||
this.watch = watch;
|
||||
this.executionTime = executionTime;
|
||||
this.triggerEvent = triggerEvent;
|
||||
this.id = generateId(watch.name(), triggerEvent.triggeredTime());
|
||||
this.id = new Wid(watch.name(), watch.nonce(), executionTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +55,7 @@ public abstract class WatchExecutionContext {
|
||||
*/
|
||||
public abstract boolean recordInHistory();
|
||||
|
||||
public String id() {
|
||||
public Wid id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -119,15 +119,11 @@ public abstract class WatchExecutionContext {
|
||||
actionsResults.put(result.id(), result);
|
||||
}
|
||||
|
||||
public Actions.Results actionsResults() {
|
||||
return new Actions.Results(actionsResults);
|
||||
public ExecutableActions.Results actionsResults() {
|
||||
return new ExecutableActions.Results(actionsResults);
|
||||
}
|
||||
|
||||
public WatchExecution finish() {
|
||||
return new WatchExecution(this);
|
||||
}
|
||||
|
||||
static String generateId(String name, DateTime time) {
|
||||
return name + "#" + time.toDateTimeISO();
|
||||
}
|
||||
}
|
||||
|
65
src/main/java/org/elasticsearch/watcher/execution/Wid.java
Normal file
65
src/main/java/org/elasticsearch/watcher/execution/Wid.java
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.execution;
|
||||
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.joda.time.format.DateTimeFormatter;
|
||||
import org.elasticsearch.common.joda.time.format.ISODateTimeFormat;
|
||||
import org.elasticsearch.watcher.WatcherException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Wid {
|
||||
|
||||
private static final DateTimeFormatter formatter = ISODateTimeFormat.dateTime();
|
||||
|
||||
private final String watchId;
|
||||
|
||||
private final String value;
|
||||
|
||||
public Wid(String watchId, long nonce, DateTime executionTime) {
|
||||
this.watchId = watchId;
|
||||
this.value = watchId + "_" + String.valueOf(nonce) + "#" + formatter.print(executionTime);
|
||||
}
|
||||
|
||||
public Wid(String value) {
|
||||
this.value = value;
|
||||
int index = value.lastIndexOf("_");
|
||||
if (index <= 0) {
|
||||
throw new WatcherException("invalid watcher execution id [{}]", value);
|
||||
}
|
||||
this.watchId = value.substring(0, index);
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String watchId() {
|
||||
return watchId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Wid wid = (Wid) o;
|
||||
|
||||
return value.equals(wid.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ public class HistoryStore extends AbstractComponent {
|
||||
public void put(WatchRecord watchRecord) throws HistoryException {
|
||||
String index = getHistoryIndexNameForTime(watchRecord.triggerEvent().triggeredTime());
|
||||
try {
|
||||
IndexRequest request = new IndexRequest(index, DOC_TYPE, watchRecord.id())
|
||||
IndexRequest request = new IndexRequest(index, DOC_TYPE, watchRecord.id().value())
|
||||
.source(XContentFactory.jsonBuilder().value(watchRecord))
|
||||
.opType(IndexRequest.OpType.CREATE);
|
||||
IndexResponse response = client.index(request);
|
||||
@ -74,7 +74,7 @@ public class HistoryStore extends AbstractComponent {
|
||||
logger.debug("updating watch record [{}]...", watchRecord);
|
||||
try {
|
||||
BytesReference bytes = XContentFactory.jsonBuilder().value(watchRecord).bytes();
|
||||
IndexRequest request = new IndexRequest(getHistoryIndexNameForTime(watchRecord.triggerEvent().triggeredTime()), DOC_TYPE, watchRecord.id())
|
||||
IndexRequest request = new IndexRequest(getHistoryIndexNameForTime(watchRecord.triggerEvent().triggeredTime()), DOC_TYPE, watchRecord.id().value())
|
||||
.source(bytes, true)
|
||||
.version(watchRecord.version());
|
||||
IndexResponse response = client.index(request);
|
||||
@ -126,8 +126,8 @@ public class HistoryStore extends AbstractComponent {
|
||||
response = client.searchScroll(response.getScrollId(), scrollTimeout);
|
||||
while (response.getHits().hits().length != 0) {
|
||||
for (SearchHit sh : response.getHits()) {
|
||||
String historyId = sh.getId();
|
||||
WatchRecord record = recordParser.parse(sh.getSourceRef(), historyId, sh.version());
|
||||
String id = sh.getId();
|
||||
WatchRecord record = recordParser.parse(id, sh.version(), sh.getSourceRef());
|
||||
assert record.state() == recordState;
|
||||
logger.debug("loaded watch record [{}/{}/{}]", sh.index(), sh.type(), sh.id());
|
||||
records.add(record);
|
||||
|
@ -21,6 +21,7 @@ import org.elasticsearch.watcher.WatcherSettingsException;
|
||||
import org.elasticsearch.watcher.actions.ActionRegistry;
|
||||
import org.elasticsearch.watcher.condition.Condition;
|
||||
import org.elasticsearch.watcher.condition.ConditionRegistry;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.input.Input;
|
||||
import org.elasticsearch.watcher.input.InputRegistry;
|
||||
import org.elasticsearch.watcher.transform.TransformRegistry;
|
||||
@ -36,7 +37,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class WatchRecord implements ToXContent {
|
||||
|
||||
private String id;
|
||||
private Wid id;
|
||||
private String name;
|
||||
private TriggerEvent triggerEvent;
|
||||
private Input input;
|
||||
@ -55,7 +56,7 @@ public class WatchRecord implements ToXContent {
|
||||
WatchRecord() {
|
||||
}
|
||||
|
||||
public WatchRecord(String id, Watch watch, TriggerEvent triggerEvent) {
|
||||
public WatchRecord(Wid id, Watch watch, TriggerEvent triggerEvent) {
|
||||
this.id = id;
|
||||
this.name = watch.name();
|
||||
this.triggerEvent = triggerEvent;
|
||||
@ -66,7 +67,7 @@ public class WatchRecord implements ToXContent {
|
||||
this.version = 1;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
public Wid id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -170,7 +171,7 @@ public class WatchRecord implements ToXContent {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id;
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
public enum State {
|
||||
@ -226,17 +227,17 @@ public class WatchRecord implements ToXContent {
|
||||
this.triggerService = triggerService;
|
||||
}
|
||||
|
||||
public WatchRecord parse(BytesReference source, String historyId, long version) {
|
||||
public WatchRecord parse(String id, long version, BytesReference source) {
|
||||
try (XContentParser parser = XContentHelper.createParser(source)) {
|
||||
return parse(parser, historyId, version);
|
||||
return parse(id, version, parser);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("unable to parse watch record", e);
|
||||
}
|
||||
}
|
||||
|
||||
public WatchRecord parse(XContentParser parser, String id, long version) throws IOException {
|
||||
public WatchRecord parse(String id, long version, XContentParser parser) throws IOException {
|
||||
WatchRecord record = new WatchRecord();
|
||||
record.id = id;
|
||||
record.id = new Wid(id);
|
||||
record.version = version;
|
||||
|
||||
String currentFieldName = null;
|
||||
@ -253,7 +254,7 @@ public class WatchRecord implements ToXContent {
|
||||
} else if (METADATA_FIELD.match(currentFieldName)) {
|
||||
record.metadata = parser.map();
|
||||
} else if (WATCH_EXECUTION_FIELD.match(currentFieldName)) {
|
||||
record.execution = WatchExecution.Parser.parse(parser, conditionRegistry, actionRegistry, inputRegistry, transformRegistry);
|
||||
record.execution = WatchExecution.Parser.parse(record.id, parser, conditionRegistry, actionRegistry, inputRegistry, transformRegistry);
|
||||
} else if (TRIGGER_EVENT_FIELD.match(currentFieldName)) {
|
||||
record.triggerEvent = triggerService.parseTriggerEvent(id, parser);
|
||||
} else {
|
||||
|
@ -7,6 +7,8 @@ package org.elasticsearch.watcher.input;
|
||||
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.watcher.input.http.HttpInput;
|
||||
import org.elasticsearch.watcher.input.search.SearchInput;
|
||||
import org.elasticsearch.watcher.input.simple.SimpleInput;
|
||||
@ -35,6 +37,18 @@ public final class InputBuilders {
|
||||
return simpleInput(new HashMap<String, Object>());
|
||||
}
|
||||
|
||||
public static SimpleInput.SourceBuilder simpleInput(String key, Object value) {
|
||||
return simpleInput(MapBuilder.<String, Object>newMapBuilder().put(key, value));
|
||||
}
|
||||
|
||||
public static SimpleInput.SourceBuilder simpleInput(ImmutableMap.Builder<String, Object> data) {
|
||||
return simpleInput(data.build());
|
||||
}
|
||||
|
||||
public static SimpleInput.SourceBuilder simpleInput(MapBuilder<String, Object> data) {
|
||||
return simpleInput(data.map());
|
||||
}
|
||||
|
||||
public static SimpleInput.SourceBuilder simpleInput(Map<String, Object> data) {
|
||||
return new SimpleInput.SourceBuilder(data);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ public interface Payload extends ToXContent {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "simple_input[" + Objects.toString(data) + "]";
|
||||
return "simple[" + Objects.toString(data) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.WatcherException;
|
||||
import org.elasticsearch.watcher.WatcherSettingsException;
|
||||
import org.elasticsearch.watcher.actions.ActionRegistry;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.condition.Condition;
|
||||
import org.elasticsearch.watcher.condition.ConditionRegistry;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
@ -44,6 +44,7 @@ import org.elasticsearch.watcher.trigger.TriggerService;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static org.elasticsearch.watcher.support.WatcherDateUtils.*;
|
||||
|
||||
@ -53,7 +54,7 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
||||
private final Trigger trigger;
|
||||
private final Input input;
|
||||
private final Condition condition;
|
||||
private final Actions actions;
|
||||
private final ExecutableActions actions;
|
||||
private final Throttler throttler;
|
||||
private final Status status;
|
||||
private final TimeValue throttlePeriod;
|
||||
@ -64,8 +65,10 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
||||
@Nullable
|
||||
private final Transform transform;
|
||||
|
||||
private final transient AtomicLong nonceCounter = new AtomicLong();
|
||||
|
||||
public Watch(String name, Clock clock, LicenseService licenseService, Trigger trigger, Input input, Condition condition, @Nullable Transform transform,
|
||||
Actions actions, @Nullable Map<String, Object> metadata, @Nullable TimeValue throttlePeriod, @Nullable Status status) {
|
||||
ExecutableActions actions, @Nullable Map<String, Object> metadata, @Nullable TimeValue throttlePeriod, @Nullable Status status) {
|
||||
this.name = name;
|
||||
this.trigger = trigger;
|
||||
this.input = input;
|
||||
@ -100,7 +103,7 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
||||
return throttler;
|
||||
}
|
||||
|
||||
public Actions actions() {
|
||||
public ExecutableActions actions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
@ -129,6 +132,10 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
||||
return status.ackStatus.state == Status.AckStatus.State.ACKED;
|
||||
}
|
||||
|
||||
public long nonce() {
|
||||
return nonceCounter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@ -215,11 +222,11 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
||||
}
|
||||
}
|
||||
|
||||
public Watch parse(String name, boolean includeStatus, XContentParser parser) throws IOException {
|
||||
public Watch parse(String id, boolean includeStatus, XContentParser parser) throws IOException {
|
||||
Trigger trigger = null;
|
||||
Input input = defaultInput;
|
||||
Condition condition = defaultCondition;
|
||||
Actions actions = null;
|
||||
ExecutableActions actions = null;
|
||||
Transform transform = null;
|
||||
Map<String, Object> metatdata = null;
|
||||
Status status = null;
|
||||
@ -231,16 +238,16 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == null ){
|
||||
throw new WatcherException("could not parse watch [" + name + "]. null token");
|
||||
throw new WatcherException("could not parse watch [" + id + "]. null token");
|
||||
} else if ((token.isValue() || token == XContentParser.Token.START_OBJECT || token == XContentParser.Token.START_ARRAY) && currentFieldName !=null ) {
|
||||
if (TRIGGER_FIELD.match(currentFieldName)) {
|
||||
trigger = triggerService.parseTrigger(name, parser);
|
||||
trigger = triggerService.parseTrigger(id, parser);
|
||||
} else if (INPUT_FIELD.match(currentFieldName)) {
|
||||
input = inputRegistry.parse(parser);
|
||||
} else if (CONDITION_FIELD.match(currentFieldName)) {
|
||||
condition = conditionRegistry.parse(parser);
|
||||
} else if (ACTIONS_FIELD.match(currentFieldName)) {
|
||||
actions = actionRegistry.parseActions(parser);
|
||||
actions = actionRegistry.parseActions(id, parser);
|
||||
} else if (TRANSFORM_FIELD.match(currentFieldName)) {
|
||||
transform = transformRegistry.parse(parser);
|
||||
} else if (META_FIELD.match(currentFieldName)) {
|
||||
@ -253,19 +260,19 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
||||
} else if (token == XContentParser.Token.VALUE_NUMBER) {
|
||||
throttlePeriod = TimeValue.timeValueMillis(parser.longValue());
|
||||
} else {
|
||||
throw new WatcherSettingsException("could not parse watch [" + name + "] throttle period. could not parse token [" + token + "] as time value (must either be string or number)");
|
||||
throw new WatcherSettingsException("could not parse watch [" + id + "] throttle period. could not parse token [" + token + "] as time value (must either be string or number)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trigger == null) {
|
||||
throw new WatcherSettingsException("could not parse watch [" + name + "]. missing watch trigger");
|
||||
throw new WatcherSettingsException("could not parse watch [" + id + "]. missing watch trigger");
|
||||
}
|
||||
if (actions == null) {
|
||||
throw new WatcherSettingsException("could not parse watch [" + name + "]. missing watch actions");
|
||||
throw new WatcherSettingsException("could not parse watch [" + id + "]. missing watch actions");
|
||||
}
|
||||
|
||||
return new Watch(name, clock, licenseService, trigger, input, condition, transform, actions, metatdata, throttlePeriod, status);
|
||||
return new Watch(id, clock, licenseService, trigger, input, condition, transform, actions, metatdata, throttlePeriod, status);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,11 +12,12 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.WatcherException;
|
||||
import org.elasticsearch.watcher.actions.ActionRegistry;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.condition.Condition;
|
||||
import org.elasticsearch.watcher.condition.ConditionRegistry;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.input.Input;
|
||||
import org.elasticsearch.watcher.input.InputRegistry;
|
||||
import org.elasticsearch.watcher.throttle.Throttler;
|
||||
@ -34,13 +35,13 @@ public class WatchExecution implements ToXContent {
|
||||
private final Condition.Result conditionResult;
|
||||
private final Throttler.Result throttleResult;
|
||||
private final @Nullable Transform.Result transformResult;
|
||||
private final Actions.Results actionsResults;
|
||||
private final ExecutableActions.Results actionsResults;
|
||||
|
||||
public WatchExecution(WatchExecutionContext context) {
|
||||
this(context.inputResult(), context.conditionResult(), context.throttleResult(), context.transformResult(), context.actionsResults());
|
||||
}
|
||||
|
||||
WatchExecution(Input.Result inputResult, Condition.Result conditionResult, Throttler.Result throttleResult, @Nullable Transform.Result transformResult, Actions.Results actionsResults) {
|
||||
WatchExecution(Input.Result inputResult, Condition.Result conditionResult, Throttler.Result throttleResult, @Nullable Transform.Result transformResult, ExecutableActions.Results actionsResults) {
|
||||
this.inputResult = inputResult;
|
||||
this.conditionResult = conditionResult;
|
||||
this.throttleResult = throttleResult;
|
||||
@ -64,7 +65,7 @@ public class WatchExecution implements ToXContent {
|
||||
return transformResult;
|
||||
}
|
||||
|
||||
public Actions.Results actionsResults() {
|
||||
public ExecutableActions.Results actionsResults() {
|
||||
return actionsResults;
|
||||
}
|
||||
|
||||
@ -103,11 +104,11 @@ public class WatchExecution implements ToXContent {
|
||||
public static final ParseField THROTTLED = new ParseField("throttled");
|
||||
public static final ParseField THROTTLE_REASON = new ParseField("throttle_reason");
|
||||
|
||||
public static WatchExecution parse(XContentParser parser, ConditionRegistry conditionRegistry, ActionRegistry actionRegistry,
|
||||
public static WatchExecution parse(Wid wid, XContentParser parser, ConditionRegistry conditionRegistry, ActionRegistry actionRegistry,
|
||||
InputRegistry inputRegistry, TransformRegistry transformRegistry) throws IOException {
|
||||
boolean throttled = false;
|
||||
String throttleReason = null;
|
||||
Actions.Results actionResults = null;
|
||||
ExecutableActions.Results actionResults = null;
|
||||
Input.Result inputResult = null;
|
||||
Condition.Result conditionResult = null;
|
||||
Transform.Result transformResult = null;
|
||||
@ -133,7 +134,7 @@ public class WatchExecution implements ToXContent {
|
||||
} else if (Transform.Parser.TRANSFORM_RESULT_FIELD.match(currentFieldName)) {
|
||||
transformResult = transformRegistry.parseResult(parser);
|
||||
} else if (ACTIONS_RESULTS.match(currentFieldName)) {
|
||||
actionResults = actionRegistry.parseResults(parser);
|
||||
actionResults = actionRegistry.parseResults(wid, parser);
|
||||
} else {
|
||||
throw new WatcherException("unable to parse watch execution. unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.watcher.actions.email.service.*;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.template.Template;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
@ -77,7 +78,9 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
Profile profile = randomFrom(Profile.values());
|
||||
|
||||
boolean attachPayload = randomBoolean();
|
||||
EmailAction action = new EmailAction(logger, email, auth, profile, account, attachPayload, service, engine);
|
||||
|
||||
EmailAction action = new EmailAction(email, account, auth, profile, attachPayload);
|
||||
ExecutableEmailAction executable = new ExecutableEmailAction(action, logger, service, engine);
|
||||
|
||||
final Map<String, Object> data = new HashMap<>();
|
||||
Payload payload = new Payload() {
|
||||
@ -94,9 +97,9 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
|
||||
DateTime now = DateTime.now(UTC);
|
||||
|
||||
String ctxId = randomAsciiOfLength(5);
|
||||
Wid wid = new Wid(randomAsciiOfLength(5), randomLong(), DateTime.now(UTC));
|
||||
WatchExecutionContext ctx = mockExecutionContext("watch1", now, payload);
|
||||
when(ctx.id()).thenReturn(ctxId);
|
||||
when(ctx.id()).thenReturn(wid);
|
||||
Map<String, Object> expectedModel = ImmutableMap.<String, Object>builder()
|
||||
.put("ctx", ImmutableMap.<String, Object>builder()
|
||||
.put("watch_id", "watch1")
|
||||
@ -119,13 +122,13 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
when(engine.render(htmlBody, expectedModel)).thenReturn(htmlBody.getText());
|
||||
}
|
||||
|
||||
EmailAction.Result result = action.execute("_id", ctx, payload);
|
||||
EmailAction.Result result = executable.execute("_id", ctx, payload);
|
||||
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result, instanceOf(EmailAction.Result.Success.class));
|
||||
assertThat(((EmailAction.Result.Success) result).account(), equalTo(account));
|
||||
Email actualEmail = ((EmailAction.Result.Success) result).email();
|
||||
assertThat(actualEmail.id(), is(ctxId));
|
||||
assertThat(actualEmail.id(), is(wid.value()));
|
||||
assertThat(actualEmail, notNullValue());
|
||||
assertThat(actualEmail.subject(), is(subject == null ? null : subject.getText()));
|
||||
assertThat(actualEmail.textBody(), is(textBody == null ? null : textBody.getText()));
|
||||
@ -211,34 +214,35 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(bytes);
|
||||
parser.nextToken();
|
||||
|
||||
EmailAction action = new EmailAction.Parser(ImmutableSettings.EMPTY, emailService, engine).parse(parser);
|
||||
ExecutableEmailAction executable = new EmailActionFactory(ImmutableSettings.EMPTY, emailService, engine)
|
||||
.parseExecutable(randomAsciiOfLength(8), randomAsciiOfLength(3), parser);
|
||||
|
||||
assertThat(action, notNullValue());
|
||||
assertThat(action.account, is("_account"));
|
||||
assertThat(action.attachPayload, is(attachPayload));
|
||||
assertThat(action.auth, notNullValue());
|
||||
assertThat(action.auth.user(), is("_user"));
|
||||
assertThat(action.auth.password(), is("_passwd".toCharArray()));
|
||||
assertThat(action.emailTemplate.priority(), is(new Template(priority.name())));
|
||||
assertThat(executable, notNullValue());
|
||||
assertThat(executable.action().getAccount(), is("_account"));
|
||||
assertThat(executable.action().isAttachPayload(), is(attachPayload));
|
||||
assertThat(executable.action().getAuth(), notNullValue());
|
||||
assertThat(executable.action().getAuth().user(), is("_user"));
|
||||
assertThat(executable.action().getAuth().password(), is("_passwd".toCharArray()));
|
||||
assertThat(executable.action().getEmail().priority(), is(new Template(priority.name())));
|
||||
if (to != null) {
|
||||
assertThat(action.emailTemplate.to(), arrayContainingInAnyOrder(addressesToTemplates(to)));
|
||||
assertThat(executable.action().getEmail().to(), arrayContainingInAnyOrder(addressesToTemplates(to)));
|
||||
} else {
|
||||
assertThat(action.emailTemplate.to(), nullValue());
|
||||
assertThat(executable.action().getEmail().to(), nullValue());
|
||||
}
|
||||
if (cc != null) {
|
||||
assertThat(action.emailTemplate.cc(), arrayContainingInAnyOrder(addressesToTemplates(cc)));
|
||||
assertThat(executable.action().getEmail().cc(), arrayContainingInAnyOrder(addressesToTemplates(cc)));
|
||||
} else {
|
||||
assertThat(action.emailTemplate.cc(), nullValue());
|
||||
assertThat(executable.action().getEmail().cc(), nullValue());
|
||||
}
|
||||
if (bcc != null) {
|
||||
assertThat(action.emailTemplate.bcc(), arrayContainingInAnyOrder(addressesToTemplates(bcc)));
|
||||
assertThat(executable.action().getEmail().bcc(), arrayContainingInAnyOrder(addressesToTemplates(bcc)));
|
||||
} else {
|
||||
assertThat(action.emailTemplate.bcc(), nullValue());
|
||||
assertThat(executable.action().getEmail().bcc(), nullValue());
|
||||
}
|
||||
if (replyTo != null) {
|
||||
assertThat(action.emailTemplate.replyTo(), arrayContainingInAnyOrder(addressesToTemplates(replyTo)));
|
||||
assertThat(executable.action().getEmail().replyTo(), arrayContainingInAnyOrder(addressesToTemplates(replyTo)));
|
||||
} else {
|
||||
assertThat(action.emailTemplate.replyTo(), nullValue());
|
||||
assertThat(executable.action().getEmail().replyTo(), nullValue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,16 +280,17 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
String account = randomAsciiOfLength(6);
|
||||
boolean attachPayload = randomBoolean();
|
||||
|
||||
EmailAction action = new EmailAction(logger, email, auth, profile, account, attachPayload, service, engine);
|
||||
EmailAction action = new EmailAction(email, account, auth, profile, attachPayload);
|
||||
ExecutableEmailAction executable = new ExecutableEmailAction(action, logger, service, engine);
|
||||
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
action.toXContent(builder, Attachment.XContent.EMPTY_PARAMS);
|
||||
executable.toXContent(builder, Attachment.XContent.EMPTY_PARAMS);
|
||||
BytesReference bytes = builder.bytes();
|
||||
System.out.println(bytes.toUtf8());
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(bytes);
|
||||
parser.nextToken();
|
||||
EmailAction parsed = new EmailAction.Parser(ImmutableSettings.EMPTY, service, engine).parse(parser);
|
||||
assertThat(parsed, equalTo(action));
|
||||
ExecutableEmailAction parsed = new EmailActionFactory(ImmutableSettings.EMPTY, service, engine)
|
||||
.parseExecutable(randomAsciiOfLength(4), randomAsciiOfLength(10), parser);
|
||||
assertThat(parsed, equalTo(executable));
|
||||
}
|
||||
|
||||
@Test(expected = EmailActionException.class) @Repeat(iterations = 100)
|
||||
@ -295,11 +300,15 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
XContentBuilder builder = jsonBuilder().startObject().field("unknown_field", "value");
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
new EmailAction.Parser(ImmutableSettings.EMPTY, emailService, engine).parse(parser);
|
||||
new EmailActionFactory(ImmutableSettings.EMPTY, emailService, engine)
|
||||
.parseExecutable(randomAsciiOfLength(3), randomAsciiOfLength(7), parser);
|
||||
}
|
||||
|
||||
@Test @Repeat(iterations = 20)
|
||||
public void testParser_Result() throws Exception {
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now(UTC));
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
boolean success = randomBoolean();
|
||||
boolean simulated = randomBoolean();
|
||||
Email email = Email.builder().id("_id")
|
||||
@ -327,8 +336,8 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
parser.nextToken();
|
||||
EmailService service = mock(EmailService.class);
|
||||
TemplateEngine engine = mock(TemplateEngine.class);
|
||||
EmailAction.Result result = new EmailAction.Parser(ImmutableSettings.EMPTY, service, engine)
|
||||
.parseResult(parser);
|
||||
EmailAction.Result result = new EmailActionFactory(ImmutableSettings.EMPTY, service, engine)
|
||||
.parseResult(wid, actionId, parser);
|
||||
|
||||
if (simulated) {
|
||||
assertThat(result, instanceOf(EmailAction.Result.Simulated.class));
|
||||
@ -348,6 +357,9 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
|
||||
@Test
|
||||
public void testParser_Result_Simulated_SelfGenerated() throws Exception {
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now(UTC));
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
Email email = Email.builder().id("_id")
|
||||
.from(new Email.Address("from@domain"))
|
||||
.to(Email.AddressList.parse("to@domain"))
|
||||
@ -364,22 +376,25 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||
BytesReference bytes = builder.bytes();
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(bytes);
|
||||
parser.nextToken();
|
||||
EmailAction.Result result = new EmailAction.Parser(ImmutableSettings.EMPTY, mock(EmailService.class), mock(TemplateEngine.class))
|
||||
.parseResult(parser);
|
||||
EmailAction.Result result = new EmailActionFactory(ImmutableSettings.EMPTY, mock(EmailService.class), mock(TemplateEngine.class))
|
||||
.parseResult(wid, actionId, parser);
|
||||
|
||||
assertThat(result, instanceOf(EmailAction.Result.Simulated.class));
|
||||
assertThat(((EmailAction.Result.Simulated) result).email(), equalTo(email));
|
||||
}
|
||||
|
||||
@Test(expected = EmailException.class)
|
||||
@Test(expected = EmailActionException.class)
|
||||
public void testParser_Result_Invalid() throws Exception {
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now(UTC));
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.field("unknown_field", "value")
|
||||
.endObject();
|
||||
BytesReference bytes = builder.bytes();
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(bytes);
|
||||
parser.nextToken();
|
||||
new EmailAction.Parser(ImmutableSettings.EMPTY, mock(EmailService.class), mock(TemplateEngine.class))
|
||||
.parseResult(parser);
|
||||
new EmailActionFactory(ImmutableSettings.EMPTY, mock(EmailService.class), mock(TemplateEngine.class))
|
||||
.parseResult(wid, actionId, parser);
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import com.carrotsearch.randomizedtesting.annotations.Repeat;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.joda.time.DateTimeZone;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
@ -19,13 +19,13 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.watcher.actions.ActionException;
|
||||
import org.elasticsearch.watcher.actions.email.service.Authentication;
|
||||
import org.elasticsearch.watcher.actions.email.service.Email;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailService;
|
||||
import org.elasticsearch.watcher.actions.email.service.Profile;
|
||||
import org.elasticsearch.watcher.execution.TriggeredExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.http.HttpClient;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
||||
@ -38,6 +38,7 @@ import org.junit.Test;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.common.joda.time.DateTimeZone.UTC;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
|
||||
@ -50,7 +51,8 @@ public class IndexActionTests extends ElasticsearchIntegrationTest {
|
||||
@Test
|
||||
public void testIndexActionExecute() throws Exception {
|
||||
|
||||
IndexAction action = new IndexAction(logger, ClientProxy.of(client()), "test-index", "test-type");
|
||||
IndexAction action = new IndexAction("test-index", "test-type");
|
||||
ExecutableIndexAction executable = new ExecutableIndexAction(action, logger, ClientProxy.of(client()));
|
||||
final String account = "account1";
|
||||
Watch watch = WatcherTestUtils.createTestWatch("testAlert",
|
||||
ClientProxy.of(client()),
|
||||
@ -72,7 +74,7 @@ public class IndexActionTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
Map<String, Object> payloadMap = new HashMap<>();
|
||||
payloadMap.put("test", "foo");
|
||||
IndexAction.Result.IndexResult result = (IndexAction.Result.IndexResult) action.execute("_id", ctx, new Payload.Simple(payloadMap));
|
||||
IndexAction.Result.Executed result = (IndexAction.Result.Executed) executable.execute("_id", ctx, new Payload.Simple(payloadMap));
|
||||
|
||||
assertThat(result.success(), equalTo(true));
|
||||
Map<String, Object> responseData = result.response().data();
|
||||
@ -94,18 +96,18 @@ public class IndexActionTests extends ElasticsearchIntegrationTest {
|
||||
public void testParser() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
builder.startObject()
|
||||
.field(IndexAction.Parser.INDEX_FIELD.getPreferredName(), "test-index")
|
||||
.field(IndexAction.Parser.TYPE_FIELD.getPreferredName(), "test-type")
|
||||
.field(IndexAction.Field.INDEX.getPreferredName(), "test-index")
|
||||
.field(IndexAction.Field.DOC_TYPE.getPreferredName(), "test-type")
|
||||
.endObject();
|
||||
|
||||
IndexAction.Parser actionParser = new IndexAction.Parser(ImmutableSettings.EMPTY, ClientProxy.of(client()));
|
||||
IndexActionFactory actionParser = new IndexActionFactory(ImmutableSettings.EMPTY, ClientProxy.of(client()));
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
IndexAction action = actionParser.parse(parser);
|
||||
ExecutableIndexAction executable = actionParser.parseExecutable(randomAsciiOfLength(5), randomAsciiOfLength(3), parser);
|
||||
|
||||
assertThat(action.type, equalTo("test-type"));
|
||||
assertThat(action.index, equalTo("test-index"));
|
||||
assertThat(executable.action().docType, equalTo("test-type"));
|
||||
assertThat(executable.action().index, equalTo("test-index"));
|
||||
}
|
||||
|
||||
@Test @Repeat(iterations = 10)
|
||||
@ -116,77 +118,88 @@ public class IndexActionTests extends ElasticsearchIntegrationTest {
|
||||
builder.startObject();
|
||||
{
|
||||
if (useIndex) {
|
||||
builder.field(IndexAction.Parser.INDEX_FIELD.getPreferredName(), "test-index");
|
||||
builder.field(IndexAction.Field.INDEX.getPreferredName(), "test-index");
|
||||
}
|
||||
if (useType) {
|
||||
builder.field(IndexAction.Parser.TYPE_FIELD.getPreferredName(), "test-type");
|
||||
builder.field(IndexAction.Field.DOC_TYPE.getPreferredName(), "test-type");
|
||||
}
|
||||
}
|
||||
builder.endObject();
|
||||
IndexAction.Parser actionParser = new IndexAction.Parser(ImmutableSettings.EMPTY, ClientProxy.of(client()));
|
||||
IndexActionFactory actionParser = new IndexActionFactory(ImmutableSettings.EMPTY, ClientProxy.of(client()));
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
try {
|
||||
actionParser.parse(parser);
|
||||
actionParser.parseExecutable(randomAsciiOfLength(4), randomAsciiOfLength(5), parser);
|
||||
if (!(useIndex && useType)) {
|
||||
fail();
|
||||
}
|
||||
} catch (ActionException ae) {
|
||||
} catch (IndexActionException iae) {
|
||||
assertThat(useIndex && useType, equalTo(false));
|
||||
}
|
||||
}
|
||||
|
||||
@Test @Repeat(iterations =30)
|
||||
@Test @Repeat(iterations = 30)
|
||||
public void testParser_Result() throws Exception {
|
||||
boolean success = randomBoolean();
|
||||
boolean simulated = randomBoolean();
|
||||
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.field("success", success);
|
||||
Payload.Simple requestPayload = null;
|
||||
if (simulated) {
|
||||
IndexRequest request = new IndexRequest("testindex").type("testtype");
|
||||
XContentBuilder resultBuilder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
resultBuilder.startObject();
|
||||
resultBuilder.field("data", new HashMap<String, Object>());
|
||||
resultBuilder.field("timestamp", new DateTime(DateTimeZone.UTC));
|
||||
resultBuilder.endObject();
|
||||
request.source(resultBuilder);
|
||||
|
||||
requestPayload = new Payload.Simple(request.sourceAsMap());
|
||||
builder.field(IndexAction.Parser.SIMULATED_REQUEST_FIELD.getPreferredName(), requestPayload);
|
||||
}
|
||||
else if (success) {
|
||||
Payload.Simple source = null;
|
||||
String index = randomAsciiOfLength(5);
|
||||
String docType = randomAsciiOfLength(5);
|
||||
|
||||
if (simulated) {
|
||||
source = new Payload.Simple(ImmutableMap.<String, Object>builder()
|
||||
.put("data", new HashMap<String, Object>())
|
||||
.put("timestamp", DateTime.now(UTC).toString())
|
||||
.build());
|
||||
builder.startObject(IndexAction.Field.SIMULATED_REQUEST.getPreferredName())
|
||||
.field(IndexAction.Field.INDEX.getPreferredName(), index)
|
||||
.field(IndexAction.Field.DOC_TYPE.getPreferredName(), docType)
|
||||
.field(IndexAction.Field.SOURCE.getPreferredName(), source)
|
||||
.endObject();
|
||||
|
||||
} else if (success) {
|
||||
Map<String,Object> data = new HashMap<>();
|
||||
data.put("created", true);
|
||||
data.put("id", "0");
|
||||
data.put("version", 1);
|
||||
data.put("type", "test-type");
|
||||
data.put("index", "test-index");
|
||||
builder.field(IndexAction.Parser.RESPONSE_FIELD.getPreferredName(), data);
|
||||
builder.field(IndexAction.Field.RESPONSE.getPreferredName(), data);
|
||||
|
||||
} else {
|
||||
builder.field("reason", "_reason");
|
||||
}
|
||||
|
||||
Wid wid = new Wid(randomAsciiOfLength(4), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
IndexAction.Result result = new IndexAction.Parser(ImmutableSettings.EMPTY, ClientProxy.of(client()))
|
||||
.parseResult(parser);
|
||||
IndexAction.Result result = new IndexActionFactory(ImmutableSettings.EMPTY, ClientProxy.of(client()))
|
||||
.parseResult(wid, actionId, parser);
|
||||
|
||||
if (simulated){
|
||||
assertThat(result, instanceOf(IndexAction.Result.Simulated.class));
|
||||
assertThat(((IndexAction.Result.Simulated) result).indexRequest(), equalTo((Payload)requestPayload));
|
||||
assertThat(((IndexAction.Result.Simulated) result).source(), equalTo((Payload) source));
|
||||
assertThat(((IndexAction.Result.Simulated) result).index(), equalTo(index));
|
||||
assertThat(((IndexAction.Result.Simulated) result).docType(), equalTo(docType));
|
||||
|
||||
} else {
|
||||
assertThat(result.success(), is(success));
|
||||
assertThat(result, instanceOf(IndexAction.Result.IndexResult.class));
|
||||
if (success) {
|
||||
Map<String, Object> responseData = ((IndexAction.Result.IndexResult)result).response().data();
|
||||
assertThat(result, instanceOf(IndexAction.Result.Executed.class));
|
||||
Map<String, Object> responseData = ((IndexAction.Result.Executed) result).response().data();
|
||||
assertThat(responseData.get("created"), equalTo((Object) Boolean.TRUE));
|
||||
assertThat(responseData.get("version"), equalTo((Object) 1));
|
||||
assertThat(responseData.get("type").toString(), equalTo("test-type"));
|
||||
assertThat(responseData.get("index").toString(), equalTo("test-index"));
|
||||
} else {
|
||||
assertThat(((IndexAction.Result.IndexResult)result).reason, is("_reason"));
|
||||
assertThat(result, instanceOf(IndexAction.Result.Failure.class));
|
||||
assertThat(((IndexAction.Result.Failure) result).reason(), is("_reason"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -197,12 +210,14 @@ public class IndexActionTests extends ElasticsearchIntegrationTest {
|
||||
XContentBuilder resultBuilder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
resultBuilder.startObject();
|
||||
resultBuilder.field("data", new HashMap<String, Object>());
|
||||
resultBuilder.field("timestamp", new DateTime(DateTimeZone.UTC));
|
||||
resultBuilder.field("timestamp", new DateTime(UTC));
|
||||
resultBuilder.endObject();
|
||||
request.source(resultBuilder);
|
||||
Payload.Simple requestPayload = new Payload.Simple(request.sourceAsMap());
|
||||
|
||||
IndexAction.Result.Simulated simulatedResult = new IndexAction.Result.Simulated(requestPayload);
|
||||
String index = randomAsciiOfLength(4);
|
||||
String docType = randomAsciiOfLength(5);
|
||||
IndexAction.Result.Simulated simulatedResult = new IndexAction.Result.Simulated(index, docType, requestPayload);
|
||||
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
simulatedResult.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
@ -211,11 +226,16 @@ public class IndexActionTests extends ElasticsearchIntegrationTest {
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(bytes);
|
||||
parser.nextToken();
|
||||
|
||||
IndexAction.Result result = new IndexAction.Parser(ImmutableSettings.EMPTY, ClientProxy.of(client()))
|
||||
.parseResult(parser);
|
||||
Wid wid = new Wid(randomAsciiOfLength(4), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
IndexAction.Result result = new IndexActionFactory(ImmutableSettings.EMPTY, ClientProxy.of(client()))
|
||||
.parseResult(wid, actionId, parser);
|
||||
|
||||
assertThat(result, instanceOf(IndexAction.Result.Simulated.class));
|
||||
assertThat(((IndexAction.Result.Simulated) result).indexRequest(), equalTo((Payload)requestPayload));
|
||||
assertThat(((IndexAction.Result.Simulated) result).source(), equalTo((Payload) requestPayload));
|
||||
assertThat(((IndexAction.Result.Simulated) result).index(), equalTo(index));
|
||||
assertThat(((IndexAction.Result.Simulated) result).docType(), equalTo(docType));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import org.elasticsearch.watcher.actions.ActionException;
|
||||
import org.elasticsearch.watcher.actions.email.service.Attachment;
|
||||
import org.elasticsearch.watcher.execution.TriggeredExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.template.Template;
|
||||
import org.elasticsearch.watcher.support.template.TemplateEngine;
|
||||
import org.elasticsearch.watcher.trigger.schedule.ScheduleTriggerEvent;
|
||||
@ -77,14 +78,15 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
String text = randomAsciiOfLength(10);
|
||||
System.out.println("**** text: " + text);
|
||||
Template template = new Template(text);
|
||||
LoggingAction action = new LoggingAction(logger, template, "_category", level, actionLogger, engine);
|
||||
LoggingAction action = new LoggingAction(template, level, "_category");
|
||||
ExecutableLoggingAction executable = new ExecutableLoggingAction(action, logger, actionLogger, engine);
|
||||
when(engine.render(template, expectedModel)).thenReturn(text);
|
||||
|
||||
Watch watch = mock(Watch.class);
|
||||
when(watch.name()).thenReturn("_watch_name");
|
||||
WatchExecutionContext ctx = new TriggeredExecutionContext(watch, now, new ScheduleTriggerEvent(now, now));
|
||||
|
||||
LoggingAction.Result result = action.execute("_id", ctx, new Payload.Simple());
|
||||
LoggingAction.Result result = executable.execute("_id", ctx, new Payload.Simple());
|
||||
verifyLogger(actionLogger, level, text);
|
||||
|
||||
assertThat(result, notNullValue());
|
||||
@ -96,7 +98,7 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
@Test @Repeat(iterations = 10)
|
||||
public void testParser() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
String text = randomAsciiOfLength(10);
|
||||
Template template = new Template(text);
|
||||
@ -118,77 +120,70 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
XContentParser xContentParser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
xContentParser.nextToken();
|
||||
|
||||
LoggingAction action = parser.parse(xContentParser);
|
||||
ExecutableLoggingAction executable = parser.parseExecutable(randomAsciiOfLength(5), randomAsciiOfLength(3), xContentParser);
|
||||
|
||||
assertThat(action, notNullValue());
|
||||
assertThat(action.category(), is(category));
|
||||
assertThat(action.level(), level == null ? is(LoggingLevel.INFO) : is(level));
|
||||
assertThat(action.logger(), notNullValue());
|
||||
assertThat(action.text(), notNullValue());
|
||||
assertThat(action.text(), is(template));
|
||||
assertThat(executable, notNullValue());
|
||||
assertThat(executable.action().category, is(category));
|
||||
assertThat(executable.action().level, level == null ? is(LoggingLevel.INFO) : is(level));
|
||||
assertThat(executable.textLogger(), notNullValue());
|
||||
assertThat(executable.action().text, notNullValue());
|
||||
assertThat(executable.action().text, is(template));
|
||||
}
|
||||
|
||||
@Test //@Repeat(iterations = 10)
|
||||
@Test @Repeat(iterations = 10)
|
||||
public void testParser_SelfGenerated() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
String text = randomAsciiOfLength(10);
|
||||
Template template = new Template(text);
|
||||
String category = randomAsciiOfLength(10);
|
||||
LoggingAction action = new LoggingAction(logger, template, category, level, settings, engine);
|
||||
LoggingAction action = new LoggingAction(template, level, category);
|
||||
ExecutableLoggingAction executable = new ExecutableLoggingAction(action, logger, settings, engine);
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
action.toXContent(builder, Attachment.XContent.EMPTY_PARAMS);
|
||||
executable.toXContent(builder, Attachment.XContent.EMPTY_PARAMS);
|
||||
|
||||
XContentParser xContentParser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
xContentParser.nextToken();
|
||||
|
||||
LoggingAction parsedAction = parser.parse(xContentParser);
|
||||
ExecutableLoggingAction parsedAction = parser.parseExecutable(randomAsciiOfLength(5), randomAsciiOfLength(5), xContentParser);
|
||||
|
||||
assertThat(parsedAction, equalTo(action));
|
||||
assertThat(parsedAction, equalTo(executable));
|
||||
}
|
||||
|
||||
@Test //@Repeat(iterations = 10)
|
||||
public void testParser_SourceBuilder() throws Exception {
|
||||
@Test @Repeat(iterations = 10)
|
||||
public void testParser_Builder() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
String text = randomAsciiOfLength(10);
|
||||
Template template = new Template(text);
|
||||
LoggingAction.SourceBuilder sourceBuilder = loggingAction(template);
|
||||
LoggingAction.Builder actionBuilder = loggingAction(template);
|
||||
String category = null;
|
||||
if (randomBoolean()) {
|
||||
category = randomAsciiOfLength(10);
|
||||
sourceBuilder.category(category);
|
||||
actionBuilder.setCategory(category);
|
||||
}
|
||||
LoggingLevel level = null;
|
||||
if (randomBoolean()) {
|
||||
level = randomFrom(LoggingLevel.values());
|
||||
sourceBuilder.level(level);
|
||||
actionBuilder.setLevel(level);
|
||||
}
|
||||
LoggingAction action = actionBuilder.build();
|
||||
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
sourceBuilder.toXContent(builder, Attachment.XContent.EMPTY_PARAMS);
|
||||
|
||||
XContentBuilder builder = jsonBuilder().value(action);
|
||||
XContentParser xContentParser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
|
||||
assertThat(xContentParser.nextToken(), is(XContentParser.Token.START_OBJECT));
|
||||
assertThat(xContentParser.nextToken(), is(XContentParser.Token.FIELD_NAME));
|
||||
assertThat(xContentParser.currentName(), is(LoggingAction.TYPE));
|
||||
assertThat(xContentParser.nextToken(), is(XContentParser.Token.START_OBJECT));
|
||||
LoggingAction action = parser.parse(xContentParser);
|
||||
assertThat(action, notNullValue());
|
||||
assertThat(action.category(), is(category));
|
||||
assertThat(action.level(), level == null ? is(LoggingLevel.INFO) : is(level));
|
||||
assertThat(action.logger(), notNullValue());
|
||||
assertThat(action.text(), notNullValue());
|
||||
assertThat(action.text(), is(template));
|
||||
ExecutableLoggingAction executable = parser.parseExecutable(randomAsciiOfLength(4), randomAsciiOfLength(5), xContentParser);
|
||||
assertThat(executable, notNullValue());
|
||||
assertThat(executable.action(), is(action));
|
||||
}
|
||||
|
||||
@Test(expected = ActionException.class)
|
||||
public void testParser_Failure() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
XContentBuilder builder = jsonBuilder()
|
||||
.startObject().endObject();
|
||||
@ -197,13 +192,16 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
xContentParser.nextToken();
|
||||
|
||||
// will fail as there's no text
|
||||
parser.parse(xContentParser);
|
||||
parser.parseExecutable(randomAsciiOfLength(5), randomAsciiOfLength(5), xContentParser);
|
||||
}
|
||||
|
||||
@Test @Repeat(iterations = 30)
|
||||
public void testParser_Result_Success() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
String text = randomAsciiOfLength(10);
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
@ -215,7 +213,7 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
xContentParser.nextToken();
|
||||
|
||||
// will fail as there's no text
|
||||
LoggingAction.Result result = parser.parseResult(xContentParser);
|
||||
LoggingAction.Result result = parser.parseResult(wid, actionId, xContentParser);
|
||||
assertThat(result, Matchers.notNullValue());
|
||||
assertThat(result.success(), is(true));
|
||||
assertThat(result, Matchers.instanceOf(LoggingAction.Result.Success.class));
|
||||
@ -225,7 +223,10 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
@Test @Repeat(iterations = 30)
|
||||
public void testParser_Result_Failure() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
String reason = randomAsciiOfLength(10);
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
@ -237,7 +238,7 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
xContentParser.nextToken();
|
||||
|
||||
// will fail as there's no text
|
||||
LoggingAction.Result result = parser.parseResult(xContentParser);
|
||||
LoggingAction.Result result = parser.parseResult(wid, actionId, xContentParser);
|
||||
assertThat(result, Matchers.notNullValue());
|
||||
assertThat(result.success(), is(false));
|
||||
assertThat(result, Matchers.instanceOf(LoggingAction.Result.Failure.class));
|
||||
@ -247,7 +248,10 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
@Test @Repeat(iterations = 30)
|
||||
public void testParser_Result_Simulated() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
String text = randomAsciiOfLength(10);
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
@ -259,7 +263,7 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
xContentParser.nextToken();
|
||||
|
||||
// will fail as there's no text
|
||||
LoggingAction.Result result = parser.parseResult(xContentParser);
|
||||
LoggingAction.Result result = parser.parseResult(wid, actionId, xContentParser);
|
||||
assertThat(result, Matchers.notNullValue());
|
||||
assertThat(result.success(), is(true));
|
||||
assertThat(result, Matchers.instanceOf(LoggingAction.Result.Simulated.class));
|
||||
@ -269,9 +273,12 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
@Test
|
||||
public void testParser_Result_Simulated_SelfGenerated() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser actionParser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory actionParser = new LoggingActionFactory(settings, engine);
|
||||
String text = randomAsciiOfLength(10);
|
||||
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
LoggingAction.Result.Simulated simulatedResult = new LoggingAction.Result.Simulated(text);
|
||||
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
@ -285,7 +292,7 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
xContentParser.nextToken();
|
||||
|
||||
// will fail as there's no text
|
||||
LoggingAction.Result result = actionParser.parseResult(xContentParser);
|
||||
LoggingAction.Result result = actionParser.parseResult(wid, actionId, xContentParser);
|
||||
assertThat(result, Matchers.notNullValue());
|
||||
assertThat(result.success(), is(true));
|
||||
assertThat(result, Matchers.instanceOf(LoggingAction.Result.Simulated.class));
|
||||
@ -295,7 +302,10 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
@Test(expected = ActionException.class)
|
||||
public void testParser_Result_MissingSuccessField() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
String text = randomAsciiOfLength(10);
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
@ -306,13 +316,16 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
xContentParser.nextToken();
|
||||
|
||||
// will fail as there's no success boolean field
|
||||
parser.parseResult(xContentParser);
|
||||
parser.parseResult(wid, actionId, xContentParser);
|
||||
}
|
||||
|
||||
@Test(expected = ActionException.class)
|
||||
public void testParser_Result_Failure_WithoutReason() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
String text = randomAsciiOfLength(10);
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
@ -326,13 +339,16 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
xContentParser.nextToken();
|
||||
|
||||
// will fail as the reason field is missing for the failure result
|
||||
parser.parseResult(xContentParser);
|
||||
parser.parseResult(wid, actionId, xContentParser);
|
||||
}
|
||||
|
||||
@Test(expected = ActionException.class)
|
||||
public void testParser_Result_Success_WithoutLoggedText() throws Exception {
|
||||
Settings settings = ImmutableSettings.EMPTY;
|
||||
LoggingAction.Parser parser = new LoggingAction.Parser(settings, engine);
|
||||
LoggingActionFactory parser = new LoggingActionFactory(settings, engine);
|
||||
|
||||
Wid wid = new Wid(randomAsciiOfLength(3), randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
String text = randomAsciiOfLength(10);
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
@ -346,7 +362,7 @@ public class LoggingActionTests extends ElasticsearchTestCase {
|
||||
xContentParser.nextToken();
|
||||
|
||||
// will fail as the logged_text field is missing for the successful result
|
||||
parser.parseResult(xContentParser);
|
||||
parser.parseResult(wid, actionId, xContentParser);
|
||||
}
|
||||
|
||||
static void verifyLogger(ESLogger logger, LoggingLevel level, String text) {
|
||||
|
@ -24,11 +24,11 @@ import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.watcher.actions.Action;
|
||||
import org.elasticsearch.watcher.actions.ActionException;
|
||||
import org.elasticsearch.watcher.actions.email.service.*;
|
||||
import org.elasticsearch.watcher.execution.TriggeredExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.http.*;
|
||||
import org.elasticsearch.watcher.support.http.auth.BasicAuth;
|
||||
import org.elasticsearch.watcher.support.http.auth.HttpAuth;
|
||||
@ -53,8 +53,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.lessThanOrEqualTo;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
@ -111,12 +110,13 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
|
||||
HttpRequestTemplate httpRequest = getHttpRequestTemplate(method, TEST_HOST, TEST_PORT, testPath, testBody);
|
||||
|
||||
WebhookAction webhookAction = new WebhookAction(logger, httpClient, httpRequest, templateEngine);
|
||||
WebhookAction action = new WebhookAction(httpRequest);
|
||||
ExecutableWebhookAction executable = new ExecutableWebhookAction(action, logger, httpClient, templateEngine);
|
||||
|
||||
Watch watch = createWatch("test_watch", client, account);
|
||||
WatchExecutionContext ctx = new TriggeredExecutionContext(watch, new DateTime(), new ScheduleTriggerEvent(new DateTime(), new DateTime()));
|
||||
|
||||
WebhookAction.Result actionResult = webhookAction.execute("_id", ctx, new Payload.Simple());
|
||||
WebhookAction.Result actionResult = executable.execute("_id", ctx, new Payload.Simple());
|
||||
scenario.assertResult(actionResult);
|
||||
}
|
||||
|
||||
@ -145,14 +145,14 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
request.toXContent(builder, Attachment.XContent.EMPTY_PARAMS);
|
||||
|
||||
WebhookAction.Parser actionParser = getParser(ExecuteScenario.Success.client());
|
||||
WebhookActionFactory actionParser = getParser(ExecuteScenario.Success.client());
|
||||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
WebhookAction action = actionParser.parse(parser);
|
||||
ExecutableWebhookAction executable = actionParser.parseExecutable(randomAsciiOfLength(5), randomAsciiOfLength(5), parser);
|
||||
|
||||
assertThat(action.requestTemplate(), equalTo(request));
|
||||
assertThat(executable.action().getRequest(), equalTo(request));
|
||||
}
|
||||
|
||||
@Test @Repeat(iterations = 10)
|
||||
@ -160,49 +160,51 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
Template body = randomBoolean() ? new Template("_body") : null;
|
||||
Template path = new Template("_url");
|
||||
String host = "test.host";
|
||||
String watchId = "_watch";
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
HttpMethod method = randomFrom(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, null);
|
||||
|
||||
HttpRequestTemplate request = getHttpRequestTemplate(method, host, TEST_PORT, path, body);
|
||||
WebhookAction webhookAction = new WebhookAction(logger, ExecuteScenario.Success.client(), request, templateEngine);
|
||||
WebhookAction action = new WebhookAction(request);
|
||||
ExecutableWebhookAction executable = new ExecutableWebhookAction(action, logger, ExecuteScenario.Success.client(), templateEngine);
|
||||
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
webhookAction.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
executable.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
|
||||
WebhookAction.Parser actionParser = getParser(ExecuteScenario.Success.client());
|
||||
WebhookActionFactory actionParser = getParser(ExecuteScenario.Success.client());
|
||||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
WebhookAction action = actionParser.parse(parser);
|
||||
|
||||
assertThat(action.requestTemplate(), equalTo(request));
|
||||
ExecutableWebhookAction parsedExecutable = actionParser.parseExecutable(watchId, actionId, parser);
|
||||
assertThat(parsedExecutable, notNullValue());
|
||||
assertThat(parsedExecutable.action(), is(action));
|
||||
}
|
||||
|
||||
@Test //@Repeat(iterations = 10)
|
||||
public void testParser_SourceBuilder() throws Exception {
|
||||
@Test @Repeat(iterations = 10)
|
||||
public void testParser_Builder() throws Exception {
|
||||
Template body = randomBoolean() ? new Template("_body") : null;
|
||||
Template path = new Template("_url");
|
||||
String host = "test.host";
|
||||
|
||||
String watchId = "_watch";
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
HttpMethod method = randomFrom(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, null);
|
||||
HttpRequestTemplate request = getHttpRequestTemplate(method, host, TEST_PORT, path, body);
|
||||
|
||||
WebhookAction.SourceBuilder sourceBuilder = new WebhookAction.SourceBuilder(request);
|
||||
WebhookAction action = WebhookAction.builder(request).build();
|
||||
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
sourceBuilder.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
action.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
|
||||
WebhookAction.Parser actionParser = getParser(ExecuteScenario.Success.client());
|
||||
WebhookActionFactory actionParser = getParser(ExecuteScenario.Success.client());
|
||||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT));
|
||||
assertThat(parser.nextToken(), is(XContentParser.Token.FIELD_NAME));
|
||||
assertThat(parser.currentName(), is(WebhookAction.TYPE));
|
||||
assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT));
|
||||
WebhookAction parsedAction = actionParser.parse(parser);
|
||||
assertThat(parsedAction.requestTemplate().host(), equalTo(host));
|
||||
assertThat(parsedAction.requestTemplate().port(), equalTo(TEST_PORT));
|
||||
assertThat(parsedAction.requestTemplate().path(), equalTo(path));
|
||||
assertThat(parsedAction.requestTemplate().body(), equalTo(body));
|
||||
ExecutableWebhookAction parsedAction = actionParser.parseExecutable(watchId, actionId, parser);
|
||||
assertThat(parsedAction.action(), is(action));
|
||||
}
|
||||
|
||||
@Test(expected = ActionException.class)
|
||||
@ -212,9 +214,9 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
WebhookAction.Parser actionParser = getParser(ExecuteScenario.Success.client());
|
||||
WebhookActionFactory actionParser = getParser(ExecuteScenario.Success.client());
|
||||
//This should fail since we are not supplying a url
|
||||
actionParser.parse(parser);
|
||||
actionParser.parseExecutable("_watch", randomAsciiOfLength(5), parser);
|
||||
}
|
||||
|
||||
@Test @Repeat(iterations = 30)
|
||||
@ -225,6 +227,9 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
String reason = "_reason";
|
||||
HttpMethod method = randomFrom(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT);
|
||||
|
||||
Wid wid = new Wid("_watch", randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
HttpRequest request = HttpRequest.builder(host, 123)
|
||||
.path(path)
|
||||
.body(body)
|
||||
@ -239,26 +244,24 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
|
||||
HttpClient client = ExecuteScenario.Success.client();
|
||||
|
||||
WebhookAction.Parser actionParser = getParser(client);
|
||||
WebhookActionFactory actionParser = getParser(client);
|
||||
|
||||
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
builder.startObject();
|
||||
{
|
||||
builder.field(Action.Result.SUCCESS_FIELD.getPreferredName(), success);
|
||||
if (!error) {
|
||||
builder.field(WebhookAction.Parser.REQUEST_FIELD.getPreferredName(), request);
|
||||
builder.field(WebhookAction.Parser.RESPONSE_FIELD.getPreferredName(), response);
|
||||
} else {
|
||||
builder.field(WebhookAction.Parser.REASON_FIELD.getPreferredName(), reason);
|
||||
}
|
||||
XContentBuilder builder = jsonBuilder()
|
||||
.startObject()
|
||||
.field(WebhookAction.Field.SUCCESS.getPreferredName(), success);
|
||||
if (!error) {
|
||||
builder.field(WebhookAction.Field.REQUEST.getPreferredName(), request);
|
||||
builder.field(WebhookAction.Field.RESPONSE.getPreferredName(), response);
|
||||
} else {
|
||||
builder.field(WebhookAction.Field.REASON.getPreferredName(), reason);
|
||||
}
|
||||
builder.endObject();
|
||||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
WebhookAction.Result result = actionParser.parseResult(parser);
|
||||
WebhookAction.Result result = actionParser.parseResult(wid, actionId, parser);
|
||||
|
||||
assertThat(result.success(), equalTo(success));
|
||||
if (!error) {
|
||||
@ -280,6 +283,9 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
String path = "/_url";
|
||||
HttpMethod method = randomFrom(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT);
|
||||
|
||||
Wid wid = new Wid("_watch", randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
HttpRequest request = HttpRequest.builder(host, 123)
|
||||
.path(path)
|
||||
.body(body)
|
||||
@ -288,17 +294,17 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
|
||||
XContentBuilder builder = jsonBuilder()
|
||||
.startObject()
|
||||
.field(Action.Result.SUCCESS_FIELD.getPreferredName(), true)
|
||||
.field(WebhookAction.Parser.SIMULATED_REQUEST_FIELD.getPreferredName(), request)
|
||||
.field(WebhookAction.Field.SUCCESS.getPreferredName(), true)
|
||||
.field(WebhookAction.Field.SIMULATED_REQUEST.getPreferredName(), request)
|
||||
.endObject();
|
||||
|
||||
HttpClient client = ExecuteScenario.Success.client();
|
||||
|
||||
WebhookAction.Parser actionParser = getParser(client);
|
||||
WebhookActionFactory actionParser = getParser(client);
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
WebhookAction.Result result = actionParser.parseResult(parser);
|
||||
WebhookAction.Result result = actionParser.parseResult(wid, actionId, parser);
|
||||
assertThat(result, instanceOf(WebhookAction.Result.Simulated.class));
|
||||
assertThat(((WebhookAction.Result.Simulated) result).request(), equalTo(request));
|
||||
}
|
||||
@ -317,6 +323,9 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
.method(method)
|
||||
.build();
|
||||
|
||||
Wid wid = new Wid("_watch", randomLong(), DateTime.now());
|
||||
String actionId = randomAsciiOfLength(5);
|
||||
|
||||
WebhookAction.Result.Simulated simulatedResult = new WebhookAction.Result.Simulated(request);
|
||||
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
@ -327,15 +336,15 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
parser.nextToken();
|
||||
|
||||
WebhookAction.Result result = getParser(ExecuteScenario.Success.client())
|
||||
.parseResult(parser);
|
||||
.parseResult(wid, actionId, parser);
|
||||
|
||||
assertThat(result, instanceOf(WebhookAction.Result.Simulated.class));
|
||||
assertThat(((WebhookAction.Result.Simulated)result).request(), equalTo(request));
|
||||
}
|
||||
|
||||
|
||||
private WebhookAction.Parser getParser(HttpClient client) {
|
||||
return new WebhookAction.Parser(ImmutableSettings.EMPTY, client, new HttpRequest.Parser(authRegistry),
|
||||
private WebhookActionFactory getParser(HttpClient client) {
|
||||
return new WebhookActionFactory(ImmutableSettings.EMPTY, client, new HttpRequest.Parser(authRegistry),
|
||||
new HttpRequestTemplate.Parser(authRegistry), templateEngine);
|
||||
}
|
||||
|
||||
@ -347,8 +356,9 @@ public class WebhookActionTests extends ElasticsearchTestCase {
|
||||
Template path = new Template("/test_{{ctx.watch_id}}");
|
||||
String host = "test.host";
|
||||
HttpRequestTemplate requestTemplate = getHttpRequestTemplate(method, host, TEST_PORT, path, testBody);
|
||||
WebhookAction action = new WebhookAction(requestTemplate);
|
||||
|
||||
WebhookAction webhookAction = new WebhookAction(logger, httpClient, requestTemplate, templateEngine);
|
||||
ExecutableWebhookAction webhookAction = new ExecutableWebhookAction(action, logger, httpClient, templateEngine);
|
||||
|
||||
String watchName = "test_url_encode" + randomAsciiOfLength(10);
|
||||
Watch watch = createWatch(watchName, mock(ClientProxy.class), "account1");
|
||||
|
@ -31,6 +31,7 @@ import org.elasticsearch.watcher.watch.Payload;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
@ -11,8 +11,9 @@ import org.elasticsearch.common.joda.time.DateTimeZone;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.watcher.actions.Action;
|
||||
import org.elasticsearch.watcher.actions.ExecutableAction;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.condition.Condition;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysFalseCondition;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
@ -81,7 +82,7 @@ public class ExecutionServiceTests extends ElasticsearchTestCase {
|
||||
when(transform.apply(any(WatchExecutionContext.class), same(payload))).thenReturn(transformResult);
|
||||
ActionWrapper action = mock(ActionWrapper.class);
|
||||
when(action.execute(any(WatchExecutionContext.class))).thenReturn(watchActionResult);
|
||||
Actions actions = new Actions(Arrays.asList(action));
|
||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(action));
|
||||
|
||||
Watch.Status watchStatus = new Watch.Status();
|
||||
Watch watch = mock(Watch.class);
|
||||
@ -127,7 +128,7 @@ public class ExecutionServiceTests extends ElasticsearchTestCase {
|
||||
when(transform.apply(any(WatchExecutionContext.class), same(payload))).thenReturn(transformResult);
|
||||
ActionWrapper action = mock(ActionWrapper.class);
|
||||
when(action.execute(any(WatchExecutionContext.class))).thenReturn(actionResult);
|
||||
Actions actions = new Actions(Arrays.asList(action));
|
||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(action));
|
||||
|
||||
Watch.Status watchStatus = new Watch.Status();
|
||||
Watch watch = mock(Watch.class);
|
||||
@ -173,7 +174,7 @@ public class ExecutionServiceTests extends ElasticsearchTestCase {
|
||||
when(transform.apply(any(WatchExecutionContext.class), same(payload))).thenReturn(transformResult);
|
||||
ActionWrapper action = mock(ActionWrapper.class);
|
||||
when(action.execute(any(WatchExecutionContext.class))).thenReturn(actionResult);
|
||||
Actions actions = new Actions(Arrays.asList(action));
|
||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(action));
|
||||
|
||||
Watch.Status watchStatus = new Watch.Status();
|
||||
Watch watch = mock(Watch.class);
|
||||
|
@ -6,28 +6,30 @@
|
||||
package org.elasticsearch.watcher.execution;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Repeat;
|
||||
import com.carrotsearch.randomizedtesting.annotations.Seed;
|
||||
import org.elasticsearch.action.count.CountRequest;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.watcher.actions.logging.LoggingAction;
|
||||
import org.elasticsearch.watcher.client.WatchSourceBuilder;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysFalseCondition;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
import org.elasticsearch.watcher.history.HistoryStore;
|
||||
import org.elasticsearch.watcher.history.WatchRecord;
|
||||
import org.elasticsearch.watcher.input.simple.SimpleInput;
|
||||
import org.elasticsearch.watcher.support.template.Template;
|
||||
import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTests;
|
||||
import org.elasticsearch.watcher.transport.actions.get.GetWatchRequest;
|
||||
import org.elasticsearch.watcher.transport.actions.put.PutWatchRequest;
|
||||
import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse;
|
||||
import org.elasticsearch.watcher.trigger.schedule.CronSchedule;
|
||||
import org.elasticsearch.watcher.trigger.schedule.ScheduleTrigger;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
import org.elasticsearch.watcher.watch.Watch;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
|
||||
import static org.elasticsearch.watcher.client.WatchSourceBuilders.watchBuilder;
|
||||
import static org.elasticsearch.watcher.condition.ConditionBuilders.alwaysFalseCondition;
|
||||
import static org.elasticsearch.watcher.condition.ConditionBuilders.alwaysTrueCondition;
|
||||
import static org.elasticsearch.watcher.input.InputBuilders.simpleInput;
|
||||
import static org.elasticsearch.watcher.trigger.TriggerBuilders.schedule;
|
||||
import static org.elasticsearch.watcher.trigger.schedule.Schedules.cron;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
@ClusterScope(scope = Scope.SUITE, randomDynamicTemplates = false)
|
||||
@ -38,22 +40,21 @@ public class ManualExecutionTests extends AbstractWatcherIntegrationTests {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(iterations = 10)
|
||||
@Test @Repeat(iterations = 10)
|
||||
public void testExecuteWatch() throws Exception {
|
||||
ensureWatcherStarted();
|
||||
boolean ignoreCondition = randomBoolean();
|
||||
boolean persistRecord = randomBoolean();
|
||||
boolean conditionAlwaysTrue = randomBoolean();
|
||||
boolean storeWatch = randomBoolean();
|
||||
String actionIdToSimulate = randomFrom("_all", "logging", null);
|
||||
String actionIdToSimulate = randomFrom("_all", "log", null);
|
||||
|
||||
LoggingAction.SourceBuilder loggingAction = new LoggingAction.SourceBuilder(new Template("foobar"));
|
||||
WatchSourceBuilder testWatchBuilder = new WatchSourceBuilder();
|
||||
testWatchBuilder.trigger(new ScheduleTrigger.SourceBuilder(new CronSchedule("0 0 0 1 * ? 2099")));
|
||||
testWatchBuilder.condition(conditionAlwaysTrue ? new AlwaysTrueCondition.SourceBuilder() : new AlwaysFalseCondition.SourceBuilder());
|
||||
testWatchBuilder.addAction("logging", loggingAction);
|
||||
testWatchBuilder.input(new SimpleInput.SourceBuilder((new Payload.Simple("foo", "bar").data())));
|
||||
LoggingAction.Builder loggingAction = LoggingAction.builder(new Template("foobar"));
|
||||
WatchSourceBuilder testWatchBuilder = watchBuilder()
|
||||
.trigger(schedule(cron("0 0 0 1 * ? 2099")))
|
||||
.input(simpleInput("foo", "bar"))
|
||||
.condition(conditionAlwaysTrue ? alwaysTrueCondition() : alwaysFalseCondition())
|
||||
.addAction("log", loggingAction);
|
||||
|
||||
if (storeWatch) {
|
||||
PutWatchResponse putWatchResponse = watcherClient().putWatch(new PutWatchRequest("testrun", testWatchBuilder)).actionGet();
|
||||
@ -98,12 +99,12 @@ public class ManualExecutionTests extends AbstractWatcherIntegrationTests {
|
||||
}
|
||||
|
||||
if ((ignoreCondition || conditionAlwaysTrue) && actionIdToSimulate == null) {
|
||||
assertThat("The action should have run non simulated", watchRecord.execution().actionsResults().get("logging").action(),
|
||||
assertThat("The action should have run non simulated", watchRecord.execution().actionsResults().get("log").action(),
|
||||
not(instanceOf(LoggingAction.Result.Simulated.class)) );
|
||||
}
|
||||
|
||||
if ((ignoreCondition || conditionAlwaysTrue) && actionIdToSimulate != null ) {
|
||||
assertThat("The action should have run simulated", watchRecord.execution().actionsResults().get("logging").action(), instanceOf(LoggingAction.Result.Simulated.class));
|
||||
assertThat("The action should have run simulated", watchRecord.execution().actionsResults().get("log").action(), instanceOf(LoggingAction.Result.Simulated.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,14 +11,17 @@ import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.joda.time.DateTimeZone;
|
||||
import org.elasticsearch.watcher.condition.Condition;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.clock.SystemClock;
|
||||
import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTests;
|
||||
import org.elasticsearch.watcher.trigger.schedule.ScheduleTriggerEvent;
|
||||
import org.elasticsearch.watcher.watch.Watch;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.elasticsearch.common.joda.time.DateTimeZone.UTC;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
@ -36,9 +39,10 @@ public class HistoryStoreLifeCycleTest extends AbstractWatcherIntegrationTests {
|
||||
for (int i = 0; i < watchRecords.length; i++) {
|
||||
DateTime dateTime = new DateTime(i, DateTimeZone.UTC);
|
||||
ScheduleTriggerEvent event = new ScheduleTriggerEvent(dateTime, dateTime);
|
||||
watchRecords[i] = new WatchRecord("_record" + i,watch, event);
|
||||
Wid wid = new Wid("record_" + i, randomLong(), DateTime.now(UTC));
|
||||
watchRecords[i] = new WatchRecord(wid, watch, event);
|
||||
historyStore.put(watchRecords[i]);
|
||||
GetResponse getResponse = client().prepareGet(HistoryStore.getHistoryIndexNameForTime(dateTime), HistoryStore.DOC_TYPE, watchRecords[i].id())
|
||||
GetResponse getResponse = client().prepareGet(HistoryStore.getHistoryIndexNameForTime(dateTime), HistoryStore.DOC_TYPE, watchRecords[i].id().value())
|
||||
.setVersion(1)
|
||||
.get();
|
||||
assertThat(getResponse.isExists(), equalTo(true));
|
||||
@ -56,7 +60,7 @@ public class HistoryStoreLifeCycleTest extends AbstractWatcherIntegrationTests {
|
||||
assertThat(watchRecord.version(), equalTo(1l));
|
||||
watchRecord.update(WatchRecord.State.EXECUTED, "_message");
|
||||
historyStore.update(watchRecord);
|
||||
GetResponse getResponse = client().prepareGet(HistoryStore.getHistoryIndexNameForTime(watchRecord.triggerEvent().triggeredTime()), HistoryStore.DOC_TYPE, watchRecord.id())
|
||||
GetResponse getResponse = client().prepareGet(HistoryStore.getHistoryIndexNameForTime(watchRecord.triggerEvent().triggeredTime()), HistoryStore.DOC_TYPE, watchRecord.id().value())
|
||||
.setVersion(2l)
|
||||
.get();
|
||||
assertThat(getResponse.isExists(), equalTo(true));
|
||||
|
@ -32,6 +32,7 @@ import org.elasticsearch.search.internal.InternalSearchHits;
|
||||
import org.elasticsearch.search.internal.InternalSearchResponse;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.support.TemplateUtils;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
|
||||
import org.elasticsearch.watcher.trigger.schedule.ScheduleTriggerEvent;
|
||||
@ -75,13 +76,14 @@ public class HistoryStoreTests extends ElasticsearchTestCase {
|
||||
when(watch.input()).thenReturn(null);
|
||||
when(watch.metadata()).thenReturn(null);
|
||||
ScheduleTriggerEvent event = new ScheduleTriggerEvent(new DateTime(0, DateTimeZone.UTC), new DateTime(0, DateTimeZone.UTC));
|
||||
WatchRecord watchRecord = new WatchRecord("_name#1970-01-01T00:00:00.000Z", watch, event);
|
||||
Wid wid = new Wid("_name", 0, new DateTime(0, DateTimeZone.UTC));
|
||||
WatchRecord watchRecord = new WatchRecord(wid, watch, event);
|
||||
|
||||
IndexResponse indexResponse = mock(IndexResponse.class);
|
||||
long version = randomLong();
|
||||
when(indexResponse.getVersion()).thenReturn(version);
|
||||
|
||||
when(clientProxy.index(indexRequest(".watch_history_1970-01-01", HistoryStore.DOC_TYPE, "_name#1970-01-01T00:00:00.000Z", IndexRequest.OpType.CREATE))).thenReturn(indexResponse);
|
||||
when(clientProxy.index(indexRequest(".watch_history_1970-01-01", HistoryStore.DOC_TYPE, wid.value(), IndexRequest.OpType.CREATE))).thenReturn(indexResponse);
|
||||
historyStore.put(watchRecord);
|
||||
assertThat(watchRecord.version(), equalTo(version));
|
||||
}
|
||||
@ -94,14 +96,15 @@ public class HistoryStoreTests extends ElasticsearchTestCase {
|
||||
when(watch.input()).thenReturn(null);
|
||||
when(watch.metadata()).thenReturn(null);
|
||||
ScheduleTriggerEvent event = new ScheduleTriggerEvent(new DateTime(0, DateTimeZone.UTC), new DateTime(0, DateTimeZone.UTC));
|
||||
WatchRecord watchRecord = new WatchRecord("_name#1970-01-01T00:00:00.000Z", watch, event);
|
||||
Wid wid = new Wid("_name", 0, new DateTime(0, DateTimeZone.UTC));
|
||||
WatchRecord watchRecord = new WatchRecord(wid, watch, event);
|
||||
watchRecord.version(4l);
|
||||
|
||||
IndexResponse indexResponse = mock(IndexResponse.class);
|
||||
long version = randomLong();
|
||||
when(indexResponse.getVersion()).thenReturn(version);
|
||||
|
||||
when(clientProxy.index(indexRequest(".watch_history_1970-01-01", HistoryStore.DOC_TYPE, "_name#1970-01-01T00:00:00.000Z", 4L, null))).thenReturn(indexResponse);
|
||||
when(clientProxy.index(indexRequest(".watch_history_1970-01-01", HistoryStore.DOC_TYPE, wid.value(), 4L, null))).thenReturn(indexResponse);
|
||||
historyStore.update(watchRecord);
|
||||
assertThat(watchRecord.version(), equalTo(version));
|
||||
}
|
||||
@ -315,7 +318,7 @@ public class HistoryStoreTests extends ElasticsearchTestCase {
|
||||
|
||||
WatchRecord watchRecord = mock(WatchRecord.class);
|
||||
when(watchRecord.state()).thenReturn(WatchRecord.State.AWAITS_EXECUTION);
|
||||
when(parser.parse(any(BytesReference.class), eq("_id"), eq(1l))).thenReturn(watchRecord);
|
||||
when(parser.parse(eq("_id"), eq(1l), any(BytesReference.class))).thenReturn(watchRecord);
|
||||
|
||||
when(clientProxy.clearScroll(anyString())).thenReturn(new ClearScrollResponse(true, 1));
|
||||
|
||||
|
@ -17,6 +17,7 @@ import org.elasticsearch.watcher.condition.simple.AlwaysFalseCondition;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
import org.elasticsearch.watcher.execution.TriggeredExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.input.Input;
|
||||
import org.elasticsearch.watcher.input.simple.SimpleInput;
|
||||
import org.elasticsearch.watcher.support.http.HttpRequest;
|
||||
@ -41,10 +42,11 @@ public class WatchRecordTests extends AbstractWatcherIntegrationTests {
|
||||
public void testParser() throws Exception {
|
||||
Watch watch = WatcherTestUtils.createTestWatch("fired_test", scriptService(), httpClient(), noopEmailService(), logger);
|
||||
ScheduleTriggerEvent event = new ScheduleTriggerEvent(DateTime.now(UTC), DateTime.now(UTC));
|
||||
WatchRecord watchRecord = new WatchRecord("_record", watch, event);
|
||||
Wid wid = new Wid("_record", randomLong(), DateTime.now(UTC));
|
||||
WatchRecord watchRecord = new WatchRecord(wid, watch, event);
|
||||
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
|
||||
watchRecord.toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
|
||||
WatchRecord parsedWatchRecord = watchRecordParser().parse(jsonBuilder.bytes(), watchRecord.id(), 0);
|
||||
WatchRecord parsedWatchRecord = watchRecordParser().parse(watchRecord.id().value(), 0, jsonBuilder.bytes());
|
||||
|
||||
XContentBuilder jsonBuilder2 = XContentFactory.jsonBuilder();
|
||||
parsedWatchRecord.toXContent(jsonBuilder2, ToXContent.EMPTY_PARAMS);
|
||||
@ -56,7 +58,8 @@ public class WatchRecordTests extends AbstractWatcherIntegrationTests {
|
||||
public void testParser_WithSealedWatchRecord() throws Exception {
|
||||
Watch watch = WatcherTestUtils.createTestWatch("fired_test", scriptService(), httpClient(), noopEmailService(), logger);
|
||||
ScheduleTriggerEvent event = new ScheduleTriggerEvent(DateTime.now(UTC), DateTime.now(UTC));
|
||||
WatchRecord watchRecord = new WatchRecord("_record", watch, event);
|
||||
Wid wid = new Wid("_record", randomLong(), DateTime.now(UTC));
|
||||
WatchRecord watchRecord = new WatchRecord(wid, watch, event);
|
||||
WatchExecutionContext ctx = new TriggeredExecutionContext(watch, new DateTime(), event);
|
||||
ctx.onActionResult(new ActionWrapper.Result("_email", new EmailAction.Result.Failure("failed to send because blah")));
|
||||
HttpRequest request = HttpRequest.builder("localhost", 8000)
|
||||
@ -73,7 +76,7 @@ public class WatchRecordTests extends AbstractWatcherIntegrationTests {
|
||||
|
||||
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
|
||||
watchRecord.toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
|
||||
WatchRecord parsedWatchRecord = watchRecordParser().parse(jsonBuilder.bytes(), watchRecord.id(), 0);
|
||||
WatchRecord parsedWatchRecord = watchRecordParser().parse(watchRecord.id().value(), 0, jsonBuilder.bytes());
|
||||
|
||||
XContentBuilder jsonBuilder2 = XContentFactory.jsonBuilder();
|
||||
parsedWatchRecord.toXContent(jsonBuilder2, ToXContent.EMPTY_PARAMS);
|
||||
@ -102,7 +105,7 @@ public class WatchRecordTests extends AbstractWatcherIntegrationTests {
|
||||
|
||||
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
|
||||
watchRecord.toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
|
||||
WatchRecord parsedWatchRecord = watchRecordParser().parse(jsonBuilder.bytes(), watchRecord.id(), 0);
|
||||
WatchRecord parsedWatchRecord = watchRecordParser().parse(watchRecord.id().value(), 0, jsonBuilder.bytes());
|
||||
|
||||
XContentBuilder jsonBuilder2 = XContentFactory.jsonBuilder();
|
||||
parsedWatchRecord.toXContent(jsonBuilder2, ToXContent.EMPTY_PARAMS);
|
||||
|
@ -17,7 +17,7 @@ import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
import org.elasticsearch.watcher.execution.TriggeredExecutionContext;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
@ -87,7 +87,7 @@ public class HttpInputTests extends ElasticsearchTestCase {
|
||||
new SimpleInput(logger, new Payload.Simple()),
|
||||
new AlwaysTrueCondition(logger),
|
||||
null,
|
||||
new Actions(new ArrayList<ActionWrapper>()),
|
||||
new ExecutableActions(new ArrayList<ActionWrapper>()),
|
||||
null,
|
||||
null,
|
||||
new Watch.Status());
|
||||
|
@ -20,7 +20,7 @@ import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
|
||||
import org.elasticsearch.watcher.input.Input;
|
||||
import org.elasticsearch.watcher.input.InputException;
|
||||
@ -78,7 +78,7 @@ public class SearchInputTests extends ElasticsearchIntegrationTest {
|
||||
new SimpleInput(logger, new Payload.Simple()),
|
||||
new AlwaysTrueCondition(logger),
|
||||
null,
|
||||
new Actions(new ArrayList<ActionWrapper>()),
|
||||
new ExecutableActions(new ArrayList<ActionWrapper>()),
|
||||
null,
|
||||
null,
|
||||
new Watch.Status()),
|
||||
@ -116,7 +116,7 @@ public class SearchInputTests extends ElasticsearchIntegrationTest {
|
||||
new SimpleInput(logger, new Payload.Simple()),
|
||||
new AlwaysTrueCondition(logger),
|
||||
null,
|
||||
new Actions(new ArrayList<ActionWrapper>()),
|
||||
new ExecutableActions(new ArrayList<ActionWrapper>()),
|
||||
null,
|
||||
null,
|
||||
new Watch.Status()),
|
||||
|
@ -257,7 +257,7 @@ public abstract class AbstractWatcherIntegrationTests extends ElasticsearchInteg
|
||||
{
|
||||
builder.startObject("index")
|
||||
.field("index", "my-index")
|
||||
.field("type", "trail")
|
||||
.field("doc_type", "trail")
|
||||
.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
|
@ -16,12 +16,18 @@ import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.actions.email.EmailAction;
|
||||
import org.elasticsearch.watcher.actions.email.service.*;
|
||||
import org.elasticsearch.watcher.actions.email.ExecutableEmailAction;
|
||||
import org.elasticsearch.watcher.actions.email.service.Authentication;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailService;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailTemplate;
|
||||
import org.elasticsearch.watcher.actions.email.service.Profile;
|
||||
import org.elasticsearch.watcher.actions.webhook.ExecutableWebhookAction;
|
||||
import org.elasticsearch.watcher.actions.webhook.WebhookAction;
|
||||
import org.elasticsearch.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.watcher.input.search.SearchInput;
|
||||
import org.elasticsearch.watcher.input.simple.SimpleInput;
|
||||
import org.elasticsearch.watcher.license.LicenseService;
|
||||
@ -43,7 +49,6 @@ import org.elasticsearch.watcher.trigger.schedule.ScheduleTrigger;
|
||||
import org.elasticsearch.watcher.trigger.schedule.ScheduleTriggerEvent;
|
||||
import org.elasticsearch.watcher.watch.Payload;
|
||||
import org.elasticsearch.watcher.watch.Watch;
|
||||
import org.elasticsearch.watcher.execution.WatchExecutionContext;
|
||||
|
||||
import javax.mail.internet.AddressException;
|
||||
import java.util.ArrayList;
|
||||
@ -135,7 +140,7 @@ public final class WatcherTestUtils {
|
||||
|
||||
TemplateEngine engine = new MustacheTemplateEngine(ImmutableSettings.EMPTY, scriptService);
|
||||
|
||||
actions.add(new ActionWrapper("_webhook", new WebhookAction(logger, httpClient, httpRequest.build(), engine)));
|
||||
actions.add(new ActionWrapper("_webhook", new ExecutableWebhookAction(new WebhookAction(httpRequest.build()), logger, httpClient, engine)));
|
||||
|
||||
String from = "from@test.com";
|
||||
String to = "to@test.com";
|
||||
@ -149,9 +154,10 @@ public final class WatcherTestUtils {
|
||||
|
||||
Authentication auth = new Authentication("testname", "testpassword".toCharArray());
|
||||
|
||||
EmailAction emailAction = new EmailAction(logger, email, auth, Profile.STANDARD, "testaccount", false, emailService, templateEngine);
|
||||
EmailAction action = new EmailAction(email, "testaccount", auth, Profile.STANDARD, false);
|
||||
ExecutableEmailAction executale = new ExecutableEmailAction(action, logger, emailService, templateEngine);
|
||||
|
||||
actions.add(new ActionWrapper("_email", emailAction));
|
||||
actions.add(new ActionWrapper("_email", executale));
|
||||
|
||||
Map<String, Object> metadata = new LinkedHashMap<>();
|
||||
metadata.put("foo", "bar");
|
||||
@ -170,7 +176,7 @@ public final class WatcherTestUtils {
|
||||
new SimpleInput(logger, new Payload.Simple(inputData)),
|
||||
new ScriptCondition(logger, scriptService, new Script("return true")),
|
||||
new SearchTransform(logger, scriptService, client, transformRequest),
|
||||
new Actions(actions),
|
||||
new ExecutableActions(actions),
|
||||
metadata,
|
||||
new TimeValue(0),
|
||||
new Watch.Status());
|
||||
|
@ -25,6 +25,7 @@ import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse;
|
||||
import org.elasticsearch.watcher.trigger.schedule.IntervalSchedule;
|
||||
import org.elasticsearch.watcher.trigger.schedule.Schedules;
|
||||
import org.elasticsearch.watcher.watch.WatchStore;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
@ -65,7 +66,7 @@ public class BasicWatcherTests extends AbstractWatcherIntegrationTests {
|
||||
.addAction("_logger", loggingAction("\n\n************\n" +
|
||||
"total hits: {{ctx.payload.hits.total}}\n" +
|
||||
"************\n")
|
||||
.category("_category")))
|
||||
.setCategory("_category")))
|
||||
.get();
|
||||
|
||||
if (timeWarped()) {
|
||||
|
@ -10,14 +10,14 @@ import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.joda.time.DateTimeZone;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.watcher.execution.Wid;
|
||||
import org.elasticsearch.watcher.history.HistoryStore;
|
||||
import org.elasticsearch.watcher.history.WatchRecord;
|
||||
import org.elasticsearch.watcher.input.search.SearchInput;
|
||||
@ -35,11 +35,13 @@ import org.elasticsearch.watcher.trigger.schedule.ScheduleTriggerEvent;
|
||||
import org.elasticsearch.watcher.watch.Watch;
|
||||
import org.elasticsearch.watcher.watch.WatchService;
|
||||
import org.elasticsearch.watcher.watch.WatchStore;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.elasticsearch.common.joda.time.DateTimeZone.UTC;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
|
||||
@ -89,7 +91,7 @@ public class BootStrapTests extends AbstractWatcherIntegrationTests {
|
||||
new SearchInput(logger, scriptService(), ClientProxy.of(client()), searchRequest, null),
|
||||
new ScriptCondition(logger, scriptService(), new Script("return true")),
|
||||
new SearchTransform(logger, scriptService(), ClientProxy.of(client()), searchRequest),
|
||||
new Actions(new ArrayList<ActionWrapper>()),
|
||||
new ExecutableActions(new ArrayList<ActionWrapper>()),
|
||||
null, // metadata
|
||||
new TimeValue(0),
|
||||
new Watch.Status());
|
||||
@ -101,16 +103,17 @@ public class BootStrapTests extends AbstractWatcherIntegrationTests {
|
||||
refresh();
|
||||
assertThat(indexResponse.isCreated(), is(true));
|
||||
|
||||
DateTime now = DateTime.now(DateTimeZone.UTC);
|
||||
DateTime now = DateTime.now(UTC);
|
||||
ScheduleTriggerEvent event = new ScheduleTriggerEvent(now, now);
|
||||
WatchRecord watchRecord = new WatchRecord("_record", watch, event);
|
||||
Wid wid = new Wid("_record", randomLong(), DateTime.now(UTC));
|
||||
WatchRecord watchRecord = new WatchRecord(wid, watch, event);
|
||||
String actionHistoryIndex = HistoryStore.getHistoryIndexNameForTime(now);
|
||||
|
||||
createIndex(actionHistoryIndex);
|
||||
ensureGreen(actionHistoryIndex);
|
||||
logger.info("Created index {}", actionHistoryIndex);
|
||||
|
||||
indexResponse = client().prepareIndex(actionHistoryIndex, HistoryStore.DOC_TYPE, watchRecord.id())
|
||||
indexResponse = client().prepareIndex(actionHistoryIndex, HistoryStore.DOC_TYPE, watchRecord.id().value())
|
||||
.setConsistencyLevel(WriteConsistencyLevel.ALL)
|
||||
.setSource(jsonBuilder().value(watchRecord))
|
||||
.get();
|
||||
@ -128,7 +131,7 @@ public class BootStrapTests extends AbstractWatcherIntegrationTests {
|
||||
@Test
|
||||
@TestLogging("watcher.actions:DEBUG")
|
||||
public void testBootStrapManyHistoryIndices() throws Exception {
|
||||
DateTime now = new DateTime(DateTimeZone.UTC);
|
||||
DateTime now = new DateTime(UTC);
|
||||
long numberOfWatchHistoryIndices = randomIntBetween(2, 8);
|
||||
long numberOfWatchRecordsPerIndex = randomIntBetween(5, 10);
|
||||
SearchRequest searchRequest = WatcherTestUtils.newInputSearchRequest("my-index").source(searchSource().query(termQuery("field", "value")));
|
||||
@ -151,7 +154,7 @@ public class BootStrapTests extends AbstractWatcherIntegrationTests {
|
||||
searchRequest, null),
|
||||
new ScriptCondition(logger, scriptService(), new Script("return true")),
|
||||
new SearchTransform(logger, scriptService(), ClientProxy.of(client()), searchRequest),
|
||||
new Actions(new ArrayList<ActionWrapper>()),
|
||||
new ExecutableActions(new ArrayList<ActionWrapper>()),
|
||||
null, // metatdata
|
||||
new TimeValue(0),
|
||||
new Watch.Status());
|
||||
@ -162,12 +165,13 @@ public class BootStrapTests extends AbstractWatcherIntegrationTests {
|
||||
assertThat(putWatchResponse.isCreated(), is(true));
|
||||
|
||||
ScheduleTriggerEvent event = new ScheduleTriggerEvent(historyIndexDate, historyIndexDate);
|
||||
WatchRecord watchRecord = new WatchRecord("_record-" + i + "-" + j,watch, event);
|
||||
Wid wid = new Wid("record_" + i, randomLong(), DateTime.now(UTC));
|
||||
WatchRecord watchRecord = new WatchRecord(wid, watch, event);
|
||||
|
||||
XContentBuilder jsonBuilder2 = jsonBuilder();
|
||||
watchRecord.toXContent(jsonBuilder2, ToXContent.EMPTY_PARAMS);
|
||||
|
||||
IndexResponse indexResponse = client().prepareIndex(actionHistoryIndex, HistoryStore.DOC_TYPE, watchRecord.id())
|
||||
IndexResponse indexResponse = client().prepareIndex(actionHistoryIndex, HistoryStore.DOC_TYPE, watchRecord.id().value())
|
||||
.setConsistencyLevel(WriteConsistencyLevel.ALL)
|
||||
.setSource(jsonBuilder2.bytes())
|
||||
.get();
|
||||
|
@ -18,16 +18,22 @@ import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.watcher.actions.Action;
|
||||
import org.elasticsearch.watcher.actions.ActionFactory;
|
||||
import org.elasticsearch.watcher.actions.ActionRegistry;
|
||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.watcher.actions.Actions;
|
||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.watcher.actions.email.EmailAction;
|
||||
import org.elasticsearch.watcher.actions.email.EmailActionFactory;
|
||||
import org.elasticsearch.watcher.actions.email.ExecutableEmailAction;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailService;
|
||||
import org.elasticsearch.watcher.actions.email.service.EmailTemplate;
|
||||
import org.elasticsearch.watcher.actions.email.service.Profile;
|
||||
import org.elasticsearch.watcher.actions.index.ExecutableIndexAction;
|
||||
import org.elasticsearch.watcher.actions.index.IndexAction;
|
||||
import org.elasticsearch.watcher.actions.index.IndexActionFactory;
|
||||
import org.elasticsearch.watcher.actions.webhook.ExecutableWebhookAction;
|
||||
import org.elasticsearch.watcher.actions.webhook.WebhookAction;
|
||||
import org.elasticsearch.watcher.actions.webhook.WebhookActionFactory;
|
||||
import org.elasticsearch.watcher.condition.Condition;
|
||||
import org.elasticsearch.watcher.condition.ConditionRegistry;
|
||||
import org.elasticsearch.watcher.condition.script.ScriptCondition;
|
||||
@ -110,7 +116,7 @@ public class WatchTests extends ElasticsearchTestCase {
|
||||
|
||||
Transform transform = randomTransform();
|
||||
|
||||
Actions actions = randomActions();
|
||||
ExecutableActions actions = randomActions();
|
||||
ActionRegistry actionRegistry = registry(actions, transformRegistry);
|
||||
|
||||
Map<String, Object> metadata = ImmutableMap.<String, Object>of("_key", "_val");
|
||||
@ -259,37 +265,40 @@ public class WatchTests extends ElasticsearchTestCase {
|
||||
return registry;
|
||||
}
|
||||
|
||||
private Actions randomActions() {
|
||||
private ExecutableActions randomActions() {
|
||||
ImmutableList.Builder<ActionWrapper> list = ImmutableList.builder();
|
||||
if (randomBoolean()) {
|
||||
Transform transform = randomTransform();
|
||||
list.add(new ActionWrapper("_email_" + randomAsciiOfLength(8), transform, new EmailAction(logger, EmailTemplate.builder().build(), null, Profile.STANDARD, null, randomBoolean(), emailService, templateEngine)));
|
||||
EmailAction action = new EmailAction(EmailTemplate.builder().build(), null, null, Profile.STANDARD, randomBoolean());
|
||||
list.add(new ActionWrapper("_email_" + randomAsciiOfLength(8), transform, new ExecutableEmailAction(action, logger, emailService, templateEngine)));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
list.add(new ActionWrapper("_index_" + randomAsciiOfLength(8), randomTransform(), new IndexAction(logger, client, "_index", "_type")));
|
||||
IndexAction aciton = new IndexAction("_index", "_type");
|
||||
list.add(new ActionWrapper("_index_" + randomAsciiOfLength(8), randomTransform(), new ExecutableIndexAction(aciton, logger, client)));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
HttpRequestTemplate httpRequest = HttpRequestTemplate.builder("test.host", randomIntBetween(8000, 9000))
|
||||
.method(randomFrom(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT))
|
||||
.path(new Template("_url"))
|
||||
.build();
|
||||
list.add(new ActionWrapper("_webhook_" + randomAsciiOfLength(8), randomTransform(), new WebhookAction(logger, httpClient, httpRequest, templateEngine)));
|
||||
WebhookAction action = new WebhookAction(httpRequest);
|
||||
list.add(new ActionWrapper("_webhook_" + randomAsciiOfLength(8), randomTransform(), new ExecutableWebhookAction(action, logger, httpClient, templateEngine)));
|
||||
}
|
||||
return new Actions(list.build());
|
||||
return new ExecutableActions(list.build());
|
||||
}
|
||||
|
||||
private ActionRegistry registry(Actions actions, TransformRegistry transformRegistry) {
|
||||
ImmutableMap.Builder<String, Action.Parser> parsers = ImmutableMap.builder();
|
||||
private ActionRegistry registry(ExecutableActions actions, TransformRegistry transformRegistry) {
|
||||
ImmutableMap.Builder<String, ActionFactory> parsers = ImmutableMap.builder();
|
||||
for (ActionWrapper action : actions) {
|
||||
switch (action.action().type()) {
|
||||
case EmailAction.TYPE:
|
||||
parsers.put(EmailAction.TYPE, new EmailAction.Parser(settings, emailService, templateEngine));
|
||||
parsers.put(EmailAction.TYPE, new EmailActionFactory(settings, emailService, templateEngine));
|
||||
break;
|
||||
case IndexAction.TYPE:
|
||||
parsers.put(IndexAction.TYPE, new IndexAction.Parser(settings, client));
|
||||
parsers.put(IndexAction.TYPE, new IndexActionFactory(settings, client));
|
||||
break;
|
||||
case WebhookAction.TYPE:
|
||||
parsers.put(WebhookAction.TYPE, new WebhookAction.Parser(settings, httpClient,
|
||||
parsers.put(WebhookAction.TYPE, new WebhookActionFactory(settings, httpClient,
|
||||
new HttpRequest.Parser(authRegistry), new HttpRequestTemplate.Parser(authRegistry), templateEngine));
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user