diff --git a/docs/en/rest-api/watcher/ack-watch.asciidoc b/docs/en/rest-api/watcher/ack-watch.asciidoc index 17e628230b1..076b97e8b79 100644 --- a/docs/en/rest-api/watcher/ack-watch.asciidoc +++ b/docs/en/rest-api/watcher/ack-watch.asciidoc @@ -3,7 +3,7 @@ <> a watch enables you to manually throttle execution of the watch's actions. An action's _acknowledgement state_ is stored -in the `_status.actions..ack.state` structure. +in the `status.actions..ack.state` structure. To demonstrate let's create a new watch: @@ -58,7 +58,7 @@ The action state of a newly-created watch is `awaits_successful_execution`: { "found": true, "_id": "my_watch", - "_status": { + "status": { "version": 1, "actions": { "test_index": { @@ -73,9 +73,9 @@ The action state of a newly-created watch is `awaits_successful_execution`: "watch": ... } -------------------------------------------------- -// TESTRESPONSE[s/"state": \.\.\./"state": "$body._status.state"/] +// TESTRESPONSE[s/"state": \.\.\./"state": "$body.status.state"/] // TESTRESPONSE[s/"watch": \.\.\./"watch": "$body.watch"/] -// TESTRESPONSE[s/"timestamp": "2015-05-26T18:04:27.723Z"/"timestamp": "$body._status.actions.test_index.ack.timestamp"/] +// TESTRESPONSE[s/"timestamp": "2015-05-26T18:04:27.723Z"/"timestamp": "$body.status.actions.test_index.ack.timestamp"/] When the watch executes and the condition matches, the value of the `ack.state` changes to `ackable`. Let's force execution of the watch and fetch it again to @@ -95,7 +95,7 @@ and the action is now in `ackable` state: { "found": true, "_id": "my_watch", - "_status": { + "status": { "version": 1, "actions": { "test_index": { @@ -110,9 +110,9 @@ and the action is now in `ackable` state: "watch": ... } -------------------------------------------------- -// TESTRESPONSE[s/"state": \.\.\./"state": "$body._status.state"/] +// TESTRESPONSE[s/"state": \.\.\./"state": "$body.status.state"/] // TESTRESPONSE[s/"watch": \.\.\./"watch": "$body.watch"/] -// TESTRESPONSE[s/"timestamp": "2015-05-26T18:04:27.723Z"/"timestamp": "$body._status.actions.test_index.ack.timestamp"/] +// TESTRESPONSE[s/"timestamp": "2015-05-26T18:04:27.723Z"/"timestamp": "$body.status.actions.test_index.ack.timestamp"/] Now we can acknowledge it: @@ -128,7 +128,7 @@ GET _xpack/watcher/watch/my_watch { "found": true, "_id": "my_watch", - "_status": { + "status": { "version": 1, "actions": { "test_index": { @@ -143,9 +143,9 @@ GET _xpack/watcher/watch/my_watch "watch": ... } -------------------------------------------------- -// TESTRESPONSE[s/"state": \.\.\./"state": "$body._status.state"/] +// TESTRESPONSE[s/"state": \.\.\./"state": "$body.status.state"/] // TESTRESPONSE[s/"watch": \.\.\./"watch": "$body.watch"/] -// TESTRESPONSE[s/"timestamp": "2015-05-26T18:04:27.723Z"/"timestamp": "$body._status.actions.test_index.ack.timestamp"/] +// TESTRESPONSE[s/"timestamp": "2015-05-26T18:04:27.723Z"/"timestamp": "$body.status.actions.test_index.ack.timestamp"/] Acknowledging an action throttles further executions of that action until its `ack.state` is reset to `awaits_successful_execution`. This happens when the @@ -195,7 +195,7 @@ The response format looks like: [source,js] -------------------------------------------------- { - "_status": { + "status": { "last_checked": "2015-05-26T18:21:08.630Z", "last_met_condition": "2015-05-26T18:21:08.630Z", "actions": { diff --git a/docs/en/rest-api/watcher/activate-watch.asciidoc b/docs/en/rest-api/watcher/activate-watch.asciidoc index 1564b681892..81408b71394 100644 --- a/docs/en/rest-api/watcher/activate-watch.asciidoc +++ b/docs/en/rest-api/watcher/activate-watch.asciidoc @@ -19,7 +19,7 @@ GET _xpack/watcher/watch/my_watch { "found": true, "_id": "my_watch", - "_status": { + "status": { "state" : { "active" : false, "timestamp" : "2015-08-20T12:21:32.734Z" @@ -30,10 +30,10 @@ GET _xpack/watcher/watch/my_watch "watch": ... } -------------------------------------------------- -// TESTRESPONSE[s/2015-08-20T12:21:32.734Z/$body._status.state.timestamp/] -// TESTRESPONSE[s/"actions": \.\.\./"actions": "$body._status.actions"/] +// TESTRESPONSE[s/2015-08-20T12:21:32.734Z/$body.status.state.timestamp/] +// TESTRESPONSE[s/"actions": \.\.\./"actions": "$body.status.actions"/] // TESTRESPONSE[s/"watch": \.\.\./"watch": "$body.watch"/] -// TESTRESPONSE[s/"version": 1/"version": $body._status.version/] +// TESTRESPONSE[s/"version": 1/"version": $body.status.version/] You can activate the watch by executing the following API call: @@ -49,7 +49,7 @@ The new state of the watch is returned as part of its overall status: [source,js] -------------------------------------------------- { - "_status": { + "status": { "state" : { "active" : true, "timestamp" : "2015-09-04T08:39:46.816Z" @@ -59,6 +59,6 @@ The new state of the watch is returned as part of its overall status: } } -------------------------------------------------- -// TESTRESPONSE[s/2015-09-04T08:39:46.816Z/$body._status.state.timestamp/] -// TESTRESPONSE[s/"actions": \.\.\./"actions": "$body._status.actions"/] -// TESTRESPONSE[s/"version": 1/"version": $body._status.version/] +// TESTRESPONSE[s/2015-09-04T08:39:46.816Z/$body.status.state.timestamp/] +// TESTRESPONSE[s/"actions": \.\.\./"actions": "$body.status.actions"/] +// TESTRESPONSE[s/"version": 1/"version": $body.status.version/] diff --git a/docs/en/rest-api/watcher/deactivate-watch.asciidoc b/docs/en/rest-api/watcher/deactivate-watch.asciidoc index 6aaed843598..77eee4f3057 100644 --- a/docs/en/rest-api/watcher/deactivate-watch.asciidoc +++ b/docs/en/rest-api/watcher/deactivate-watch.asciidoc @@ -19,7 +19,7 @@ GET _xpack/watcher/watch/my_watch { "found": true, "_id": "my_watch", - "_status": { + "status": { "state" : { "active" : true, "timestamp" : "2015-08-20T12:21:32.734Z" @@ -30,10 +30,10 @@ GET _xpack/watcher/watch/my_watch "watch": ... } -------------------------------------------------- -// TESTRESPONSE[s/2015-08-20T12:21:32.734Z/$body._status.state.timestamp/] -// TESTRESPONSE[s/"actions": \.\.\./"actions": "$body._status.actions"/] +// TESTRESPONSE[s/2015-08-20T12:21:32.734Z/$body.status.state.timestamp/] +// TESTRESPONSE[s/"actions": \.\.\./"actions": "$body.status.actions"/] // TESTRESPONSE[s/"watch": \.\.\./"watch": "$body.watch"/] -// TESTRESPONSE[s/"version": 1/"version": $body._status.version/] +// TESTRESPONSE[s/"version": 1/"version": $body.status.version/] You can deactivate the watch by executing the following API call: @@ -49,7 +49,7 @@ The new state of the watch is returned as part of its overall status: [source,js] -------------------------------------------------- { - "_status": { + "status": { "state" : { "active" : false, "timestamp" : "2015-09-04T08:39:46.816Z" @@ -59,6 +59,6 @@ The new state of the watch is returned as part of its overall status: } } -------------------------------------------------- -// TESTRESPONSE[s/2015-09-04T08:39:46.816Z/$body._status.state.timestamp/] -// TESTRESPONSE[s/"actions": \.\.\./"actions": "$body._status.actions"/] -// TESTRESPONSE[s/"version": 1/"version": $body._status.version/] +// TESTRESPONSE[s/2015-09-04T08:39:46.816Z/$body.status.state.timestamp/] +// TESTRESPONSE[s/"actions": \.\.\./"actions": "$body.status.actions"/] +// TESTRESPONSE[s/"version": 1/"version": $body.status.version/] diff --git a/docs/en/rest-api/watcher/execute-watch.asciidoc b/docs/en/rest-api/watcher/execute-watch.asciidoc index 5f93d258f55..2b36850b62d 100644 --- a/docs/en/rest-api/watcher/execute-watch.asciidoc +++ b/docs/en/rest-api/watcher/execute-watch.asciidoc @@ -104,7 +104,7 @@ This is an example of the output: } }, "state": "executed", - "_status": { + "status": { "version": 1, "state": { "active": true, @@ -179,10 +179,10 @@ This is an example of the output: // TESTRESPONSE[s/"triggered_time": "2015-06-02T23:17:55.124Z"/"triggered_time": "$body.watch_record.trigger_event.triggered_time"/] // TESTRESPONSE[s/"scheduled_time": "2015-06-02T23:17:55.124Z"/"scheduled_time": "$body.watch_record.trigger_event.manual.schedule.scheduled_time"/] // TESTRESPONSE[s/"execution_time": "2015-06-02T23:17:55.124Z"/"execution_time": "$body.watch_record.result.execution_time"/] -// TESTRESPONSE[s/"timestamp": "2015-06-02T23:17:55.111Z"/"timestamp": "$body.watch_record._status.state.timestamp"/] -// TESTRESPONSE[s/"timestamp": "2015-06-02T23:17:55.124Z"/"timestamp": "$body.watch_record._status.actions.test_index.ack.timestamp"/] -// TESTRESPONSE[s/"last_checked": "2015-06-02T23:17:55.124Z"/"last_checked": "$body.watch_record._status.last_checked"/] -// TESTRESPONSE[s/"last_met_condition": "2015-06-02T23:17:55.124Z"/"last_met_condition": "$body.watch_record._status.last_met_condition"/] +// TESTRESPONSE[s/"timestamp": "2015-06-02T23:17:55.111Z"/"timestamp": "$body.watch_record.status.state.timestamp"/] +// TESTRESPONSE[s/"timestamp": "2015-06-02T23:17:55.124Z"/"timestamp": "$body.watch_record.status.actions.test_index.ack.timestamp"/] +// TESTRESPONSE[s/"last_checked": "2015-06-02T23:17:55.124Z"/"last_checked": "$body.watch_record.status.last_checked"/] +// TESTRESPONSE[s/"last_met_condition": "2015-06-02T23:17:55.124Z"/"last_met_condition": "$body.watch_record.status.last_met_condition"/] // TESTRESPONSE[s/"execution_duration": 12608/"execution_duration": "$body.watch_record.result.execution_duration"/] // TESTRESPONSE[s/"id": "AVSHKzPa9zx62AzUzFXY"/"id": "$body.watch_record.result.actions.0.index.response.id"/] // TESTRESPONSE[s/"node": "my_node"/"node": "$body.watch_record.node"/] diff --git a/docs/en/rest-api/watcher/get-watch.asciidoc b/docs/en/rest-api/watcher/get-watch.asciidoc index 766b58e28de..380ce638510 100644 --- a/docs/en/rest-api/watcher/get-watch.asciidoc +++ b/docs/en/rest-api/watcher/get-watch.asciidoc @@ -19,7 +19,7 @@ Response: { "found": true, "_id": "my_watch", - "_status": { <1> + "status": { <1> "version": 1, "state": { "active": true, @@ -63,5 +63,5 @@ Response: } } -------------------------------------------------- -// TESTRESPONSE[s/"timestamp": "2015-05-26T18:21:08.630Z"/"timestamp": "$body._status.state.timestamp"/] +// TESTRESPONSE[s/"timestamp": "2015-05-26T18:21:08.630Z"/"timestamp": "$body.status.state.timestamp"/] <1> The current status of the watch diff --git a/docs/en/watcher/java/ack-watch.asciidoc b/docs/en/watcher/java/ack-watch.asciidoc index 0e230490e42..f24f0b89a0e 100644 --- a/docs/en/watcher/java/ack-watch.asciidoc +++ b/docs/en/watcher/java/ack-watch.asciidoc @@ -4,7 +4,7 @@ <> a watch enables you to manually throttle execution of the watch actions. The action's _acknowledgement state_ is stored in -the `_status.actions..ack.state` structure. +the `status.actions..ack.state` structure. The current status of the watch and the state of its actions are returned as part of the <> response: diff --git a/plugin/src/main/java/org/elasticsearch/xpack/watcher/history/WatchRecord.java b/plugin/src/main/java/org/elasticsearch/xpack/watcher/history/WatchRecord.java index 7a68caceecb..614e5b47351 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/watcher/history/WatchRecord.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/watcher/history/WatchRecord.java @@ -137,7 +137,7 @@ public abstract class WatchRecord implements ToXContentObject { builder.field(Field.STATE.getPreferredName(), state.id()); if (watch != null && watch.status() != null) { - builder.field("_status", watch.status(), params); + builder.field(Field.STATUS.getPreferredName(), watch.status(), params); } builder.field(Field.TRIGGER_EVENT.getPreferredName()); @@ -195,7 +195,7 @@ public abstract class WatchRecord implements ToXContentObject { ParseField TRIGGER_EVENT = new ParseField("trigger_event"); ParseField MESSAGES = new ParseField("messages"); ParseField STATE = new ParseField("state"); - ParseField STATUS = new ParseField("_status"); + ParseField STATUS = new ParseField("status"); ParseField VARS = new ParseField("vars"); ParseField METADATA = new ParseField("metadata"); ParseField EXECUTION_RESULT = new ParseField("result"); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/watcher/rest/action/RestGetWatchAction.java b/plugin/src/main/java/org/elasticsearch/xpack/watcher/rest/action/RestGetWatchAction.java index 20d954308bd..d5d197678c5 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/watcher/rest/action/RestGetWatchAction.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/watcher/rest/action/RestGetWatchAction.java @@ -45,7 +45,7 @@ public class RestGetWatchAction extends WatcherRestHandler { .field("_id", response.getId()); if (response.isFound()) { ToXContent.MapParams xContentParams = new ToXContent.MapParams(request.params()); - builder.field("_status", response.getStatus(), xContentParams); + builder.field("status", response.getStatus(), xContentParams); builder.field("watch", response.getSource(), xContentParams); } builder.endObject(); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java b/plugin/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java index 3a4235d9921..7dde069870c 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java @@ -37,7 +37,7 @@ import static java.util.Collections.unmodifiableMap; public class WatcherIndexTemplateRegistry extends AbstractComponent implements ClusterStateListener { private static final String FORBIDDEN_INDEX_SETTING = "index.mapper.dynamic"; - public static final String INDEX_TEMPLATE_VERSION = "4"; + public static final String INDEX_TEMPLATE_VERSION = "5"; public static final String HISTORY_TEMPLATE_NAME = "watch_history_" + INDEX_TEMPLATE_VERSION; public static final String TRIGGERED_TEMPLATE_NAME = "triggered_watches"; diff --git a/plugin/src/main/java/org/elasticsearch/xpack/watcher/watch/Watch.java b/plugin/src/main/java/org/elasticsearch/xpack/watcher/watch/Watch.java index b3d1f429c7d..4cdae04a6fc 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/watcher/watch/Watch.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/watcher/watch/Watch.java @@ -303,7 +303,7 @@ public class Watch implements ToXContentObject { actions = actionRegistry.parseActions(id, parser); } else if (Field.METADATA.match(currentFieldName)) { metatdata = parser.map(); - } else if (Field.STATUS.match(currentFieldName)) { + } else if (Field.STATUS.match(currentFieldName) || Field.STATUS_V5.match(currentFieldName)) { if (includeStatus) { status = WatchStatus.parse(id, parser, clock); } else { @@ -349,7 +349,8 @@ public class Watch implements ToXContentObject { ParseField THROTTLE_PERIOD = new ParseField("throttle_period_in_millis"); ParseField THROTTLE_PERIOD_HUMAN = new ParseField("throttle_period"); ParseField METADATA = new ParseField("metadata"); - ParseField STATUS = new ParseField("_status"); + ParseField STATUS = new ParseField("status"); + ParseField STATUS_V5 = new ParseField("_status"); } private static final Pattern NO_WS_PATTERN = Pattern.compile("\\S+"); diff --git a/plugin/src/main/resources/watch_history.json b/plugin/src/main/resources/watch_history.json index ed6709845e0..168f4711871 100644 --- a/plugin/src/main/resources/watch_history.json +++ b/plugin/src/main/resources/watch_history.json @@ -103,6 +103,11 @@ "enabled" : false, "dynamic" : true }, + "status": { + "type": "object", + "enabled" : false, + "dynamic" : true + }, "messages": { "type": "text" }, diff --git a/plugin/src/main/resources/watches.json b/plugin/src/main/resources/watches.json index b2029de8da3..5916428de8d 100644 --- a/plugin/src/main/resources/watches.json +++ b/plugin/src/main/resources/watches.json @@ -15,6 +15,11 @@ "enabled" : false, "dynamic" : true }, + "status": { + "type": "object", + "enabled" : false, + "dynamic" : true + }, "trigger" : { "type": "object", "enabled" : false, diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/OldWatcherIndicesBackwardsCompatibilityTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/OldWatcherIndicesBackwardsCompatibilityTests.java index 8b3065b0687..f5e7d2e3ab5 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/OldWatcherIndicesBackwardsCompatibilityTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/OldWatcherIndicesBackwardsCompatibilityTests.java @@ -21,12 +21,15 @@ import org.elasticsearch.xpack.watcher.transport.actions.stats.WatcherStatsRespo import org.elasticsearch.xpack.watcher.trigger.schedule.IntervalSchedule; import org.elasticsearch.xpack.watcher.trigger.schedule.IntervalSchedule.Interval; import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTrigger; +import org.elasticsearch.xpack.watcher.watch.Watch; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasEntry; @@ -57,6 +60,17 @@ public class OldWatcherIndicesBackwardsCompatibilityTests extends AbstractOldXPa .stream().map(WatcherStatsResponse.Node::getWatcherState).collect(Collectors.toList()); assertThat(states, everyItem(is(WatcherState.STARTED))); }); + + // in order to go from 5.x to master, we assume someone executed the upgrade API, which will install the new index templates + // in this test we just do this manually, by adding the _status field to the mapping + // this can be removed once the API supports regular upgrade from 5.x to 6.x + assertAcked(client().admin().indices().preparePutMapping(Watch.INDEX).setType(Watch.DOC_TYPE) + .setSource(jsonBuilder().startObject().startObject("properties").startObject("status") + .field("type", "object") + .field("enabled", false) + .field("dynamic", true).endObject().endObject().endObject()) + .get()); + try { assertWatchIndexContentsWork(version); assertBasicWatchInteractions(); 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 index 3a74335ab2f..79791f28bc3 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ManualExecutionTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/execution/ManualExecutionTests.java @@ -147,7 +147,7 @@ public class ManualExecutionTests extends AbstractWatcherIntegrationTestCase { is(ActionStatus.AckStatus.State.AWAITS_SUCCESSFUL_EXECUTION)); } } else { - String ackState = executeWatchResponse.getRecordSource().getValue("_status.actions.log.ack.state"); + 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 { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HistoryIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HistoryIntegrationTests.java index f98457f1421..6b902ae8d71 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HistoryIntegrationTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HistoryIntegrationTests.java @@ -176,32 +176,32 @@ public class HistoryIntegrationTests extends AbstractWatcherIntegrationTestCase XContentSource source = new XContentSource(hit.getSourceRef(), XContentType.JSON); - Boolean active = source.getValue("_status.state.active"); + Boolean active = source.getValue("status.state.active"); assertThat(active, is(status.state().isActive())); - String timestamp = source.getValue("_status.state.timestamp"); + String timestamp = source.getValue("status.state.timestamp"); assertThat(timestamp, is(status.state().getTimestamp().toString())); - String lastChecked = source.getValue("_status.last_checked"); + String lastChecked = source.getValue("status.last_checked"); assertThat(lastChecked, is(status.lastChecked().toString())); - Integer version = source.getValue("_status.version"); + Integer version = source.getValue("status.version"); int expectedVersion = (int) (status.version() - 1); assertThat(version, is(expectedVersion)); ActionStatus actionStatus = status.actionStatus("_logger"); - String ackStatusState = source.getValue("_status.actions._logger.ack.state").toString().toUpperCase(Locale.ROOT); + String ackStatusState = source.getValue("status.actions._logger.ack.state").toString().toUpperCase(Locale.ROOT); assertThat(ackStatusState, is(actionStatus.ackStatus().state().toString())); - Boolean lastExecutionSuccesful = source.getValue("_status.actions._logger.last_execution.successful"); + Boolean lastExecutionSuccesful = source.getValue("status.actions._logger.last_execution.successful"); assertThat(lastExecutionSuccesful, is(actionStatus.lastExecution().successful())); - // also ensure that the _status field is disabled in the watch history + // also ensure that the status field is disabled in the watch history GetMappingsResponse response = client().admin().indices().prepareGetMappings(".watcher-history*").addTypes("watch_record").get(); byte[] bytes = response.getMappings().values().iterator().next().value.get("watch_record").source().uncompressed(); XContentSource mappingSource = new XContentSource(new BytesArray(bytes), XContentType.JSON); - assertThat(mappingSource.getValue("watch_record.properties._status.enabled"), is(false)); - assertThat(mappingSource.getValue("watch_record.properties._status.properties.status"), is(nullValue())); - assertThat(mappingSource.getValue("watch_record.properties._status.properties.status.properties.active"), is(nullValue())); + assertThat(mappingSource.getValue("watch_record.properties.status.enabled"), is(false)); + assertThat(mappingSource.getValue("watch_record.properties.status.properties.status"), is(nullValue())); + assertThat(mappingSource.getValue("watch_record.properties.status.properties.status.properties.active"), is(nullValue())); } } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/activate/ActivateWatchTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/activate/ActivateWatchTests.java index 3d4fca0609e..d8f32275092 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/activate/ActivateWatchTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/transport/action/activate/ActivateWatchTests.java @@ -147,10 +147,10 @@ public class ActivateWatchTests extends AbstractWatcherIntegrationTestCase { "transform.**", "actions.**", "metadata.**", - "_status.version", - "_status.last_checked", - "_status.last_met_condition", - "_status.actions.**"); + "status.version", + "status.last_checked", + "status.last_met_condition", + "status.actions.**"); XContentBuilder builder = new XContentBuilder(XContentType.JSON.xContent(), new BytesStreamOutput(), filters); source.toXContent(builder, ToXContent.EMPTY_PARAMS); 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 2716a26ff2a..e4d3301b9ea 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 @@ -81,7 +81,7 @@ public class ExecuteWatchTests extends AbstractWatcherIntegrationTestCase { 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")); - assertValue(record, "_status.actions.log.ack.state", is("ackable")); + assertValue(record, "status.actions.log.ack.state", is("ackable")); } public void testExecuteCustomTriggerData() throws Exception { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchStatusIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchStatusIntegrationTests.java index 8c67c8501b8..0edcf5800a5 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchStatusIntegrationTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchStatusIntegrationTests.java @@ -48,7 +48,7 @@ public class WatchStatusIntegrationTests extends AbstractWatcherIntegrationTestC GetResponse getResponse = client().prepareGet(".watches", "watch", "_name").get(); getResponse.getSource(); XContentSource source = new XContentSource(getResponse.getSourceAsBytesRef(), XContentType.JSON); - String lastChecked = source.getValue("_status.last_checked"); + String lastChecked = source.getValue("status.last_checked"); assertThat(lastChecked, is(notNullValue())); assertThat(getWatchResponse.getStatus().lastChecked().toString(), is(lastChecked)); 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 e2f17edc313..8328ef0cf79 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 @@ -15,7 +15,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; @@ -112,6 +112,7 @@ import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.junit.Before; +import java.io.IOException; import java.time.Clock; import java.util.ArrayList; import java.util.Arrays; @@ -127,6 +128,7 @@ import static java.util.Collections.singleton; import static java.util.Collections.singletonMap; import static java.util.Collections.unmodifiableMap; import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; 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; @@ -201,7 +203,7 @@ public class WatchTests extends ESTestCase { Watch watch = new Watch("_name", trigger, input, condition, transform, throttlePeriod, actions, metadata, watchStatus); - BytesReference bytes = XContentFactory.jsonBuilder().value(watch).bytes(); + BytesReference bytes = jsonBuilder().value(watch).bytes(); logger.info("{}", bytes.utf8ToString()); Watch.Parser watchParser = new Watch.Parser(settings, triggerService, actionRegistry, inputRegistry, null, clock); @@ -220,6 +222,49 @@ public class WatchTests extends ESTestCase { assertThat(parsedWatch.actions(), equalTo(actions)); } + public void testThatBothStatusFieldsCanBeRead() throws Exception { + InputRegistry inputRegistry = mock(InputRegistry.class); + ActionRegistry actionRegistry = mock(ActionRegistry.class); + // a fake trigger service that advances past the trigger end object, which cannot be done with mocking + TriggerService triggerService = new TriggerService(Settings.EMPTY, Collections.emptySet()) { + @Override + public Trigger parseTrigger(String jobName, XContentParser parser) throws IOException { + XContentParser.Token token; + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + } + + return new ScheduleTrigger(randomSchedule()); + } + }; + + DateTime now = new DateTime(UTC); + ClockMock clock = ClockMock.frozen(); + clock.setTime(now); + + List actions = randomActions(); + Map actionsStatuses = new HashMap<>(); + for (ActionWrapper action : actions) { + actionsStatuses.put(action.id(), new ActionStatus(now)); + } + WatchStatus watchStatus = new WatchStatus(new DateTime(clock.millis()), unmodifiableMap(actionsStatuses)); + + Watch.Parser watchParser = new Watch.Parser(settings, triggerService, actionRegistry, inputRegistry, null, clock); + XContentBuilder builder = jsonBuilder().startObject() + .startObject("trigger").endObject(); + if (randomBoolean()) { + builder.field("_status", watchStatus); + } else { + builder.field("status", watchStatus); + } + + builder.endObject(); + Watch watch = watchParser.parse("foo", true, builder.bytes(), XContentType.JSON); + assertThat(watch.status().state().getTimestamp().getMillis(), is(clock.millis())); + for (ActionWrapper action : actions) { + assertThat(watch.status().actionStatus(action.id()), is(actionsStatuses.get(action.id()))); + } + } + public void testParserBadActions() throws Exception { ClockMock clock = ClockMock.frozen(); ScheduleRegistry scheduleRegistry = registry(randomSchedule()); @@ -235,7 +280,7 @@ public class WatchTests extends ESTestCase { ActionRegistry actionRegistry = registry(actions,conditionRegistry, transformRegistry); - XContentBuilder jsonBuilder = XContentFactory.jsonBuilder() + XContentBuilder jsonBuilder = jsonBuilder() .startObject() .startArray("actions").endArray() .endObject(); @@ -259,7 +304,7 @@ public class WatchTests extends ESTestCase { TransformRegistry transformRegistry = transformRegistry(); ActionRegistry actionRegistry = registry(Collections.emptyList(), conditionRegistry, transformRegistry); - XContentBuilder builder = XContentFactory.jsonBuilder(); + XContentBuilder builder = jsonBuilder(); builder.startObject(); builder.startObject(Watch.Field.TRIGGER.getPreferredName()) .field(ScheduleTrigger.TYPE, schedule(schedule).build()) @@ -290,7 +335,7 @@ public class WatchTests extends ESTestCase { WatcherSearchTemplateService searchTemplateService = new WatcherSearchTemplateService(settings, scriptService, xContentRegistry()); - XContentBuilder builder = XContentFactory.jsonBuilder(); + XContentBuilder builder = jsonBuilder(); builder.startObject(); builder.startObject("trigger"); diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/10_basic.yaml b/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/10_basic.yaml index aa1ac99a3dd..024840be780 100644 --- a/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/10_basic.yaml +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/10_basic.yaml @@ -43,14 +43,14 @@ xpack.watcher.ack_watch: watch_id: "my_watch" - - match: { "_status.actions.test_index.ack.state" : "awaits_successful_execution" } + - match: { "status.actions.test_index.ack.state" : "awaits_successful_execution" } - do: search: index: .watches body: { "query": { "term": { "_id": "my_watch" } } } - match: { hits.total: 1 } - - match: { hits.hits.0._source._status.actions.test_index.ack.state: "awaits_successful_execution" } + - match: { hits.hits.0._source.status.actions.test_index.ack.state: "awaits_successful_execution" } - do: xpack.watcher.delete_watch: diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/20_ack_individual_action.yaml b/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/20_ack_individual_action.yaml index 3c5aefa09d0..ffcf7c93ba6 100644 --- a/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/20_ack_individual_action.yaml +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/20_ack_individual_action.yaml @@ -44,7 +44,7 @@ watch_id: "my_watch" action_id: "test_index" - - match: { "_status.actions.test_index.ack.state" : "awaits_successful_execution" } + - match: { "status.actions.test_index.ack.state" : "awaits_successful_execution" } - do: xpack.watcher.delete_watch: diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/30_reset_ack_after_unmet_condition.yaml b/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/30_reset_ack_after_unmet_condition.yaml index 5479de679a9..fb2670deaf5 100644 --- a/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/30_reset_ack_after_unmet_condition.yaml +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/ack_watch/30_reset_ack_after_unmet_condition.yaml @@ -53,17 +53,17 @@ teardown: { "record_execution" : true } - - match: { watch_record._status.actions.indexme.ack.state: "ackable" } + - match: { watch_record.status.actions.indexme.ack.state: "ackable" } - do: xpack.watcher.ack_watch: watch_id: "my_watch" - - match: { "_status.actions.indexme.ack.state" : "acked" } + - match: { "status.actions.indexme.ack.state" : "acked" } - do: xpack.watcher.get_watch: id: "my_watch" - - match: { "_status.actions.indexme.ack.state" : "acked" } + - match: { "status.actions.indexme.ack.state" : "acked" } # having a false result will reset the ack state - do: @@ -79,12 +79,12 @@ teardown: "indexme" : "force_execute" } } - - match: { watch_record._status.actions.indexme.ack.state: "awaits_successful_execution" } + - match: { watch_record.status.actions.indexme.ack.state: "awaits_successful_execution" } - do: xpack.watcher.get_watch: id: "my_watch" - - match: { "_status.actions.indexme.ack.state" : "awaits_successful_execution" } + - match: { "status.actions.indexme.ack.state" : "awaits_successful_execution" } - do: xpack.watcher.execute_watch: @@ -96,10 +96,10 @@ teardown: "indexme" : "force_execute" } } - - match: { watch_record._status.actions.indexme.ack.state: "ackable" } + - match: { watch_record.status.actions.indexme.ack.state: "ackable" } - do: xpack.watcher.get_watch: id: "my_watch" - - match: { "_status.actions.indexme.ack.state" : "ackable" } + - match: { "status.actions.indexme.ack.state" : "ackable" } diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/activate_watch/10_basic.yaml b/plugin/src/test/resources/rest-api-spec/test/watcher/activate_watch/10_basic.yaml index 65c7e460459..bf56890126c 100644 --- a/plugin/src/test/resources/rest-api-spec/test/watcher/activate_watch/10_basic.yaml +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/activate_watch/10_basic.yaml @@ -41,40 +41,40 @@ - match: { found : true} - match: { _id: "my_watch" } - - match: { _status.state.active: true } + - match: { status.state.active: true } - do: xpack.watcher.deactivate_watch: watch_id: "my_watch" - - match: { _status.state.active : false } + - match: { status.state.active : false } - do: search: index: .watches body: { "query": { "term": { "_id": "my_watch" } } } - match: { hits.total: 1 } - - match: { hits.hits.0._source._status.state.active: false } + - match: { hits.hits.0._source.status.state.active: false } - do: xpack.watcher.get_watch: id: "my_watch" - match: { found : true} - match: { _id: "my_watch" } - - match: { _status.state.active: false } + - match: { status.state.active: false } - do: xpack.watcher.activate_watch: watch_id: "my_watch" - - match: { _status.state.active : true } + - match: { status.state.active : true } - do: search: index: .watches body: { "query": { "term": { "_id": "my_watch" } } } - match: { hits.total: 1 } - - match: { hits.hits.0._source._status.state.active: true } + - match: { hits.hits.0._source.status.state.active: true } - do: xpack.watcher.get_watch: @@ -82,7 +82,7 @@ - match: { found : true} - match: { _id: "my_watch" } - - match: { _status.state.active: true } + - match: { status.state.active: true } - do: xpack.watcher.delete_watch: diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/10_basic.yaml b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/10_basic.yaml index 77c9d6b23e6..d1b06dddbcc 100644 --- a/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/10_basic.yaml +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/execute_watch/10_basic.yaml @@ -58,9 +58,9 @@ teardown: - 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: "executed" } - - match: { watch_record._status.state.active: true } + - match: { watch_record.status.state.active: true } - is_true: watch_record.node - - match: { watch_record._status.actions.indexme.ack.state: "ackable" } + - match: { watch_record.status.actions.indexme.ack.state: "ackable" } --- "Test execute watch API with user supplied watch": @@ -96,8 +96,8 @@ teardown: - match: { watch_record.watch_id: "_inlined_" } - match: { watch_record.trigger_event.type: "manual" } - match: { watch_record.state: "executed" } - - match: { watch_record._status.state.active: true } - - match: { watch_record._status.actions.indexme.ack.state: "ackable" } + - match: { watch_record.status.state.active: true } + - match: { watch_record.status.actions.indexme.ack.state: "ackable" } --- "Execute unknown watch results in 404": diff --git a/plugin/src/test/resources/rest-api-spec/test/watcher/put_watch/40_put_watch_as_inactive.yaml b/plugin/src/test/resources/rest-api-spec/test/watcher/put_watch/40_put_watch_as_inactive.yaml index ee25ab5acc1..2e4fbf350f2 100644 --- a/plugin/src/test/resources/rest-api-spec/test/watcher/put_watch/40_put_watch_as_inactive.yaml +++ b/plugin/src/test/resources/rest-api-spec/test/watcher/put_watch/40_put_watch_as_inactive.yaml @@ -54,4 +54,4 @@ teardown: - match: { found : true } - match: { _id: "my_watch" } - - match: { _status.state.active: false } + - match: { status.state.active: false } diff --git a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatchBackwardsCompatibilityIT.java b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatchBackwardsCompatibilityIT.java index ae617062744..6e1bb236f18 100644 --- a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatchBackwardsCompatibilityIT.java +++ b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatchBackwardsCompatibilityIT.java @@ -5,7 +5,9 @@ */ package org.elasticsearch.upgrades; +import org.apache.http.HttpEntity; import org.apache.http.HttpHost; +import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; @@ -20,6 +22,7 @@ import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.yaml.ObjectPath; import org.elasticsearch.xpack.watcher.condition.AlwaysCondition; +import org.elasticsearch.xpack.watcher.watch.Watch; import org.junit.Before; import java.io.IOException; @@ -31,6 +34,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_TEMPLATE_NAME; import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.loggingAction; import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; @@ -104,6 +108,20 @@ public class WatchBackwardsCompatibilityIT extends ESRestTestCase { } + @Override + protected boolean preserveIndicesUponCompletion() { + return true; + } + + @Override + protected Settings restClientSettings() { + String token = "Basic " + Base64.getEncoder() + .encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8)); + return Settings.builder() + .put(ThreadContext.PREFIX + ".Authorization", token) + .build(); + } + public void testWatcherStats() throws Exception { executeAgainstAllNodes(client -> assertOK(client.performRequest("GET", "/_xpack/watcher/stats")) @@ -128,15 +146,12 @@ public class WatchBackwardsCompatibilityIT extends ESRestTestCase { ContentType.APPLICATION_JSON); executeAgainstAllNodes(client -> { - assertOK(client.performRequest("PUT", "/_xpack/watcher/watch/my-watch", - Collections.emptyMap(), entity)); + fakeUpgradeFrom5x(client); + assertOK(client.performRequest("PUT", "/_xpack/watcher/watch/my-watch", Collections.emptyMap(), entity)); assertOK(client.performRequest("GET", "/_xpack/watcher/watch/my-watch")); - assertOK(client.performRequest("POST", "/_xpack/watcher/watch/my-watch/_execute")); - assertOK(client.performRequest("PUT", "/_xpack/watcher/watch/my-watch/_deactivate")); - assertOK(client.performRequest("PUT", "/_xpack/watcher/watch/my-watch/_activate")); }); } @@ -156,24 +171,26 @@ public class WatchBackwardsCompatibilityIT extends ESRestTestCase { } } - @Override - protected boolean preserveIndicesUponCompletion() { - return true; - } - - @Override - protected Settings restClientSettings() { - String token = "Basic " + Base64.getEncoder() - .encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8)); - return Settings.builder() - .put(ThreadContext.PREFIX + ".Authorization", token) - .build(); - } - private void assertOK(Response response) { assertThat(response.getStatusLine().getStatusCode(), anyOf(equalTo(200), equalTo(201))); } + // This is needed for fake the upgrade from 5.x to 6.0, where a new watches template is created, that contains mapping for the status + // field, as _status will be moved to status + // This can be removed once the upgrade API supports everything + private void fakeUpgradeFrom5x(RestClient client) throws IOException { + BytesReference mappingJson = jsonBuilder().startObject().startObject("properties").startObject("status") + .field("type", "object") + .field("enabled", false) + .field("dynamic", true) + .endObject().endObject().endObject() + .bytes(); + HttpEntity data = new ByteArrayEntity(mappingJson.toBytesRef().bytes, ContentType.APPLICATION_JSON); + + Response response = client.performRequest("PUT", "/" + Watch.INDEX + "/_mapping/" + Watch.DOC_TYPE, Collections.emptyMap(), data); + assertOK(response); + } + private Nodes buildNodeAndVersions() throws IOException { Response response = client().performRequest("GET", "_nodes"); ObjectPath objectPath = ObjectPath.createFromResponse(response);