Skip to content

Commit 90d62e6

Browse files
Add Delete Snapshot High Level REST API
With this commit we add the delete snapshot API to the Java high level REST client. Relates #27205 Relates #31393
1 parent db1b97f commit 90d62e6

File tree

9 files changed

+287
-0
lines changed

9 files changed

+287
-0
lines changed

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

+13
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
4040
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
4141
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
42+
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
4243
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
4344
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
4445
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
@@ -844,6 +845,18 @@ static Request verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest)
844845
return request;
845846
}
846847

848+
static Request deleteSnapshot(DeleteSnapshotRequest deleteSnapshotRequest) {
849+
String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot")
850+
.addPathPart(deleteSnapshotRequest.repository())
851+
.addPathPart(deleteSnapshotRequest.snapshot())
852+
.build();
853+
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
854+
855+
Params parameters = new Params(request);
856+
parameters.withMasterTimeout(deleteSnapshotRequest.masterNodeTimeout());
857+
return request;
858+
}
859+
847860
static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) throws IOException {
848861
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addPathPart(putIndexTemplateRequest.name()).build();
849862
Request request = new Request(HttpPut.METHOD_NAME, endpoint);

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

+32
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
2929
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
3030
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
31+
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
32+
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
3133

3234
import java.io.IOException;
3335

@@ -161,4 +163,34 @@ public void verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryReques
161163
restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository, options,
162164
VerifyRepositoryResponse::fromXContent, listener, emptySet());
163165
}
166+
167+
/**
168+
* Deletes a snapshot.
169+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
170+
* API on elastic.co</a>
171+
*
172+
* @param deleteSnapshotRequest the request
173+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
174+
* @return the response
175+
* @throws IOException in case there is a problem sending the request or parsing back the response
176+
*/
177+
public DeleteSnapshotResponse delete(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options) throws IOException {
178+
return restHighLevelClient.performRequestAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
179+
DeleteSnapshotResponse::fromXContent, emptySet());
180+
}
181+
182+
/**
183+
* Asynchronously deletes a snapshot.
184+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
185+
* API on elastic.co</a>
186+
*
187+
* @param deleteSnapshotRequest the request
188+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
189+
* @param listener the listener to be notified upon request completion
190+
*/
191+
public void deleteAsync(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options,
192+
ActionListener<DeleteSnapshotResponse> listener) {
193+
restHighLevelClient.performRequestAsyncAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
194+
DeleteSnapshotResponse::fromXContent, listener, emptySet());
195+
}
164196
}

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

+20
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
3838
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
3939
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
40+
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
4041
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
4142
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
4243
import org.elasticsearch.action.admin.indices.alias.Alias;
@@ -1857,6 +1858,25 @@ public void testVerifyRepository() {
18571858
assertThat(expectedParams, equalTo(request.getParameters()));
18581859
}
18591860

1861+
public void testDeleteSnapshot() {
1862+
Map<String, String> expectedParams = new HashMap<>();
1863+
String repository = randomIndicesNames(1, 1)[0];
1864+
String snapshot = "snapshot-" + randomAlphaOfLengthBetween(2, 5).toLowerCase(Locale.ROOT);
1865+
1866+
String endpoint = String.format(Locale.ROOT, "/_snapshot/%s/%s", repository, snapshot);
1867+
1868+
DeleteSnapshotRequest deleteSnapshotRequest = new DeleteSnapshotRequest();
1869+
deleteSnapshotRequest.repository(repository);
1870+
deleteSnapshotRequest.snapshot(snapshot);
1871+
setRandomMasterTimeout(deleteSnapshotRequest, expectedParams);
1872+
1873+
Request request = RequestConverters.deleteSnapshot(deleteSnapshotRequest);
1874+
assertThat(endpoint, equalTo(request.getEndpoint()));
1875+
assertThat(HttpDelete.METHOD_NAME, equalTo(request.getMethod()));
1876+
assertThat(expectedParams, equalTo(request.getParameters()));
1877+
assertNull(request.getEntity());
1878+
}
1879+
18601880
public void testPutTemplateRequest() throws Exception {
18611881
Map<String, String> names = new HashMap<>();
18621882
names.put("log", "log");

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

+27
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@
2828
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
2929
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
3030
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
31+
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
32+
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
3133
import org.elasticsearch.common.xcontent.XContentType;
3234
import org.elasticsearch.repositories.fs.FsRepository;
3335
import org.elasticsearch.rest.RestStatus;
3436

3537
import java.io.IOException;
38+
import java.util.Locale;
3639

3740
import static org.hamcrest.Matchers.equalTo;
3841

@@ -46,6 +49,13 @@ private PutRepositoryResponse createTestRepository(String repository, String typ
4649
highLevelClient().snapshot()::createRepositoryAsync);
4750
}
4851

52+
private Response createTestSnapshot(String repository, String snapshot) throws IOException {
53+
Request createSnapshot = new Request("put", String.format(Locale.ROOT, "_snapshot/%s/%s", repository, snapshot));
54+
createSnapshot.addParameter("wait_for_completion", "true");
55+
return highLevelClient().getLowLevelClient().performRequest(createSnapshot);
56+
}
57+
58+
4959
public void testCreateRepository() throws IOException {
5060
PutRepositoryResponse response = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
5161
assertTrue(response.isAcknowledged());
@@ -108,4 +118,21 @@ public void testVerifyRepository() throws IOException {
108118
highLevelClient().snapshot()::verifyRepositoryAsync);
109119
assertThat(response.getNodes().size(), equalTo(1));
110120
}
121+
122+
public void testDeleteSnapshot() throws IOException {
123+
String repository = "test_repository";
124+
String snapshot = "test_snapshot";
125+
126+
PutRepositoryResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
127+
assertTrue(putRepositoryResponse.isAcknowledged());
128+
129+
Response putSnapshotResponse = createTestSnapshot(repository, snapshot);
130+
// check that the request went ok without parsing JSON here. When using the high level client, check acknowledgement instead.
131+
assertEquals(200, putSnapshotResponse.getStatusLine().getStatusCode());
132+
133+
DeleteSnapshotRequest request = new DeleteSnapshotRequest(repository, snapshot);
134+
DeleteSnapshotResponse response = execute(request, highLevelClient().snapshot()::delete, highLevelClient().snapshot()::deleteAsync);
135+
136+
assertTrue(response.isAcknowledged());
137+
}
111138
}

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

+73
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@
2929
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
3030
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
3131
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
32+
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
33+
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
3234
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
35+
import org.elasticsearch.client.Request;
3336
import org.elasticsearch.client.RequestOptions;
37+
import org.elasticsearch.client.Response;
3438
import org.elasticsearch.client.RestHighLevelClient;
3539
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
3640
import org.elasticsearch.common.settings.Settings;
@@ -41,6 +45,7 @@
4145
import java.io.IOException;
4246
import java.util.HashMap;
4347
import java.util.List;
48+
import java.util.Locale;
4449
import java.util.Map;
4550
import java.util.concurrent.CountDownLatch;
4651
import java.util.concurrent.TimeUnit;
@@ -69,6 +74,8 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
6974

7075
private static final String repositoryName = "test_repository";
7176

77+
private static final String snapshotName = "test_snapshot";
78+
7279
public void testSnapshotCreateRepository() throws IOException {
7380
RestHighLevelClient client = highLevelClient();
7481

@@ -360,10 +367,76 @@ public void onFailure(Exception e) {
360367
}
361368
}
362369

370+
public void testSnapshotDeleteSnapshot() throws IOException {
371+
RestHighLevelClient client = highLevelClient();
372+
373+
createTestRepositories();
374+
createTestSnapshots();
375+
376+
// tag::delete-snapshot-request
377+
DeleteSnapshotRequest request = new DeleteSnapshotRequest(repositoryName);
378+
request.snapshot(snapshotName);
379+
// end::delete-snapshot-request
380+
381+
// tag::delete-snapshot-request-masterTimeout
382+
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
383+
request.masterNodeTimeout("1m"); // <2>
384+
// end::delete-snapshot-request-masterTimeout
385+
386+
// tag::delete-snapshot-execute
387+
DeleteSnapshotResponse response = client.snapshot().delete(request, RequestOptions.DEFAULT);
388+
// end::delete-snapshot-execute
389+
390+
// tag::delete-snapshot-response
391+
boolean acknowledged = response.isAcknowledged(); // <1>
392+
// end::delete-snapshot-response
393+
assertTrue(acknowledged);
394+
}
395+
396+
public void testSnapshotDeleteSnapshotAsync() throws InterruptedException {
397+
RestHighLevelClient client = highLevelClient();
398+
{
399+
DeleteSnapshotRequest request = new DeleteSnapshotRequest();
400+
401+
// tag::delete-snapshot-execute-listener
402+
ActionListener<DeleteSnapshotResponse> listener =
403+
new ActionListener<DeleteSnapshotResponse>() {
404+
@Override
405+
public void onResponse(DeleteSnapshotResponse deleteSnapshotResponse) {
406+
// <1>
407+
}
408+
409+
@Override
410+
public void onFailure(Exception e) {
411+
// <2>
412+
}
413+
};
414+
// end::delete-snapshot-execute-listener
415+
416+
// Replace the empty listener by a blocking listener in test
417+
final CountDownLatch latch = new CountDownLatch(1);
418+
listener = new LatchedActionListener<>(listener, latch);
419+
420+
// tag::delete-snapshot-execute-async
421+
client.snapshot().deleteAsync(request, RequestOptions.DEFAULT, listener); // <1>
422+
// end::delete-snapshot-execute-async
423+
424+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
425+
}
426+
}
427+
363428
private void createTestRepositories() throws IOException {
364429
PutRepositoryRequest request = new PutRepositoryRequest(repositoryName);
365430
request.type(FsRepository.TYPE);
366431
request.settings("{\"location\": \".\"}", XContentType.JSON);
367432
assertTrue(highLevelClient().snapshot().createRepository(request, RequestOptions.DEFAULT).isAcknowledged());
368433
}
434+
435+
private void createTestSnapshots() throws IOException {
436+
Request createSnapshot = new Request("put", String.format(Locale.ROOT, "_snapshot/%s/%s", repositoryName, snapshotName));
437+
createSnapshot.addParameter("wait_for_completion", "true");
438+
Response response = highLevelClient().getLowLevelClient().performRequest(createSnapshot);
439+
// check that the request went ok without parsing JSON here. When using the high level client, check acknowledgement instead.
440+
assertEquals(200, response.getStatusLine().getStatusCode());
441+
}
369442
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
[[java-rest-high-snapshot-delete-snapshot]]
2+
=== Delete Snapshot API
3+
4+
The Delete Snapshot API allows to delete a snapshot.
5+
6+
[[java-rest-high-snapshot-delete-snapshot-request]]
7+
==== Delete Snapshot Request
8+
9+
A `DeleteSnapshotRequest`:
10+
11+
["source","java",subs="attributes,callouts,macros"]
12+
--------------------------------------------------
13+
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-request]
14+
--------------------------------------------------
15+
16+
==== Optional Arguments
17+
The following arguments can optionally be provided:
18+
19+
["source","java",subs="attributes,callouts,macros"]
20+
--------------------------------------------------
21+
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-request-masterTimeout]
22+
--------------------------------------------------
23+
<1> Timeout to connect to the master node as a `TimeValue`
24+
<2> Timeout to connect to the master node as a `String`
25+
26+
[[java-rest-high-snapshot-delete-snapshot-sync]]
27+
==== Synchronous Execution
28+
29+
["source","java",subs="attributes,callouts,macros"]
30+
--------------------------------------------------
31+
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-execute]
32+
--------------------------------------------------
33+
34+
[[java-rest-high-snapshot-delete-snapshot-async]]
35+
==== Asynchronous Execution
36+
37+
The asynchronous execution of a delete snapshot request requires both the
38+
`DeleteSnapshotRequest` instance and an `ActionListener` instance to be
39+
passed to the asynchronous method:
40+
41+
["source","java",subs="attributes,callouts,macros"]
42+
--------------------------------------------------
43+
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-execute-async]
44+
--------------------------------------------------
45+
<1> The `DeleteSnapshotRequest` to execute and the `ActionListener`
46+
to use when the execution completes
47+
48+
The asynchronous method does not block and returns immediately. Once it is
49+
completed the `ActionListener` is called back using the `onResponse` method
50+
if the execution successfully completed or using the `onFailure` method if
51+
it failed.
52+
53+
A typical listener for `DeleteSnapshotResponse` looks like:
54+
55+
["source","java",subs="attributes,callouts,macros"]
56+
--------------------------------------------------
57+
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-execute-listener]
58+
--------------------------------------------------
59+
<1> Called when the execution is successfully completed. The response is
60+
provided as an argument
61+
<2> Called in case of a failure. The raised exception is provided as an argument
62+
63+
[[java-rest-high-cluster-delete-snapshot-response]]
64+
==== Delete Snapshot Response
65+
66+
The returned `DeleteSnapshotResponse` allows to retrieve information about the
67+
executed operation as follows:
68+
69+
["source","java",subs="attributes,callouts,macros"]
70+
--------------------------------------------------
71+
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-response]
72+
--------------------------------------------------
73+
<1> Indicates the node has acknowledged the request

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

+2
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,13 @@ The Java High Level REST Client supports the following Snapshot APIs:
136136
* <<java-rest-high-snapshot-create-repository>>
137137
* <<java-rest-high-snapshot-delete-repository>>
138138
* <<java-rest-high-snapshot-verify-repository>>
139+
* <<java-rest-high-snapshot-delete-snapshot>>
139140

140141
include::snapshot/get_repository.asciidoc[]
141142
include::snapshot/create_repository.asciidoc[]
142143
include::snapshot/delete_repository.asciidoc[]
143144
include::snapshot/verify_repository.asciidoc[]
145+
include::snapshot/delete_snapshot.asciidoc[]
144146

145147
== Tasks APIs
146148

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponse.java

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.elasticsearch.action.admin.cluster.snapshots.delete;
2121

2222
import org.elasticsearch.action.support.master.AcknowledgedResponse;
23+
import org.elasticsearch.common.xcontent.XContentParser;
2324

2425
/**
2526
* Delete snapshot response
@@ -32,4 +33,9 @@ public class DeleteSnapshotResponse extends AcknowledgedResponse {
3233
DeleteSnapshotResponse(boolean acknowledged) {
3334
super(acknowledged);
3435
}
36+
37+
public static DeleteSnapshotResponse fromXContent(XContentParser parser) {
38+
return new DeleteSnapshotResponse(parseAcknowledged(parser));
39+
}
40+
3541
}

0 commit comments

Comments
 (0)