[ML] Expect an array of events in request (elastic/x-pack-elasticsearch#3537)
* Expect an array of events in request Original commit: elastic/x-pack-elasticsearch@f60bc0b544
This commit is contained in:
parent
79a9576596
commit
86e9f63b19
|
@ -12,16 +12,12 @@ import org.elasticsearch.action.ActionRequestValidationException;
|
|||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.xpack.ml.calendars.Calendar;
|
||||
import org.elasticsearch.xpack.ml.calendars.ScheduledEvent;
|
||||
import org.elasticsearch.xpack.ml.job.messages.Messages;
|
||||
|
@ -33,8 +29,6 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.elasticsearch.xpack.ClientHelper.executeAsyncWithOrigin;
|
||||
|
||||
public class PostCalendarEventsAction extends Action<PostCalendarEventsAction.Request, PostCalendarEventsAction.Response,
|
||||
PostCalendarEventsAction.RequestBuilder> {
|
||||
public static final PostCalendarEventsAction INSTANCE = new PostCalendarEventsAction();
|
||||
|
@ -58,55 +52,25 @@ public class PostCalendarEventsAction extends Action<PostCalendarEventsAction.Re
|
|||
|
||||
public static class Request extends ActionRequest {
|
||||
|
||||
public static Request parseRequest(String calendarId, BytesReference data, XContentType contentType) throws IOException {
|
||||
List<ScheduledEvent.Builder> events = new ArrayList<>();
|
||||
private static final ObjectParser<List<ScheduledEvent.Builder>, Void> PARSER = new ObjectParser<>(NAME, ArrayList::new);
|
||||
|
||||
XContent xContent = contentType.xContent();
|
||||
int lineNumber = 0;
|
||||
int from = 0;
|
||||
int length = data.length();
|
||||
byte marker = xContent.streamSeparator();
|
||||
while (true) {
|
||||
int nextMarker = findNextMarker(marker, from, data, length);
|
||||
if (nextMarker == -1) {
|
||||
break;
|
||||
}
|
||||
lineNumber++;
|
||||
|
||||
try (XContentParser parser = xContent.createParser(NamedXContentRegistry.EMPTY, data.slice(from, nextMarker - from))) {
|
||||
try {
|
||||
ScheduledEvent.Builder event = ScheduledEvent.PARSER.apply(parser, null);
|
||||
events.add(event);
|
||||
} catch (ParsingException pe) {
|
||||
throw ExceptionsHelper.badRequestException("Failed to parse scheduled event on line [" + lineNumber + "]", pe);
|
||||
static {
|
||||
PARSER.declareObjectArray(List::addAll, (p, c) -> ScheduledEvent.PARSER.apply(p, null), ScheduledEvent.RESULTS_FIELD);
|
||||
}
|
||||
|
||||
from = nextMarker + 1;
|
||||
}
|
||||
}
|
||||
public static Request parseRequest(String calendarId, XContentParser parser) throws IOException {
|
||||
List<ScheduledEvent.Builder> events = PARSER.apply(parser, null);
|
||||
|
||||
for (ScheduledEvent.Builder event : events) {
|
||||
if (event.getCalendarId() != null && event.getCalendarId().equals(calendarId) == false) {
|
||||
throw ExceptionsHelper.badRequestException(Messages.getMessage(Messages.INCONSISTENT_ID,
|
||||
Calendar.ID.getPreferredName(), event.getCalendarId(), calendarId));
|
||||
}
|
||||
|
||||
// Set the calendar Id in case it is null
|
||||
event.calendarId(calendarId);
|
||||
}
|
||||
return new Request(calendarId, events.stream().map(ScheduledEvent.Builder::build).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private static int findNextMarker(byte marker, int from, BytesReference data, int length) {
|
||||
for (int i = from; i < length; i++) {
|
||||
if (data.get(i) == marker) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (from != length) {
|
||||
throw new IllegalArgumentException("The post calendar events request must be terminated by a newline [\n]");
|
||||
}
|
||||
return -1;
|
||||
return new Request(calendarId, events.stream().map(ScheduledEvent.Builder::build).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private String calendarId;
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.xpack.ml.rest.calendar;
|
|||
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
|
@ -34,8 +35,9 @@ public class RestPostCalendarEventAction extends BaseRestHandler {
|
|||
protected BaseRestHandler.RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
|
||||
String calendarId = restRequest.param(Calendar.ID.getPreferredName());
|
||||
|
||||
XContentParser parser = restRequest.contentOrSourceParamParser();
|
||||
PostCalendarEventsAction.Request request =
|
||||
PostCalendarEventsAction.Request.parseRequest(calendarId, restRequest.requiredContent(), restRequest.getXContentType());
|
||||
PostCalendarEventsAction.Request.parseRequest(calendarId, parser);
|
||||
return channel -> client.execute(PostCalendarEventsAction.INSTANCE, request, new RestToXContentListener<>(channel));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,13 @@ package org.elasticsearch.xpack.ml.action;
|
|||
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.AbstractStreamableTestCase;
|
||||
import org.elasticsearch.xpack.ml.calendars.ScheduledEvent;
|
||||
import org.elasticsearch.xpack.ml.calendars.ScheduledEventTests;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -47,13 +46,16 @@ public class PostCalendarEventActionRequestTests extends AbstractStreamableTestC
|
|||
PostCalendarEventsAction.Request sourceRequest = createTestInstance();
|
||||
|
||||
StringBuilder requestString = new StringBuilder();
|
||||
requestString.append("{\"events\": [");
|
||||
for (ScheduledEvent event: sourceRequest.getScheduledEvents()) {
|
||||
requestString.append(Strings.toString(event)).append("\r\n");
|
||||
requestString.append(Strings.toString(event)).append(',');
|
||||
}
|
||||
requestString.replace(requestString.length() -1, requestString.length(), "]");
|
||||
requestString.append('}');
|
||||
|
||||
BytesArray data = new BytesArray(requestString.toString().getBytes(StandardCharsets.UTF_8), 0, requestString.length());
|
||||
XContentParser parser = createParser(XContentType.JSON.xContent(), requestString.toString());
|
||||
PostCalendarEventsAction.Request parsedRequest = PostCalendarEventsAction.Request.parseRequest(
|
||||
sourceRequest.getCalendarId(), data, XContentType.JSON);
|
||||
sourceRequest.getCalendarId(), parser);
|
||||
|
||||
assertEquals(sourceRequest, parsedRequest);
|
||||
}
|
||||
|
@ -62,15 +64,17 @@ public class PostCalendarEventActionRequestTests extends AbstractStreamableTestC
|
|||
PostCalendarEventsAction.Request sourceRequest = createTestInstance("foo");
|
||||
PostCalendarEventsAction.Request request = new PostCalendarEventsAction.Request("bar", sourceRequest.getScheduledEvents());
|
||||
|
||||
|
||||
StringBuilder requestString = new StringBuilder();
|
||||
requestString.append("{\"events\": [");
|
||||
for (ScheduledEvent event: sourceRequest.getScheduledEvents()) {
|
||||
requestString.append(Strings.toString(event)).append("\r\n");
|
||||
requestString.append(Strings.toString(event)).append(',');
|
||||
}
|
||||
requestString.replace(requestString.length() -1, requestString.length(), "]");
|
||||
requestString.append('}');
|
||||
|
||||
BytesArray data = new BytesArray(requestString.toString().getBytes(StandardCharsets.UTF_8), 0, requestString.length());
|
||||
XContentParser parser = createParser(XContentType.JSON.xContent(), requestString.toString());
|
||||
ElasticsearchStatusException e = expectThrows(ElasticsearchStatusException.class,
|
||||
() -> PostCalendarEventsAction.Request.parseRequest(request.getCalendarId(), data, XContentType.JSON));
|
||||
() -> PostCalendarEventsAction.Request.parseRequest("bar", parser));
|
||||
assertEquals("Inconsistent calendar_id; 'foo' specified in the body differs from 'bar' specified as a URL argument",
|
||||
e.getMessage());
|
||||
}
|
||||
|
|
|
@ -251,10 +251,13 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "events"
|
||||
body: >
|
||||
{ "description": "event 1", "start_time": "2017-12-01T00:00:00Z", "end_time": "2017-12-02T00:00:00Z", "calendar_id": "events" }
|
||||
{ "description": "event 2", "start_time": "2017-12-05T00:00:00Z", "end_time": "2017-12-06T00:00:00Z", "calendar_id": "events" }
|
||||
{ "description": "event 3", "start_time": "2017-12-12T00:00:00Z", "end_time": "2017-12-13T00:00:00Z", "calendar_id": "events" }
|
||||
{ "description": "event 4", "start_time": "2017-12-12T00:00:00Z", "end_time": "2017-12-15T00:00:00Z", "calendar_id": "events" }
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "event 1", "start_time": "2017-12-01T00:00:00Z", "end_time": "2017-12-02T00:00:00Z", "calendar_id": "events" },
|
||||
{ "description": "event 2", "start_time": "2017-12-05T00:00:00Z", "end_time": "2017-12-06T00:00:00Z", "calendar_id": "events" },
|
||||
{ "description": "event 3", "start_time": "2017-12-12T00:00:00Z", "end_time": "2017-12-13T00:00:00Z", "calendar_id": "events" },
|
||||
{ "description": "event 4", "start_time": "2017-12-12T00:00:00Z", "end_time": "2017-12-15T00:00:00Z", "calendar_id": "events" }]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.ml.get_calendar_events:
|
||||
|
@ -309,15 +312,21 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "events-2"
|
||||
body: >
|
||||
{ "description": "event 21", "start_time": "2017-12-02T00:00:00Z", "end_time": "2017-12-02T05:00:00Z"}
|
||||
{ "description": "event 22", "start_time": "2017-12-25T00:00:00Z", "end_time": "2017-12-26T00:00:00Z"}
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "event 21", "start_time": "2017-12-02T00:00:00Z", "end_time": "2017-12-02T05:00:00Z"},
|
||||
{ "description": "event 22", "start_time": "2017-12-25T00:00:00Z", "end_time": "2017-12-26T00:00:00Z"}]
|
||||
}
|
||||
|
||||
- do:
|
||||
catch: bad_request
|
||||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "events-2"
|
||||
body: >
|
||||
{ "description": "event 21", "start_time": "2017-12-02T00:00:00Z", "end_time": "2017-12-03T00:00:00Z", "calendar_id": "events"}
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "event 21", "start_time": "2017-12-02T00:00:00Z", "end_time": "2017-12-03T00:00:00Z", "calendar_id": "events"}]
|
||||
}
|
||||
|
||||
# Event is not in calendar events-2
|
||||
- do:
|
||||
|
@ -349,9 +358,12 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "cal-foo"
|
||||
body: >
|
||||
{ "description": "event 1", "start_time": "2017-12-01T00:00:00Z", "end_time": "2017-12-02T00:00:00Z" }
|
||||
{ "description": "event 2", "start_time": "2017-12-05T00:00:00Z", "end_time": "2017-12-06T00:00:00Z" }
|
||||
{ "description": "event 2", "start_time": "2017-12-05T00:00:00Z", "end_time": "2017-12-06T00:00:00Z" }
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "event 1", "start_time": "2017-12-01T00:00:00Z", "end_time": "2017-12-02T00:00:00Z" },
|
||||
{ "description": "event 2", "start_time": "2017-12-05T00:00:00Z", "end_time": "2017-12-06T00:00:00Z" },
|
||||
{ "description": "event 2", "start_time": "2017-12-05T00:00:00Z", "end_time": "2017-12-06T00:00:00Z" }]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.ml.put_calendar:
|
||||
|
@ -361,8 +373,11 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "cal-bar"
|
||||
body: >
|
||||
{ "description": "event 21", "start_time": "2017-12-02T00:00:00Z", "end_time": "2017-12-02T05:00:00Z"}
|
||||
{ "description": "event 22", "start_time": "2017-12-25T00:00:00Z", "end_time": "2017-12-26T00:00:00Z"}
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "event 21", "start_time": "2017-12-02T00:00:00Z", "end_time": "2017-12-02T05:00:00Z"},
|
||||
{ "description": "event 22", "start_time": "2017-12-25T00:00:00Z", "end_time": "2017-12-26T00:00:00Z"}]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.ml.delete_calendar:
|
||||
|
@ -404,8 +419,11 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "dave-holidays"
|
||||
body: >
|
||||
{ "description": "xmas", "start_time": "2017-12-25T00:00:00Z", "end_time": "2017-12-26T00:00:00Z" }
|
||||
{ "description": "ny", "start_time": "2018-01-01T00:00:00Z", "end_time": "2018-01-02T00:00:00Z" }
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "xmas", "start_time": "2017-12-25T00:00:00Z", "end_time": "2017-12-26T00:00:00Z" },
|
||||
{ "description": "ny", "start_time": "2018-01-01T00:00:00Z", "end_time": "2018-01-02T00:00:00Z" }]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.ml.put_calendar:
|
||||
|
@ -415,8 +433,11 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "tom-holidays"
|
||||
body: >
|
||||
{ "description": "xmas", "start_time": "2017-12-20T00:00:00Z", "end_time": "2017-12-26T00:00:00Z" }
|
||||
{ "description": "other", "start_time": "2017-12-27T00:00:00Z", "end_time": "2018-01-02T00:00:00Z" }
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "xmas", "start_time": "2017-12-20T00:00:00Z", "end_time": "2017-12-26T00:00:00Z" },
|
||||
{ "description": "other", "start_time": "2017-12-27T00:00:00Z", "end_time": "2018-01-02T00:00:00Z" }]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.ml.get_calendar_events:
|
||||
|
@ -450,8 +471,10 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "dave-holidays"
|
||||
body: >
|
||||
{ "description": "xmas", "start_time": "2017-12-25T00:00:00Z", "end_time": "2017-12-26T00:00:00Z" }
|
||||
{ "description": "ny", "start_time": "2018-01-01T00:00:00Z", "end_time": "2018-01-02T00:00:00Z" }
|
||||
{
|
||||
"events" : [{ "description": "xmas", "start_time": "2017-12-25T00:00:00Z", "end_time": "2017-12-26T00:00:00Z" },
|
||||
{ "description": "ny", "start_time": "2018-01-01T00:00:00Z", "end_time": "2018-01-02T00:00:00Z" }]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.ml.put_calendar:
|
||||
|
@ -465,8 +488,11 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "tom-holidays"
|
||||
body: >
|
||||
{ "description": "xmas", "start_time": "2017-12-20T00:00:00Z", "end_time": "2017-12-26T00:00:00Z" }
|
||||
{ "description": "other", "start_time": "2018-01-15T00:00:00Z", "end_time": "2018-01-16T00:00:00Z" }
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "xmas", "start_time": "2017-12-20T00:00:00Z", "end_time": "2017-12-26T00:00:00Z" },
|
||||
{ "description": "other", "start_time": "2018-01-15T00:00:00Z", "end_time": "2018-01-16T00:00:00Z" }]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.ml.put_calendar:
|
||||
|
@ -476,8 +502,11 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "not-used-by-job"
|
||||
body: >
|
||||
{ "description": "random", "start_time": "2018-01-20T00:00:00Z", "end_time": "2018-01-26T00:00:00Z" }
|
||||
{ "description": "random2", "start_time": "2018-02-20T00:00:00Z", "end_time": "2018-02-26T00:00:00Z" }
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "random", "start_time": "2018-01-20T00:00:00Z", "end_time": "2018-01-26T00:00:00Z" },
|
||||
{ "description": "random2", "start_time": "2018-02-20T00:00:00Z", "end_time": "2018-02-26T00:00:00Z" }]
|
||||
}
|
||||
|
||||
|
||||
# Calendar Id must be _all if a job id is used
|
||||
|
@ -532,8 +561,11 @@
|
|||
xpack.ml.post_calendar_events:
|
||||
calendar_id: "ben-holidays"
|
||||
body: >
|
||||
{ "description": "ski", "start_time": "2018-01-20T00:00:00Z", "end_time": "2018-01-27T00:00:00Z" }
|
||||
{ "description": "snow", "start_time": "2018-01-30T00:00:00Z", "end_time": "2018-02-01T00:00:00Z" }
|
||||
{
|
||||
"events" : [
|
||||
{ "description": "ski", "start_time": "2018-01-20T00:00:00Z", "end_time": "2018-01-27T00:00:00Z" },
|
||||
{ "description": "snow", "start_time": "2018-01-30T00:00:00Z", "end_time": "2018-02-01T00:00:00Z" }]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.ml.get_calendar_events:
|
||||
|
|
Loading…
Reference in New Issue