Browse Source

[HLRC][ML] Add ML delete datafeed API to HLRC (#33667)

Relates #29827
Dimitris Athanasiou 7 years ago
parent
commit
9600819cef

+ 14 - 0
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.DeleteDatafeedRequest;
 import org.elasticsearch.client.ml.DeleteForecastRequest;
 import org.elasticsearch.client.ml.DeleteJobRequest;
 import org.elasticsearch.client.ml.FlushJobRequest;
@@ -195,6 +196,19 @@ final class MLRequestConverters {
         return request;
     }
 
+    static Request deleteDatafeed(DeleteDatafeedRequest deleteDatafeedRequest) {
+        String endpoint = new EndpointBuilder()
+                .addPathPartAsIs("_xpack")
+                .addPathPartAsIs("ml")
+                .addPathPartAsIs("datafeeds")
+                .addPathPart(deleteDatafeedRequest.getDatafeedId())
+                .build();
+        Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
+        RequestConverters.Params params = new RequestConverters.Params(request);
+        params.putParam("force", Boolean.toString(deleteDatafeedRequest.isForce()));
+        return request;
+    }
+
     static Request deleteForecast(DeleteForecastRequest deleteForecastRequest) throws IOException {
         String endpoint = new EndpointBuilder()
             .addPathPartAsIs("_xpack")

+ 45 - 5
client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java

@@ -22,9 +22,9 @@ 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.DeleteDatafeedRequest;
 import org.elasticsearch.client.ml.DeleteForecastRequest;
 import org.elasticsearch.client.ml.DeleteJobRequest;
-import org.elasticsearch.client.ml.DeleteJobResponse;
 import org.elasticsearch.client.ml.FlushJobRequest;
 import org.elasticsearch.client.ml.FlushJobResponse;
 import org.elasticsearch.client.ml.ForecastJobRequest;
@@ -204,11 +204,11 @@ public final class MachineLearningClient {
      * @return action acknowledgement
      * @throws IOException when there is a serialization issue sending the request or receiving the response
      */
-    public DeleteJobResponse deleteJob(DeleteJobRequest request, RequestOptions options) throws IOException {
+    public AcknowledgedResponse deleteJob(DeleteJobRequest request, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(request,
             MLRequestConverters::deleteJob,
             options,
-            DeleteJobResponse::fromXContent,
+            AcknowledgedResponse::fromXContent,
             Collections.emptySet());
     }
 
@@ -222,11 +222,11 @@ public final class MachineLearningClient {
      * @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 deleteJobAsync(DeleteJobRequest request, RequestOptions options, ActionListener<DeleteJobResponse> listener) {
+    public void deleteJobAsync(DeleteJobRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::deleteJob,
             options,
-            DeleteJobResponse::fromXContent,
+            AcknowledgedResponse::fromXContent,
             listener,
             Collections.emptySet());
     }
@@ -492,6 +492,46 @@ public final class MachineLearningClient {
                 Collections.emptySet());
     }
 
+    /**
+     * Deletes the given Machine Learning Datafeed
+     * <p>
+     *     For additional info
+     *     see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-datafeed.html">
+     *         ML Delete Datafeed documentation</a>
+     * </p>
+     * @param request The request to delete the datafeed
+     * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return action acknowledgement
+     * @throws IOException when there is a serialization issue sending the request or receiving the response
+     */
+    public AcknowledgedResponse deleteDatafeed(DeleteDatafeedRequest request, RequestOptions options) throws IOException {
+        return restHighLevelClient.performRequestAndParseEntity(request,
+                MLRequestConverters::deleteDatafeed,
+                options,
+                AcknowledgedResponse::fromXContent,
+                Collections.emptySet());
+    }
+
+    /**
+     * Deletes the given Machine Learning Datafeed asynchronously and notifies the listener on completion
+     * <p>
+     *     For additional info
+     *     see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-datafeed.html">
+     *         ML Delete Datafeed documentation</a>
+     * </p>
+     * @param request The request to delete the datafeed
+     * @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 deleteDatafeedAsync(DeleteDatafeedRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
+        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+                MLRequestConverters::deleteDatafeed,
+                options,
+                AcknowledgedResponse::fromXContent,
+                listener,
+                Collections.emptySet());
+    }
+
     /**
      * Deletes Machine Learning Job Forecasts
      *

+ 80 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteDatafeedRequest.java

@@ -0,0 +1,80 @@
+/*
+ * 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.util.Objects;
+
+/**
+ * Request to delete a Machine Learning Datafeed via its ID
+ */
+public class DeleteDatafeedRequest extends ActionRequest {
+
+    private String datafeedId;
+    private boolean force;
+
+    public DeleteDatafeedRequest(String datafeedId) {
+        this.datafeedId = Objects.requireNonNull(datafeedId, "[datafeed_id] must not be null");
+    }
+
+    public String getDatafeedId() {
+        return datafeedId;
+    }
+
+    public boolean isForce() {
+        return force;
+    }
+
+    /**
+     * Used to forcefully delete a started datafeed.
+     * This method is quicker than stopping and deleting the datafeed.
+     *
+     * @param force When {@code true} forcefully delete a started datafeed. Defaults to {@code false}
+     */
+    public void setForce(boolean force) {
+        this.force = force;
+    }
+
+    @Override
+    public ActionRequestValidationException validate() {
+       return null;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(datafeedId, force);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null || obj.getClass() != getClass()) {
+            return false;
+        }
+
+        DeleteDatafeedRequest other = (DeleteDatafeedRequest) obj;
+        return Objects.equals(datafeedId, other.datafeedId) && Objects.equals(force, other.force);
+    }
+
+}

+ 0 - 63
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobResponse.java

@@ -1,63 +0,0 @@
-/*
- * 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.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-import java.io.IOException;
-import java.util.Objects;
-
-/**
- * Response acknowledging the Machine Learning Job request
- */
-public class DeleteJobResponse extends AcknowledgedResponse {
-
-   public DeleteJobResponse(boolean acknowledged) {
-       super(acknowledged);
-   }
-
-   public DeleteJobResponse() {
-   }
-
-    public static DeleteJobResponse fromXContent(XContentParser parser) throws IOException {
-        AcknowledgedResponse response = AcknowledgedResponse.fromXContent(parser);
-        return new DeleteJobResponse(response.isAcknowledged());
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        if (this == other) {
-            return true;
-        }
-
-        if (other == null || getClass() != other.getClass()) {
-            return false;
-        }
-
-        DeleteJobResponse that = (DeleteJobResponse) other;
-        return isAcknowledged() == that.isAcknowledged();
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(isAcknowledged());
-    }
-
-}

+ 15 - 0
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.DeleteDatafeedRequest;
 import org.elasticsearch.client.ml.DeleteForecastRequest;
 import org.elasticsearch.client.ml.DeleteJobRequest;
 import org.elasticsearch.client.ml.FlushJobRequest;
@@ -223,6 +224,20 @@ public class MLRequestConvertersTests extends ESTestCase {
         }
     }
 
+    public void testDeleteDatafeed() {
+        String datafeedId = randomAlphaOfLength(10);
+        DeleteDatafeedRequest deleteDatafeedRequest = new DeleteDatafeedRequest(datafeedId);
+
+        Request request = MLRequestConverters.deleteDatafeed(deleteDatafeedRequest);
+        assertEquals(HttpDelete.METHOD_NAME, request.getMethod());
+        assertEquals("/_xpack/ml/datafeeds/" + datafeedId, request.getEndpoint());
+        assertEquals(Boolean.toString(false), request.getParameters().get("force"));
+
+        deleteDatafeedRequest.setForce(true);
+        request = MLRequestConverters.deleteDatafeed(deleteDatafeedRequest);
+        assertEquals(Boolean.toString(true), request.getParameters().get("force"));
+    }
+
     public void testDeleteForecast() throws Exception {
         String jobId = randomAlphaOfLength(10);
         DeleteForecastRequest deleteForecastRequest = new DeleteForecastRequest(jobId);

+ 18 - 2
client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java

@@ -25,9 +25,9 @@ import org.elasticsearch.action.get.GetResponse;
 import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ml.CloseJobRequest;
 import org.elasticsearch.client.ml.CloseJobResponse;
+import org.elasticsearch.client.ml.DeleteDatafeedRequest;
 import org.elasticsearch.client.ml.DeleteForecastRequest;
 import org.elasticsearch.client.ml.DeleteJobRequest;
-import org.elasticsearch.client.ml.DeleteJobResponse;
 import org.elasticsearch.client.ml.FlushJobRequest;
 import org.elasticsearch.client.ml.FlushJobResponse;
 import org.elasticsearch.client.ml.ForecastJobRequest;
@@ -129,7 +129,7 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
         MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
         machineLearningClient.putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
 
-        DeleteJobResponse response = execute(new DeleteJobRequest(jobId),
+        AcknowledgedResponse response = execute(new DeleteJobRequest(jobId),
             machineLearningClient::deleteJob,
             machineLearningClient::deleteJobAsync);
 
@@ -312,6 +312,22 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
         assertThat(createdDatafeed.getIndices(), equalTo(datafeedConfig.getIndices()));
     }
 
+    public void testDeleteDatafeed() throws Exception {
+        String jobId = randomValidJobId();
+        Job job = buildJob(jobId);
+        MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
+        machineLearningClient.putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
+
+        String datafeedId = "datafeed-" + jobId;
+        DatafeedConfig datafeedConfig = DatafeedConfig.builder(datafeedId, jobId).setIndices("some_data_index").build();
+        execute(new PutDatafeedRequest(datafeedConfig), machineLearningClient::putDatafeed, machineLearningClient::putDatafeedAsync);
+
+        AcknowledgedResponse response = execute(new DeleteDatafeedRequest(datafeedId), machineLearningClient::deleteDatafeed,
+                machineLearningClient::deleteDatafeedAsync);
+
+        assertTrue(response.isAcknowledged());
+    }
+
     public void testDeleteForecast() throws Exception {
         String jobId = "test-delete-forecast";
 

+ 59 - 4
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java

@@ -34,9 +34,9 @@ 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.DeleteDatafeedRequest;
 import org.elasticsearch.client.ml.DeleteForecastRequest;
 import org.elasticsearch.client.ml.DeleteJobRequest;
-import org.elasticsearch.client.ml.DeleteJobResponse;
 import org.elasticsearch.client.ml.FlushJobRequest;
 import org.elasticsearch.client.ml.FlushJobResponse;
 import org.elasticsearch.client.ml.ForecastJobRequest;
@@ -264,7 +264,7 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
             //tag::x-pack-delete-ml-job-request
             DeleteJobRequest deleteJobRequest = new DeleteJobRequest("my-first-machine-learning-job");
             deleteJobRequest.setForce(false); //<1>
-            DeleteJobResponse deleteJobResponse = client.machineLearning().deleteJob(deleteJobRequest, RequestOptions.DEFAULT);
+            AcknowledgedResponse deleteJobResponse = client.machineLearning().deleteJob(deleteJobRequest, RequestOptions.DEFAULT);
             //end::x-pack-delete-ml-job-request
 
             //tag::x-pack-delete-ml-job-response
@@ -273,9 +273,9 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
         }
         {
             //tag::x-pack-delete-ml-job-request-listener
-            ActionListener<DeleteJobResponse> listener = new ActionListener<DeleteJobResponse>() {
+            ActionListener<AcknowledgedResponse> listener = new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(DeleteJobResponse deleteJobResponse) {
+                public void onResponse(AcknowledgedResponse acknowledgedResponse) {
                     // <1>
                 }
 
@@ -587,6 +587,61 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
         }
     }
 
+    public void testDeleteDatafeed() throws Exception {
+        RestHighLevelClient client = highLevelClient();
+
+        String jobId = "test-delete-datafeed-job";
+        Job job = MachineLearningIT.buildJob(jobId);
+        client.machineLearning().putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
+
+        String datafeedId = "test-delete-datafeed";
+        DatafeedConfig datafeed = DatafeedConfig.builder(datafeedId, jobId).setIndices("foo").build();
+        client.machineLearning().putDatafeed(new PutDatafeedRequest(datafeed), RequestOptions.DEFAULT);
+
+        {
+            //tag::x-pack-delete-ml-datafeed-request
+            DeleteDatafeedRequest deleteDatafeedRequest = new DeleteDatafeedRequest(datafeedId);
+            deleteDatafeedRequest.setForce(false); //<1>
+            AcknowledgedResponse deleteDatafeedResponse = client.machineLearning().deleteDatafeed(
+                    deleteDatafeedRequest, RequestOptions.DEFAULT);
+            //end::x-pack-delete-ml-datafeed-request
+
+            //tag::x-pack-delete-ml-datafeed-response
+            boolean isAcknowledged = deleteDatafeedResponse.isAcknowledged(); //<1>
+            //end::x-pack-delete-ml-datafeed-response
+        }
+
+        // Recreate datafeed to allow second deletion
+        client.machineLearning().putDatafeed(new PutDatafeedRequest(datafeed), RequestOptions.DEFAULT);
+
+        {
+            //tag::x-pack-delete-ml-datafeed-request-listener
+            ActionListener<AcknowledgedResponse> listener = new ActionListener<AcknowledgedResponse>() {
+                @Override
+                public void onResponse(AcknowledgedResponse acknowledgedResponse) {
+                    // <1>
+                }
+
+                @Override
+                public void onFailure(Exception e) {
+                    // <2>
+                }
+            };
+            //end::x-pack-delete-ml-datafeed-request-listener
+
+            // Replace the empty listener by a blocking listener in test
+            final CountDownLatch latch = new CountDownLatch(1);
+            listener = new LatchedActionListener<>(listener, latch);
+
+            //tag::x-pack-delete-ml-datafeed-request-async
+            DeleteDatafeedRequest deleteDatafeedRequest = new DeleteDatafeedRequest(datafeedId);
+            client.machineLearning().deleteDatafeedAsync(deleteDatafeedRequest, RequestOptions.DEFAULT, listener); // <1>
+            //end::x-pack-delete-ml-datafeed-request-async
+
+            assertTrue(latch.await(30L, TimeUnit.SECONDS));
+        }
+    }
+
     public void testGetBuckets() throws IOException, InterruptedException {
         RestHighLevelClient client = highLevelClient();
 

+ 14 - 14
client/rest-high-level/src/test/java/org/elasticsearch/client/ml/DeleteJobResponseTests.java → client/rest-high-level/src/test/java/org/elasticsearch/client/ml/DeleteDatafeedRequestTests.java

@@ -18,25 +18,25 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractXContentTestCase;
+import org.elasticsearch.client.ml.datafeed.DatafeedConfigTests;
+import org.elasticsearch.test.ESTestCase;
 
-import java.io.IOException;
+public class DeleteDatafeedRequestTests extends ESTestCase {
 
-public class DeleteJobResponseTests extends AbstractXContentTestCase<DeleteJobResponse> {
-
-    @Override
-    protected DeleteJobResponse createTestInstance() {
-        return new DeleteJobResponse();
+    public void testConstructor_GivenNullId() {
+        NullPointerException ex = expectThrows(NullPointerException.class, () -> new DeleteJobRequest(null));
+        assertEquals("[job_id] must not be null", ex.getMessage());
     }
 
-    @Override
-    protected DeleteJobResponse doParseInstance(XContentParser parser) throws IOException {
-        return DeleteJobResponse.fromXContent(parser);
+    public void testSetForce() {
+        DeleteDatafeedRequest deleteDatafeedRequest = createTestInstance();
+        assertFalse(deleteDatafeedRequest.isForce());
+
+        deleteDatafeedRequest.setForce(true);
+        assertTrue(deleteDatafeedRequest.isForce());
     }
 
-    @Override
-    protected boolean supportsUnknownFields() {
-        return false;
+    private DeleteDatafeedRequest createTestInstance() {
+        return new DeleteDatafeedRequest(DatafeedConfigTests.randomValidDatafeedId());
     }
 }

+ 49 - 0
docs/java-rest/high-level/ml/delete-datafeed.asciidoc

@@ -0,0 +1,49 @@
+[[java-rest-high-x-pack-ml-delete-datafeed]]
+=== Delete Datafeed API
+
+[[java-rest-high-x-pack-machine-learning-delete-datafeed-request]]
+==== Delete Datafeed Request
+
+A `DeleteDatafeedRequest` object requires a non-null `datafeedId` and can optionally set `force`.
+Can be executed as follows:
+
+["source","java",subs="attributes,callouts,macros"]
+---------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-datafeed-request]
+---------------------------------------------------
+<1> Use to forcefully delete a started datafeed;
+this method is quicker than stopping and deleting the datafeed.
+Defaults to `false`.
+
+[[java-rest-high-x-pack-machine-learning-delete-datafeed-response]]
+==== Delete Datafeed Response
+
+The returned `AcknowledgedResponse` object indicates the acknowledgement of the request:
+["source","java",subs="attributes,callouts,macros"]
+---------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-datafeed-response]
+---------------------------------------------------
+<1> `isAcknowledged` was the deletion request acknowledged or not
+
+[[java-rest-high-x-pack-machine-learning-delete-datafeed-async]]
+==== Delete Datafeed Asynchronously
+
+This request can also be made asynchronously.
+["source","java",subs="attributes,callouts,macros"]
+---------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-datafeed-request-async]
+---------------------------------------------------
+<1> The `DeleteDatafeedRequest` to execute and the `ActionListener` to alert on completion or error.
+
+The deletion request returns immediately. Once the request is completed, the `ActionListener` is
+called back using the `onResponse` or `onFailure`. The latter indicates some failure occurred when
+making the request.
+
+A typical listener for a `DeleteDatafeedRequest` could be defined as follows:
+
+["source","java",subs="attributes,callouts,macros"]
+---------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-datafeed-request-listener]
+---------------------------------------------------
+<1> The action to be taken when it is completed
+<2> What to do when a failure occurs

+ 1 - 1
docs/java-rest/high-level/ml/delete-job.asciidoc

@@ -18,7 +18,7 @@ Defaults to `false`
 [[java-rest-high-x-pack-machine-learning-delete-job-response]]
 ==== Delete Job Response
 
-The returned `DeleteJobResponse` object indicates the acknowledgement of the request:
+The returned `AcknowledgedResponse` object indicates the acknowledgement of the request:
 ["source","java",subs="attributes,callouts,macros"]
 ---------------------------------------------------
 include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-job-response]

+ 2 - 0
docs/java-rest/high-level/supported-apis.asciidoc

@@ -221,6 +221,7 @@ The Java High Level REST Client supports the following Machine Learning APIs:
 * <<java-rest-high-x-pack-ml-update-job>>
 * <<java-rest-high-x-pack-ml-get-job-stats>>
 * <<java-rest-high-x-pack-ml-put-datafeed>>
+* <<java-rest-high-x-pack-ml-delete-datafeed>>
 * <<java-rest-high-x-pack-ml-forecast-job>>
 * <<java-rest-high-x-pack-ml-delete-forecast>>
 * <<java-rest-high-x-pack-ml-get-buckets>>
@@ -238,6 +239,7 @@ include::ml/close-job.asciidoc[]
 include::ml/update-job.asciidoc[]
 include::ml/flush-job.asciidoc[]
 include::ml/put-datafeed.asciidoc[]
+include::ml/delete-datafeed.asciidoc[]
 include::ml/get-job-stats.asciidoc[]
 include::ml/forecast-job.asciidoc[]
 include::ml/delete-forecast.asciidoc[]