Skip to content

Commit 26a8ca0

Browse files
authored
[7.x] [ML][Inference][HLRC] Delete trained model API (#49567) (#49585)
* [ML][Inference][HLRC] Delete trained model API (#49567) * fixing for backport
1 parent b0cb7bf commit 26a8ca0

File tree

9 files changed

+278
-0
lines changed

9 files changed

+278
-0
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
3030
import org.elasticsearch.client.core.PageParams;
3131
import org.elasticsearch.client.ml.CloseJobRequest;
32+
import org.elasticsearch.client.ml.DeleteTrainedModelRequest;
3233
import org.elasticsearch.client.ml.ExplainDataFrameAnalyticsRequest;
3334
import org.elasticsearch.client.ml.DeleteCalendarEventRequest;
3435
import org.elasticsearch.client.ml.DeleteCalendarJobRequest;
@@ -748,6 +749,14 @@ static Request getTrainedModels(GetTrainedModelsRequest getTrainedModelsRequest)
748749
return request;
749750
}
750751

752+
static Request deleteTrainedModel(DeleteTrainedModelRequest deleteRequest) {
753+
String endpoint = new EndpointBuilder()
754+
.addPathPartAsIs("_ml", "inference")
755+
.addPathPart(deleteRequest.getId())
756+
.build();
757+
return new Request(HttpDelete.METHOD_NAME, endpoint);
758+
}
759+
751760
static Request putFilter(PutFilterRequest putFilterRequest) throws IOException {
752761
String endpoint = new EndpointBuilder()
753762
.addPathPartAsIs("_ml")

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.action.support.master.AcknowledgedResponse;
2323
import org.elasticsearch.client.ml.CloseJobRequest;
2424
import org.elasticsearch.client.ml.CloseJobResponse;
25+
import org.elasticsearch.client.ml.DeleteTrainedModelRequest;
2526
import org.elasticsearch.client.ml.ExplainDataFrameAnalyticsRequest;
2627
import org.elasticsearch.client.ml.ExplainDataFrameAnalyticsResponse;
2728
import org.elasticsearch.client.ml.DeleteCalendarEventRequest;
@@ -2337,4 +2338,46 @@ public Cancellable getTrainedModelsAsync(GetTrainedModelsRequest request,
23372338
Collections.emptySet());
23382339
}
23392340

2341+
/**
2342+
* Deletes the given Trained Model
2343+
* <p>
2344+
* For additional info
2345+
* see <a href="TODO">
2346+
* DELETE Trained Model documentation</a>
2347+
*
2348+
* @param request The {@link DeleteTrainedModelRequest}
2349+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
2350+
* @return action acknowledgement
2351+
* @throws IOException when there is a serialization issue sending the request or receiving the response
2352+
*/
2353+
public AcknowledgedResponse deleteTrainedModel(DeleteTrainedModelRequest request, RequestOptions options) throws IOException {
2354+
return restHighLevelClient.performRequestAndParseEntity(request,
2355+
MLRequestConverters::deleteTrainedModel,
2356+
options,
2357+
AcknowledgedResponse::fromXContent,
2358+
Collections.emptySet());
2359+
}
2360+
2361+
/**
2362+
* Deletes the given Trained Model asynchronously and notifies listener upon completion
2363+
* <p>
2364+
* For additional info
2365+
* see <a href="TODO">
2366+
* DELETE Trained Model documentation</a>
2367+
*
2368+
* @param request The {@link DeleteTrainedModelRequest}
2369+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
2370+
* @param listener Listener to be notified upon request completion
2371+
* @return cancellable that may be used to cancel the request
2372+
*/
2373+
public Cancellable deleteTrainedModelAsync(DeleteTrainedModelRequest request,
2374+
RequestOptions options,
2375+
ActionListener<AcknowledgedResponse> listener) {
2376+
return restHighLevelClient.performRequestAsyncAndParseEntity(request,
2377+
MLRequestConverters::deleteTrainedModel,
2378+
options,
2379+
AcknowledgedResponse::fromXContent,
2380+
listener,
2381+
Collections.emptySet());
2382+
}
23402383
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.ml;
21+
22+
import org.elasticsearch.client.Validatable;
23+
import org.elasticsearch.client.ValidationException;
24+
25+
import java.util.Objects;
26+
import java.util.Optional;
27+
28+
/**
29+
* Request to delete a data frame analytics config
30+
*/
31+
public class DeleteTrainedModelRequest implements Validatable {
32+
33+
private final String id;
34+
35+
public DeleteTrainedModelRequest(String id) {
36+
this.id = id;
37+
}
38+
39+
public String getId() {
40+
return id;
41+
}
42+
43+
@Override
44+
public Optional<ValidationException> validate() {
45+
if (id == null) {
46+
return Optional.of(ValidationException.withError("trained model id must not be null"));
47+
}
48+
return Optional.empty();
49+
}
50+
51+
@Override
52+
public boolean equals(Object o) {
53+
if (this == o) return true;
54+
if (o == null || getClass() != o.getClass()) return false;
55+
56+
DeleteTrainedModelRequest other = (DeleteTrainedModelRequest) o;
57+
return Objects.equals(id, other.id);
58+
}
59+
60+
@Override
61+
public int hashCode() {
62+
return Objects.hash(id);
63+
}
64+
}

client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.http.client.methods.HttpPut;
2626
import org.elasticsearch.client.core.PageParams;
2727
import org.elasticsearch.client.ml.CloseJobRequest;
28+
import org.elasticsearch.client.ml.DeleteTrainedModelRequest;
2829
import org.elasticsearch.client.ml.ExplainDataFrameAnalyticsRequest;
2930
import org.elasticsearch.client.ml.DeleteCalendarEventRequest;
3031
import org.elasticsearch.client.ml.DeleteCalendarJobRequest;
@@ -836,6 +837,14 @@ public void testGetTrainedModels() {
836837
assertNull(request.getEntity());
837838
}
838839

840+
public void testDeleteTrainedModel() {
841+
DeleteTrainedModelRequest deleteRequest = new DeleteTrainedModelRequest(randomAlphaOfLength(10));
842+
Request request = MLRequestConverters.deleteTrainedModel(deleteRequest);
843+
assertEquals(HttpDelete.METHOD_NAME, request.getMethod());
844+
assertEquals("/_ml/inference/" + deleteRequest.getId(), request.getEndpoint());
845+
assertNull(request.getEntity());
846+
}
847+
839848
public void testPutFilter() throws IOException {
840849
MlFilter filter = MlFilterTests.createRandomBuilder("foo").build();
841850
PutFilterRequest putFilterRequest = new PutFilterRequest(filter);

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.elasticsearch.client.indices.GetIndexRequest;
3333
import org.elasticsearch.client.ml.CloseJobRequest;
3434
import org.elasticsearch.client.ml.CloseJobResponse;
35+
import org.elasticsearch.client.ml.DeleteTrainedModelRequest;
3536
import org.elasticsearch.client.ml.ExplainDataFrameAnalyticsRequest;
3637
import org.elasticsearch.client.ml.ExplainDataFrameAnalyticsResponse;
3738
import org.elasticsearch.client.ml.DeleteCalendarEventRequest;
@@ -2122,6 +2123,33 @@ public void testGetTrainedModels() throws Exception {
21222123
}
21232124
}
21242125

2126+
public void testDeleteTrainedModel() throws Exception {
2127+
MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
2128+
String modelId = "delete-trained-model-test";
2129+
putTrainedModel(modelId);
2130+
2131+
GetTrainedModelsResponse getTrainedModelsResponse = execute(
2132+
new GetTrainedModelsRequest(modelId + "*").setIncludeDefinition(false).setAllowNoMatch(true),
2133+
machineLearningClient::getTrainedModels,
2134+
machineLearningClient::getTrainedModelsAsync);
2135+
2136+
assertThat(getTrainedModelsResponse.getCount(), equalTo(1L));
2137+
assertThat(getTrainedModelsResponse.getTrainedModels(), hasSize(1));
2138+
2139+
AcknowledgedResponse deleteTrainedModelResponse = execute(
2140+
new DeleteTrainedModelRequest(modelId),
2141+
machineLearningClient::deleteTrainedModel, machineLearningClient::deleteTrainedModelAsync);
2142+
assertTrue(deleteTrainedModelResponse.isAcknowledged());
2143+
2144+
getTrainedModelsResponse = execute(
2145+
new GetTrainedModelsRequest(modelId + "*").setIncludeDefinition(false).setAllowNoMatch(true),
2146+
machineLearningClient::getTrainedModels,
2147+
machineLearningClient::getTrainedModelsAsync);
2148+
2149+
assertThat(getTrainedModelsResponse.getCount(), equalTo(0L));
2150+
assertThat(getTrainedModelsResponse.getTrainedModels(), hasSize(0));
2151+
}
2152+
21252153
public void testPutFilter() throws Exception {
21262154
String filterId = "filter-job-test";
21272155
MlFilter mlFilter = MlFilter.builder(filterId)

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.elasticsearch.client.indices.CreateIndexRequest;
3737
import org.elasticsearch.client.ml.CloseJobRequest;
3838
import org.elasticsearch.client.ml.CloseJobResponse;
39+
import org.elasticsearch.client.ml.DeleteTrainedModelRequest;
3940
import org.elasticsearch.client.ml.ExplainDataFrameAnalyticsRequest;
4041
import org.elasticsearch.client.ml.ExplainDataFrameAnalyticsResponse;
4142
import org.elasticsearch.client.ml.DeleteCalendarEventRequest;
@@ -3592,6 +3593,53 @@ public void onFailure(Exception e) {
35923593
}
35933594
}
35943595

3596+
public void testDeleteTrainedModel() throws Exception {
3597+
RestHighLevelClient client = highLevelClient();
3598+
{
3599+
putTrainedModel("my-trained-model");
3600+
// tag::delete-trained-model-request
3601+
DeleteTrainedModelRequest request = new DeleteTrainedModelRequest("my-trained-model"); // <1>
3602+
// end::delete-trained-model-request
3603+
3604+
// tag::delete-trained-model-execute
3605+
AcknowledgedResponse response = client.machineLearning().deleteTrainedModel(request, RequestOptions.DEFAULT);
3606+
// end::delete-trained-model-execute
3607+
3608+
// tag::delete-trained-model-response
3609+
boolean deleted = response.isAcknowledged();
3610+
// end::delete-trained-model-response
3611+
3612+
assertThat(deleted, is(true));
3613+
}
3614+
{
3615+
putTrainedModel("my-trained-model");
3616+
DeleteTrainedModelRequest request = new DeleteTrainedModelRequest("my-trained-model");
3617+
3618+
// tag::delete-trained-model-execute-listener
3619+
ActionListener<AcknowledgedResponse> listener = new ActionListener<AcknowledgedResponse>() {
3620+
@Override
3621+
public void onResponse(AcknowledgedResponse response) {
3622+
// <1>
3623+
}
3624+
3625+
@Override
3626+
public void onFailure(Exception e) {
3627+
// <2>
3628+
}
3629+
};
3630+
// end::delete-trained-model-execute-listener
3631+
3632+
// Replace the empty listener by a blocking listener in test
3633+
CountDownLatch latch = new CountDownLatch(1);
3634+
listener = new LatchedActionListener<>(listener, latch);
3635+
3636+
// tag::delete-trained-model-execute-async
3637+
client.machineLearning().deleteTrainedModelAsync(request, RequestOptions.DEFAULT, listener); // <1>
3638+
// end::delete-trained-model-execute-async
3639+
3640+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
3641+
}
3642+
}
35953643

35963644
public void testCreateFilter() throws Exception {
35973645
RestHighLevelClient client = highLevelClient();
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.ml;
21+
22+
import org.elasticsearch.test.ESTestCase;
23+
24+
import java.util.Optional;
25+
26+
import static org.hamcrest.Matchers.containsString;
27+
28+
public class DeleteTrainedModelRequestTests extends ESTestCase {
29+
30+
public void testValidate_Ok() {
31+
assertEquals(Optional.empty(), new DeleteTrainedModelRequest("valid-id").validate());
32+
assertEquals(Optional.empty(), new DeleteTrainedModelRequest("").validate());
33+
}
34+
35+
public void testValidate_Failure() {
36+
assertThat(new DeleteTrainedModelRequest(null).validate().get().getMessage(),
37+
containsString("trained model id must not be null"));
38+
}
39+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--
2+
:api: delete-trained-model
3+
:request: DeleteTrainedModelRequest
4+
:response: AcknowledgedResponse
5+
--
6+
[role="xpack"]
7+
[id="{upid}-{api}"]
8+
=== Delete Trained Model API
9+
10+
experimental[]
11+
12+
Deletes a previously saved Trained Model.
13+
The API accepts a +{request}+ object and returns a +{response}+.
14+
15+
[id="{upid}-{api}-request"]
16+
==== Delete Trained Model request
17+
18+
A +{request}+ requires a valid Trained Model ID.
19+
20+
["source","java",subs="attributes,callouts,macros"]
21+
--------------------------------------------------
22+
include-tagged::{doc-tests-file}[{api}-request]
23+
--------------------------------------------------
24+
<1> Constructing a new DELETE request referencing an existing Trained Model
25+
26+
include::../execution.asciidoc[]
27+
28+
[id="{upid}-{api}-response"]
29+
==== Response
30+
31+
The returned +{response}+ object acknowledges the Trained Model deletion.
32+
33+
["source","java",subs="attributes,callouts,macros"]
34+
--------------------------------------------------
35+
include-tagged::{doc-tests-file}[{api}-response]
36+
--------------------------------------------------

docs/java-rest/high-level/supported-apis.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ The Java High Level REST Client supports the following Machine Learning APIs:
302302
* <<{upid}-evaluate-data-frame>>
303303
* <<{upid}-explain-data-frame-analytics>>
304304
* <<{upid}-get-trained-models>>
305+
* <<{upid}-delete-trained-model>>
305306
* <<{upid}-put-filter>>
306307
* <<{upid}-get-filters>>
307308
* <<{upid}-update-filter>>
@@ -355,6 +356,7 @@ include::ml/stop-data-frame-analytics.asciidoc[]
355356
include::ml/evaluate-data-frame.asciidoc[]
356357
include::ml/explain-data-frame-analytics.asciidoc[]
357358
include::ml/get-trained-models.asciidoc[]
359+
include::ml/delete-trained-model.asciidoc[]
358360
include::ml/put-filter.asciidoc[]
359361
include::ml/get-filters.asciidoc[]
360362
include::ml/update-filter.asciidoc[]

0 commit comments

Comments
 (0)