diff --git a/plugin/src/main/java/org/elasticsearch/xpack/watcher/actions/logging/ExecutableLoggingAction.java b/plugin/src/main/java/org/elasticsearch/xpack/watcher/actions/logging/ExecutableLoggingAction.java index d9cac7cf3d1..e4a07d789ee 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/watcher/actions/logging/ExecutableLoggingAction.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/watcher/actions/logging/ExecutableLoggingAction.java @@ -22,7 +22,7 @@ public class ExecutableLoggingAction extends ExecutableAction { private final Logger textLogger; private final TextTemplateEngine templateEngine; - ExecutableLoggingAction(LoggingAction action, Logger logger, Settings settings, TextTemplateEngine templateEngine) { + public ExecutableLoggingAction(LoggingAction action, Logger logger, Settings settings, TextTemplateEngine templateEngine) { super(action, logger); this.textLogger = action.category != null ? Loggers.getLogger(action.category, settings) : logger; this.templateEngine = templateEngine; diff --git a/plugin/src/main/java/org/elasticsearch/xpack/watcher/actions/logging/LoggingActionFactory.java b/plugin/src/main/java/org/elasticsearch/xpack/watcher/actions/logging/LoggingActionFactory.java index 3dbe5ff259c..23552affddb 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/watcher/actions/logging/LoggingActionFactory.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/watcher/actions/logging/LoggingActionFactory.java @@ -28,6 +28,5 @@ public class LoggingActionFactory extends ActionFactory { public ExecutableLoggingAction parseExecutable(String watchId, String actionId, XContentParser parser) throws IOException { LoggingAction action = LoggingAction.parse(watchId, actionId, parser); return new ExecutableLoggingAction(action, actionLogger, settings, templateEngine); - } } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/condition/ScriptConditionSearchTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/condition/ScriptConditionSearchTests.java deleted file mode 100644 index d5ded151220..00000000000 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/condition/ScriptConditionSearchTests.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.watcher.condition; - -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.action.search.ShardSearchFailure; -import org.elasticsearch.common.text.Text; -import org.elasticsearch.common.xcontent.support.XContentMapValues; -import org.elasticsearch.index.Index; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.script.MockScriptPlugin; -import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.SearchHits; -import org.elasticsearch.search.SearchShardTarget; -import org.elasticsearch.search.aggregations.AggregationBuilders; -import org.elasticsearch.search.aggregations.BucketOrder; -import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval; -import org.elasticsearch.search.internal.InternalSearchResponse; -import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext; -import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; -import org.elasticsearch.xpack.watcher.watch.Payload; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.mockExecutionContext; -import static org.hamcrest.Matchers.is; -import static org.mockito.Mockito.when; - -public class ScriptConditionSearchTests extends AbstractWatcherIntegrationTestCase { - - @Override - protected List> pluginTypes() { - List> types = super.pluginTypes(); - types.add(CustomScriptPlugin.class); - return types; - } - - public static class CustomScriptPlugin extends MockScriptPlugin { - - @Override - @SuppressWarnings("unchecked") - protected Map, Object>> pluginScripts() { - Map, Object>> scripts = new HashMap<>(); - - scripts.put("ctx.payload.aggregations.rate.buckets[0]?.doc_count >= 5", vars -> { - List buckets = (List) XContentMapValues.extractValue("ctx.payload.aggregations.rate.buckets", vars); - int docCount = (int) XContentMapValues.extractValue("doc_count", (Map) buckets.get(0)); - return docCount >= 5; - }); - - scripts.put("ctx.payload.hits?.hits[0]?._score == 1.0", vars -> { - List> searchHits = (List>) XContentMapValues.extractValue("ctx.payload.hits.hits", - vars); - double score = (double) XContentMapValues.extractValue("_score", searchHits.get(0)); - return score == 1.0; - }); - - return scripts; - } - } - - public void testExecuteWithAggs() throws Exception { - client().prepareIndex("my-index", "my-type").setSource("@timestamp", "2005-01-01T00:00").get(); - client().prepareIndex("my-index", "my-type").setSource("@timestamp", "2005-01-01T00:10").get(); - client().prepareIndex("my-index", "my-type").setSource("@timestamp", "2005-01-01T00:20").get(); - client().prepareIndex("my-index", "my-type").setSource("@timestamp", "2005-01-01T00:30").get(); - refresh(); - - SearchResponse response = client().prepareSearch("my-index") - .addAggregation(AggregationBuilders.dateHistogram("rate").field("@timestamp") - .dateHistogramInterval(DateHistogramInterval.HOUR).order(BucketOrder.count(false))) - .get(); - - ScriptService scriptService = internalCluster().getInstance(ScriptService.class); - ScriptCondition condition = new ScriptCondition( - mockScript("ctx.payload.aggregations.rate.buckets[0]?.doc_count >= 5"), - scriptService); - - WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response)); - assertFalse(condition.execute(ctx).met()); - - client().prepareIndex("my-index", "my-type").setSource("@timestamp", "2005-01-01T00:40").get(); - refresh(); - - response = client().prepareSearch("my-index").addAggregation(AggregationBuilders.dateHistogram("rate").field("@timestamp") - .dateHistogramInterval(DateHistogramInterval.HOUR).order(BucketOrder.count(false))) - .get(); - - ctx = mockExecutionContext("_name", new Payload.XContent(response)); - assertThat(condition.execute(ctx).met(), is(true)); - } - - public void testExecuteAccessHits() throws Exception { - ScriptService scriptService = internalCluster().getInstance(ScriptService.class); - ScriptCondition condition = new ScriptCondition( - mockScript("ctx.payload.hits?.hits[0]?._score == 1.0"), scriptService); - SearchHit hit = new SearchHit(0, "1", new Text("type"), null); - hit.score(1f); - hit.shard(new SearchShardTarget("a", new Index("a", "testUUID"), 0, null)); - - InternalSearchResponse internalSearchResponse = new InternalSearchResponse(new SearchHits( - new SearchHit[]{hit}, 1L, 1f), null, null, null, false, false, 1); - SearchResponse response = new SearchResponse(internalSearchResponse, "", 3, 3, 0, 500L, new ShardSearchFailure[0]); - - WatchExecutionContext ctx = mockExecutionContext("_watch_name", new Payload.XContent(response)); - assertThat(condition.execute(ctx).met(), is(true)); - hit.score(2f); - when(ctx.payload()).thenReturn(new Payload.XContent(response)); - assertThat(condition.execute(ctx).met(), is(false)); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ExecutionServiceTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ExecutionServiceTests.java index e0164d45974..fa39794717e 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ExecutionServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ExecutionServiceTests.java @@ -72,6 +72,7 @@ import static java.util.Arrays.asList; import static java.util.Collections.singletonMap; import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; @@ -202,7 +203,7 @@ public class ExecutionServiceTests extends ESTestCase { when(watch.input()).thenReturn(input); when(watch.condition()).thenReturn(condition); when(watch.transform()).thenReturn(watchTransform); - when(watch.actions()).thenReturn(Arrays.asList(actionWrapper)); + when(watch.actions()).thenReturn(Collections.singletonList(actionWrapper)); when(watch.status()).thenReturn(watchStatus); WatchRecord watchRecord = executionService.execute(context); @@ -221,6 +222,10 @@ public class ExecutionServiceTests extends ESTestCase { verify(watchTransform, times(1)).execute(context, payload); verify(action, times(1)).execute("_action", context, payload); + // test execution duration + assertThat(watchRecord.result().executionDurationMs(), is(greaterThan(0L))); + assertThat(watchRecord.result().executionTime(), is(notNullValue())); + // test stats XContentSource source = new XContentSource(jsonBuilder().map(executionService.usageStats())); assertThat(source.getValue("execution.actions._all.total_time_in_ms"), is(notNullValue())); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ManualExecutionTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ManualExecutionTests.java deleted file mode 100644 index 79791f28bc3..00000000000 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ManualExecutionTests.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * 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.execution; - -import org.elasticsearch.action.ActionRequestValidationException; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.support.XContentMapValues; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.script.MockScriptPlugin; -import org.elasticsearch.script.Script; -import org.elasticsearch.script.ScriptType; -import org.elasticsearch.xpack.watcher.actions.ActionStatus; -import org.elasticsearch.xpack.watcher.client.WatchSourceBuilder; -import org.elasticsearch.xpack.watcher.condition.AlwaysCondition; -import org.elasticsearch.xpack.watcher.condition.NeverCondition; -import org.elasticsearch.xpack.watcher.condition.ScriptCondition; -import org.elasticsearch.xpack.watcher.history.HistoryStore; -import org.elasticsearch.xpack.watcher.support.xcontent.ObjectPath; -import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; -import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchRequest; -import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchRequestBuilder; -import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchResponse; -import org.elasticsearch.xpack.watcher.transport.actions.get.GetWatchRequest; -import org.elasticsearch.xpack.watcher.transport.actions.get.GetWatchResponse; -import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchRequest; -import org.elasticsearch.xpack.watcher.trigger.TriggerEvent; -import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTriggerEvent; -import org.elasticsearch.xpack.watcher.watch.Watch; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; - -import java.time.Clock; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.function.Function; - -import static java.util.Collections.singletonMap; -import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; -import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.loggingAction; -import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; -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.cron; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.startsWith; - -public class ManualExecutionTests extends AbstractWatcherIntegrationTestCase { - - @Override - protected boolean enableSecurity() { - return false; - } - - @Override - protected List> pluginTypes() { - List> types = super.pluginTypes(); - types.add(CustomScriptPlugin.class); - return types; - } - - public static class CustomScriptPlugin extends MockScriptPlugin { - - @Override - @SuppressWarnings("unchecked") - protected Map, Object>> pluginScripts() { - Map, Object>> scripts = new HashMap<>(); - - scripts.put("sleep", vars -> { - Number millis = (Number) XContentMapValues.extractValue("millis", vars); - if (millis != null) { - try { - Thread.sleep(millis.longValue()); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } else { - throw new RuntimeException("Unable to sleep, [millis] parameter is missing!"); - } - return true; - }); - return scripts; - } - - @Override - public String pluginScriptLang() { - return WATCHER_LANG; - } - } - - public void testExecuteWatch() throws Exception { - boolean ignoreCondition = randomBoolean(); - boolean recordExecution = randomBoolean(); - boolean conditionAlwaysTrue = randomBoolean(); - String action = randomFrom("_all", "log"); - - WatchSourceBuilder watchBuilder = watchBuilder() - .trigger(schedule(cron("0 0 0 1 * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(conditionAlwaysTrue ? AlwaysCondition.INSTANCE : NeverCondition.INSTANCE) - .addAction("log", loggingAction("foobar")); - - watcherClient().putWatch(new PutWatchRequest("_id", watchBuilder)).actionGet(); - - ExecuteWatchRequestBuilder executeWatchRequestBuilder = watcherClient().prepareExecuteWatch("_id"); - executeWatchRequestBuilder.setIgnoreCondition(ignoreCondition); - executeWatchRequestBuilder.setRecordExecution(recordExecution); - executeWatchRequestBuilder.setActionMode(action, ActionExecutionMode.SIMULATE); - - refresh(); - long oldRecordCount = docCount(HistoryStore.INDEX_PREFIX_WITH_TEMPLATE + "*", HistoryStore.DOC_TYPE, matchAllQuery()); - - ExecuteWatchResponse executeWatchResponse = executeWatchRequestBuilder.get(); - Map responseMap = executeWatchResponse.getRecordSource().getAsMap(); - - refresh(); - long newRecordCount = docCount(HistoryStore.INDEX_PREFIX_WITH_TEMPLATE + "*", HistoryStore.DOC_TYPE, matchAllQuery()); - long expectedCount = oldRecordCount + (recordExecution ? 1 : 0); - - assertThat("the expected count of history records should be [" + expectedCount + "]", newRecordCount, equalTo(expectedCount)); - - List> actions = ObjectPath.eval("result.actions", responseMap); - if (ignoreCondition) { - assertThat("The action should have run", actions.size(), equalTo(1)); - } else if (!conditionAlwaysTrue) { - assertThat("The action should not have run", actions.size(), equalTo(0)); - } - - if (ignoreCondition || conditionAlwaysTrue) { - assertThat("The action should have run simulated", actions.get(0).get("status"), is("simulated")); - } - - if (recordExecution) { - GetWatchResponse response = watcherClient().getWatch(new GetWatchRequest("_id")).actionGet(); - if (ignoreCondition || conditionAlwaysTrue) { - assertThat(response.getStatus().actionStatus("log").ackStatus().state(), is(ActionStatus.AckStatus.State.ACKABLE)); - } else { - assertThat(response.getStatus().actionStatus("log").ackStatus().state(), - is(ActionStatus.AckStatus.State.AWAITS_SUCCESSFUL_EXECUTION)); - } - } else { - String ackState = executeWatchResponse.getRecordSource().getValue("status.actions.log.ack.state"); - if (ignoreCondition || conditionAlwaysTrue) { - assertThat(ackState, is(ActionStatus.AckStatus.State.ACKABLE.toString().toLowerCase(Locale.ROOT))); - } else { - assertThat(ackState, is(ActionStatus.AckStatus.State.AWAITS_SUCCESSFUL_EXECUTION.toString().toLowerCase(Locale.ROOT))); - } - } - } - - public void testExecutionWithInlineWatch() throws Exception { - WatchSourceBuilder watchBuilder = watchBuilder() - .trigger(schedule(cron("0 0 0 1 * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(AlwaysCondition.INSTANCE) - .addAction("log", loggingAction("foobar")); - - ExecuteWatchRequestBuilder builder = watcherClient().prepareExecuteWatch() - .setWatchSource(watchBuilder); - if (randomBoolean()) { - builder.setRecordExecution(false); - } - if (randomBoolean()) { - DateTime now = new DateTime(DateTimeZone.UTC); - builder.setTriggerEvent(new ScheduleTriggerEvent(now, now)); - } - - ExecuteWatchResponse executeWatchResponse = builder.get(); - assertThat(executeWatchResponse.getRecordId(), startsWith(ExecuteWatchRequest.INLINE_WATCH_ID)); - assertThat(executeWatchResponse.getRecordSource().getValue("watch_id").toString(), equalTo(ExecuteWatchRequest.INLINE_WATCH_ID)); - assertThat(executeWatchResponse.getRecordSource().getValue("state").toString(), equalTo("executed")); - assertThat(executeWatchResponse.getRecordSource().getValue("trigger_event.type").toString(), equalTo("manual")); - } - - public void testExecutionWithInlineWatchWithRecordExecutionEnabled() throws Exception { - WatchSourceBuilder watchBuilder = watchBuilder() - .trigger(schedule(cron("0 0 0 1 * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(AlwaysCondition.INSTANCE) - .addAction("log", loggingAction("foobar")); - - ActionRequestValidationException e = expectThrows(ActionRequestValidationException.class, () -> - watcherClient().prepareExecuteWatch() - .setWatchSource(watchBuilder) - .setRecordExecution(true) - .setTriggerEvent(new ScheduleTriggerEvent(new DateTime(DateTimeZone.UTC), new DateTime(DateTimeZone.UTC))) - .get()); - assertThat(e.getMessage(), containsString("the execution of an inline watch cannot be recorded")); - } - - public void testExecutionWithInlineWatch_withWatchId() throws Exception { - WatchSourceBuilder watchBuilder = watchBuilder() - .trigger(schedule(cron("0 0 0 1 * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(AlwaysCondition.INSTANCE) - .addAction("log", loggingAction("foobar")); - - try { - watcherClient().prepareExecuteWatch() - .setId("_id") - .setWatchSource(watchBuilder) - .setRecordExecution(false) - .setTriggerEvent(new ScheduleTriggerEvent(new DateTime(DateTimeZone.UTC), new DateTime(DateTimeZone.UTC))) - .get(); - fail(); - } catch (ActionRequestValidationException e) { - assertThat(e.getMessage(), - containsString("a watch execution request must either have a watch id or an inline watch source but not both")); - } - } - - public void testDifferentAlternativeInputs() throws Exception { - WatchSourceBuilder watchBuilder = watchBuilder() - .trigger(schedule(cron("0 0 0 1 * ? 2099"))) - .addAction("log", loggingAction("foobar")); - - watcherClient().putWatch(new PutWatchRequest("_id", watchBuilder)).actionGet(); - refresh(Watch.INDEX); - - Map map1 = new HashMap<>(); - map1.put("foo", "bar"); - - Map map2 = new HashMap<>(); - map2.put("foo", map1); - - ExecuteWatchResponse firstResponse = watcherClient().prepareExecuteWatch("_id") - .setActionMode("_all", ActionExecutionMode.SIMULATE) - .setAlternativeInput(map1) - .setRecordExecution(true) - .setTriggerEvent(new ScheduleTriggerEvent(new DateTime(DateTimeZone.UTC), new DateTime(DateTimeZone.UTC))) - .get(); - - ExecuteWatchResponse secondResponse = watcherClient().prepareExecuteWatch("_id") - .setActionMode("_all", ActionExecutionMode.SIMULATE) - .setAlternativeInput(map2) - .setRecordExecution(true) - .setTriggerEvent(new ScheduleTriggerEvent(new DateTime(DateTimeZone.UTC), new DateTime(DateTimeZone.UTC))) - .get(); - - String firstPayload = ObjectPath.eval("result.input.payload.foo", firstResponse.getRecordSource().getAsMap()); - assertThat(firstPayload, is("bar")); - Map secondPayload = ObjectPath.eval("result.input.payload", secondResponse.getRecordSource().getAsMap()); - assertThat(secondPayload, instanceOf(Map.class)); - } - - public void testExecutionRequestDefaults() throws Exception { - WatchSourceBuilder watchBuilder = watchBuilder() - .trigger(schedule(cron("0 0 0 1 * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(NeverCondition.INSTANCE) - .defaultThrottlePeriod(TimeValue.timeValueHours(1)) - .addAction("log", loggingAction("foobar")); - watcherClient().putWatch(new PutWatchRequest("_id", watchBuilder)).actionGet(); - - DateTime now = new DateTime(Clock.systemUTC().millis()); - TriggerEvent triggerEvent = new ScheduleTriggerEvent(now, now); - - Map executeWatchResult = watcherClient().prepareExecuteWatch() - .setId("_id") - .setTriggerEvent(triggerEvent) - .get().getRecordSource().getAsMap(); - - assertThat(ObjectPath.eval("state", executeWatchResult), equalTo(ExecutionState.EXECUTION_NOT_NEEDED.toString())); - assertThat(ObjectPath.eval("result.input.payload.foo", executeWatchResult), equalTo("bar")); - - watchBuilder = watchBuilder() - .trigger(schedule(cron("0 0 0 1 * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(AlwaysCondition.INSTANCE) - .defaultThrottlePeriod(TimeValue.timeValueHours(1)) - .addAction("log", loggingAction("foobar")); - watcherClient().putWatch(new PutWatchRequest("_id", watchBuilder)).actionGet(); - - executeWatchResult = watcherClient().prepareExecuteWatch() - .setId("_id").setTriggerEvent(triggerEvent).setRecordExecution(true) - .get().getRecordSource().getAsMap(); - - assertThat(ObjectPath.eval("state", executeWatchResult), equalTo(ExecutionState.EXECUTED.toString())); - assertThat(ObjectPath.eval("result.input.payload.foo", executeWatchResult), equalTo("bar")); - assertThat(ObjectPath.eval("result.actions.0.id", executeWatchResult), equalTo("log")); - - executeWatchResult = watcherClient().prepareExecuteWatch() - .setId("_id").setTriggerEvent(triggerEvent) - .get().getRecordSource().getAsMap(); - - assertThat(ObjectPath.eval("state", executeWatchResult), equalTo(ExecutionState.THROTTLED.toString())); - } - - public void testWatchExecutionDuration() throws Exception { - Script script = new Script(ScriptType.INLINE, WATCHER_LANG, "sleep", singletonMap("millis", 100L)); - WatchSourceBuilder watchBuilder = watchBuilder() - .trigger(schedule(cron("0 0 0 1 * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(new ScriptCondition(script)) - .addAction("log", loggingAction("foobar")); - - watcherClient().preparePutWatch("_id").setSource(watchBuilder).get(); - refresh(Watch.INDEX); - - ScheduleTriggerEvent triggerEvent = new ScheduleTriggerEvent(new DateTime(DateTimeZone.UTC), new DateTime(DateTimeZone.UTC)); - ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id").setTriggerEvent(triggerEvent).get(); - Integer duration = ObjectPath.eval("result.execution_duration", executeWatchResponse.getRecordSource().getAsMap()); - - assertThat(duration, greaterThanOrEqualTo(100)); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/delete/DeleteWatchTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/delete/DeleteWatchTests.java index eeda439db0d..c3c7e5ef472 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/delete/DeleteWatchTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/delete/DeleteWatchTests.java @@ -11,11 +11,9 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.test.http.MockResponse; import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.common.http.HttpRequestTemplate; -import org.elasticsearch.xpack.watcher.condition.AlwaysCondition; import org.elasticsearch.xpack.watcher.history.HistoryStore; import org.elasticsearch.xpack.watcher.support.xcontent.ObjectPath; import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; -import org.elasticsearch.xpack.watcher.transport.actions.delete.DeleteWatchRequest; import org.elasticsearch.xpack.watcher.transport.actions.delete.DeleteWatchResponse; import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchResponse; import org.elasticsearch.xpack.watcher.transport.actions.get.GetWatchResponse; @@ -29,43 +27,14 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitC import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.loggingAction; import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; import static org.elasticsearch.xpack.watcher.input.InputBuilders.httpInput; -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.hasKey; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; public class DeleteWatchTests extends AbstractWatcherIntegrationTestCase { - public void testDelete() throws Exception { - ensureWatcherStarted(); - PutWatchResponse putResponse = watcherClient().preparePutWatch("_name").setSource(watchBuilder() - .trigger(schedule(interval("5m"))) - .input(simpleInput()) - .condition(AlwaysCondition.INSTANCE) - .addAction("_action1", loggingAction("anything"))) - .get(); - - assertThat(putResponse, notNullValue()); - assertThat(putResponse.isCreated(), is(true)); - - DeleteWatchResponse deleteResponse = watcherClient().deleteWatch(new DeleteWatchRequest("_name")).get(); - assertThat(deleteResponse, notNullValue()); - assertThat(deleteResponse.getId(), is("_name")); - assertThat(deleteResponse.getVersion(), is(putResponse.getVersion() + 1)); - assertThat(deleteResponse.isFound(), is(true)); - } - - public void testDeleteNotFound() throws Exception { - DeleteWatchResponse response = watcherClient().deleteWatch(new DeleteWatchRequest("_name")).get(); - assertThat(response, notNullValue()); - assertThat(response.getId(), is("_name")); - assertThat(response.getVersion(), is(1L)); - assertThat(response.isFound(), is(false)); - } - // This is a special case, since locking is removed // Deleting a watch while it is being executed is possible now // This test ensures that there are no leftovers, like a watch status without a watch in the watch store diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/execute/ExecuteWatchTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/execute/ExecuteWatchTests.java index e4d3301b9ea..0ec3b6f16c7 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/execute/ExecuteWatchTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/execute/ExecuteWatchTests.java @@ -9,27 +9,17 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.xpack.watcher.actions.ActionStatus; import org.elasticsearch.xpack.watcher.client.WatcherClient; import org.elasticsearch.xpack.watcher.condition.AlwaysCondition; -import org.elasticsearch.xpack.watcher.condition.NeverCondition; import org.elasticsearch.xpack.watcher.execution.ActionExecutionMode; import org.elasticsearch.xpack.watcher.execution.Wid; -import org.elasticsearch.xpack.watcher.support.WatcherDateTimeUtils; import org.elasticsearch.xpack.watcher.support.xcontent.XContentSource; import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; import org.elasticsearch.xpack.watcher.transport.actions.ack.AckWatchRequestBuilder; import org.elasticsearch.xpack.watcher.transport.actions.ack.AckWatchResponse; -import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchRequestBuilder; import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchResponse; import org.elasticsearch.xpack.watcher.transport.actions.get.GetWatchResponse; import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchResponse; -import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTriggerEvent; import org.elasticsearch.xpack.watcher.watch.WatchStatus; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import java.util.HashMap; -import java.util.Map; - -import static java.util.Collections.singletonMap; import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.loggingAction; import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput; @@ -84,149 +74,6 @@ public class ExecuteWatchTests extends AbstractWatcherIntegrationTestCase { assertValue(record, "status.actions.log.ack.state", is("ackable")); } - public void testExecuteCustomTriggerData() throws Exception { - WatcherClient watcherClient = watcherClient(); - - PutWatchResponse putWatchResponse = watcherClient.preparePutWatch() - .setId("_id") - .setSource(watchBuilder() - .trigger(schedule(cron("0/5 * * * * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(AlwaysCondition.INSTANCE) - .addAction("log", loggingAction("_text"))) - .get(); - - assertThat(putWatchResponse.isCreated(), is(true)); - - DateTime triggeredTime = DateTime.now(DateTimeZone.UTC); - DateTime scheduledTime = randomBoolean() ? triggeredTime.minusDays(1) : triggeredTime; - - ExecuteWatchRequestBuilder requestBuilder = watcherClient.prepareExecuteWatch("_id"); - if (randomBoolean()) { - Map data = new HashMap<>(); - data.put("triggered_time", WatcherDateTimeUtils.formatDate(triggeredTime)); - if (scheduledTime != triggeredTime) { - data.put("scheduled_time", WatcherDateTimeUtils.formatDate(scheduledTime)); - } - requestBuilder.setTriggerData(data); - } else { - ScheduleTriggerEvent event = new ScheduleTriggerEvent(triggeredTime, scheduledTime); - requestBuilder.setTriggerEvent(event); - } - ExecuteWatchResponse response = requestBuilder.get(); - - assertThat(response, notNullValue()); - assertThat(response.getRecordId(), notNullValue()); - Wid wid = new Wid(response.getRecordId()); - assertThat(wid.watchId(), is("_id")); - - XContentSource record = response.getRecordSource(); - assertValue(record, "watch_id", is("_id")); - assertValue(record, "trigger_event.type", is("manual")); - assertValue(record, "trigger_event.triggered_time", is(WatcherDateTimeUtils.formatDate(triggeredTime))); - assertValue(record, "trigger_event.manual.schedule.scheduled_time", is(WatcherDateTimeUtils.formatDate(scheduledTime))); - assertValue(record, "state", is("executed")); - assertValue(record, "input.simple.foo", is("bar")); - assertValue(record, "condition.always", notNullValue()); - assertValue(record, "result.execution_time", notNullValue()); - assertValue(record, "result.execution_duration", notNullValue()); - assertValue(record, "result.input.type", is("simple")); - assertValue(record, "result.input.payload.foo", is("bar")); - assertValue(record, "result.condition.type", is("always")); - assertValue(record, "result.condition.met", is(true)); - assertValue(record, "result.actions.0.id", is("log")); - assertValue(record, "result.actions.0.type", is("logging")); - assertValue(record, "result.actions.0.status", is("success")); - assertValue(record, "result.actions.0.logging.logged_text", is("_text")); - } - - public void testExecuteAlternativeInput() throws Exception { - WatcherClient watcherClient = watcherClient(); - - PutWatchResponse putWatchResponse = watcherClient.preparePutWatch() - .setId("_id") - .setSource(watchBuilder() - .trigger(schedule(cron("0/5 * * * * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(AlwaysCondition.INSTANCE) - .addAction("log", loggingAction("_text"))) - .get(); - - assertThat(putWatchResponse.isCreated(), is(true)); - - ExecuteWatchResponse response = watcherClient.prepareExecuteWatch("_id") - .setAlternativeInput(singletonMap("foo1", "bar1")) - .get(); - assertThat(response, notNullValue()); - assertThat(response.getRecordId(), notNullValue()); - Wid wid = new Wid(response.getRecordId()); - assertThat(wid.watchId(), is("_id")); - - XContentSource record = response.getRecordSource(); - assertValue(record, "watch_id", is("_id")); - assertValue(record, "trigger_event.type", is("manual")); - assertValue(record, "trigger_event.triggered_time", notNullValue()); - String triggeredTime = record.getValue("trigger_event.triggered_time"); - assertValue(record, "trigger_event.manual.schedule.scheduled_time", is(triggeredTime)); - assertValue(record, "state", is("executed")); - assertValue(record, "input.simple.foo", is("bar")); // this is the original input - assertValue(record, "condition.always", notNullValue()); - assertValue(record, "result.execution_time", notNullValue()); - assertValue(record, "result.execution_duration", notNullValue()); - assertValue(record, "result.input.type", is("simple")); - assertValue(record, "result.input.payload.foo1", is("bar1")); // this is the alternative one - assertValue(record, "result.condition.type", is("always")); - assertValue(record, "result.condition.met", is(true)); - assertValue(record, "result.actions.0.id", is("log")); - assertValue(record, "result.actions.0.type", is("logging")); - assertValue(record, "result.actions.0.status", is("success")); - assertValue(record, "result.actions.0.logging.logged_text", is("_text")); - } - - public void testExecuteIgnoreCondition() throws Exception { - WatcherClient watcherClient = watcherClient(); - - PutWatchResponse putWatchResponse = watcherClient.preparePutWatch() - .setId("_id") - .setSource(watchBuilder() - .trigger(schedule(cron("0/5 * * * * ? 2099"))) - .input(simpleInput("foo", "bar")) - .condition(NeverCondition.INSTANCE) - .addAction("log", loggingAction("_text"))) - .get(); - - assertThat(putWatchResponse.isCreated(), is(true)); - - ExecuteWatchResponse response = watcherClient.prepareExecuteWatch("_id") - .setIgnoreCondition(true) - .get(); - - assertThat(response, notNullValue()); - assertThat(response.getRecordId(), notNullValue()); - Wid wid = new Wid(response.getRecordId()); - assertThat(wid.watchId(), is("_id")); - - XContentSource record = response.getRecordSource(); - assertValue(record, "watch_id", is("_id")); - assertValue(record, "trigger_event.type", is("manual")); - assertValue(record, "trigger_event.triggered_time", notNullValue()); - String triggeredTime = record.getValue("trigger_event.triggered_time"); - assertValue(record, "trigger_event.manual.schedule.scheduled_time", is(triggeredTime)); - assertValue(record, "state", is("executed")); - assertValue(record, "input.simple.foo", is("bar")); - assertValue(record, "condition.never", notNullValue()); // the original condition - assertValue(record, "result.execution_time", notNullValue()); - assertValue(record, "result.execution_duration", notNullValue()); - assertValue(record, "result.input.type", is("simple")); - assertValue(record, "result.input.payload.foo", is("bar")); - assertValue(record, "result.condition.type", is("always")); // when ignored, the condition is replaced with "always" - assertValue(record, "result.condition.met", is(true)); - assertValue(record, "result.actions.0.id", is("log")); - assertValue(record, "result.actions.0.type", is("logging")); - assertValue(record, "result.actions.0.status", is("success")); - assertValue(record, "result.actions.0.logging.logged_text", is("_text")); - } - public void testExecuteActionMode() throws Exception { final WatcherClient watcherClient = watcherClient(); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/put/PutWatchTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/put/PutWatchTests.java deleted file mode 100644 index 8bc1482c7db..00000000000 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/put/PutWatchTests.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.transport.action.put; - - -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.xpack.watcher.client.WatchSourceBuilder; -import org.elasticsearch.xpack.watcher.condition.AlwaysCondition; -import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; -import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchResponse; - -import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.loggingAction; -import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; -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.notNullValue; - -public class PutWatchTests extends AbstractWatcherIntegrationTestCase { - public void testPut() throws Exception { - WatchSourceBuilder source = watchBuilder() - .trigger(schedule(interval("5m"))); - - if (randomBoolean()) { - source.input(simpleInput()); - } - if (randomBoolean()) { - source.condition(AlwaysCondition.INSTANCE); - } - if (randomBoolean()) { - source.addAction("_action1", loggingAction("{{ctx.watch_id}}")); - } - - PutWatchResponse response = watcherClient().preparePutWatch("_name").setSource(source).get(); - - assertThat(response, notNullValue()); - assertThat(response.isCreated(), is(true)); - assertThat(response.getVersion(), is(1L)); - } - - public void testPutNoTrigger() throws Exception { - ElasticsearchException exception = expectThrows(ElasticsearchException.class, - () -> watcherClient().preparePutWatch("_name").setSource(watchBuilder() - .input(simpleInput()) - .condition(AlwaysCondition.INSTANCE) - .addAction("_action1", loggingAction("{{ctx.watch_id}}"))) - .get()); - assertEquals("Failed to build ToXContent", exception.getMessage()); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java index c98eac9a788..94c4bab055f 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java @@ -50,6 +50,9 @@ import org.elasticsearch.xpack.watcher.actions.email.ExecutableEmailAction; import org.elasticsearch.xpack.watcher.actions.index.ExecutableIndexAction; import org.elasticsearch.xpack.watcher.actions.index.IndexAction; import org.elasticsearch.xpack.watcher.actions.index.IndexActionFactory; +import org.elasticsearch.xpack.watcher.actions.logging.ExecutableLoggingAction; +import org.elasticsearch.xpack.watcher.actions.logging.LoggingAction; +import org.elasticsearch.xpack.watcher.actions.logging.LoggingActionFactory; import org.elasticsearch.xpack.watcher.actions.throttler.ActionThrottler; import org.elasticsearch.xpack.watcher.actions.webhook.ExecutableWebhookAction; import org.elasticsearch.xpack.watcher.actions.webhook.WebhookAction; @@ -68,6 +71,7 @@ import org.elasticsearch.xpack.watcher.input.InputBuilders; import org.elasticsearch.xpack.watcher.input.InputFactory; import org.elasticsearch.xpack.watcher.input.InputRegistry; import org.elasticsearch.xpack.watcher.input.none.ExecutableNoneInput; +import org.elasticsearch.xpack.watcher.input.none.NoneInput; import org.elasticsearch.xpack.watcher.input.search.ExecutableSearchInput; import org.elasticsearch.xpack.watcher.input.search.SearchInput; import org.elasticsearch.xpack.watcher.input.search.SearchInputFactory; @@ -76,6 +80,7 @@ import org.elasticsearch.xpack.watcher.input.simple.SimpleInput; import org.elasticsearch.xpack.watcher.input.simple.SimpleInputFactory; import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest; import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService; +import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine; import org.elasticsearch.xpack.watcher.test.WatcherTestUtils; import org.elasticsearch.xpack.watcher.transform.ExecutableTransform; import org.elasticsearch.xpack.watcher.transform.TransformFactory; @@ -132,7 +137,9 @@ import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; import static org.elasticsearch.xpack.watcher.input.InputBuilders.searchInput; import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.templateRequest; import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -375,6 +382,76 @@ public class WatchTests extends ESTestCase { assertThat(((ScriptQueryBuilder) searchRequest.source().query()).script().getLang(), equalTo(Script.DEFAULT_SCRIPT_LANG)); } + public void testParseWatchWithoutInput() throws Exception { + try (XContentBuilder builder = jsonBuilder()) { + builder.startObject(); + + builder.startObject("trigger").startObject("schedule").field("interval", "99w").endObject().endObject(); + builder.startObject("condition").startObject("always").endObject().endObject(); + builder.startObject("actions").startObject("logme") + .startObject("logging").field("text", "foo").endObject() + .endObject().endObject(); + builder.endObject(); + + Watch.Parser parser = createWatchparser(); + Watch watch = parser.parse("_id", false, builder.bytes(), XContentType.JSON); + assertThat(watch, is(notNullValue())); + assertThat(watch.input().type(), is(NoneInput.TYPE)); + } + } + + public void testParseWatchWithoutAction() throws Exception { + try (XContentBuilder builder = jsonBuilder()) { + builder.startObject(); + + builder.startObject("trigger").startObject("schedule").field("interval", "99w").endObject().endObject(); + builder.startObject("input").startObject("simple").endObject().endObject(); + builder.startObject("condition").startObject("always").endObject().endObject(); + builder.endObject(); + + Watch.Parser parser = createWatchparser(); + Watch watch = parser.parse("_id", false, builder.bytes(), XContentType.JSON); + assertThat(watch, is(notNullValue())); + assertThat(watch.actions(), hasSize(0)); + } + } + + public void testParseWatchWithoutTriggerDoesNotWork() throws Exception { + try (XContentBuilder builder = jsonBuilder()) { + builder.startObject(); + + builder.startObject("input").startObject("simple").endObject().endObject(); + builder.startObject("condition").startObject("always").endObject().endObject(); + builder.startObject("actions").startObject("logme") + .startObject("logging").field("text", "foo").endObject() + .endObject().endObject(); + builder.endObject(); + + Watch.Parser parser = createWatchparser(); + ElasticsearchParseException e = expectThrows(ElasticsearchParseException.class, + () -> parser.parse("_id", false, builder.bytes(), XContentType.JSON)); + assertThat(e.getMessage(), is("could not parse watch [_id]. missing required field [trigger]")); + } + } + + private Watch.Parser createWatchparser() throws Exception { + LoggingAction loggingAction = new LoggingAction(new TextTemplate("foo"), null, null); + List actions = Collections.singletonList(new ActionWrapper("_logging_", randomThrottler(), null, null, + new ExecutableLoggingAction(loggingAction, logger, settings, new MockTextTemplateEngine()))); + + ScheduleRegistry scheduleRegistry = registry(new IntervalSchedule(new IntervalSchedule.Interval(1, + IntervalSchedule.Interval.Unit.SECONDS))); + TriggerEngine triggerEngine = new ParseOnlyScheduleTriggerEngine(Settings.EMPTY, scheduleRegistry, Clock.systemUTC()); + TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine)); + + ConditionRegistry conditionRegistry = conditionRegistry(); + InputRegistry inputRegistry = registry(SimpleInput.TYPE); + TransformRegistry transformRegistry = transformRegistry(); + ActionRegistry actionRegistry = registry(actions, conditionRegistry, transformRegistry); + + return new Watch.Parser(settings, triggerService, actionRegistry, inputRegistry, null, Clock.systemUTC()); + } + private static Schedule randomSchedule() { String type = randomFrom(CronSchedule.TYPE, HourlySchedule.TYPE, DailySchedule.TYPE, WeeklySchedule.TYPE, MonthlySchedule.TYPE, YearlySchedule.TYPE, IntervalSchedule.TYPE); @@ -541,6 +618,9 @@ public class WatchTests extends ESTestCase { parsers.put(WebhookAction.TYPE, new WebhookActionFactory(settings, httpClient, new HttpRequestTemplate.Parser(authRegistry), templateEngine)); break; + case LoggingAction.TYPE: + parsers.put(LoggingAction.TYPE, new LoggingActionFactory(settings, new MockTextTemplateEngine())); + break; } } return new ActionRegistry(unmodifiableMap(parsers), conditionRegistry, transformRegistry, Clock.systemUTC(), licenseState); diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/delete_watch/10_basic.yml b/plugin/src/test/resources/rest-api-spec/test/watcher/delete_watch/10_basic.yml index 51b51702204..351ae3bb87e 100644 --- a/plugin/src/test/resources/rest-api-spec/test/watcher/delete_watch/10_basic.yml +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/delete_watch/10_basic.yml @@ -1,9 +1,18 @@ --- -"Test delete watch api": +setup: - do: cluster.health: wait_for_status: yellow +--- +teardown: + - do: + xpack.watcher.delete_watch: + id: "my_watch" + ignore: 404 + +--- +"Test delete watch api": - do: xpack.watcher.put_watch: id: "my_watch" @@ -37,6 +46,7 @@ } } - match: { _id: "my_watch" } + - match: { created: true } - do: xpack.watcher.delete_watch: @@ -51,10 +61,6 @@ --- "Non existent watch returns 404": - - do: - cluster.health: - wait_for_status: yellow - - do: xpack.watcher.delete_watch: id: "non-existent-watch" diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/10_basic.yml b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/10_basic.yml index d1b06dddbcc..5993cc44478 100644 --- a/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/10_basic.yml +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/10_basic.yml @@ -106,3 +106,49 @@ teardown: xpack.watcher.execute_watch: id: "non-existent-watch" catch: missing + +--- +"Test execute watch with alternative input": + + - do: + xpack.watcher.put_watch: + id: "test_watch" + body: > + { + "trigger": { + "schedule" : { "cron" : "0 0 0 1 * ? 2099" } + }, + "input": { + "simple": { + "foo": "bar" + } + }, + "actions": { + "indexme" : { + "index" : { + "index" : "my-index", + "doc_type" : "my-type", + "doc_id": "my-id" + } + } + } + } + - match: { _id: "test_watch" } + - match: { created: true } + + - do: + xpack.watcher.execute_watch: + id: "test_watch" + body: > + { + "alternative_input" : { + "spam" : "eggs" + } + } + + - match: { watch_record.watch_id: "test_watch" } + - match: { watch_record.state: "executed" } + - match: { watch_record.status.state.active: true } + - is_true: watch_record.node + - is_false: watch_record.result.input.payload.foo + - is_true: watch_record.result.input.payload.spam diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/30_throttled.yml b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/30_throttled.yml new file mode 100644 index 00000000000..f33b33ca136 --- /dev/null +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/30_throttled.yml @@ -0,0 +1,118 @@ +--- +setup: + - do: + cluster.health: + wait_for_status: yellow + +--- +teardown: + - do: + xpack.watcher.delete_watch: + id: "test_watch" + ignore: 404 + +--- +"Test execute watch api works with throttling": + - do: + xpack.watcher.put_watch: + id: "test_watch" + body: > + { + "trigger": { + "schedule" : { "cron" : "0 0 0 1 * ? 2099" } + }, + "input": { + "simple": { + "foo": "bar" + } + }, + "condition": { + "never": {} + }, + "actions": { + "logging" : { + "logging" : { + "text" : "logging text from test: execute_watch/30_throttled.yml" + } + } + } + } + - match: { _id: "test_watch" } + - match: { created: true } + + - do: + xpack.watcher.execute_watch: + id: "test_watch" + body: > + { + "trigger_data" : { + "triggered_time" : "2012-12-12T12:12:12.120Z", + "scheduled_time" : "2000-12-12T12:12:12.120Z" + } + } + + - match: { watch_record.watch_id: "test_watch" } + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.trigger_event.triggered_time: "2012-12-12T12:12:12.120Z" } + - match: { watch_record.trigger_event.manual.schedule.scheduled_time: "2000-12-12T12:12:12.120Z" } + - match: { watch_record.state: "execution_not_needed" } + - match: { watch_record.status.state.active: true } + + - do: + xpack.watcher.put_watch: + id: "test_watch" + body: > + { + "trigger": { + "schedule" : { "cron" : "0 0 0 1 * ? 2099" } + }, + "input": { + "simple": { + "foo": "bar" + } + }, + "condition": { + "always": {} + }, + "throttle_period" : "1h", + "actions": { + "logging" : { + "logging" : { + "text" : "logging text from test: execute_watch/30_throttled.yml" + } + } + } + } + - match: { _id: "test_watch" } + + - do: + xpack.watcher.execute_watch: + id: "test_watch" + body: > + { + "trigger_data" : { + "triggered_time" : "2012-12-12T12:12:12.120Z", + "scheduled_time" : "2000-12-12T12:12:12.120Z" + }, + "record_execution": true + } + + - match: { watch_record.watch_id: "test_watch" } + - match: { watch_record.state: "executed" } + + - do: + xpack.watcher.execute_watch: + id: "test_watch" + body: > + { + "trigger_data" : { + "triggered_time" : "2012-12-12T12:12:12.120Z", + "scheduled_time" : "2000-12-12T12:12:12.120Z" + }, + "record_execution": true + } + + - match: { watch_record.watch_id: "test_watch" } + - match: { watch_record.state: "throttled" } + + diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/40_ignore_condition.yml b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/40_ignore_condition.yml new file mode 100644 index 00000000000..d5ec95d77cb --- /dev/null +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/40_ignore_condition.yml @@ -0,0 +1,63 @@ +--- +setup: + - do: + cluster.health: + wait_for_status: yellow + +--- +teardown: + - do: + xpack.watcher.delete_watch: + id: "test_watch" + ignore: 404 + +--- +"Test execute watch api can ignore conditions": + - do: + xpack.watcher.put_watch: + id: "test_watch" + body: > + { + "trigger": { + "schedule" : { "cron" : "0 0 0 1 * ? 2099" } + }, + "input": { + "simple": { + "foo": "bar" + } + }, + "condition": { + "never": {} + }, + "actions": { + "logging" : { + "logging" : { + "text" : "logging text from test: execute_watch/30_throttled.yml" + } + } + } + } + - match: { _id: "test_watch" } + - match: { created: true } + + - do: + xpack.watcher.execute_watch: + id: "test_watch" + body: > + { + "ignore_condition" : true + } + + - match: { watch_record.watch_id: "test_watch" } + - match: { watch_record.input.simple.foo: "bar" } + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.state: "executed" } + - match: { watch_record.status.state.active: true } + - match: { watch_record.status.actions.logging.ack.state: "ackable" } + - is_true: watch_record.condition.never + - is_true: watch_record.result.execution_time + - is_true: watch_record.result.execution_duration + - match: { watch_record.result.input.type: "simple" } + - match: { watch_record.result.input.payload.foo: "bar" } + - match: { watch_record.result.condition.type: "always" } + - match: { watch_record.result.condition.met: true } diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/50_action_mode.yml b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/50_action_mode.yml new file mode 100644 index 00000000000..d3c7a8d7aab --- /dev/null +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/50_action_mode.yml @@ -0,0 +1,71 @@ +--- +setup: + - do: + cluster.health: + wait_for_status: yellow + +--- +teardown: + - do: + xpack.watcher.delete_watch: + id: "test_watch" + ignore: 404 + +--- +"Test execute watch api supports action modes": + - do: + xpack.watcher.put_watch: + id: "test_watch" + body: > + { + "trigger": { + "schedule" : { "cron" : "0 0 0 1 * ? 2099" } + }, + "input": { + "simple": { + "foo": "bar" + } + }, + "actions": { + "logging" : { + "logging" : { + "text" : "logging text from test: execute_watch/30_throttled.yml" + } + } + } + } + - match: { _id: "test_watch" } + - match: { created: true } + + - do: + xpack.watcher.execute_watch: + id: "test_watch" + body: > + { + "action_modes" : { + "logging" : "simulate" + } + } + + - match: { watch_record.watch_id: "test_watch" } + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.state: "executed" } + - match: { watch_record.result.actions.0.id: "logging" } + - match: { watch_record.result.actions.0.status: "simulated" } + + - do: + xpack.watcher.execute_watch: + id: "test_watch" + body: > + { + "action_modes" : { + "_all" : "simulate" + } + } + + - match: { watch_record.watch_id: "test_watch" } + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.state: "executed" } + - match: { watch_record.result.actions.0.id: "logging" } + - match: { watch_record.result.actions.0.status: "simulated" } +