diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java
index 62c1740ab82..6f2f4072859 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java
@@ -28,6 +28,7 @@ import org.apache.http.entity.ByteArrayEntity;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
import org.elasticsearch.client.ml.CloseJobRequest;
+import org.elasticsearch.client.ml.DeleteCalendarJobRequest;
import org.elasticsearch.client.ml.DeleteCalendarRequest;
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
import org.elasticsearch.client.ml.DeleteFilterRequest;
@@ -514,6 +515,18 @@ final class MLRequestConverters {
return new Request(HttpPut.METHOD_NAME, endpoint);
}
+ static Request deleteCalendarJob(DeleteCalendarJobRequest deleteCalendarJobRequest) {
+ String endpoint = new EndpointBuilder()
+ .addPathPartAsIs("_xpack")
+ .addPathPartAsIs("ml")
+ .addPathPartAsIs("calendars")
+ .addPathPart(deleteCalendarJobRequest.getCalendarId())
+ .addPathPartAsIs("jobs")
+ .addPathPart(Strings.collectionToCommaDelimitedString(deleteCalendarJobRequest.getJobIds()))
+ .build();
+ return new Request(HttpDelete.METHOD_NAME, endpoint);
+ }
+
static Request deleteCalendar(DeleteCalendarRequest deleteCalendarRequest) {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java
index c34385bc759..bb526b810c4 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java
@@ -22,6 +22,7 @@ import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.ml.CloseJobRequest;
import org.elasticsearch.client.ml.CloseJobResponse;
+import org.elasticsearch.client.ml.DeleteCalendarJobRequest;
import org.elasticsearch.client.ml.DeleteCalendarRequest;
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
import org.elasticsearch.client.ml.DeleteFilterRequest;
@@ -1301,6 +1302,47 @@ public final class MachineLearningClient {
Collections.emptySet());
}
+ /**
+ * Removes Machine Learning Job(s) from a calendar
+ *
+ * For additional info
+ * see
+ * ML Delete calendar job documentation
+ *
+ * @param request The request
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return The {@link PutCalendarResponse} containing the updated calendar
+ * @throws IOException when there is a serialization issue sending the request or receiving the response
+ */
+ public PutCalendarResponse deleteCalendarJob(DeleteCalendarJobRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request,
+ MLRequestConverters::deleteCalendarJob,
+ options,
+ PutCalendarResponse::fromXContent,
+ Collections.emptySet());
+ }
+
+ /**
+ * Removes Machine Learning Job(s) from a calendar, notifies listener when completed
+ *
+ * For additional info
+ * see
+ * ML Delete calendar job documentation
+ *
+ * @param request The request
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener Listener to be notified upon request completion
+ */
+ public void deleteCalendarJobAsync(DeleteCalendarJobRequest request,
+ RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request,
+ MLRequestConverters::deleteCalendarJob,
+ options,
+ PutCalendarResponse::fromXContent,
+ listener,
+ Collections.emptySet());
+ }
/**
* Deletes the given Machine Learning Calendar
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarJobRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarJobRequest.java
new file mode 100644
index 00000000000..a1bd3a412c7
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarJobRequest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Request class for removing Machine Learning Jobs from an existing calendar
+ */
+public class DeleteCalendarJobRequest extends ActionRequest {
+
+ private final List jobIds;
+ private final String calendarId;
+
+ /**
+ * Create a new request referencing an existing Calendar and which JobIds to remove
+ * from it.
+ *
+ * @param calendarId The non-null ID of the calendar
+ * @param jobIds JobIds to remove from the calendar, cannot be empty, or contain null values.
+ * It can be a list of jobs or groups.
+ */
+ public DeleteCalendarJobRequest(String calendarId, String... jobIds) {
+ this.calendarId = Objects.requireNonNull(calendarId, "[calendar_id] must not be null.");
+ if (jobIds.length == 0) {
+ throw new InvalidParameterException("jobIds must not be empty.");
+ }
+ if (Arrays.stream(jobIds).anyMatch(Objects::isNull)) {
+ throw new NullPointerException("jobIds must not contain null values.");
+ }
+ this.jobIds = Arrays.asList(jobIds);
+ }
+
+ public List getJobIds() {
+ return jobIds;
+ }
+
+ public String getCalendarId() {
+ return calendarId;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobIds, calendarId);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ DeleteCalendarJobRequest that = (DeleteCalendarJobRequest) other;
+ return Objects.equals(jobIds, that.jobIds) &&
+ Objects.equals(calendarId, that.calendarId);
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java
index b47ee4d4bbb..7e47f8c1ea8 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java
@@ -24,6 +24,7 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.elasticsearch.client.ml.CloseJobRequest;
+import org.elasticsearch.client.ml.DeleteCalendarJobRequest;
import org.elasticsearch.client.ml.DeleteCalendarRequest;
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
import org.elasticsearch.client.ml.DeleteFilterRequest;
@@ -536,7 +537,7 @@ public class MLRequestConvertersTests extends ESTestCase {
}
}
- public void testPutCalendarJob() throws IOException {
+ public void testPutCalendarJob() {
String calendarId = randomAlphaOfLength(10);
String job1 = randomAlphaOfLength(5);
String job2 = randomAlphaOfLength(5);
@@ -546,6 +547,16 @@ public class MLRequestConvertersTests extends ESTestCase {
assertEquals("/_xpack/ml/calendars/" + calendarId + "/jobs/" + job1 + "," + job2, request.getEndpoint());
}
+ public void testDeleteCalendarJob() {
+ String calendarId = randomAlphaOfLength(10);
+ String job1 = randomAlphaOfLength(5);
+ String job2 = randomAlphaOfLength(5);
+ DeleteCalendarJobRequest deleteCalendarJobRequest = new DeleteCalendarJobRequest(calendarId, job1, job2);
+ Request request = MLRequestConverters.deleteCalendarJob(deleteCalendarJobRequest);
+ assertEquals(HttpDelete.METHOD_NAME, request.getMethod());
+ assertEquals("/_xpack/ml/calendars/" + calendarId + "/jobs/" + job1 + "," + job2, request.getEndpoint());
+ }
+
public void testGetCalendars() throws IOException {
GetCalendarsRequest getCalendarsRequest = new GetCalendarsRequest();
String expectedEndpoint = "/_xpack/ml/calendars";
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java
index 4b52c8d8d54..7716d7c20bb 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java
@@ -29,6 +29,7 @@ import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.ml.CloseJobRequest;
import org.elasticsearch.client.ml.CloseJobResponse;
+import org.elasticsearch.client.ml.DeleteCalendarJobRequest;
import org.elasticsearch.client.ml.DeleteCalendarRequest;
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
import org.elasticsearch.client.ml.DeleteFilterRequest;
@@ -851,6 +852,29 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
assertThat(putCalendarResponse.getCalendar().getJobIds(), containsInAnyOrder(jobId1, jobId2, "put-calendar-job-0"));
}
+ public void testDeleteCalendarJob() throws IOException {
+ Calendar calendar = new Calendar("del-calendar-job-id",
+ Arrays.asList("del-calendar-job-0", "del-calendar-job-1", "del-calendar-job-2"),
+ null);
+ MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
+ PutCalendarResponse putCalendarResponse =
+ machineLearningClient.putCalendar(new PutCalendarRequest(calendar), RequestOptions.DEFAULT);
+
+ assertThat(putCalendarResponse.getCalendar().getJobIds(),
+ containsInAnyOrder("del-calendar-job-0", "del-calendar-job-1", "del-calendar-job-2"));
+
+ String jobId1 = "del-calendar-job-0";
+ String jobId2 = "del-calendar-job-2";
+
+ DeleteCalendarJobRequest deleteCalendarJobRequest = new DeleteCalendarJobRequest(calendar.getId(), jobId1, jobId2);
+
+ putCalendarResponse = execute(deleteCalendarJobRequest,
+ machineLearningClient::deleteCalendarJob,
+ machineLearningClient::deleteCalendarJobAsync);
+
+ assertThat(putCalendarResponse.getCalendar().getJobIds(), containsInAnyOrder("del-calendar-job-1"));
+ }
+
public void testGetCalendars() throws Exception {
Calendar calendar1 = CalendarTests.testInstance();
Calendar calendar2 = CalendarTests.testInstance();
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java
index 38203a38d81..4886bce1853 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java
@@ -35,6 +35,7 @@ import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.ml.CloseJobRequest;
import org.elasticsearch.client.ml.CloseJobResponse;
+import org.elasticsearch.client.ml.DeleteCalendarJobRequest;
import org.elasticsearch.client.ml.DeleteCalendarRequest;
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
import org.elasticsearch.client.ml.DeleteFilterRequest;
@@ -2214,6 +2215,60 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
}
}
+ public void testDeleteCalendarJob() throws IOException, InterruptedException {
+ RestHighLevelClient client = highLevelClient();
+
+ Calendar calendar = new Calendar("holidays",
+ Arrays.asList("job_1", "job_group_1", "job_2"),
+ "A calendar for public holidays");
+ PutCalendarRequest putRequest = new PutCalendarRequest(calendar);
+ client.machineLearning().putCalendar(putRequest, RequestOptions.DEFAULT);
+ {
+ // tag::delete-calendar-job-request
+ DeleteCalendarJobRequest request = new DeleteCalendarJobRequest("holidays", // <1>
+ "job_1", "job_group_1"); // <2>
+ // end::delete-calendar-job-request
+
+ // tag::delete-calendar-job-execute
+ PutCalendarResponse response = client.machineLearning().deleteCalendarJob(request, RequestOptions.DEFAULT);
+ // end::delete-calendar-job-execute
+
+ // tag::delete-calendar-job-response
+ Calendar updatedCalendar = response.getCalendar(); // <1>
+ // end::delete-calendar-job-response
+
+ assertThat(updatedCalendar.getJobIds(), containsInAnyOrder("job_2"));
+ }
+ {
+ DeleteCalendarJobRequest request = new DeleteCalendarJobRequest("holidays", "job_2");
+
+ // tag::delete-calendar-job-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(PutCalendarResponse deleteCalendarsResponse) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::delete-calendar-job-execute-listener
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ // tag::delete-calendar-job-execute-async
+ client.machineLearning().deleteCalendarJobAsync(request, RequestOptions.DEFAULT, listener); // <1>
+ // end::delete-calendar-job-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+ }
+
public void testGetCalendar() throws IOException, InterruptedException {
RestHighLevelClient client = highLevelClient();
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/DeleteCalendarJobRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/DeleteCalendarJobRequestTests.java
new file mode 100644
index 00000000000..63d78b45986
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/DeleteCalendarJobRequestTests.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.test.ESTestCase;
+
+public class DeleteCalendarJobRequestTests extends ESTestCase {
+
+ public void testWithNullId() {
+ NullPointerException ex = expectThrows(NullPointerException.class,
+ () -> new DeleteCalendarJobRequest(null, "job1"));
+ assertEquals("[calendar_id] must not be null.", ex.getMessage());
+ }
+
+ public void testSetJobIds() {
+ String calendarId = randomAlphaOfLength(10);
+
+ NullPointerException ex = expectThrows(NullPointerException.class,
+ () ->new DeleteCalendarJobRequest(calendarId, "job1", null));
+ assertEquals("jobIds must not contain null values.", ex.getMessage());
+
+ IllegalArgumentException illegalArgumentException =
+ expectThrows(IllegalArgumentException.class, () -> new DeleteCalendarJobRequest(calendarId));
+ assertEquals("jobIds must not be empty.", illegalArgumentException.getMessage());
+ }
+}
diff --git a/docs/java-rest/high-level/ml/delete-calendar-job.asciidoc b/docs/java-rest/high-level/ml/delete-calendar-job.asciidoc
new file mode 100644
index 00000000000..d7686315f0f
--- /dev/null
+++ b/docs/java-rest/high-level/ml/delete-calendar-job.asciidoc
@@ -0,0 +1,36 @@
+--
+:api: delete-calendar-job
+:request: DeleteCalendarJobRequest
+:response: PutCalendarResponse
+--
+[id="{upid}-{api}"]
+=== Delete Calendar Job API
+Removes {ml} jobs from an existing {ml} calendar.
+The API accepts a +{request}+ and responds
+with a +{response}+ object.
+
+[id="{upid}-{api}-request"]
+==== Delete Calendar Job Request
+
+A +{request}+ is constructed referencing a non-null
+calendar ID, and JobIDs which to remove from the calendar
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+<1> The ID of the calendar from which to remove the jobs
+<2> The JobIds to remove from the calendar
+
+[id="{upid}-{api}-response"]
+==== Delete Calendar Response
+
+The returned +{response}+ contains the updated Calendar:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
+<1> The updated Calendar with the jobs removed
+
+include::../execution.asciidoc[]
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index 76f05570174..3a1878ab78b 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -267,6 +267,7 @@ The Java High Level REST Client supports the following Machine Learning APIs:
* <<{upid}-get-calendars>>
* <<{upid}-put-calendar>>
* <<{upid}-put-calendar-job>>
+* <<{upid}-delete-calendar-job>>
* <<{upid}-delete-calendar>>
* <<{upid}-put-filter>>
* <<{upid}-get-filters>>
@@ -303,6 +304,7 @@ include::ml/get-categories.asciidoc[]
include::ml/get-calendars.asciidoc[]
include::ml/put-calendar.asciidoc[]
include::ml/put-calendar-job.asciidoc[]
+include::ml/delete-calendar-job.asciidoc[]
include::ml/delete-calendar.asciidoc[]
include::ml/put-filter.asciidoc[]
include::ml/get-model-snapshots.asciidoc[]