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 aa998591159f6..62c1740ab8250 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 @@ -61,6 +61,7 @@ import org.elasticsearch.client.ml.UpdateDatafeedRequest; import org.elasticsearch.client.ml.UpdateFilterRequest; import org.elasticsearch.client.ml.UpdateJobRequest; +import org.elasticsearch.client.ml.UpdateModelSnapshotRequest; import org.elasticsearch.client.ml.job.util.PageParams; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; @@ -391,6 +392,21 @@ static Request getModelSnapshots(GetModelSnapshotsRequest getModelSnapshotsReque return request; } + static Request updateModelSnapshot(UpdateModelSnapshotRequest updateModelSnapshotRequest) throws IOException { + String endpoint = new EndpointBuilder() + .addPathPartAsIs("_xpack") + .addPathPartAsIs("ml") + .addPathPartAsIs("anomaly_detectors") + .addPathPart(updateModelSnapshotRequest.getJobId()) + .addPathPartAsIs("model_snapshots") + .addPathPart(updateModelSnapshotRequest.getSnapshotId()) + .addPathPartAsIs("_update") + .build(); + Request request = new Request(HttpPost.METHOD_NAME, endpoint); + request.setEntity(createEntity(updateModelSnapshotRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; + } + static Request getOverallBuckets(GetOverallBucketsRequest getOverallBucketsRequest) throws IOException { 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 a35bbb042e7a2..c34385bc7599e 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 @@ -79,6 +79,8 @@ import org.elasticsearch.client.ml.UpdateDatafeedRequest; import org.elasticsearch.client.ml.UpdateFilterRequest; import org.elasticsearch.client.ml.UpdateJobRequest; +import org.elasticsearch.client.ml.UpdateModelSnapshotRequest; +import org.elasticsearch.client.ml.UpdateModelSnapshotResponse; import org.elasticsearch.client.ml.job.stats.JobStats; import java.io.IOException; @@ -984,6 +986,47 @@ public void getModelSnapshotsAsync(GetModelSnapshotsRequest request, RequestOpti Collections.emptySet()); } + /** + * Updates a snapshot for a Machine Learning Job. + *

+ * For additional info + * see + * ML UPDATE model snapshots documentation + * + * @param request The request + * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @throws IOException when there is a serialization issue sending the request or receiving the response + */ + public UpdateModelSnapshotResponse updateModelSnapshot(UpdateModelSnapshotRequest request, + RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(request, + MLRequestConverters::updateModelSnapshot, + options, + UpdateModelSnapshotResponse::fromXContent, + Collections.emptySet()); + } + + /** + * Updates a snapshot for a Machine Learning Job, notifies listener once the requested snapshots are retrieved. + *

+ * For additional info + * see + * ML UPDATE model snapshots 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 updateModelSnapshotAsync(UpdateModelSnapshotRequest request, RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(request, + MLRequestConverters::updateModelSnapshot, + options, + UpdateModelSnapshotResponse::fromXContent, + listener, + Collections.emptySet()); + } + /** * Gets overall buckets for a set of Machine Learning Jobs. *

diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateModelSnapshotRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateModelSnapshotRequest.java new file mode 100644 index 0000000000000..b2b6417ab2edb --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateModelSnapshotRequest.java @@ -0,0 +1,135 @@ +/* + * 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 org.elasticsearch.client.ml.job.config.Job; +import org.elasticsearch.client.ml.job.process.ModelSnapshot; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Objects; + +/** + * A request to update information about an existing model snapshot for a given job + */ +public class UpdateModelSnapshotRequest extends ActionRequest implements ToXContentObject { + + + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( + "update_model_snapshot_request", a -> new UpdateModelSnapshotRequest((String) a[0], (String) a[1])); + + + static { + PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID); + PARSER.declareString(ConstructingObjectParser.constructorArg(), ModelSnapshot.SNAPSHOT_ID); + PARSER.declareStringOrNull(UpdateModelSnapshotRequest::setDescription, ModelSnapshot.DESCRIPTION); + PARSER.declareBoolean(UpdateModelSnapshotRequest::setRetain, ModelSnapshot.RETAIN); + } + + private final String jobId; + private String snapshotId; + private String description; + private Boolean retain; + + /** + * Constructs a request to update information for a snapshot of given job + * @param jobId id of the job from which to retrieve results + * @param snapshotId id of the snapshot from which to retrieve results + */ + public UpdateModelSnapshotRequest(String jobId, String snapshotId) { + this.jobId = Objects.requireNonNull(jobId, "[" + Job.ID + "] must not be null"); + this.snapshotId = Objects.requireNonNull(snapshotId, "[" + ModelSnapshot.SNAPSHOT_ID + "] must not be null"); + } + + public String getJobId() { + return jobId; + } + + public String getSnapshotId() { + return snapshotId; + } + + public String getDescription() { + return description; + } + + /** + * The new description of the snapshot. + * @param description the updated snapshot description + */ + public void setDescription(String description) { + this.description = description; + } + + public Boolean getRetain() { + return retain; + } + + /** + * The new value of the "retain" property of the snapshot + * @param retain the updated retain property + */ + public void setRetain(boolean retain) { + this.retain = retain; + } + + @Override + public ActionRequestValidationException validate() { + return null; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(Job.ID.getPreferredName(), jobId); + builder.field(ModelSnapshot.SNAPSHOT_ID.getPreferredName(), snapshotId); + if (description != null) { + builder.field(ModelSnapshot.DESCRIPTION.getPreferredName(), description); + } + if (retain != null) { + builder.field(ModelSnapshot.RETAIN.getPreferredName(), retain); + } + builder.endObject(); + return builder; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + UpdateModelSnapshotRequest request = (UpdateModelSnapshotRequest) obj; + return Objects.equals(jobId, request.jobId) + && Objects.equals(snapshotId, request.snapshotId) + && Objects.equals(description, request.description) + && Objects.equals(retain, request.retain); + } + + @Override + public int hashCode() { + return Objects.hash(jobId, snapshotId, description, retain); + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateModelSnapshotResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateModelSnapshotResponse.java new file mode 100644 index 0000000000000..049a24c02d10a --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateModelSnapshotResponse.java @@ -0,0 +1,109 @@ +/* + * 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.ActionResponse; +import org.elasticsearch.client.ml.job.process.ModelSnapshot; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.Objects; + +/** + * A response acknowledging the update of information for an existing model snapshot for a given job + */ +public class UpdateModelSnapshotResponse extends ActionResponse implements ToXContentObject { + + private static final ParseField ACKNOWLEDGED = new ParseField("acknowledged"); + private static final ParseField MODEL = new ParseField("model"); + + public UpdateModelSnapshotResponse(boolean acknowledged, ModelSnapshot.Builder modelSnapshot) { + this.acknowledged = acknowledged; + this.model = modelSnapshot.build(); + } + + public static final ConstructingObjectParser PARSER = + new ConstructingObjectParser<>("update_model_snapshot_response", true, + a -> new UpdateModelSnapshotResponse((Boolean) a[0], ((ModelSnapshot.Builder) a[1]))); + + static { + PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), ACKNOWLEDGED); + PARSER.declareObject(ConstructingObjectParser.constructorArg(), ModelSnapshot.PARSER, MODEL); + } + + public static UpdateModelSnapshotResponse fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); + } + + private final Boolean acknowledged; + private final ModelSnapshot model; + + /** + * Get the action acknowledgement + * @return a {@code boolean} that indicates whether the model snapshot was updated successfully. + */ + public Boolean getAcknowledged() { + return acknowledged; + } + + /** + * Get the updated snapshot of the model + * @return the updated model snapshot. + */ + public ModelSnapshot getModel() { + return model; + } + + @Override + public int hashCode() { + return Objects.hash(acknowledged, model); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { + builder.startObject(); + if (acknowledged != null) { + builder.field(ACKNOWLEDGED.getPreferredName(), acknowledged); + } + if (model != null) { + builder.field(MODEL.getPreferredName(), model); + } + builder.endObject(); + return builder; + } + + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + UpdateModelSnapshotResponse request = (UpdateModelSnapshotResponse) obj; + return Objects.equals(acknowledged, request.acknowledged) + && Objects.equals(model, request.model); + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/process/ModelSnapshot.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/process/ModelSnapshot.java index 603bff0d90653..5d95e091d40b1 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/process/ModelSnapshot.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/process/ModelSnapshot.java @@ -176,6 +176,10 @@ public Quantiles getQuantiles() { return quantiles; } + public boolean getRetain() { + return retain; + } + public Date getLatestRecordTimeStamp() { return latestRecordTimeStamp; } 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 a38584b0d020e..b47ee4d4bbb12 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 @@ -57,6 +57,7 @@ import org.elasticsearch.client.ml.StopDatafeedRequest; import org.elasticsearch.client.ml.UpdateFilterRequest; import org.elasticsearch.client.ml.UpdateJobRequest; +import org.elasticsearch.client.ml.UpdateModelSnapshotRequest; import org.elasticsearch.client.ml.calendars.Calendar; import org.elasticsearch.client.ml.calendars.CalendarTests; import org.elasticsearch.client.ml.datafeed.DatafeedConfig; @@ -422,6 +423,22 @@ public void testGetModelSnapshots() throws IOException { } } + public void testUpdateModelSnapshot() throws IOException { + String jobId = randomAlphaOfLength(10); + String snapshotId = randomAlphaOfLength(10); + UpdateModelSnapshotRequest updateModelSnapshotRequest = new UpdateModelSnapshotRequest(jobId, snapshotId); + updateModelSnapshotRequest.setDescription("My First Snapshot"); + updateModelSnapshotRequest.setRetain(true); + + Request request = MLRequestConverters.updateModelSnapshot(updateModelSnapshotRequest); + assertEquals(HttpPost.METHOD_NAME, request.getMethod()); + assertEquals("/_xpack/ml/anomaly_detectors/" + jobId + "/model_snapshots/" + snapshotId + "/_update", request.getEndpoint()); + try (XContentParser parser = createParser(JsonXContent.jsonXContent, request.getEntity().getContent())) { + UpdateModelSnapshotRequest parsedRequest = UpdateModelSnapshotRequest.PARSER.apply(parser, null); + assertThat(parsedRequest, equalTo(updateModelSnapshotRequest)); + } + } + public void testGetOverallBuckets() throws IOException { String jobId = randomAlphaOfLength(10); GetOverallBucketsRequest getOverallBucketsRequest = new GetOverallBucketsRequest(jobId); 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 bffdc1aa1a07b..4b52c8d8d5419 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 @@ -52,6 +52,8 @@ import org.elasticsearch.client.ml.GetJobResponse; import org.elasticsearch.client.ml.GetJobStatsRequest; import org.elasticsearch.client.ml.GetJobStatsResponse; +import org.elasticsearch.client.ml.GetModelSnapshotsRequest; +import org.elasticsearch.client.ml.GetModelSnapshotsResponse; import org.elasticsearch.client.ml.OpenJobRequest; import org.elasticsearch.client.ml.OpenJobResponse; import org.elasticsearch.client.ml.PostDataRequest; @@ -74,6 +76,8 @@ import org.elasticsearch.client.ml.UpdateDatafeedRequest; import org.elasticsearch.client.ml.UpdateFilterRequest; import org.elasticsearch.client.ml.UpdateJobRequest; +import org.elasticsearch.client.ml.UpdateModelSnapshotRequest; +import org.elasticsearch.client.ml.UpdateModelSnapshotResponse; import org.elasticsearch.client.ml.calendars.Calendar; import org.elasticsearch.client.ml.calendars.CalendarTests; import org.elasticsearch.client.ml.datafeed.DatafeedConfig; @@ -1047,10 +1051,11 @@ private String createAndPutDatafeed(String jobId, String indexName) throws IOExc } public void createModelSnapshot(String jobId, String snapshotId) throws IOException { + String documentId = jobId + "_model_snapshot_" + snapshotId; Job job = MachineLearningIT.buildJob(jobId); highLevelClient().machineLearning().putJob(new PutJobRequest(job), RequestOptions.DEFAULT); - IndexRequest indexRequest = new IndexRequest(".ml-anomalies-shared", "doc"); + IndexRequest indexRequest = new IndexRequest(".ml-anomalies-shared", "doc", documentId); indexRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE); indexRequest.source("{\"job_id\":\"" + jobId + "\", \"timestamp\":1541587919000, " + "\"description\":\"State persisted due to job close at 2018-11-07T10:51:59+0000\", " + @@ -1079,4 +1084,40 @@ public void testDeleteModelSnapshot() throws IOException { assertTrue(response.isAcknowledged()); } + + public void testUpdateModelSnapshot() throws Exception { + String jobId = "test-update-model-snapshot"; + + String snapshotId = "1541587919"; + createModelSnapshot(jobId, snapshotId); + + MachineLearningClient machineLearningClient = highLevelClient().machineLearning(); + + GetModelSnapshotsRequest getModelSnapshotsRequest = new GetModelSnapshotsRequest(jobId); + + GetModelSnapshotsResponse getModelSnapshotsResponse1 = execute(getModelSnapshotsRequest, machineLearningClient::getModelSnapshots, + machineLearningClient::getModelSnapshotsAsync); + + assertEquals(getModelSnapshotsResponse1.count(), 1L); + assertEquals("State persisted due to job close at 2018-11-07T10:51:59+0000", + getModelSnapshotsResponse1.snapshots().get(0).getDescription()); + + UpdateModelSnapshotRequest request = new UpdateModelSnapshotRequest(jobId, snapshotId); + request.setDescription("Updated description"); + request.setRetain(true); + + UpdateModelSnapshotResponse response = execute(request, machineLearningClient::updateModelSnapshot, + machineLearningClient::updateModelSnapshotAsync); + + assertTrue(response.getAcknowledged()); + assertEquals("Updated description", response.getModel().getDescription()); + assertTrue(response.getModel().getRetain()); + + GetModelSnapshotsResponse getModelSnapshotsResponse2 = execute(getModelSnapshotsRequest, machineLearningClient::getModelSnapshots, + machineLearningClient::getModelSnapshotsAsync); + + assertEquals(getModelSnapshotsResponse2.count(), 1L); + assertEquals("Updated description", + getModelSnapshotsResponse2.snapshots().get(0).getDescription()); + } } 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 a2f29fae60a0d..38203a38d8144 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 @@ -92,6 +92,8 @@ import org.elasticsearch.client.ml.UpdateDatafeedRequest; import org.elasticsearch.client.ml.UpdateFilterRequest; import org.elasticsearch.client.ml.UpdateJobRequest; +import org.elasticsearch.client.ml.UpdateModelSnapshotRequest; +import org.elasticsearch.client.ml.UpdateModelSnapshotResponse; import org.elasticsearch.client.ml.calendars.Calendar; import org.elasticsearch.client.ml.datafeed.ChunkingConfig; import org.elasticsearch.client.ml.datafeed.DatafeedConfig; @@ -2042,6 +2044,82 @@ public void onFailure(Exception e) { } } + public void testUpdateModelSnapshot() throws IOException, InterruptedException { + RestHighLevelClient client = highLevelClient(); + + String jobId = "test-update-model-snapshot"; + String snapshotId = "1541587919"; + String documentId = jobId + "_model_snapshot_" + snapshotId; + Job job = MachineLearningIT.buildJob(jobId); + client.machineLearning().putJob(new PutJobRequest(job), RequestOptions.DEFAULT); + + // Let us index a snapshot + IndexRequest indexRequest = new IndexRequest(".ml-anomalies-shared", "doc", documentId); + indexRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE); + indexRequest.source("{\"job_id\":\"test-update-model-snapshot\", \"timestamp\":1541587919000, " + + "\"description\":\"State persisted due to job close at 2018-11-07T10:51:59+0000\", " + + "\"snapshot_id\":\"1541587919\", \"snapshot_doc_count\":1, \"model_size_stats\":{" + + "\"job_id\":\"test-update-model-snapshot\", \"result_type\":\"model_size_stats\",\"model_bytes\":51722, " + + "\"total_by_field_count\":3, \"total_over_field_count\":0, \"total_partition_field_count\":2," + + "\"bucket_allocation_failures_count\":0, \"memory_status\":\"ok\", \"log_time\":1541587919000, " + + "\"timestamp\":1519930800000}, \"latest_record_time_stamp\":1519931700000," + + "\"latest_result_time_stamp\":1519930800000, \"retain\":false}", XContentType.JSON); + client.index(indexRequest, RequestOptions.DEFAULT); + + { + // tag::update-model-snapshot-request + UpdateModelSnapshotRequest request = new UpdateModelSnapshotRequest(jobId, snapshotId); // <1> + // end::update-model-snapshot-request + + // tag::update-model-snapshot-description + request.setDescription("My Snapshot"); // <1> + // end::update-model-snapshot-description + + // tag::update-model-snapshot-retain + request.setRetain(true); // <1> + // end::update-model-snapshot-retain + + // tag::update-model-snapshot-execute + UpdateModelSnapshotResponse response = client.machineLearning().updateModelSnapshot(request, RequestOptions.DEFAULT); + // end::update-model-snapshot-execute + + // tag::update-model-snapshot-response + boolean acknowledged = response.getAcknowledged(); // <1> + ModelSnapshot modelSnapshot = response.getModel(); // <2> + // end::update-model-snapshot-response + + assertTrue(acknowledged); + assertEquals("My Snapshot", modelSnapshot.getDescription()); } + { + UpdateModelSnapshotRequest request = new UpdateModelSnapshotRequest(jobId, snapshotId); + + // tag::update-model-snapshot-execute-listener + ActionListener listener = + new ActionListener() { + @Override + public void onResponse(UpdateModelSnapshotResponse updateModelSnapshotResponse) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::update-model-snapshot-execute-listener + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::update-model-snapshot-execute-async + client.machineLearning().updateModelSnapshotAsync(request, RequestOptions.DEFAULT, listener); // <1> + // end::update-model-snapshot-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + } + } + public void testPutCalendar() throws IOException, InterruptedException { RestHighLevelClient client = highLevelClient(); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/UpdateModelSnapshotRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/UpdateModelSnapshotRequestTests.java new file mode 100644 index 0000000000000..659265fcfeac4 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/UpdateModelSnapshotRequestTests.java @@ -0,0 +1,53 @@ +/* + * 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.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; + + +public class UpdateModelSnapshotRequestTests extends AbstractXContentTestCase { + + @Override + protected UpdateModelSnapshotRequest createTestInstance() { + String jobId = randomAlphaOfLengthBetween(1, 20); + String snapshotId = randomAlphaOfLengthBetween(1, 20); + UpdateModelSnapshotRequest request = new UpdateModelSnapshotRequest(jobId, snapshotId); + if (randomBoolean()) { + request.setDescription(String.valueOf(randomNonNegativeLong())); + } + if (randomBoolean()) { + request.setRetain(randomBoolean()); + } + + return request; + } + + @Override + protected UpdateModelSnapshotRequest doParseInstance(XContentParser parser) throws IOException { + return UpdateModelSnapshotRequest.PARSER.apply(parser, null); + } + + @Override + protected boolean supportsUnknownFields() { + return false; + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/UpdateModelSnapshotResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/UpdateModelSnapshotResponseTests.java new file mode 100644 index 0000000000000..b03c07d880435 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/UpdateModelSnapshotResponseTests.java @@ -0,0 +1,47 @@ +/* + * 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.client.ml.job.process.ModelSnapshot; +import org.elasticsearch.client.ml.job.process.ModelSnapshotTests; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; + + +public class UpdateModelSnapshotResponseTests extends AbstractXContentTestCase { + + @Override + protected UpdateModelSnapshotResponse createTestInstance() { + Boolean acknowledged = randomBoolean(); + ModelSnapshot.Builder modelBuilder = ModelSnapshotTests.createRandomizedBuilder(); + return new UpdateModelSnapshotResponse(acknowledged, modelBuilder); + } + + @Override + protected UpdateModelSnapshotResponse doParseInstance(XContentParser parser) throws IOException { + return UpdateModelSnapshotResponse.fromXContent(parser); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } +} diff --git a/docs/java-rest/high-level/ml/update-model-snapshot.asciidoc b/docs/java-rest/high-level/ml/update-model-snapshot.asciidoc new file mode 100644 index 0000000000000..b38539b062224 --- /dev/null +++ b/docs/java-rest/high-level/ml/update-model-snapshot.asciidoc @@ -0,0 +1,53 @@ +-- +:api: update-model-snapshot +:request: UpdateModelSnapshotRequest +:response: UpdateModelSnapshotResponse +-- +[id="{upid}-{api}"] +=== Update Model Snapshot API + +The Update Model Snapshot API provides the ability to update a {ml} model snapshot. +It accepts a +{request}+ object and responds +with a +{response}+ object. + +[id="{upid}-{api}-request"] +==== Update Model Snapshot Request + +A +{request}+ requires the following arguments: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-request] +-------------------------------------------------- +<1> Constructing a new request referencing existing `jobId` and `snapshotId` values. + +==== Optional Arguments + +The following arguments are optional: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-description] +-------------------------------------------------- +<1> The updated description of the {ml} model snapshot + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-retain] +-------------------------------------------------- +<1> The updated `retain` property of the {ml} model snapshot + + +include::../execution.asciidoc[] + +[id="{upid}-{api}-response"] +==== Update Job Response + +A +{response}+ contains an acknowledgement of the update request and the full representation of the updated `ModelSnapshot` object + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-response] +-------------------------------------------------- +<1> An acknowledgement of the request +<2> The updated `ModelSnapshot` diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index cabd20d52ff07..76f05570174b6 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -274,6 +274,7 @@ The Java High Level REST Client supports the following Machine Learning APIs: * <<{upid}-update-filter>> * <<{upid}-delete-filter>> * <<{upid}-get-model-snapshots>> +* <<{upid}-update-model-snapshot>> include::ml/put-job.asciidoc[] include::ml/get-job.asciidoc[] @@ -309,6 +310,7 @@ include::ml/get-filters.asciidoc[] include::ml/delete-model-snapshot.asciidoc[] include::ml/update-filter.asciidoc[] include::ml/delete-filter.asciidoc[] +include::ml/update-model-snapshot.asciidoc[] == Migration APIs