From 4ac13fa9c51e95d671d1bc10b8556273d395165f Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Wed, 30 Aug 2017 11:46:28 +0200 Subject: [PATCH] Watcher: Replace integration tests with unit and REST tests (elastic/x-pack-elasticsearch#2322) A bunch of integration tests should have been built as unit tests or already have unit test equivalents. This commit removes integration tests as well as adding REST equivalents or creating unit tests instead of extending from AbstractWatcherIntegrationTestCase Original commit: elastic/x-pack-elasticsearch@a97b99467d01cd703dee084f8b3968d57626b4c8 --- .../logging/ExecutableLoggingAction.java | 2 +- .../actions/logging/LoggingActionFactory.java | 1 - .../condition/ScriptConditionSearchTests.java | 118 ------- .../execution/ExecutionServiceTests.java | 7 +- .../execution/ManualExecutionTests.java | 314 ------------------ .../action/delete/DeleteWatchTests.java | 31 -- .../action/execute/ExecuteWatchTests.java | 153 --------- .../transport/action/put/PutWatchTests.java | 54 --- .../xpack/watcher/watch/WatchTests.java | 80 +++++ .../test/watcher/delete_watch/10_basic.yml | 16 +- .../test/watcher/execute_watch/10_basic.yml | 46 +++ .../watcher/execute_watch/30_throttled.yml | 118 +++++++ .../execute_watch/40_ignore_condition.yml | 63 ++++ .../watcher/execute_watch/50_action_mode.yml | 71 ++++ 14 files changed, 396 insertions(+), 678 deletions(-) delete mode 100644 plugin/src/test/java/org/elasticsearch/xpack/watcher/condition/ScriptConditionSearchTests.java delete mode 100644 plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ManualExecutionTests.java delete mode 100644 plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/put/PutWatchTests.java create mode 100644 plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/30_throttled.yml create mode 100644 plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/40_ignore_condition.yml create mode 100644 plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/50_action_mode.yml 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" } +