diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/watch/WatchStatus.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/watch/WatchStatus.java index 0da93fe9ab2..df63022aa57 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/watch/WatchStatus.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/watch/WatchStatus.java @@ -80,6 +80,10 @@ public class WatchStatus implements ToXContentObject, Streamable { return lastChecked; } + public ZonedDateTime lastMetCondition() { + return lastMetCondition; + } + public ActionStatus actionStatus(String actionId) { return actions.get(actionId); } @@ -252,10 +256,10 @@ public class WatchStatus implements ToXContentObject, Streamable { builder.field(Field.STATE.getPreferredName(), state, params); } if (lastChecked != null) { - builder.timeField(Field.LAST_CHECKED.getPreferredName(), lastChecked); + writeDate(Field.LAST_CHECKED.getPreferredName(), builder, lastChecked); } if (lastMetCondition != null) { - builder.timeField(Field.LAST_MET_CONDITION.getPreferredName(), lastMetCondition); + writeDate(Field.LAST_MET_CONDITION.getPreferredName(), builder, lastMetCondition); } if (actions != null) { builder.startObject(Field.ACTIONS.getPreferredName()); diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/WatcherTestUtils.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/WatcherTestUtils.java index 7f7ff8c9360..9636d159b52 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/WatcherTestUtils.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/WatcherTestUtils.java @@ -21,6 +21,7 @@ import org.elasticsearch.xpack.core.watcher.actions.ActionWrapper; import org.elasticsearch.xpack.core.watcher.common.secret.Secret; import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext; import org.elasticsearch.xpack.core.watcher.execution.Wid; +import org.elasticsearch.xpack.core.watcher.support.WatcherDateTimeUtils; import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource; import org.elasticsearch.xpack.core.watcher.trigger.TriggerEvent; import org.elasticsearch.xpack.core.watcher.watch.Payload; @@ -52,6 +53,7 @@ import org.elasticsearch.xpack.watcher.trigger.schedule.CronSchedule; import org.elasticsearch.xpack.watcher.trigger.schedule.IntervalSchedule; import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTrigger; import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTriggerEvent; +import org.hamcrest.Matcher; import javax.mail.internet.AddressException; import java.io.IOException; @@ -69,6 +71,7 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; import static org.elasticsearch.test.ESTestCase.randomFrom; +import static org.hamcrest.Matchers.is; public final class WatcherTestUtils { @@ -188,4 +191,13 @@ public final class WatcherTestUtils { public static SearchType getRandomSupportedSearchType() { return randomFrom(SearchType.QUERY_THEN_FETCH, SearchType.DFS_QUERY_THEN_FETCH); } + + public static Matcher isSameDate(ZonedDateTime zonedDateTime) { + /* + When comparing timestamps returned from _search/.watcher-history* the same format of date has to be used + during serialisation to json on index time. + The toString of ZonedDateTime is omitting the millisecond part when is 0. This was not the case in joda. + */ + return is(WatcherDateTimeUtils.formatDate(zonedDateTime)); + } } diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HistoryIntegrationTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HistoryIntegrationTests.java index 35bd7077c3f..93d5cb1b4be 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HistoryIntegrationTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HistoryIntegrationTests.java @@ -17,15 +17,13 @@ import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.xpack.core.watcher.actions.ActionStatus; import org.elasticsearch.xpack.core.watcher.client.WatchSourceBuilder; import org.elasticsearch.xpack.core.watcher.input.Input; -import org.elasticsearch.xpack.core.watcher.support.WatcherDateTimeUtils; import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource; import org.elasticsearch.xpack.core.watcher.watch.WatchStatus; import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest; import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; +import org.elasticsearch.xpack.watcher.test.WatcherTestUtils; import org.elasticsearch.xpack.watcher.trigger.schedule.IntervalSchedule; -import org.hamcrest.Matcher; -import java.time.ZonedDateTime; import java.util.Locale; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; @@ -152,7 +150,6 @@ public class HistoryIntegrationTests extends AbstractWatcherIntegrationTestCase } } - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/38693") public void testThatHistoryContainsStatus() throws Exception { watcherClient().preparePutWatch("test_watch") .setSource(watchBuilder() @@ -176,10 +173,12 @@ public class HistoryIntegrationTests extends AbstractWatcherIntegrationTestCase assertThat(active, is(status.state().isActive())); String timestamp = source.getValue("status.state.timestamp"); - assertThat(timestamp, isSameDate(status.state().getTimestamp())); + assertThat(timestamp, WatcherTestUtils.isSameDate(status.state().getTimestamp())); String lastChecked = source.getValue("status.last_checked"); - assertThat(lastChecked, isSameDate(status.lastChecked())); + assertThat(lastChecked, WatcherTestUtils.isSameDate(status.lastChecked())); + String lastMetCondition = source.getValue("status.last_met_condition"); + assertThat(lastMetCondition, WatcherTestUtils.isSameDate(status.lastMetCondition())); Integer version = source.getValue("status.version"); int expectedVersion = (int) (status.version() - 1); @@ -202,12 +201,4 @@ public class HistoryIntegrationTests extends AbstractWatcherIntegrationTestCase } - private Matcher isSameDate(ZonedDateTime zonedDateTime) { - /* - When comparing timestamps returned from _search/.watcher-history* the same format of date has to be used - during serialisation to json on index time. - The toString of ZonedDateTime is omitting the millisecond part when is 0. This was not the case in joda. - */ - return is(WatcherDateTimeUtils.formatDate(zonedDateTime)); - } } diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchStatusIntegrationTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchStatusIntegrationTests.java index 20e27bd8b8d..5d1a24a8d91 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchStatusIntegrationTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchStatusIntegrationTests.java @@ -12,6 +12,12 @@ import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource; import org.elasticsearch.xpack.core.watcher.transport.actions.get.GetWatchResponse; import org.elasticsearch.xpack.watcher.condition.NeverCondition; import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; +import org.elasticsearch.xpack.watcher.test.WatcherTestUtils; +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; + +import java.time.ZonedDateTime; +import java.time.temporal.ChronoField; import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.loggingAction; import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; @@ -19,12 +25,13 @@ 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.IntervalSchedule.Interval.Unit.SECONDS; import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; public class WatchStatusIntegrationTests extends AbstractWatcherIntegrationTestCase { - @AwaitsFix(bugUrl="https://github.com/elastic/elasticsearch/issues/38619") public void testThatStatusGetsUpdated() { WatcherClient watcherClient = watcherClient(); watcherClient.preparePutWatch("_name") @@ -44,10 +51,24 @@ public class WatchStatusIntegrationTests extends AbstractWatcherIntegrationTestC GetResponse getResponse = client().prepareGet(".watches", "doc", "_name").get(); getResponse.getSource(); XContentSource source = new XContentSource(getResponse.getSourceAsBytesRef(), XContentType.JSON); - String lastChecked = source.getValue("status.last_checked"); - assertThat(lastChecked, is(notNullValue())); - assertThat(getWatchResponse.getStatus().lastChecked().toString(), is(lastChecked)); + String lastChecked = source.getValue("status.last_checked"); + assertThat(lastChecked, WatcherTestUtils.isSameDate(getWatchResponse.getStatus().lastChecked())); + assertThat(getWatchResponse.getStatus().lastChecked(), isMillisResolution()); + // not started yet, so both nulls + String lastMetCondition = source.getValue("status.last_met_condition"); + assertThat(lastMetCondition, is(nullValue())); + assertThat(getWatchResponse.getStatus().lastMetCondition(), is(nullValue())); + } + + private Matcher isMillisResolution() { + return new FeatureMatcher(equalTo(true), "has millisecond precision", "precission") { + @Override + protected Boolean featureValueOf(ZonedDateTime actual) { + //if date has millisecond precision its nanosecond field will be rounded to millis (equal millis * 10^6) + return actual.getNano() == actual.get(ChronoField.MILLI_OF_SECOND) * 1000_000; + } + }; } }