mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-09 14:35:04 +00:00
[Watcher] Add Condition to Action
This adds a "condition" to every action (via the ActionWrapper) that prevents execution of the action if the condition fails. An action-level condition is only useful when there is more than one action, but nothing checks to ensure that it's only used in that scenario. Original commit: elastic/x-pack-elasticsearch@704cfb1a86
This commit is contained in:
parent
101d791ec4
commit
53d022a20a
@ -27,6 +27,7 @@ public interface Action extends ToXContent {
|
|||||||
FAILURE,
|
FAILURE,
|
||||||
PARTIAL_FAILURE,
|
PARTIAL_FAILURE,
|
||||||
THROTTLED,
|
THROTTLED,
|
||||||
|
CONDITION_FAILED,
|
||||||
SIMULATED;
|
SIMULATED;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -51,12 +52,17 @@ public interface Action extends ToXContent {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Failure extends Result {
|
/**
|
||||||
|
* {@code StoppedResult} is a {@link Result} with a {@link #reason()}.
|
||||||
|
* <p>
|
||||||
|
* Any {@code StoppedResult} should provide a reason <em>why</em> it is stopped.
|
||||||
|
*/
|
||||||
|
public static class StoppedResult extends Result {
|
||||||
|
|
||||||
private final String reason;
|
private final String reason;
|
||||||
|
|
||||||
public Failure(String type, String reason, Object... args) {
|
protected StoppedResult(String type, Status status, String reason, Object... args) {
|
||||||
super(type, Status.FAILURE);
|
super(type, status);
|
||||||
this.reason = LoggerMessageFormat.format(reason, args);
|
this.reason = LoggerMessageFormat.format(reason, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,25 +74,42 @@ public interface Action extends ToXContent {
|
|||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
return builder.field(Field.REASON.getPreferredName(), reason);
|
return builder.field(Field.REASON.getPreferredName(), reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Throttled extends Result {
|
/**
|
||||||
|
* {@code Failure} is a {@link StoppedResult} with a status of {@link Status#FAILURE} for actiosn that have failed unexpectedly
|
||||||
|
* (e.g., an exception was thrown in a place that wouldn't expect one, like transformation or an HTTP request).
|
||||||
|
*/
|
||||||
|
public static class Failure extends StoppedResult {
|
||||||
|
|
||||||
private final String reason;
|
public Failure(String type, String reason, Object... args) {
|
||||||
|
super(type, Status.FAILURE, reason, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code Throttled} is a {@link StoppedResult} with a status of {@link Status#THROTTLED} for actions that have been throttled.
|
||||||
|
*/
|
||||||
|
public static class Throttled extends StoppedResult {
|
||||||
|
|
||||||
public Throttled(String type, String reason) {
|
public Throttled(String type, String reason) {
|
||||||
super(type, Status.THROTTLED);
|
super(type, Status.THROTTLED, reason);
|
||||||
this.reason = reason;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String reason() {
|
}
|
||||||
return reason;
|
|
||||||
|
/**
|
||||||
|
* {@code ConditionFailed} is a {@link StoppedResult} with a status of {@link Status#FAILURE} for actions that have been skipped
|
||||||
|
* because the action's condition failed (either expected or unexpected).
|
||||||
|
*/
|
||||||
|
public static class ConditionFailed extends StoppedResult {
|
||||||
|
|
||||||
|
public ConditionFailed(String type, String reason, Object... args) {
|
||||||
|
super(type, Status.CONDITION_FAILED, reason, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder.field(Field.REASON.getPreferredName(), reason);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import org.elasticsearch.common.inject.Inject;
|
|||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.license.XPackLicenseState;
|
import org.elasticsearch.license.XPackLicenseState;
|
||||||
import org.elasticsearch.xpack.support.clock.Clock;
|
import org.elasticsearch.xpack.support.clock.Clock;
|
||||||
|
import org.elasticsearch.xpack.watcher.condition.ConditionRegistry;
|
||||||
import org.elasticsearch.xpack.watcher.support.validation.Validation;
|
import org.elasticsearch.xpack.watcher.support.validation.Validation;
|
||||||
import org.elasticsearch.xpack.watcher.transform.TransformRegistry;
|
import org.elasticsearch.xpack.watcher.transform.TransformRegistry;
|
||||||
|
|
||||||
@ -23,14 +24,18 @@ import java.util.Map;
|
|||||||
public class ActionRegistry {
|
public class ActionRegistry {
|
||||||
|
|
||||||
private final Map<String, ActionFactory> parsers;
|
private final Map<String, ActionFactory> parsers;
|
||||||
|
private final ConditionRegistry conditionRegistry;
|
||||||
private final TransformRegistry transformRegistry;
|
private final TransformRegistry transformRegistry;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final XPackLicenseState licenseState;
|
private final XPackLicenseState licenseState;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ActionRegistry(Map<String, ActionFactory> parsers, TransformRegistry transformRegistry, Clock clock,
|
public ActionRegistry(Map<String, ActionFactory> parsers,
|
||||||
|
ConditionRegistry conditionRegistry, TransformRegistry transformRegistry,
|
||||||
|
Clock clock,
|
||||||
XPackLicenseState licenseState) {
|
XPackLicenseState licenseState) {
|
||||||
this.parsers = parsers;
|
this.parsers = parsers;
|
||||||
|
this.conditionRegistry = conditionRegistry;
|
||||||
this.transformRegistry = transformRegistry;
|
this.transformRegistry = transformRegistry;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.licenseState = licenseState;
|
this.licenseState = licenseState;
|
||||||
@ -57,8 +62,7 @@ public class ActionRegistry {
|
|||||||
throw new ElasticsearchParseException("could not parse action [{}] for watch [{}]. {}", id, watchId, error);
|
throw new ElasticsearchParseException("could not parse action [{}] for watch [{}]. {}", id, watchId, error);
|
||||||
}
|
}
|
||||||
} else if (token == XContentParser.Token.START_OBJECT && id != null) {
|
} else if (token == XContentParser.Token.START_OBJECT && id != null) {
|
||||||
ActionWrapper action = ActionWrapper.parse(watchId, id, parser, this, transformRegistry, clock, licenseState);
|
actions.add(ActionWrapper.parse(watchId, id, parser, this, conditionRegistry, transformRegistry, clock, licenseState));
|
||||||
actions.add(action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ExecutableActions(actions);
|
return new ExecutableActions(actions);
|
||||||
|
@ -17,6 +17,9 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
|||||||
import org.elasticsearch.license.XPackLicenseState;
|
import org.elasticsearch.license.XPackLicenseState;
|
||||||
import org.elasticsearch.xpack.watcher.actions.throttler.ActionThrottler;
|
import org.elasticsearch.xpack.watcher.actions.throttler.ActionThrottler;
|
||||||
import org.elasticsearch.xpack.watcher.actions.throttler.Throttler;
|
import org.elasticsearch.xpack.watcher.actions.throttler.Throttler;
|
||||||
|
import org.elasticsearch.xpack.watcher.condition.Condition;
|
||||||
|
import org.elasticsearch.xpack.watcher.condition.ConditionRegistry;
|
||||||
|
import org.elasticsearch.xpack.watcher.condition.ExecutableCondition;
|
||||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||||
import org.elasticsearch.xpack.watcher.support.WatcherDateTimeUtils;
|
import org.elasticsearch.xpack.watcher.support.WatcherDateTimeUtils;
|
||||||
import org.elasticsearch.xpack.support.clock.Clock;
|
import org.elasticsearch.xpack.support.clock.Clock;
|
||||||
@ -24,6 +27,7 @@ import org.elasticsearch.xpack.watcher.transform.ExecutableTransform;
|
|||||||
import org.elasticsearch.xpack.watcher.transform.Transform;
|
import org.elasticsearch.xpack.watcher.transform.Transform;
|
||||||
import org.elasticsearch.xpack.watcher.transform.TransformRegistry;
|
import org.elasticsearch.xpack.watcher.transform.TransformRegistry;
|
||||||
import org.elasticsearch.xpack.watcher.watch.Payload;
|
import org.elasticsearch.xpack.watcher.watch.Payload;
|
||||||
|
import org.elasticsearch.xpack.watcher.watch.Watch;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -33,16 +37,23 @@ import java.io.IOException;
|
|||||||
public class ActionWrapper implements ToXContent {
|
public class ActionWrapper implements ToXContent {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
@Nullable private final ExecutableTransform transform;
|
@Nullable
|
||||||
|
private final ExecutableCondition condition;
|
||||||
|
@Nullable
|
||||||
|
private final ExecutableTransform transform;
|
||||||
private final ActionThrottler throttler;
|
private final ActionThrottler throttler;
|
||||||
private final ExecutableAction action;
|
private final ExecutableAction action;
|
||||||
|
|
||||||
public ActionWrapper(String id, ExecutableAction action) {
|
public ActionWrapper(String id, ExecutableAction action) {
|
||||||
this(id, null, null, action);
|
this(id, null, null, null, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionWrapper(String id, ActionThrottler throttler, @Nullable ExecutableTransform transform, ExecutableAction action) {
|
public ActionWrapper(String id, ActionThrottler throttler,
|
||||||
|
@Nullable ExecutableCondition condition,
|
||||||
|
@Nullable ExecutableTransform transform,
|
||||||
|
ExecutableAction action) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.condition = condition;
|
||||||
this.throttler = throttler;
|
this.throttler = throttler;
|
||||||
this.transform = transform;
|
this.transform = transform;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
@ -52,6 +63,10 @@ public class ActionWrapper implements ToXContent {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExecutableCondition condition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
public ExecutableTransform transform() {
|
public ExecutableTransform transform() {
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
@ -64,7 +79,21 @@ public class ActionWrapper implements ToXContent {
|
|||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionWrapper.Result execute(WatchExecutionContext ctx) throws IOException {
|
/**
|
||||||
|
* Execute the current {@link #action()}.
|
||||||
|
* <p>
|
||||||
|
* This executes in the order of:
|
||||||
|
* <ol>
|
||||||
|
* <li>Throttling</li>
|
||||||
|
* <li>Conditional Check</li>
|
||||||
|
* <li>Transformation</li>
|
||||||
|
* <li>Action</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @param ctx The current watch's context
|
||||||
|
* @return Never {@code null}
|
||||||
|
*/
|
||||||
|
public ActionWrapper.Result execute(WatchExecutionContext ctx) {
|
||||||
ActionWrapper.Result result = ctx.actionsResults().get(id);
|
ActionWrapper.Result result = ctx.actionsResults().get(id);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
@ -75,6 +104,20 @@ public class ActionWrapper implements ToXContent {
|
|||||||
return new ActionWrapper.Result(id, new Action.Result.Throttled(action.type(), throttleResult.reason()));
|
return new ActionWrapper.Result(id, new Action.Result.Throttled(action.type(), throttleResult.reason()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Condition.Result conditionResult = null;
|
||||||
|
if (condition != null) {
|
||||||
|
try {
|
||||||
|
conditionResult = condition.execute(ctx);
|
||||||
|
if (conditionResult.met() == false) {
|
||||||
|
return new ActionWrapper.Result(id, conditionResult, null,
|
||||||
|
new Action.Result.ConditionFailed(action.type(), "condition not met. skipping"));
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
action.logger().error("failed to execute action [{}/{}]. failed to execute condition", e, ctx.watch().id(), id);
|
||||||
|
return new ActionWrapper.Result(id, new Action.Result.ConditionFailed(action.type(),
|
||||||
|
"condition failed. skipping: {}", e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
Payload payload = ctx.payload();
|
Payload payload = ctx.payload();
|
||||||
Transform.Result transformResult = null;
|
Transform.Result transformResult = null;
|
||||||
if (transform != null) {
|
if (transform != null) {
|
||||||
@ -84,18 +127,19 @@ public class ActionWrapper implements ToXContent {
|
|||||||
action.logger().error("failed to execute action [{}/{}]. failed to transform payload. {}", ctx.watch().id(), id,
|
action.logger().error("failed to execute action [{}/{}]. failed to transform payload. {}", ctx.watch().id(), id,
|
||||||
transformResult.reason());
|
transformResult.reason());
|
||||||
String msg = "Failed to transform payload";
|
String msg = "Failed to transform payload";
|
||||||
return new ActionWrapper.Result(id, transformResult, new Action.Result.Failure(action.type(), msg));
|
return new ActionWrapper.Result(id, conditionResult, transformResult, new Action.Result.Failure(action.type(), msg));
|
||||||
}
|
}
|
||||||
payload = transformResult.payload();
|
payload = transformResult.payload();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
action.logger().error("failed to execute action [{}/{}]. failed to transform payload.", e, ctx.watch().id(), id);
|
action.logger().error("failed to execute action [{}/{}]. failed to transform payload.", e, ctx.watch().id(), id);
|
||||||
return new ActionWrapper.Result(id, new Action.Result.Failure(action.type(), "Failed to transform payload. error: " +
|
return new ActionWrapper.Result(id, conditionResult, null,
|
||||||
ExceptionsHelper.detailedMessage(e)));
|
new Action.Result.Failure(action.type(), "Failed to transform payload. error: {}",
|
||||||
|
ExceptionsHelper.detailedMessage(e)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Action.Result actionResult = action.execute(id, ctx, payload);
|
Action.Result actionResult = action.execute(id, ctx, payload);
|
||||||
return new ActionWrapper.Result(id, transformResult, actionResult);
|
return new ActionWrapper.Result(id, conditionResult, transformResult, actionResult);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
action.logger().error("failed to execute action [{}/{}]", e, ctx.watch().id(), id);
|
action.logger().error("failed to execute action [{}/{}]", e, ctx.watch().id(), id);
|
||||||
return new ActionWrapper.Result(id, new Action.Result.Failure(action.type(), ExceptionsHelper.detailedMessage(e)));
|
return new ActionWrapper.Result(id, new Action.Result.Failure(action.type(), ExceptionsHelper.detailedMessage(e)));
|
||||||
@ -110,6 +154,7 @@ public class ActionWrapper implements ToXContent {
|
|||||||
ActionWrapper that = (ActionWrapper) o;
|
ActionWrapper that = (ActionWrapper) o;
|
||||||
|
|
||||||
if (!id.equals(that.id)) return false;
|
if (!id.equals(that.id)) return false;
|
||||||
|
if (condition != null ? !condition.equals(that.condition) : that.condition != null) return false;
|
||||||
if (transform != null ? !transform.equals(that.transform) : that.transform != null) return false;
|
if (transform != null ? !transform.equals(that.transform) : that.transform != null) return false;
|
||||||
return action.equals(that.action);
|
return action.equals(that.action);
|
||||||
}
|
}
|
||||||
@ -117,6 +162,7 @@ public class ActionWrapper implements ToXContent {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = id.hashCode();
|
int result = id.hashCode();
|
||||||
|
result = 31 * result + (condition != null ? condition.hashCode() : 0);
|
||||||
result = 31 * result + (transform != null ? transform.hashCode() : 0);
|
result = 31 * result + (transform != null ? transform.hashCode() : 0);
|
||||||
result = 31 * result + action.hashCode();
|
result = 31 * result + action.hashCode();
|
||||||
return result;
|
return result;
|
||||||
@ -129,6 +175,11 @@ public class ActionWrapper implements ToXContent {
|
|||||||
if (throttlePeriod != null) {
|
if (throttlePeriod != null) {
|
||||||
builder.field(Throttler.Field.THROTTLE_PERIOD.getPreferredName(), throttlePeriod);
|
builder.field(Throttler.Field.THROTTLE_PERIOD.getPreferredName(), throttlePeriod);
|
||||||
}
|
}
|
||||||
|
if (condition != null) {
|
||||||
|
builder.startObject(Watch.Field.CONDITION.getPreferredName())
|
||||||
|
.field(condition.type(), condition, params)
|
||||||
|
.endObject();
|
||||||
|
}
|
||||||
if (transform != null) {
|
if (transform != null) {
|
||||||
builder.startObject(Transform.Field.TRANSFORM.getPreferredName())
|
builder.startObject(Transform.Field.TRANSFORM.getPreferredName())
|
||||||
.field(transform.type(), transform, params)
|
.field(transform.type(), transform, params)
|
||||||
@ -139,11 +190,12 @@ public class ActionWrapper implements ToXContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ActionWrapper parse(String watchId, String actionId, XContentParser parser,
|
static ActionWrapper parse(String watchId, String actionId, XContentParser parser,
|
||||||
ActionRegistry actionRegistry, TransformRegistry transformRegistry,
|
ActionRegistry actionRegistry, ConditionRegistry conditionRegistry, TransformRegistry transformRegistry,
|
||||||
Clock clock, XPackLicenseState licenseState) throws IOException {
|
Clock clock, XPackLicenseState licenseState) throws IOException {
|
||||||
|
|
||||||
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
|
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
|
||||||
|
|
||||||
|
ExecutableCondition condition = null;
|
||||||
ExecutableTransform transform = null;
|
ExecutableTransform transform = null;
|
||||||
TimeValue throttlePeriod = null;
|
TimeValue throttlePeriod = null;
|
||||||
ExecutableAction action = null;
|
ExecutableAction action = null;
|
||||||
@ -154,7 +206,9 @@ public class ActionWrapper implements ToXContent {
|
|||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
currentFieldName = parser.currentName();
|
currentFieldName = parser.currentName();
|
||||||
} else {
|
} else {
|
||||||
if (ParseFieldMatcher.STRICT.match(currentFieldName, Transform.Field.TRANSFORM)) {
|
if (ParseFieldMatcher.STRICT.match(currentFieldName, Watch.Field.CONDITION)) {
|
||||||
|
condition = conditionRegistry.parseExecutable(watchId, parser);
|
||||||
|
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Transform.Field.TRANSFORM)) {
|
||||||
transform = transformRegistry.parse(watchId, parser);
|
transform = transformRegistry.parse(watchId, parser);
|
||||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Throttler.Field.THROTTLE_PERIOD)) {
|
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Throttler.Field.THROTTLE_PERIOD)) {
|
||||||
try {
|
try {
|
||||||
@ -179,21 +233,25 @@ public class ActionWrapper implements ToXContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ActionThrottler throttler = new ActionThrottler(clock, throttlePeriod, licenseState);
|
ActionThrottler throttler = new ActionThrottler(clock, throttlePeriod, licenseState);
|
||||||
return new ActionWrapper(actionId, throttler, transform, action);
|
return new ActionWrapper(actionId, throttler, condition, transform, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Result implements ToXContent {
|
public static class Result implements ToXContent {
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
@Nullable private final Transform.Result transform;
|
@Nullable
|
||||||
|
private final Condition.Result condition;
|
||||||
|
@Nullable
|
||||||
|
private final Transform.Result transform;
|
||||||
private final Action.Result action;
|
private final Action.Result action;
|
||||||
|
|
||||||
public Result(String id, Action.Result action) {
|
public Result(String id, Action.Result action) {
|
||||||
this(id, null, action);
|
this(id, null, null, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result(String id, @Nullable Transform.Result transform, Action.Result action) {
|
public Result(String id, @Nullable Condition.Result condition, @Nullable Transform.Result transform, Action.Result action) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.condition = condition;
|
||||||
this.transform = transform;
|
this.transform = transform;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
}
|
}
|
||||||
@ -202,6 +260,10 @@ public class ActionWrapper implements ToXContent {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Condition.Result condition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
public Transform.Result transform() {
|
public Transform.Result transform() {
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
@ -218,6 +280,7 @@ public class ActionWrapper implements ToXContent {
|
|||||||
Result result = (Result) o;
|
Result result = (Result) o;
|
||||||
|
|
||||||
if (!id.equals(result.id)) return false;
|
if (!id.equals(result.id)) return false;
|
||||||
|
if (condition != null ? !condition.equals(result.condition) : result.condition != null) return false;
|
||||||
if (transform != null ? !transform.equals(result.transform) : result.transform != null) return false;
|
if (transform != null ? !transform.equals(result.transform) : result.transform != null) return false;
|
||||||
return action.equals(result.action);
|
return action.equals(result.action);
|
||||||
}
|
}
|
||||||
@ -225,6 +288,7 @@ public class ActionWrapper implements ToXContent {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = id.hashCode();
|
int result = id.hashCode();
|
||||||
|
result = 31 * result + (condition != null ? condition.hashCode() : 0);
|
||||||
result = 31 * result + (transform != null ? transform.hashCode() : 0);
|
result = 31 * result + (transform != null ? transform.hashCode() : 0);
|
||||||
result = 31 * result + action.hashCode();
|
result = 31 * result + action.hashCode();
|
||||||
return result;
|
return result;
|
||||||
@ -235,7 +299,10 @@ public class ActionWrapper implements ToXContent {
|
|||||||
builder.startObject();
|
builder.startObject();
|
||||||
builder.field(Field.ID.getPreferredName(), id);
|
builder.field(Field.ID.getPreferredName(), id);
|
||||||
builder.field(Field.TYPE.getPreferredName(), action.type());
|
builder.field(Field.TYPE.getPreferredName(), action.type());
|
||||||
builder.field(Field.STATUS.getPreferredName(), action.status, params);
|
builder.field(Field.STATUS.getPreferredName(), action.status(), params);
|
||||||
|
if (condition != null) {
|
||||||
|
builder.field(Watch.Field.CONDITION.getPreferredName(), condition, params);
|
||||||
|
}
|
||||||
if (transform != null) {
|
if (transform != null) {
|
||||||
builder.field(Transform.Field.TRANSFORM.getPreferredName(), transform, params);
|
builder.field(Transform.Field.TRANSFORM.getPreferredName(), transform, params);
|
||||||
}
|
}
|
||||||
|
@ -97,12 +97,26 @@ public class WatchSourceBuilder implements ToXContent {
|
|||||||
return addAction(id, null, transform.build(), action.build());
|
return addAction(id, null, transform.build(), action.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WatchSourceBuilder addAction(String id, Condition.Builder condition, Action.Builder action) {
|
||||||
|
return addAction(id, null, condition.build(), null, action.build());
|
||||||
|
}
|
||||||
|
|
||||||
public WatchSourceBuilder addAction(String id, TimeValue throttlePeriod, Transform.Builder transform, Action.Builder action) {
|
public WatchSourceBuilder addAction(String id, TimeValue throttlePeriod, Transform.Builder transform, Action.Builder action) {
|
||||||
return addAction(id, throttlePeriod, transform.build(), action.build());
|
return addAction(id, throttlePeriod, transform.build(), action.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public WatchSourceBuilder addAction(String id, TimeValue throttlePeriod, Transform transform, Action action) {
|
public WatchSourceBuilder addAction(String id, TimeValue throttlePeriod, Transform transform, Action action) {
|
||||||
actions.put(id, new TransformedAction(id, action, throttlePeriod, transform));
|
actions.put(id, new TransformedAction(id, action, throttlePeriod, null, transform));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WatchSourceBuilder addAction(String id, TimeValue throttlePeriod, Condition.Builder condition, Transform.Builder transform,
|
||||||
|
Action.Builder action) {
|
||||||
|
return addAction(id, throttlePeriod, condition.build(), transform.build(), action.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public WatchSourceBuilder addAction(String id, TimeValue throttlePeriod, Condition condition, Transform transform, Action action) {
|
||||||
|
actions.put(id, new TransformedAction(id, action, throttlePeriod, condition, transform));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,11 +187,14 @@ public class WatchSourceBuilder implements ToXContent {
|
|||||||
private final String id;
|
private final String id;
|
||||||
private final Action action;
|
private final Action action;
|
||||||
@Nullable private final TimeValue throttlePeriod;
|
@Nullable private final TimeValue throttlePeriod;
|
||||||
|
@Nullable private final Condition condition;
|
||||||
@Nullable private final Transform transform;
|
@Nullable private final Transform transform;
|
||||||
|
|
||||||
public TransformedAction(String id, Action action, @Nullable TimeValue throttlePeriod, @Nullable Transform transform) {
|
public TransformedAction(String id, Action action, @Nullable TimeValue throttlePeriod,
|
||||||
|
@Nullable Condition condition, @Nullable Transform transform) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.throttlePeriod = throttlePeriod;
|
this.throttlePeriod = throttlePeriod;
|
||||||
|
this.condition = condition;
|
||||||
this.transform = transform;
|
this.transform = transform;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
}
|
}
|
||||||
@ -188,6 +205,11 @@ public class WatchSourceBuilder implements ToXContent {
|
|||||||
if (throttlePeriod != null) {
|
if (throttlePeriod != null) {
|
||||||
builder.field(Throttler.Field.THROTTLE_PERIOD.getPreferredName(), throttlePeriod);
|
builder.field(Throttler.Field.THROTTLE_PERIOD.getPreferredName(), throttlePeriod);
|
||||||
}
|
}
|
||||||
|
if (condition != null) {
|
||||||
|
builder.startObject(Watch.Field.CONDITION.getPreferredName())
|
||||||
|
.field(condition.type(), condition, params)
|
||||||
|
.endObject();
|
||||||
|
}
|
||||||
if (transform != null) {
|
if (transform != null) {
|
||||||
builder.startObject(Transform.Field.TRANSFORM.getPreferredName())
|
builder.startObject(Transform.Field.TRANSFORM.getPreferredName())
|
||||||
.field(transform.type(), transform, params)
|
.field(transform.type(), transform, params)
|
||||||
|
@ -31,6 +31,7 @@ public interface Condition extends ToXContent {
|
|||||||
protected final boolean met;
|
protected final boolean met;
|
||||||
|
|
||||||
public Result(String type, boolean met) {
|
public Result(String type, boolean met) {
|
||||||
|
// TODO: FAILURE status is never used, but a some code assumes that it is used
|
||||||
this.status = Status.SUCCESS;
|
this.status = Status.SUCCESS;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.met = met;
|
this.met = met;
|
||||||
@ -46,7 +47,6 @@ public interface Condition extends ToXContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean met() {
|
public boolean met() {
|
||||||
assert status == Status.SUCCESS;
|
|
||||||
return met;
|
return met;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ import org.elasticsearch.common.unit.TimeValue;
|
|||||||
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
|
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
|
||||||
import org.elasticsearch.xpack.support.clock.Clock;
|
import org.elasticsearch.xpack.support.clock.Clock;
|
||||||
import org.elasticsearch.xpack.watcher.Watcher;
|
import org.elasticsearch.xpack.watcher.Watcher;
|
||||||
import org.elasticsearch.xpack.watcher.WatcherFeatureSet;
|
|
||||||
import org.elasticsearch.xpack.common.stats.Counters;
|
import org.elasticsearch.xpack.common.stats.Counters;
|
||||||
import org.elasticsearch.xpack.watcher.actions.ActionWrapper;
|
import org.elasticsearch.xpack.watcher.actions.ActionWrapper;
|
||||||
import org.elasticsearch.xpack.watcher.condition.Condition;
|
import org.elasticsearch.xpack.watcher.condition.Condition;
|
||||||
@ -32,7 +31,6 @@ import org.elasticsearch.xpack.watcher.watch.WatchStore;
|
|||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -349,7 +347,7 @@ public class ExecutionService extends AbstractComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WatchRecord executeInner(WatchExecutionContext ctx) throws IOException {
|
WatchRecord executeInner(WatchExecutionContext ctx) {
|
||||||
ctx.start();
|
ctx.start();
|
||||||
Watch watch = ctx.watch();
|
Watch watch = ctx.watch();
|
||||||
|
|
||||||
|
@ -14,11 +14,8 @@ import org.elasticsearch.common.settings.Settings;
|
|||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.index.query.QueryParseContext;
|
import org.elasticsearch.index.query.QueryParseContext;
|
||||||
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
|
||||||
import org.elasticsearch.script.ScriptService;
|
import org.elasticsearch.script.ScriptService;
|
||||||
import org.elasticsearch.search.SearchRequestParsers;
|
import org.elasticsearch.search.SearchRequestParsers;
|
||||||
import org.elasticsearch.search.aggregations.AggregatorParsers;
|
|
||||||
import org.elasticsearch.search.suggest.Suggesters;
|
|
||||||
import org.elasticsearch.xpack.security.InternalClient;
|
import org.elasticsearch.xpack.security.InternalClient;
|
||||||
import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy;
|
import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy;
|
||||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package org.elasticsearch.xpack.watcher.execution;
|
package org.elasticsearch.xpack.watcher.execution;
|
||||||
|
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.common.collect.Tuple;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
import org.elasticsearch.xpack.support.clock.Clock;
|
import org.elasticsearch.xpack.support.clock.Clock;
|
||||||
@ -67,7 +68,6 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
private Input.Result inputResult;
|
private Input.Result inputResult;
|
||||||
|
|
||||||
private WatchStore watchStore;
|
private WatchStore watchStore;
|
||||||
private TriggeredWatchStore triggeredWatchStore;
|
|
||||||
private HistoryStore historyStore;
|
private HistoryStore historyStore;
|
||||||
private WatchLockService watchLockService;
|
private WatchLockService watchLockService;
|
||||||
private ExecutionService executionService;
|
private ExecutionService executionService;
|
||||||
@ -75,6 +75,8 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
|
TriggeredWatchStore triggeredWatchStore;
|
||||||
|
|
||||||
payload = mock(Payload.class);
|
payload = mock(Payload.class);
|
||||||
input = mock(ExecutableInput.class);
|
input = mock(ExecutableInput.class);
|
||||||
inputResult = mock(Input.Result.class);
|
inputResult = mock(Input.Result.class);
|
||||||
@ -87,7 +89,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
historyStore = mock(HistoryStore.class);
|
historyStore = mock(HistoryStore.class);
|
||||||
|
|
||||||
WatchExecutor executor = mock(WatchExecutor.class);
|
WatchExecutor executor = mock(WatchExecutor.class);
|
||||||
when(executor.queue()).thenReturn(new ArrayBlockingQueue<Runnable>(1));
|
when(executor.queue()).thenReturn(new ArrayBlockingQueue<>(1));
|
||||||
|
|
||||||
watchLockService = mock(WatchLockService.class);
|
watchLockService = mock(WatchLockService.class);
|
||||||
clock = new ClockMock();
|
clock = new ClockMock();
|
||||||
@ -95,7 +97,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
watchLockService, clock);
|
watchLockService, clock);
|
||||||
|
|
||||||
ClusterState clusterState = mock(ClusterState.class);
|
ClusterState clusterState = mock(ClusterState.class);
|
||||||
when(triggeredWatchStore.loadTriggeredWatches(clusterState)).thenReturn(new ArrayList<TriggeredWatch>());
|
when(triggeredWatchStore.loadTriggeredWatches(clusterState)).thenReturn(new ArrayList<>());
|
||||||
executionService.start(clusterState);
|
executionService.start(clusterState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,11 +129,27 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionThrottler throttler = mock(ActionThrottler.class);
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
|
// action level conditional
|
||||||
|
ExecutableCondition actionCondition = null;
|
||||||
|
Condition.Result actionConditionResult = null;
|
||||||
|
|
||||||
|
if (randomBoolean()) {
|
||||||
|
Tuple<ExecutableCondition, Condition.Result> pair = whenCondition(context);
|
||||||
|
|
||||||
|
actionCondition = pair.v1();
|
||||||
|
actionConditionResult = pair.v2();
|
||||||
|
}
|
||||||
|
|
||||||
// action level transform
|
// action level transform
|
||||||
Transform.Result actionTransformResult = mock(Transform.Result.class);
|
ExecutableTransform actionTransform = null;
|
||||||
when(actionTransformResult.payload()).thenReturn(payload);
|
Transform.Result actionTransformResult = null;
|
||||||
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
|
||||||
when(actionTransform.execute(context, payload)).thenReturn(actionTransformResult);
|
if (randomBoolean()) {
|
||||||
|
Tuple<ExecutableTransform, Transform.Result> pair = whenTransform(context);
|
||||||
|
|
||||||
|
actionTransform = pair.v1();
|
||||||
|
actionTransformResult = pair.v2();
|
||||||
|
}
|
||||||
|
|
||||||
// the action
|
// the action
|
||||||
Action.Result actionResult = mock(Action.Result.class);
|
Action.Result actionResult = mock(Action.Result.class);
|
||||||
@ -141,7 +159,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
when(action.type()).thenReturn("MY_AWESOME_TYPE");
|
when(action.type()).thenReturn("MY_AWESOME_TYPE");
|
||||||
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
||||||
|
|
||||||
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionTransform, action);
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
||||||
@ -158,6 +176,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionWrapper.Result result = watchRecord.result().actionsResults().get("_action");
|
ActionWrapper.Result result = watchRecord.result().actionsResults().get("_action");
|
||||||
assertThat(result, notNullValue());
|
assertThat(result, notNullValue());
|
||||||
assertThat(result.id(), is("_action"));
|
assertThat(result.id(), is("_action"));
|
||||||
|
assertThat(result.condition(), sameInstance(actionConditionResult));
|
||||||
assertThat(result.transform(), sameInstance(actionTransformResult));
|
assertThat(result.transform(), sameInstance(actionTransformResult));
|
||||||
assertThat(result.action(), sameInstance(actionResult));
|
assertThat(result.action(), sameInstance(actionResult));
|
||||||
|
|
||||||
@ -208,11 +227,10 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionThrottler throttler = mock(ActionThrottler.class);
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
// action level transform
|
// action level condition (unused)
|
||||||
Transform.Result actionTransformResult = mock(Transform.Result.class);
|
ExecutableCondition actionCondition = randomBoolean() ? mock(ExecutableCondition.class) : null;
|
||||||
when(actionTransformResult.payload()).thenReturn(payload);
|
// action level transform (unused)
|
||||||
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
ExecutableTransform actionTransform = randomBoolean() ? mock(ExecutableTransform.class) : null;
|
||||||
when(actionTransform.execute(context, payload)).thenReturn(actionTransformResult);
|
|
||||||
|
|
||||||
// the action
|
// the action
|
||||||
Action.Result actionResult = mock(Action.Result.class);
|
Action.Result actionResult = mock(Action.Result.class);
|
||||||
@ -221,7 +239,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ExecutableAction action = mock(ExecutableAction.class);
|
ExecutableAction action = mock(ExecutableAction.class);
|
||||||
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
||||||
|
|
||||||
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionTransform, action);
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
||||||
@ -276,11 +294,10 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionThrottler throttler = mock(ActionThrottler.class);
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
// action level transform
|
// action level condition (unused)
|
||||||
Transform.Result actionTransformResult = mock(Transform.Result.class);
|
ExecutableCondition actionCondition = randomBoolean() ? mock(ExecutableCondition.class) : null;
|
||||||
when(actionTransformResult.payload()).thenReturn(payload);
|
// action level transform (unused)
|
||||||
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
ExecutableTransform actionTransform = randomBoolean() ? mock(ExecutableTransform.class) : null;
|
||||||
when(actionTransform.execute(context, payload)).thenReturn(actionTransformResult);
|
|
||||||
|
|
||||||
// the action
|
// the action
|
||||||
Action.Result actionResult = mock(Action.Result.class);
|
Action.Result actionResult = mock(Action.Result.class);
|
||||||
@ -289,7 +306,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ExecutableAction action = mock(ExecutableAction.class);
|
ExecutableAction action = mock(ExecutableAction.class);
|
||||||
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
||||||
|
|
||||||
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionTransform, action);
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
||||||
@ -343,11 +360,10 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionThrottler throttler = mock(ActionThrottler.class);
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
// action level transform
|
// action level condition (unused)
|
||||||
Transform.Result actionTransformResult = mock(Transform.Result.class);
|
ExecutableCondition actionCondition = randomBoolean() ? mock(ExecutableCondition.class) : null;
|
||||||
when(actionTransformResult.payload()).thenReturn(payload);
|
// action level transform (unused)
|
||||||
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
ExecutableTransform actionTransform = randomBoolean() ? mock(ExecutableTransform.class) : null;
|
||||||
when(actionTransform.execute(context, payload)).thenReturn(actionTransformResult);
|
|
||||||
|
|
||||||
// the action
|
// the action
|
||||||
Action.Result actionResult = mock(Action.Result.class);
|
Action.Result actionResult = mock(Action.Result.class);
|
||||||
@ -356,7 +372,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ExecutableAction action = mock(ExecutableAction.class);
|
ExecutableAction action = mock(ExecutableAction.class);
|
||||||
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
||||||
|
|
||||||
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionTransform, action);
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
||||||
@ -410,6 +426,17 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionThrottler throttler = mock(ActionThrottler.class);
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
|
// action level condition
|
||||||
|
ExecutableCondition actionCondition = null;
|
||||||
|
Condition.Result actionConditionResult = null;
|
||||||
|
|
||||||
|
if (randomBoolean()) {
|
||||||
|
Tuple<ExecutableCondition, Condition.Result> pair = whenCondition(context);
|
||||||
|
|
||||||
|
actionCondition = pair.v1();
|
||||||
|
actionConditionResult = pair.v2();
|
||||||
|
}
|
||||||
|
|
||||||
// action level transform
|
// action level transform
|
||||||
Transform.Result actionTransformResult = mock(Transform.Result.class);
|
Transform.Result actionTransformResult = mock(Transform.Result.class);
|
||||||
when(actionTransformResult.status()).thenReturn(Transform.Result.Status.FAILURE);
|
when(actionTransformResult.status()).thenReturn(Transform.Result.Status.FAILURE);
|
||||||
@ -425,7 +452,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
when(action.logger()).thenReturn(logger);
|
when(action.logger()).thenReturn(logger);
|
||||||
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
||||||
|
|
||||||
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionTransform, action);
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(clock.nowUTC())));
|
||||||
@ -442,6 +469,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
assertThat(watchRecord.result().transformResult(), is(watchTransformResult));
|
assertThat(watchRecord.result().transformResult(), is(watchTransformResult));
|
||||||
assertThat(watchRecord.result().actionsResults(), notNullValue());
|
assertThat(watchRecord.result().actionsResults(), notNullValue());
|
||||||
assertThat(watchRecord.result().actionsResults().count(), is(1));
|
assertThat(watchRecord.result().actionsResults().count(), is(1));
|
||||||
|
assertThat(watchRecord.result().actionsResults().get("_action").condition(), is(actionConditionResult));
|
||||||
assertThat(watchRecord.result().actionsResults().get("_action").transform(), is(actionTransformResult));
|
assertThat(watchRecord.result().actionsResults().get("_action").transform(), is(actionTransformResult));
|
||||||
assertThat(watchRecord.result().actionsResults().get("_action").action().status(), is(Action.Result.Status.FAILURE));
|
assertThat(watchRecord.result().actionsResults().get("_action").action().status(), is(Action.Result.Status.FAILURE));
|
||||||
|
|
||||||
@ -476,11 +504,27 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionThrottler throttler = mock(ActionThrottler.class);
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
|
// action level conditional
|
||||||
|
ExecutableCondition actionCondition = null;
|
||||||
|
Condition.Result actionConditionResult = null;
|
||||||
|
|
||||||
|
if (randomBoolean()) {
|
||||||
|
Tuple<ExecutableCondition, Condition.Result> pair = whenCondition(context);
|
||||||
|
|
||||||
|
actionCondition = pair.v1();
|
||||||
|
actionConditionResult = pair.v2();
|
||||||
|
}
|
||||||
|
|
||||||
// action level transform
|
// action level transform
|
||||||
Transform.Result actionTransformResult = mock(Transform.Result.class);
|
ExecutableTransform actionTransform = null;
|
||||||
when(actionTransformResult.payload()).thenReturn(payload);
|
Transform.Result actionTransformResult = null;
|
||||||
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
|
||||||
when(actionTransform.execute(context, payload)).thenReturn(actionTransformResult);
|
if (randomBoolean()) {
|
||||||
|
Tuple<ExecutableTransform, Transform.Result> pair = whenTransform(context);
|
||||||
|
|
||||||
|
actionTransform = pair.v1();
|
||||||
|
actionTransformResult = pair.v2();
|
||||||
|
}
|
||||||
|
|
||||||
// the action
|
// the action
|
||||||
Action.Result actionResult = mock(Action.Result.class);
|
Action.Result actionResult = mock(Action.Result.class);
|
||||||
@ -489,7 +533,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ExecutableAction action = mock(ExecutableAction.class);
|
ExecutableAction action = mock(ExecutableAction.class);
|
||||||
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
when(action.execute("_action", context, payload)).thenReturn(actionResult);
|
||||||
|
|
||||||
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionTransform, action);
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(now)));
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(now)));
|
||||||
@ -506,6 +550,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionWrapper.Result result = watchRecord.result().actionsResults().get("_action");
|
ActionWrapper.Result result = watchRecord.result().actionsResults().get("_action");
|
||||||
assertThat(result, notNullValue());
|
assertThat(result, notNullValue());
|
||||||
assertThat(result.id(), is("_action"));
|
assertThat(result.id(), is("_action"));
|
||||||
|
assertThat(result.condition(), sameInstance(actionConditionResult));
|
||||||
assertThat(result.transform(), sameInstance(actionTransformResult));
|
assertThat(result.transform(), sameInstance(actionTransformResult));
|
||||||
assertThat(result.action(), sameInstance(actionResult));
|
assertThat(result.action(), sameInstance(actionResult));
|
||||||
|
|
||||||
@ -524,17 +569,20 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ExecutableCondition condition = mock(ExecutableCondition.class);
|
ExecutableCondition condition = mock(ExecutableCondition.class);
|
||||||
when(condition.execute(any(WatchExecutionContext.class))).thenReturn(conditionResult);
|
when(condition.execute(any(WatchExecutionContext.class))).thenReturn(conditionResult);
|
||||||
|
|
||||||
|
// action throttler
|
||||||
Throttler.Result throttleResult = mock(Throttler.Result.class);
|
Throttler.Result throttleResult = mock(Throttler.Result.class);
|
||||||
when(throttleResult.throttle()).thenReturn(true);
|
when(throttleResult.throttle()).thenReturn(true);
|
||||||
when(throttleResult.reason()).thenReturn("_throttle_reason");
|
when(throttleResult.reason()).thenReturn("_throttle_reason");
|
||||||
ActionThrottler throttler = mock(ActionThrottler.class);
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
ExecutableTransform transform = mock(ExecutableTransform.class);
|
// unused with throttle
|
||||||
|
ExecutableCondition actionCondition = mock(ExecutableCondition.class);
|
||||||
|
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
||||||
|
|
||||||
ExecutableAction action = mock(ExecutableAction.class);
|
ExecutableAction action = mock(ExecutableAction.class);
|
||||||
when(action.type()).thenReturn("_type");
|
when(action.type()).thenReturn("_type");
|
||||||
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, transform, action);
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(now)));
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(now)));
|
||||||
@ -552,6 +600,7 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ActionWrapper.Result result = watchRecord.result().actionsResults().get("_action");
|
ActionWrapper.Result result = watchRecord.result().actionsResults().get("_action");
|
||||||
assertThat(result, notNullValue());
|
assertThat(result, notNullValue());
|
||||||
assertThat(result.id(), is("_action"));
|
assertThat(result.id(), is("_action"));
|
||||||
|
assertThat(result.condition(), nullValue());
|
||||||
assertThat(result.transform(), nullValue());
|
assertThat(result.transform(), nullValue());
|
||||||
assertThat(result.action(), instanceOf(Action.Result.Throttled.class));
|
assertThat(result.action(), instanceOf(Action.Result.Throttled.class));
|
||||||
Action.Result.Throttled throttled = (Action.Result.Throttled) result.action();
|
Action.Result.Throttled throttled = (Action.Result.Throttled) result.action();
|
||||||
@ -559,7 +608,8 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
|
|
||||||
verify(condition, times(1)).execute(context);
|
verify(condition, times(1)).execute(context);
|
||||||
verify(throttler, times(1)).throttle("_action", context);
|
verify(throttler, times(1)).throttle("_action", context);
|
||||||
verify(transform, never()).execute(context, payload);
|
verify(actionCondition, never()).execute(context);
|
||||||
|
verify(actionTransform, never()).execute(context, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExecuteInnerConditionNotMet() throws Exception {
|
public void testExecuteInnerConditionNotMet() throws Exception {
|
||||||
@ -568,6 +618,126 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
ScheduleTriggerEvent event = new ScheduleTriggerEvent("_id", now, now);
|
ScheduleTriggerEvent event = new ScheduleTriggerEvent("_id", now, now);
|
||||||
WatchExecutionContext context = new TriggeredExecutionContext(watch, now, event, timeValueSeconds(5));
|
WatchExecutionContext context = new TriggeredExecutionContext(watch, now, event, timeValueSeconds(5));
|
||||||
|
|
||||||
|
Condition.Result conditionResult = AlwaysCondition.Result.INSTANCE;
|
||||||
|
ExecutableCondition condition = mock(ExecutableCondition.class);
|
||||||
|
when(condition.execute(any(WatchExecutionContext.class))).thenReturn(conditionResult);
|
||||||
|
|
||||||
|
// action throttler
|
||||||
|
Throttler.Result throttleResult = mock(Throttler.Result.class);
|
||||||
|
when(throttleResult.throttle()).thenReturn(false);
|
||||||
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
|
// action condition (always fails)
|
||||||
|
Condition.Result actionConditionResult = mock(Condition.Result.class);
|
||||||
|
// note: sometimes it can be met _with_ success
|
||||||
|
if (randomBoolean()) {
|
||||||
|
when(actionConditionResult.status()).thenReturn(Condition.Result.Status.SUCCESS);
|
||||||
|
} else {
|
||||||
|
when(actionConditionResult.status()).thenReturn(Condition.Result.Status.FAILURE);
|
||||||
|
}
|
||||||
|
when(actionConditionResult.met()).thenReturn(false);
|
||||||
|
ExecutableCondition actionCondition = mock(ExecutableCondition.class);
|
||||||
|
when(actionCondition.execute(context)).thenReturn(actionConditionResult);
|
||||||
|
|
||||||
|
// unused with failed condition
|
||||||
|
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
||||||
|
|
||||||
|
ExecutableAction action = mock(ExecutableAction.class);
|
||||||
|
when(action.type()).thenReturn("_type");
|
||||||
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(now)));
|
||||||
|
|
||||||
|
when(watch.input()).thenReturn(input);
|
||||||
|
when(watch.condition()).thenReturn(condition);
|
||||||
|
when(watch.actions()).thenReturn(actions);
|
||||||
|
when(watch.status()).thenReturn(watchStatus);
|
||||||
|
|
||||||
|
WatchRecord watchRecord = executionService.executeInner(context);
|
||||||
|
assertThat(watchRecord.result().inputResult(), sameInstance(inputResult));
|
||||||
|
assertThat(watchRecord.result().conditionResult(), sameInstance(conditionResult));
|
||||||
|
assertThat(watchRecord.result().transformResult(), nullValue());
|
||||||
|
assertThat(watchRecord.result().actionsResults().count(), is(1));
|
||||||
|
ActionWrapper.Result result = watchRecord.result().actionsResults().get("_action");
|
||||||
|
assertThat(result, notNullValue());
|
||||||
|
assertThat(result.id(), is("_action"));
|
||||||
|
assertThat(result.condition(), sameInstance(actionConditionResult));
|
||||||
|
assertThat(result.transform(), nullValue());
|
||||||
|
assertThat(result.action(), instanceOf(Action.Result.ConditionFailed.class));
|
||||||
|
Action.Result.ConditionFailed conditionFailed = (Action.Result.ConditionFailed) result.action();
|
||||||
|
assertThat(conditionFailed.reason(), is("condition not met. skipping"));
|
||||||
|
|
||||||
|
verify(condition, times(1)).execute(context);
|
||||||
|
verify(throttler, times(1)).throttle("_action", context);
|
||||||
|
verify(actionCondition, times(1)).execute(context);
|
||||||
|
verify(actionTransform, never()).execute(context, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExecuteInnerConditionNotMetDueToException() throws Exception {
|
||||||
|
DateTime now = DateTime.now(DateTimeZone.UTC);
|
||||||
|
Watch watch = mock(Watch.class);
|
||||||
|
when(watch.id()).thenReturn(getTestName());
|
||||||
|
ScheduleTriggerEvent event = new ScheduleTriggerEvent("_id", now, now);
|
||||||
|
WatchExecutionContext context = new TriggeredExecutionContext(watch, now, event, timeValueSeconds(5));
|
||||||
|
|
||||||
|
Condition.Result conditionResult = AlwaysCondition.Result.INSTANCE;
|
||||||
|
ExecutableCondition condition = mock(ExecutableCondition.class);
|
||||||
|
when(condition.execute(any(WatchExecutionContext.class))).thenReturn(conditionResult);
|
||||||
|
|
||||||
|
// action throttler
|
||||||
|
Throttler.Result throttleResult = mock(Throttler.Result.class);
|
||||||
|
when(throttleResult.throttle()).thenReturn(false);
|
||||||
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
|
when(throttler.throttle("_action", context)).thenReturn(throttleResult);
|
||||||
|
|
||||||
|
// action condition (always fails)
|
||||||
|
ExecutableCondition actionCondition = mock(ExecutableCondition.class);
|
||||||
|
when(actionCondition.execute(context)).thenThrow(new IllegalArgumentException("[expected] failed for test"));
|
||||||
|
|
||||||
|
// unused with failed condition
|
||||||
|
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
||||||
|
|
||||||
|
ExecutableAction action = mock(ExecutableAction.class);
|
||||||
|
when(action.type()).thenReturn("_type");
|
||||||
|
when(action.logger()).thenReturn(logger);
|
||||||
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(now)));
|
||||||
|
|
||||||
|
when(watch.input()).thenReturn(input);
|
||||||
|
when(watch.condition()).thenReturn(condition);
|
||||||
|
when(watch.actions()).thenReturn(actions);
|
||||||
|
when(watch.status()).thenReturn(watchStatus);
|
||||||
|
|
||||||
|
WatchRecord watchRecord = executionService.executeInner(context);
|
||||||
|
assertThat(watchRecord.result().inputResult(), sameInstance(inputResult));
|
||||||
|
assertThat(watchRecord.result().conditionResult(), sameInstance(conditionResult));
|
||||||
|
assertThat(watchRecord.result().transformResult(), nullValue());
|
||||||
|
assertThat(watchRecord.result().actionsResults().count(), is(1));
|
||||||
|
ActionWrapper.Result result = watchRecord.result().actionsResults().get("_action");
|
||||||
|
assertThat(result, notNullValue());
|
||||||
|
assertThat(result.id(), is("_action"));
|
||||||
|
assertThat(result.condition(), nullValue());
|
||||||
|
assertThat(result.transform(), nullValue());
|
||||||
|
assertThat(result.action(), instanceOf(Action.Result.ConditionFailed.class));
|
||||||
|
Action.Result.ConditionFailed conditionFailed = (Action.Result.ConditionFailed) result.action();
|
||||||
|
assertThat(conditionFailed.reason(), is("condition failed. skipping: [expected] failed for test"));
|
||||||
|
|
||||||
|
verify(condition, times(1)).execute(context);
|
||||||
|
verify(throttler, times(1)).throttle("_action", context);
|
||||||
|
verify(actionCondition, times(1)).execute(context);
|
||||||
|
verify(actionTransform, never()).execute(context, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExecuteConditionNotMet() throws Exception {
|
||||||
|
DateTime now = DateTime.now(DateTimeZone.UTC);
|
||||||
|
Watch watch = mock(Watch.class);
|
||||||
|
ScheduleTriggerEvent event = new ScheduleTriggerEvent("_id", now, now);
|
||||||
|
WatchExecutionContext context = new TriggeredExecutionContext(watch, now, event, timeValueSeconds(5));
|
||||||
|
|
||||||
Condition.Result conditionResult = NeverCondition.Result.INSTANCE;
|
Condition.Result conditionResult = NeverCondition.Result.INSTANCE;
|
||||||
ExecutableCondition condition = mock(ExecutableCondition.class);
|
ExecutableCondition condition = mock(ExecutableCondition.class);
|
||||||
when(condition.execute(any(WatchExecutionContext.class))).thenReturn(conditionResult);
|
when(condition.execute(any(WatchExecutionContext.class))).thenReturn(conditionResult);
|
||||||
@ -577,9 +747,10 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
|
|
||||||
// action throttler
|
// action throttler
|
||||||
ActionThrottler throttler = mock(ActionThrottler.class);
|
ActionThrottler throttler = mock(ActionThrottler.class);
|
||||||
|
ExecutableCondition actionCondition = mock(ExecutableCondition.class);
|
||||||
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
ExecutableTransform actionTransform = mock(ExecutableTransform.class);
|
||||||
ExecutableAction action = mock(ExecutableAction.class);
|
ExecutableAction action = mock(ExecutableAction.class);
|
||||||
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionTransform, action);
|
ActionWrapper actionWrapper = new ActionWrapper("_action", throttler, actionCondition, actionTransform, action);
|
||||||
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
ExecutableActions actions = new ExecutableActions(Arrays.asList(actionWrapper));
|
||||||
|
|
||||||
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(now)));
|
WatchStatus watchStatus = new WatchStatus(clock.nowUTC(), singletonMap("_action", new ActionStatus(now)));
|
||||||
@ -602,4 +773,23 @@ public class ExecutionServiceTests extends ESTestCase {
|
|||||||
verify(actionTransform, never()).execute(context, payload);
|
verify(actionTransform, never()).execute(context, payload);
|
||||||
verify(action, never()).execute("_action", context, payload);
|
verify(action, never()).execute("_action", context, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Tuple<ExecutableCondition, Condition.Result> whenCondition(final WatchExecutionContext context) {
|
||||||
|
Condition.Result conditionResult = mock(Condition.Result.class);
|
||||||
|
when(conditionResult.met()).thenReturn(true);
|
||||||
|
ExecutableCondition condition = mock(ExecutableCondition.class);
|
||||||
|
when(condition.execute(context)).thenReturn(conditionResult);
|
||||||
|
|
||||||
|
return new Tuple<>(condition, conditionResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tuple<ExecutableTransform, Transform.Result> whenTransform(final WatchExecutionContext context) {
|
||||||
|
Transform.Result transformResult = mock(Transform.Result.class);
|
||||||
|
when(transformResult.payload()).thenReturn(payload);
|
||||||
|
ExecutableTransform transform = mock(ExecutableTransform.class);
|
||||||
|
when(transform.execute(context, payload)).thenReturn(transformResult);
|
||||||
|
|
||||||
|
return new Tuple<>(transform, transformResult);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.xpack.watcher.history;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
import org.elasticsearch.script.MockScriptPlugin;
|
||||||
|
import org.elasticsearch.search.SearchHit;
|
||||||
|
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||||
|
import org.elasticsearch.xpack.watcher.client.WatchSourceBuilder;
|
||||||
|
import org.elasticsearch.xpack.watcher.condition.Condition;
|
||||||
|
import org.elasticsearch.xpack.watcher.condition.compare.CompareCondition;
|
||||||
|
import org.elasticsearch.xpack.watcher.execution.ExecutionState;
|
||||||
|
import org.elasticsearch.xpack.watcher.input.Input;
|
||||||
|
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||||
|
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||||
|
import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchResponse;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||||
|
import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.loggingAction;
|
||||||
|
import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder;
|
||||||
|
import static org.elasticsearch.xpack.watcher.condition.ConditionBuilders.alwaysCondition;
|
||||||
|
import static org.elasticsearch.xpack.watcher.condition.ConditionBuilders.compareCondition;
|
||||||
|
import static org.elasticsearch.xpack.watcher.condition.ConditionBuilders.neverCondition;
|
||||||
|
import static org.elasticsearch.xpack.watcher.condition.ConditionBuilders.scriptCondition;
|
||||||
|
import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput;
|
||||||
|
import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule;
|
||||||
|
import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test makes sure per-action conditions are honored.
|
||||||
|
*/
|
||||||
|
public class HistoryActionConditionTests extends AbstractWatcherIntegrationTestCase {
|
||||||
|
|
||||||
|
private final Input input = simpleInput("key", 15).build();
|
||||||
|
|
||||||
|
private final Condition.Builder scriptConditionPasses = mockScriptCondition("return true;");
|
||||||
|
private final Condition.Builder compareConditionPasses = compareCondition("ctx.payload.key", CompareCondition.Op.GTE, 15);
|
||||||
|
private final Condition.Builder conditionPasses = randomFrom(alwaysCondition(), scriptConditionPasses, compareConditionPasses);
|
||||||
|
|
||||||
|
private final Condition.Builder scriptConditionFails = mockScriptCondition("return false;");
|
||||||
|
private final Condition.Builder compareConditionFails = compareCondition("ctx.payload.key", CompareCondition.Op.LT, 15);
|
||||||
|
private final Condition.Builder conditionFails = randomFrom(neverCondition(), scriptConditionFails, compareConditionFails);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Class<? extends Plugin>> pluginTypes() {
|
||||||
|
List<Class<? extends Plugin>> types = super.pluginTypes();
|
||||||
|
types.add(CustomScriptPlugin.class);
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CustomScriptPlugin extends MockScriptPlugin {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
|
||||||
|
Map<String, Function<Map<String, Object>, Object>> scripts = new HashMap<>();
|
||||||
|
|
||||||
|
scripts.put("return true;", vars -> true);
|
||||||
|
scripts.put("return false;", vars -> false);
|
||||||
|
scripts.put("throw new IllegalStateException('failed');", vars -> {
|
||||||
|
throw new IllegalStateException("[expected] failed hard");
|
||||||
|
});
|
||||||
|
|
||||||
|
return scripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean timeWarped() {
|
||||||
|
return true; // just to have better control over the triggers
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean enableSecurity() {
|
||||||
|
return false; // remove security noise from this test
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hard failure is where an exception is thrown by the script condition.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testActionConditionWithHardFailures() throws Exception {
|
||||||
|
final String id = "testActionConditionWithHardFailures";
|
||||||
|
|
||||||
|
final Condition.Builder scriptConditionFailsHard = mockScriptCondition("throw new IllegalStateException('failed');");
|
||||||
|
final List<Condition.Builder> actionConditionsWithFailure =
|
||||||
|
Lists.newArrayList(scriptConditionFailsHard, conditionPasses, alwaysCondition());
|
||||||
|
|
||||||
|
Collections.shuffle(actionConditionsWithFailure, random());
|
||||||
|
|
||||||
|
final int failedIndex = actionConditionsWithFailure.indexOf(scriptConditionFailsHard);
|
||||||
|
|
||||||
|
putAndTriggerWatch(id, input, actionConditionsWithFailure.toArray(new Condition.Builder[actionConditionsWithFailure.size()]));
|
||||||
|
|
||||||
|
flush();
|
||||||
|
|
||||||
|
assertWatchWithMinimumActionsCount(id, ExecutionState.EXECUTED, 1);
|
||||||
|
|
||||||
|
// only one action should have failed via condition
|
||||||
|
final SearchResponse response = searchHistory(SearchSourceBuilder.searchSource().query(termQuery("watch_id", id)));
|
||||||
|
assertThat(response.getHits().getTotalHits(), is(1L));
|
||||||
|
|
||||||
|
final SearchHit hit = response.getHits().getAt(0);
|
||||||
|
final List<Object> actions = getActionsFromHit(hit.getSource());
|
||||||
|
|
||||||
|
for (int i = 0; i < actionConditionsWithFailure.size(); ++i) {
|
||||||
|
final Map<String, Object> action = (Map<String, Object>)actions.get(i);
|
||||||
|
final Map<String, Object> condition = (Map<String, Object>)action.get("condition");
|
||||||
|
final Map<String, Object> logging = (Map<String, Object>)action.get("logging");
|
||||||
|
|
||||||
|
assertThat(action.get("id"), is("action" + i));
|
||||||
|
|
||||||
|
if (i == failedIndex) {
|
||||||
|
assertThat(action.get("status"), is("condition_failed"));
|
||||||
|
assertThat(action.get("reason"), is("condition failed. skipping: [expected] failed hard"));
|
||||||
|
assertThat(condition, nullValue());
|
||||||
|
assertThat(logging, nullValue());
|
||||||
|
} else {
|
||||||
|
assertThat(condition.get("type"), is(actionConditionsWithFailure.get(i).build().type()));
|
||||||
|
|
||||||
|
assertThat(action.get("status"), is("success"));
|
||||||
|
assertThat(condition.get("met"), is(true));
|
||||||
|
assertThat(action.get("reason"), nullValue());
|
||||||
|
assertThat(logging.get("logged_text"), is(Integer.toString(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testActionConditionWithFailures() throws Exception {
|
||||||
|
final String id = "testActionConditionWithFailures";
|
||||||
|
final List<Condition.Builder> actionConditionsWithFailure = Lists.newArrayList(conditionFails, conditionPasses, alwaysCondition());
|
||||||
|
|
||||||
|
Collections.shuffle(actionConditionsWithFailure, random());
|
||||||
|
|
||||||
|
final int failedIndex = actionConditionsWithFailure.indexOf(conditionFails);
|
||||||
|
|
||||||
|
putAndTriggerWatch(id, input, actionConditionsWithFailure.toArray(new Condition.Builder[actionConditionsWithFailure.size()]));
|
||||||
|
|
||||||
|
flush();
|
||||||
|
|
||||||
|
assertWatchWithMinimumActionsCount(id, ExecutionState.EXECUTED, 1);
|
||||||
|
|
||||||
|
// only one action should have failed via condition
|
||||||
|
final SearchResponse response = searchHistory(SearchSourceBuilder.searchSource().query(termQuery("watch_id", id)));
|
||||||
|
assertThat(response.getHits().getTotalHits(), is(1L));
|
||||||
|
|
||||||
|
final SearchHit hit = response.getHits().getAt(0);
|
||||||
|
final List<Object> actions = getActionsFromHit(hit.getSource());
|
||||||
|
|
||||||
|
for (int i = 0; i < actionConditionsWithFailure.size(); ++i) {
|
||||||
|
final Map<String, Object> action = (Map<String, Object>)actions.get(i);
|
||||||
|
final Map<String, Object> condition = (Map<String, Object>)action.get("condition");
|
||||||
|
final Map<String, Object> logging = (Map<String, Object>)action.get("logging");
|
||||||
|
|
||||||
|
assertThat(action.get("id"), is("action" + i));
|
||||||
|
assertThat(condition.get("type"), is(actionConditionsWithFailure.get(i).build().type()));
|
||||||
|
|
||||||
|
if (i == failedIndex) {
|
||||||
|
assertThat(action.get("status"), is("condition_failed"));
|
||||||
|
assertThat(condition.get("met"), is(false));
|
||||||
|
assertThat(action.get("reason"), is("condition not met. skipping"));
|
||||||
|
assertThat(logging, nullValue());
|
||||||
|
} else {
|
||||||
|
assertThat(action.get("status"), is("success"));
|
||||||
|
assertThat(condition.get("met"), is(true));
|
||||||
|
assertThat(action.get("reason"), nullValue());
|
||||||
|
assertThat(logging.get("logged_text"), is(Integer.toString(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testActionCondition() throws Exception {
|
||||||
|
final String id = "testActionCondition";
|
||||||
|
final List<Condition.Builder> actionConditions = Lists.newArrayList(conditionPasses);
|
||||||
|
|
||||||
|
if (randomBoolean()) {
|
||||||
|
actionConditions.add(alwaysCondition());
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.shuffle(actionConditions, random());
|
||||||
|
|
||||||
|
putAndTriggerWatch(id, input, actionConditions.toArray(new Condition.Builder[actionConditions.size()]));
|
||||||
|
|
||||||
|
flush();
|
||||||
|
|
||||||
|
assertWatchWithMinimumActionsCount(id, ExecutionState.EXECUTED, 1);
|
||||||
|
|
||||||
|
// all actions should be successful
|
||||||
|
final SearchResponse response = searchHistory(SearchSourceBuilder.searchSource().query(termQuery("watch_id", id)));
|
||||||
|
assertThat(response.getHits().getTotalHits(), is(1L));
|
||||||
|
|
||||||
|
final SearchHit hit = response.getHits().getAt(0);
|
||||||
|
final List<Object> actions = getActionsFromHit(hit.getSource());
|
||||||
|
|
||||||
|
for (int i = 0; i < actionConditions.size(); ++i) {
|
||||||
|
final Map<String, Object> action = (Map<String, Object>)actions.get(i);
|
||||||
|
final Map<String, Object> condition = (Map<String, Object>)action.get("condition");
|
||||||
|
final Map<String, Object> logging = (Map<String, Object>)action.get("logging");
|
||||||
|
|
||||||
|
assertThat(action.get("id"), is("action" + i));
|
||||||
|
assertThat(action.get("status"), is("success"));
|
||||||
|
assertThat(condition.get("type"), is(actionConditions.get(i).build().type()));
|
||||||
|
assertThat(condition.get("met"), is(true));
|
||||||
|
assertThat(action.get("reason"), nullValue());
|
||||||
|
assertThat(logging.get("logged_text"), is(Integer.toString(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the "actions" from the Watch History hit.
|
||||||
|
*
|
||||||
|
* @param source The hit's source.
|
||||||
|
* @return The list of "actions"
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private List<Object> getActionsFromHit(final Map<String, Object> source) {
|
||||||
|
final Map<String, Object> result = (Map<String, Object>)source.get("result");
|
||||||
|
|
||||||
|
return (List<Object>)result.get("actions");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Watch with the specified {@code id} and {@code input}.
|
||||||
|
* <p>
|
||||||
|
* The {@code actionConditions} are
|
||||||
|
*
|
||||||
|
* @param id The ID of the Watch
|
||||||
|
* @param input The input to use for the Watch
|
||||||
|
* @param actionConditions The conditions to add to the Watch
|
||||||
|
*/
|
||||||
|
private void putAndTriggerWatch(final String id, final Input input, final Condition.Builder... actionConditions) {
|
||||||
|
WatchSourceBuilder source = watchBuilder().trigger(schedule(interval("5s"))).input(input).condition(alwaysCondition());
|
||||||
|
|
||||||
|
for (int i = 0; i < actionConditions.length; ++i) {
|
||||||
|
source.addAction("action" + i, actionConditions[i], loggingAction(Integer.toString(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch(id).setSource(source).get();
|
||||||
|
|
||||||
|
assertThat(putWatchResponse.isCreated(), is(true));
|
||||||
|
|
||||||
|
timeWarp().scheduler().trigger(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an inline script using the {@link CustomScriptPlugin}.
|
||||||
|
*
|
||||||
|
* @param inlineScript The script to "compile" and run
|
||||||
|
* @return Never {@code null}
|
||||||
|
*/
|
||||||
|
private static Condition.Builder mockScriptCondition(String inlineScript) {
|
||||||
|
WatcherScript.Builder builder = new WatcherScript.Builder.Inline(inlineScript);
|
||||||
|
|
||||||
|
builder.lang(MockScriptPlugin.NAME);
|
||||||
|
|
||||||
|
return scriptCondition(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -79,8 +79,6 @@ public class HttpSecretsIntegrationTests extends AbstractWatcherIntegrationTestC
|
|||||||
webServer.shutdown();
|
webServer.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Settings nodeSettings(int nodeOrdinal) {
|
protected Settings nodeSettings(int nodeOrdinal) {
|
||||||
if (encryptSensitiveData == null) {
|
if (encryptSensitiveData == null) {
|
||||||
@ -213,8 +211,11 @@ public class HttpSecretsIntegrationTests extends AbstractWatcherIntegrationTestC
|
|||||||
.setTriggerEvent(triggerEvent)
|
.setTriggerEvent(triggerEvent)
|
||||||
.get();
|
.get();
|
||||||
assertThat(executeResponse, notNullValue());
|
assertThat(executeResponse, notNullValue());
|
||||||
|
|
||||||
contentSource = executeResponse.getRecordSource();
|
contentSource = executeResponse.getRecordSource();
|
||||||
|
|
||||||
|
assertThat(contentSource.getValue("result.actions.0.status"), is("success"));
|
||||||
|
|
||||||
value = contentSource.getValue("result.actions.0.webhook.response.status");
|
value = contentSource.getValue("result.actions.0.webhook.response.status");
|
||||||
assertThat(value, notNullValue());
|
assertThat(value, notNullValue());
|
||||||
assertThat(value, instanceOf(Number.class));
|
assertThat(value, instanceOf(Number.class));
|
||||||
|
@ -183,12 +183,12 @@ public class WatchTests extends ESTestCase {
|
|||||||
InputRegistry inputRegistry = registry(input);
|
InputRegistry inputRegistry = registry(input);
|
||||||
|
|
||||||
ExecutableCondition condition = randomCondition();
|
ExecutableCondition condition = randomCondition();
|
||||||
ConditionRegistry conditionRegistry = registry(condition);
|
ConditionRegistry conditionRegistry = conditionRegistry();
|
||||||
|
|
||||||
ExecutableTransform transform = randomTransform();
|
ExecutableTransform transform = randomTransform();
|
||||||
|
|
||||||
ExecutableActions actions = randomActions();
|
ExecutableActions actions = randomActions();
|
||||||
ActionRegistry actionRegistry = registry(actions, transformRegistry);
|
ActionRegistry actionRegistry = registry(actions, conditionRegistry, transformRegistry);
|
||||||
|
|
||||||
Map<String, Object> metadata = singletonMap("_key", "_val");
|
Map<String, Object> metadata = singletonMap("_key", "_val");
|
||||||
|
|
||||||
@ -227,15 +227,14 @@ public class WatchTests extends ESTestCase {
|
|||||||
ScheduleRegistry scheduleRegistry = registry(randomSchedule());
|
ScheduleRegistry scheduleRegistry = registry(randomSchedule());
|
||||||
TriggerEngine triggerEngine = new ParseOnlyScheduleTriggerEngine(Settings.EMPTY, scheduleRegistry, clock);
|
TriggerEngine triggerEngine = new ParseOnlyScheduleTriggerEngine(Settings.EMPTY, scheduleRegistry, clock);
|
||||||
TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine));
|
TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine));
|
||||||
ExecutableCondition condition = randomCondition();
|
ConditionRegistry conditionRegistry = conditionRegistry();
|
||||||
ConditionRegistry conditionRegistry = registry(condition);
|
|
||||||
ExecutableInput input = randomInput();
|
ExecutableInput input = randomInput();
|
||||||
InputRegistry inputRegistry = registry(input);
|
InputRegistry inputRegistry = registry(input);
|
||||||
|
|
||||||
TransformRegistry transformRegistry = transformRegistry();
|
TransformRegistry transformRegistry = transformRegistry();
|
||||||
|
|
||||||
ExecutableActions actions = randomActions();
|
ExecutableActions actions = randomActions();
|
||||||
ActionRegistry actionRegistry = registry(actions, transformRegistry);
|
ActionRegistry actionRegistry = registry(actions,conditionRegistry, transformRegistry);
|
||||||
|
|
||||||
|
|
||||||
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder()
|
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder()
|
||||||
@ -258,11 +257,11 @@ public class WatchTests extends ESTestCase {
|
|||||||
TriggerEngine triggerEngine = new ParseOnlyScheduleTriggerEngine(Settings.EMPTY, scheduleRegistry, SystemClock.INSTANCE);
|
TriggerEngine triggerEngine = new ParseOnlyScheduleTriggerEngine(Settings.EMPTY, scheduleRegistry, SystemClock.INSTANCE);
|
||||||
TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine));
|
TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine));
|
||||||
|
|
||||||
ConditionRegistry conditionRegistry = registry(new ExecutableAlwaysCondition(logger));
|
ConditionRegistry conditionRegistry = conditionRegistry();
|
||||||
InputRegistry inputRegistry = registry(new ExecutableNoneInput(logger));
|
InputRegistry inputRegistry = registry(new ExecutableNoneInput(logger));
|
||||||
TransformRegistry transformRegistry = transformRegistry();
|
TransformRegistry transformRegistry = transformRegistry();
|
||||||
ExecutableActions actions = new ExecutableActions(Collections.emptyList());
|
ExecutableActions actions = new ExecutableActions(Collections.emptyList());
|
||||||
ActionRegistry actionRegistry = registry(actions, transformRegistry);
|
ActionRegistry actionRegistry = registry(actions, conditionRegistry, transformRegistry);
|
||||||
|
|
||||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
@ -377,22 +376,13 @@ public class WatchTests extends ESTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConditionRegistry registry(ExecutableCondition condition) {
|
private ConditionRegistry conditionRegistry() {
|
||||||
Map<String, ConditionFactory> parsers = new HashMap<>();
|
Map<String, ConditionFactory> parsers = new HashMap<>();
|
||||||
switch (condition.type()) {
|
parsers.put(ScriptCondition.TYPE, new ScriptConditionFactory(settings, scriptService));
|
||||||
case ScriptCondition.TYPE:
|
parsers.put(CompareCondition.TYPE, new CompareConditionFactory(settings, SystemClock.INSTANCE));
|
||||||
parsers.put(ScriptCondition.TYPE, new ScriptConditionFactory(settings, scriptService));
|
parsers.put(ArrayCompareCondition.TYPE, new ArrayCompareConditionFactory(settings, SystemClock.INSTANCE));
|
||||||
return new ConditionRegistry(parsers);
|
parsers.put(AlwaysCondition.TYPE, new AlwaysConditionFactory(settings));
|
||||||
case CompareCondition.TYPE:
|
return new ConditionRegistry(parsers);
|
||||||
parsers.put(CompareCondition.TYPE, new CompareConditionFactory(settings, SystemClock.INSTANCE));
|
|
||||||
return new ConditionRegistry(parsers);
|
|
||||||
case ArrayCompareCondition.TYPE:
|
|
||||||
parsers.put(ArrayCompareCondition.TYPE, new ArrayCompareConditionFactory(settings, SystemClock.INSTANCE));
|
|
||||||
return new ConditionRegistry(parsers);
|
|
||||||
default:
|
|
||||||
parsers.put(AlwaysCondition.TYPE, new AlwaysConditionFactory(settings));
|
|
||||||
return new ConditionRegistry(parsers);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExecutableTransform randomTransform() {
|
private ExecutableTransform randomTransform() {
|
||||||
@ -429,24 +419,22 @@ public class WatchTests extends ESTestCase {
|
|||||||
Map<String, TransformFactory> factories = new HashMap<>();
|
Map<String, TransformFactory> factories = new HashMap<>();
|
||||||
factories.put(ScriptTransform.TYPE, new ScriptTransformFactory(settings, scriptService));
|
factories.put(ScriptTransform.TYPE, new ScriptTransformFactory(settings, scriptService));
|
||||||
factories.put(SearchTransform.TYPE, new SearchTransformFactory(settings, client, searchParsers, scriptService));
|
factories.put(SearchTransform.TYPE, new SearchTransformFactory(settings, client, searchParsers, scriptService));
|
||||||
TransformRegistry registry = new TransformRegistry(Settings.EMPTY, unmodifiableMap(factories));
|
return new TransformRegistry(Settings.EMPTY, unmodifiableMap(factories));
|
||||||
return registry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExecutableActions randomActions() {
|
private ExecutableActions randomActions() {
|
||||||
List<ActionWrapper> list = new ArrayList<>();
|
List<ActionWrapper> list = new ArrayList<>();
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
ExecutableTransform transform = randomTransform();
|
|
||||||
EmailAction action = new EmailAction(EmailTemplate.builder().build(), null, null, Profile.STANDARD,
|
EmailAction action = new EmailAction(EmailTemplate.builder().build(), null, null, Profile.STANDARD,
|
||||||
randomFrom(DataAttachment.JSON, DataAttachment.YAML), EmailAttachments.EMPTY_ATTACHMENTS);
|
randomFrom(DataAttachment.JSON, DataAttachment.YAML), EmailAttachments.EMPTY_ATTACHMENTS);
|
||||||
list.add(new ActionWrapper("_email_" + randomAsciiOfLength(8), randomThrottler(), transform,
|
list.add(new ActionWrapper("_email_" + randomAsciiOfLength(8), randomThrottler(), randomCondition(), randomTransform(),
|
||||||
new ExecutableEmailAction(action, logger, emailService, templateEngine, htmlSanitizer, Collections.emptyMap())));
|
new ExecutableEmailAction(action, logger, emailService, templateEngine, htmlSanitizer, Collections.emptyMap())));
|
||||||
}
|
}
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
DateTimeZone timeZone = randomBoolean() ? DateTimeZone.UTC : null;
|
DateTimeZone timeZone = randomBoolean() ? DateTimeZone.UTC : null;
|
||||||
TimeValue timeout = randomBoolean() ? TimeValue.timeValueSeconds(30) : null;
|
TimeValue timeout = randomBoolean() ? TimeValue.timeValueSeconds(30) : null;
|
||||||
IndexAction action = new IndexAction("_index", "_type", null, timeout, timeZone);
|
IndexAction action = new IndexAction("_index", "_type", null, timeout, timeZone);
|
||||||
list.add(new ActionWrapper("_index_" + randomAsciiOfLength(8), randomThrottler(), randomTransform(),
|
list.add(new ActionWrapper("_index_" + randomAsciiOfLength(8), randomThrottler(), randomCondition(), randomTransform(),
|
||||||
new ExecutableIndexAction(action, logger, client, null)));
|
new ExecutableIndexAction(action, logger, client, null)));
|
||||||
}
|
}
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
@ -455,13 +443,13 @@ public class WatchTests extends ESTestCase {
|
|||||||
.path(TextTemplate.inline("_url").build())
|
.path(TextTemplate.inline("_url").build())
|
||||||
.build();
|
.build();
|
||||||
WebhookAction action = new WebhookAction(httpRequest);
|
WebhookAction action = new WebhookAction(httpRequest);
|
||||||
list.add(new ActionWrapper("_webhook_" + randomAsciiOfLength(8), randomThrottler(), randomTransform(),
|
list.add(new ActionWrapper("_webhook_" + randomAsciiOfLength(8), randomThrottler(), randomCondition(), randomTransform(),
|
||||||
new ExecutableWebhookAction(action, logger, httpClient, templateEngine)));
|
new ExecutableWebhookAction(action, logger, httpClient, templateEngine)));
|
||||||
}
|
}
|
||||||
return new ExecutableActions(list);
|
return new ExecutableActions(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionRegistry registry(ExecutableActions actions, TransformRegistry transformRegistry) {
|
private ActionRegistry registry(ExecutableActions actions, ConditionRegistry conditionRegistry, TransformRegistry transformRegistry) {
|
||||||
Map<String, ActionFactory> parsers = new HashMap<>();
|
Map<String, ActionFactory> parsers = new HashMap<>();
|
||||||
for (ActionWrapper action : actions) {
|
for (ActionWrapper action : actions) {
|
||||||
switch (action.action().type()) {
|
switch (action.action().type()) {
|
||||||
@ -478,7 +466,7 @@ public class WatchTests extends ESTestCase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ActionRegistry(unmodifiableMap(parsers), transformRegistry, SystemClock.INSTANCE, licenseState);
|
return new ActionRegistry(unmodifiableMap(parsers), conditionRegistry, transformRegistry, SystemClock.INSTANCE, licenseState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionThrottler randomThrottler() {
|
private ActionThrottler randomThrottler() {
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
setup:
|
||||||
|
- do:
|
||||||
|
cluster.health:
|
||||||
|
wait_for_status: yellow
|
||||||
|
|
||||||
|
---
|
||||||
|
teardown:
|
||||||
|
- do:
|
||||||
|
xpack.watcher.delete_watch:
|
||||||
|
id: "my_watch1"
|
||||||
|
ignore: 404
|
||||||
|
|
||||||
|
---
|
||||||
|
"Test put watch api with action level condition":
|
||||||
|
- do:
|
||||||
|
xpack.watcher.put_watch:
|
||||||
|
id: "my_watch1"
|
||||||
|
master_timeout: "40s"
|
||||||
|
body: >
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"schedule": {
|
||||||
|
"hourly": {
|
||||||
|
"minute": [ 0, 5 ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"input": {
|
||||||
|
"simple": {
|
||||||
|
"payload": {
|
||||||
|
"value": 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"always": {}
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"test_index": {
|
||||||
|
"condition": {
|
||||||
|
"ctx.payload.value": {
|
||||||
|
"gt": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"index": "test",
|
||||||
|
"doc_type": "test2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- match: { _id: "my_watch1" }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
xpack.watcher.get_watch:
|
||||||
|
id: "my_watch1"
|
||||||
|
- match: { found : true}
|
||||||
|
- match: { _id: "my_watch1" }
|
||||||
|
- match: { watch.actions.test_index.condition.ctx.payload.value.gt: 10 }
|
Loading…
x
Reference in New Issue
Block a user