Watcher: Replace _status field with status (elastic/x-pack-elasticsearch#1285)

As fields with underscores will be disallowed in master, and we have to
prepare the upgrade, this commit renames the _status field to status.

When the 5.x upgrade logic is in place in the 5.x we can remove all the
old style _status handling from the master branch.

Note: All the BWC compatibility tests, that load 5.x indices are now
faking a finished upgrade by adding the `status` field to the mapping
of the watches index.

Original commit: elastic/x-pack-elasticsearch@9d5cc9aaec
This commit is contained in:
Alexander Reelsen 2017-05-04 10:08:34 +02:00 committed by GitHub
parent 8633fd1f07
commit 4078b2f1b2
26 changed files with 191 additions and 104 deletions

View File

@ -3,7 +3,7 @@
<<actions-ack-throttle, Acknowledging>> a watch enables you to manually throttle
execution of the watch's actions. An action's _acknowledgement state_ is stored
in the `_status.actions.<id>.ack.state` structure.
in the `status.actions.<id>.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": {

View File

@ -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/]

View File

@ -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/]

View File

@ -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"/]

View File

@ -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

View File

@ -4,7 +4,7 @@
<<actions-ack-throttle, Acknowledging>> a watch enables you to manually throttle
execution of the watch actions. The action's _acknowledgement state_ is stored in
the `_status.actions.<id>.ack.state` structure.
the `status.actions.<id>.ack.state` structure.
The current status of the watch and the state of its actions are returned as part
of the <<api-java-get-watch, Get Watch API>> response:

View File

@ -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");

View File

@ -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();

View File

@ -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";

View File

@ -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+");

View File

@ -103,6 +103,11 @@
"enabled" : false,
"dynamic" : true
},
"status": {
"type": "object",
"enabled" : false,
"dynamic" : true
},
"messages": {
"type": "text"
},

View File

@ -15,6 +15,11 @@
"enabled" : false,
"dynamic" : true
},
"status": {
"type": "object",
"enabled" : false,
"dynamic" : true
},
"trigger" : {
"type": "object",
"enabled" : false,

View File

@ -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();

View File

@ -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 {

View File

@ -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()));
}
}

View File

@ -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);

View File

@ -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 {

View File

@ -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));

View File

@ -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<ActionWrapper> actions = randomActions();
Map<String, ActionStatus> 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");

View File

@ -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:

View File

@ -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:

View File

@ -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" }

View File

@ -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:

View File

@ -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":

View File

@ -54,4 +54,4 @@ teardown:
- match: { found : true }
- match: { _id: "my_watch" }
- match: { _status.state.active: false }
- match: { status.state.active: false }

View File

@ -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);