diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
index 9d4582494eb..cd67bc8e483 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
@@ -39,6 +39,7 @@ import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyReposito
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
@@ -844,6 +845,18 @@ final class RequestConverters {
return request;
}
+ static Request deleteSnapshot(DeleteSnapshotRequest deleteSnapshotRequest) {
+ String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot")
+ .addPathPart(deleteSnapshotRequest.repository())
+ .addPathPart(deleteSnapshotRequest.snapshot())
+ .build();
+ Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
+
+ Params parameters = new Params(request);
+ parameters.withMasterTimeout(deleteSnapshotRequest.masterNodeTimeout());
+ return request;
+ }
+
static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) throws IOException {
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addPathPart(putIndexTemplateRequest.name()).build();
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
index b7cd2d52732..36b4f473ce8 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
@@ -28,6 +28,8 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequ
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
import java.io.IOException;
@@ -161,4 +163,34 @@ public final class SnapshotClient {
restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository, options,
VerifyRepositoryResponse::fromXContent, listener, emptySet());
}
+
+ /**
+ * Deletes a snapshot.
+ * See Snapshot and Restore
+ * API on elastic.co
+ *
+ * @param deleteSnapshotRequest the request
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return the response
+ * @throws IOException in case there is a problem sending the request or parsing back the response
+ */
+ public DeleteSnapshotResponse delete(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
+ DeleteSnapshotResponse::fromXContent, emptySet());
+ }
+
+ /**
+ * Asynchronously deletes a snapshot.
+ * See Snapshot and Restore
+ * API on elastic.co
+ *
+ * @param deleteSnapshotRequest the request
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener the listener to be notified upon request completion
+ */
+ public void deleteAsync(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
+ DeleteSnapshotResponse::fromXContent, listener, emptySet());
+ }
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java
index e7d56a4332b..eee37cea561 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java
@@ -37,6 +37,7 @@ import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRe
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
import org.elasticsearch.action.admin.indices.alias.Alias;
@@ -1857,6 +1858,25 @@ public class RequestConvertersTests extends ESTestCase {
assertThat(expectedParams, equalTo(request.getParameters()));
}
+ public void testDeleteSnapshot() {
+ Map expectedParams = new HashMap<>();
+ String repository = randomIndicesNames(1, 1)[0];
+ String snapshot = "snapshot-" + randomAlphaOfLengthBetween(2, 5).toLowerCase(Locale.ROOT);
+
+ String endpoint = String.format(Locale.ROOT, "/_snapshot/%s/%s", repository, snapshot);
+
+ DeleteSnapshotRequest deleteSnapshotRequest = new DeleteSnapshotRequest();
+ deleteSnapshotRequest.repository(repository);
+ deleteSnapshotRequest.snapshot(snapshot);
+ setRandomMasterTimeout(deleteSnapshotRequest, expectedParams);
+
+ Request request = RequestConverters.deleteSnapshot(deleteSnapshotRequest);
+ assertThat(endpoint, equalTo(request.getEndpoint()));
+ assertThat(HttpDelete.METHOD_NAME, equalTo(request.getMethod()));
+ assertThat(expectedParams, equalTo(request.getParameters()));
+ assertNull(request.getEntity());
+ }
+
public void testPutTemplateRequest() throws Exception {
Map names = new HashMap<>();
names.put("log", "log");
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java
index 3b27c2631f4..f4d325e158b 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java
@@ -28,11 +28,14 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequ
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.rest.RestStatus;
import java.io.IOException;
+import java.util.Locale;
import static org.hamcrest.Matchers.equalTo;
@@ -46,6 +49,13 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
highLevelClient().snapshot()::createRepositoryAsync);
}
+ private Response createTestSnapshot(String repository, String snapshot) throws IOException {
+ Request createSnapshot = new Request("put", String.format(Locale.ROOT, "_snapshot/%s/%s", repository, snapshot));
+ createSnapshot.addParameter("wait_for_completion", "true");
+ return highLevelClient().getLowLevelClient().performRequest(createSnapshot);
+ }
+
+
public void testCreateRepository() throws IOException {
PutRepositoryResponse response = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
assertTrue(response.isAcknowledged());
@@ -108,4 +118,21 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
highLevelClient().snapshot()::verifyRepositoryAsync);
assertThat(response.getNodes().size(), equalTo(1));
}
+
+ public void testDeleteSnapshot() throws IOException {
+ String repository = "test_repository";
+ String snapshot = "test_snapshot";
+
+ PutRepositoryResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
+ assertTrue(putRepositoryResponse.isAcknowledged());
+
+ Response putSnapshotResponse = createTestSnapshot(repository, snapshot);
+ // check that the request went ok without parsing JSON here. When using the high level client, check acknowledgement instead.
+ assertEquals(200, putSnapshotResponse.getStatusLine().getStatusCode());
+
+ DeleteSnapshotRequest request = new DeleteSnapshotRequest(repository, snapshot);
+ DeleteSnapshotResponse response = execute(request, highLevelClient().snapshot()::delete, highLevelClient().snapshot()::deleteAsync);
+
+ assertTrue(response.isAcknowledged());
+ }
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
index 8c158a91a51..965f9641e48 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
@@ -29,8 +29,12 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequ
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
+import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.common.settings.Settings;
@@ -41,6 +45,7 @@ import org.elasticsearch.repositories.fs.FsRepository;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -69,6 +74,8 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
private static final String repositoryName = "test_repository";
+ private static final String snapshotName = "test_snapshot";
+
public void testSnapshotCreateRepository() throws IOException {
RestHighLevelClient client = highLevelClient();
@@ -360,10 +367,76 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
}
}
+ public void testSnapshotDeleteSnapshot() throws IOException {
+ RestHighLevelClient client = highLevelClient();
+
+ createTestRepositories();
+ createTestSnapshots();
+
+ // tag::delete-snapshot-request
+ DeleteSnapshotRequest request = new DeleteSnapshotRequest(repositoryName);
+ request.snapshot(snapshotName);
+ // end::delete-snapshot-request
+
+ // tag::delete-snapshot-request-masterTimeout
+ request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
+ request.masterNodeTimeout("1m"); // <2>
+ // end::delete-snapshot-request-masterTimeout
+
+ // tag::delete-snapshot-execute
+ DeleteSnapshotResponse response = client.snapshot().delete(request, RequestOptions.DEFAULT);
+ // end::delete-snapshot-execute
+
+ // tag::delete-snapshot-response
+ boolean acknowledged = response.isAcknowledged(); // <1>
+ // end::delete-snapshot-response
+ assertTrue(acknowledged);
+ }
+
+ public void testSnapshotDeleteSnapshotAsync() throws InterruptedException {
+ RestHighLevelClient client = highLevelClient();
+ {
+ DeleteSnapshotRequest request = new DeleteSnapshotRequest();
+
+ // tag::delete-snapshot-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(DeleteSnapshotResponse deleteSnapshotResponse) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::delete-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::delete-snapshot-execute-async
+ client.snapshot().deleteAsync(request, RequestOptions.DEFAULT, listener); // <1>
+ // end::delete-snapshot-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+ }
+
private void createTestRepositories() throws IOException {
PutRepositoryRequest request = new PutRepositoryRequest(repositoryName);
request.type(FsRepository.TYPE);
request.settings("{\"location\": \".\"}", XContentType.JSON);
assertTrue(highLevelClient().snapshot().createRepository(request, RequestOptions.DEFAULT).isAcknowledged());
}
+
+ private void createTestSnapshots() throws IOException {
+ Request createSnapshot = new Request("put", String.format(Locale.ROOT, "_snapshot/%s/%s", repositoryName, snapshotName));
+ createSnapshot.addParameter("wait_for_completion", "true");
+ Response response = highLevelClient().getLowLevelClient().performRequest(createSnapshot);
+ // check that the request went ok without parsing JSON here. When using the high level client, check acknowledgement instead.
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ }
}
diff --git a/docs/java-rest/high-level/snapshot/delete_snapshot.asciidoc b/docs/java-rest/high-level/snapshot/delete_snapshot.asciidoc
new file mode 100644
index 00000000000..a594db5b602
--- /dev/null
+++ b/docs/java-rest/high-level/snapshot/delete_snapshot.asciidoc
@@ -0,0 +1,73 @@
+[[java-rest-high-snapshot-delete-snapshot]]
+=== Delete Snapshot API
+
+The Delete Snapshot API allows to delete a snapshot.
+
+[[java-rest-high-snapshot-delete-snapshot-request]]
+==== Delete Snapshot Request
+
+A `DeleteSnapshotRequest`:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-request]
+--------------------------------------------------
+
+==== Optional Arguments
+The following arguments can optionally be provided:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-request-masterTimeout]
+--------------------------------------------------
+<1> Timeout to connect to the master node as a `TimeValue`
+<2> Timeout to connect to the master node as a `String`
+
+[[java-rest-high-snapshot-delete-snapshot-sync]]
+==== Synchronous Execution
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-execute]
+--------------------------------------------------
+
+[[java-rest-high-snapshot-delete-snapshot-async]]
+==== Asynchronous Execution
+
+The asynchronous execution of a delete snapshot request requires both the
+`DeleteSnapshotRequest` instance and an `ActionListener` instance to be
+passed to the asynchronous method:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-execute-async]
+--------------------------------------------------
+<1> The `DeleteSnapshotRequest` to execute and the `ActionListener`
+to use when the execution completes
+
+The asynchronous method does not block and returns immediately. Once it is
+completed the `ActionListener` is called back using the `onResponse` method
+if the execution successfully completed or using the `onFailure` method if
+it failed.
+
+A typical listener for `DeleteSnapshotResponse` looks like:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-execute-listener]
+--------------------------------------------------
+<1> Called when the execution is successfully completed. The response is
+provided as an argument
+<2> Called in case of a failure. The raised exception is provided as an argument
+
+[[java-rest-high-cluster-delete-snapshot-response]]
+==== Delete Snapshot Response
+
+The returned `DeleteSnapshotResponse` allows to retrieve information about the
+executed operation as follows:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-response]
+--------------------------------------------------
+<1> Indicates the node has acknowledged the request
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index 17acc8f13c0..727088aa573 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -136,11 +136,13 @@ The Java High Level REST Client supports the following Snapshot APIs:
* <>
* <>
* <>
+* <>
include::snapshot/get_repository.asciidoc[]
include::snapshot/create_repository.asciidoc[]
include::snapshot/delete_repository.asciidoc[]
include::snapshot/verify_repository.asciidoc[]
+include::snapshot/delete_snapshot.asciidoc[]
== Tasks APIs
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponse.java
index d8de78c3e5b..ac6e74d3970 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponse.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponse.java
@@ -20,6 +20,7 @@
package org.elasticsearch.action.admin.cluster.snapshots.delete;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
+import org.elasticsearch.common.xcontent.XContentParser;
/**
* Delete snapshot response
@@ -32,4 +33,9 @@ public class DeleteSnapshotResponse extends AcknowledgedResponse {
DeleteSnapshotResponse(boolean acknowledged) {
super(acknowledged);
}
+
+ public static DeleteSnapshotResponse fromXContent(XContentParser parser) {
+ return new DeleteSnapshotResponse(parseAcknowledged(parser));
+ }
+
}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponseTests.java
new file mode 100644
index 00000000000..d77dadfb81e
--- /dev/null
+++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponseTests.java
@@ -0,0 +1,41 @@
+/*
+ * 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.action.admin.cluster.snapshots.delete;
+
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.AbstractStreamableXContentTestCase;
+
+public class DeleteSnapshotResponseTests extends AbstractStreamableXContentTestCase {
+
+ @Override
+ protected DeleteSnapshotResponse doParseInstance(XContentParser parser) {
+ return DeleteSnapshotResponse.fromXContent(parser);
+ }
+
+ @Override
+ protected DeleteSnapshotResponse createBlankInstance() {
+ return new DeleteSnapshotResponse();
+ }
+
+ @Override
+ protected DeleteSnapshotResponse createTestInstance() {
+ return new DeleteSnapshotResponse(randomBoolean());
+ }
+}