Watcher: Ignore deactivated state with execute watch API (elastic/x-pack-elasticsearch#4054)

If a watch is not active, it should still be executed, if it is called
via the execute watch API.

This commit adds an additional method to the execution context to check
for this, which returns true for a manual execution context but checks
the watch status for the triggered one.

Original commit: elastic/x-pack-elasticsearch@18f3f9e84b
This commit is contained in:
Alexander Reelsen 2018-03-19 07:31:06 -07:00 committed by GitHub
parent a68051405a
commit 955b0dddad
5 changed files with 55 additions and 2 deletions

View File

@ -68,6 +68,11 @@ public abstract class WatchExecutionContext {
public abstract boolean skipThrottling(String actionId);
/**
* @return true if execution is allowed (this depends on the type of the watch context)
*/
public abstract boolean shouldBeExecuted();
/**
* @return true if this execution should be recorded in the .watcher-history index
*/

View File

@ -300,7 +300,7 @@ public class ExecutionService extends AbstractComponent {
}
if (ctx.watch() != null) {
if (ctx.watch().status().state().isActive()) {
if (ctx.shouldBeExecuted()) {
logger.debug("executing watch [{}]", watchId);
record = executeInner(ctx);
@ -308,7 +308,7 @@ public class ExecutionService extends AbstractComponent {
updateWatchStatus(ctx.watch());
}
} else {
logger.debug("not executing watch [{}] because it is marked as inactive", watchId);
logger.debug("not executing watch [{}]", watchId);
record = ctx.abortBeforeExecution(ExecutionState.EXECUTION_NOT_NEEDED, "Watch is not active");
}
}

View File

@ -95,6 +95,13 @@ public class ManualExecutionContext extends WatchExecutionContext {
return mode != null && mode.force();
}
@Override
public boolean shouldBeExecuted() {
// we always want to execute a manually triggered watch as the user has triggered this via an
// external API call
return true;
}
@Override
public final boolean recordExecution() {
return recordExecution;

View File

@ -44,6 +44,11 @@ public class TriggeredExecutionContext extends WatchExecutionContext {
return false;
}
@Override
public boolean shouldBeExecuted() {
return watch().status().state().isActive();
}
@Override
public final boolean recordExecution() {
return true;

View File

@ -1037,6 +1037,42 @@ public class ExecutionServiceTests extends ESTestCase {
assertThat(assertionsTriggered.get(), is(true));
}
public void testManualWatchExecutionContextGetsAlwaysExecuted() throws Exception {
Watch watch = mock(Watch.class);
when(watch.id()).thenReturn("_id");
DateTime now = new DateTime(clock.millis());
ScheduleTriggerEvent event = new ScheduleTriggerEvent("_id", now, now);
ManualExecutionContext ctx = ManualExecutionContext.builder(watch, true,
new ManualTriggerEvent("foo", event), timeValueSeconds(5)).build();
when(watch.input()).thenReturn(input);
Condition.Result conditionResult = InternalAlwaysCondition.RESULT_INSTANCE;
ExecutableCondition condition = mock(ExecutableCondition.class);
when(condition.execute(any(WatchExecutionContext.class))).thenReturn(conditionResult);
when(watch.condition()).thenReturn(condition);
Action.Result actionResult = mock(Action.Result.class);
when(actionResult.type()).thenReturn("_action_type");
when(actionResult.status()).thenReturn(Action.Result.Status.SUCCESS);
ExecutableAction action = mock(ExecutableAction.class);
when(action.logger()).thenReturn(logger);
when(action.execute(eq("_action"), eq(ctx), eq(payload))).thenReturn(actionResult);
ActionWrapper actionWrapper = mock(ActionWrapper.class);
ActionWrapperResult actionWrapperResult = new ActionWrapperResult("_action", actionResult);
when(actionWrapper.execute(anyObject())).thenReturn(actionWrapperResult);
when(watch.actions()).thenReturn(Collections.singletonList(actionWrapper));
WatchStatus status = mock(WatchStatus.class);
when(status.state()).thenReturn(new WatchStatus.State(false, now()));
when(watch.status()).thenReturn(status);
WatchRecord watchRecord = executionService.execute(ctx);
assertThat(watchRecord.state(), is(ExecutionState.EXECUTED));
}
private WatchExecutionContext createMockWatchExecutionContext(String watchId, DateTime executionTime) {
WatchExecutionContext ctx = mock(WatchExecutionContext.class);
when(ctx.id()).thenReturn(new Wid(watchId, executionTime));