Skip to content

Commit 61eefc8

Browse files
authored
Add Create Snapshot to High-Level Rest Client (#31215)
Added support to the high-level rest client for the create snapshot API call. This required several changes to toXContent which may need to be cleaned up in a later PR. Also added several parsers for fromXContent to be able to retrieve appropriate responses along with tests.
1 parent 01623f6 commit 61eefc8

File tree

15 files changed

+877
-34
lines changed

15 files changed

+877
-34
lines changed

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

+14
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.create.CreateSnapshotRequest;
4041
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
4142
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
4243
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
@@ -880,6 +881,19 @@ static Request verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest)
880881
return request;
881882
}
882883

884+
static Request createSnapshot(CreateSnapshotRequest createSnapshotRequest) throws IOException {
885+
String endpoint = new EndpointBuilder().addPathPart("_snapshot")
886+
.addPathPart(createSnapshotRequest.repository())
887+
.addPathPart(createSnapshotRequest.snapshot())
888+
.build();
889+
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
890+
Params params = new Params(request);
891+
params.withMasterTimeout(createSnapshotRequest.masterNodeTimeout());
892+
params.withWaitForCompletion(createSnapshotRequest.waitForCompletion());
893+
request.setEntity(createEntity(createSnapshotRequest, REQUEST_BODY_CONTENT_TYPE));
894+
return request;
895+
}
896+
883897
static Request deleteSnapshot(DeleteSnapshotRequest deleteSnapshotRequest) {
884898
String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot")
885899
.addPathPart(deleteSnapshotRequest.repository())

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

+26
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.create.CreateSnapshotRequest;
32+
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
3133
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
3234
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
3335

@@ -164,6 +166,30 @@ public void verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryReques
164166
VerifyRepositoryResponse::fromXContent, listener, emptySet());
165167
}
166168

169+
/**
170+
* Creates a snapshot.
171+
* <p>
172+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
173+
* API on elastic.co</a>
174+
*/
175+
public CreateSnapshotResponse createSnapshot(CreateSnapshotRequest createSnapshotRequest, RequestOptions options)
176+
throws IOException {
177+
return restHighLevelClient.performRequestAndParseEntity(createSnapshotRequest, RequestConverters::createSnapshot, options,
178+
CreateSnapshotResponse::fromXContent, emptySet());
179+
}
180+
181+
/**
182+
* Asynchronously creates a snapshot.
183+
* <p>
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+
public void createSnapshotAsync(CreateSnapshotRequest createSnapshotRequest, RequestOptions options,
188+
ActionListener<CreateSnapshotResponse> listener) {
189+
restHighLevelClient.performRequestAsyncAndParseEntity(createSnapshotRequest, RequestConverters::createSnapshot, options,
190+
CreateSnapshotResponse::fromXContent, listener, emptySet());
191+
}
192+
167193
/**
168194
* Deletes a snapshot.
169195
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore

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

+23
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.create.CreateSnapshotRequest;
4041
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
4142
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
4243
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
@@ -1988,6 +1989,28 @@ public void testVerifyRepository() {
19881989
assertThat(expectedParams, equalTo(request.getParameters()));
19891990
}
19901991

1992+
public void testCreateSnapshot() throws IOException {
1993+
Map<String, String> expectedParams = new HashMap<>();
1994+
String repository = randomIndicesNames(1, 1)[0];
1995+
String snapshot = "snapshot-" + generateRandomStringArray(1, randomInt(10), false, false)[0];
1996+
String endpoint = "/_snapshot/" + repository + "/" + snapshot;
1997+
1998+
CreateSnapshotRequest createSnapshotRequest = new CreateSnapshotRequest(repository, snapshot);
1999+
setRandomMasterTimeout(createSnapshotRequest, expectedParams);
2000+
Boolean waitForCompletion = randomBoolean();
2001+
createSnapshotRequest.waitForCompletion(waitForCompletion);
2002+
2003+
if (waitForCompletion) {
2004+
expectedParams.put("wait_for_completion", waitForCompletion.toString());
2005+
}
2006+
2007+
Request request = RequestConverters.createSnapshot(createSnapshotRequest);
2008+
assertThat(endpoint, equalTo(request.getEndpoint()));
2009+
assertThat(HttpPut.METHOD_NAME, equalTo(request.getMethod()));
2010+
assertThat(expectedParams, equalTo(request.getParameters()));
2011+
assertToXContentBody(createSnapshotRequest, request.getEntity());
2012+
}
2013+
19912014
public void testDeleteSnapshot() {
19922015
Map<String, String> expectedParams = new HashMap<>();
19932016
String repository = randomIndicesNames(1, 1)[0];

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

+26-8
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@
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.create.CreateSnapshotRequest;
32+
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
3133
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
3234
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
3335
import org.elasticsearch.common.xcontent.XContentType;
3436
import org.elasticsearch.repositories.fs.FsRepository;
3537
import org.elasticsearch.rest.RestStatus;
3638

3739
import java.io.IOException;
38-
import java.util.Locale;
3940

4041
import static org.hamcrest.Matchers.equalTo;
4142

@@ -49,12 +50,12 @@ private PutRepositoryResponse createTestRepository(String repository, String typ
4950
highLevelClient().snapshot()::createRepositoryAsync);
5051
}
5152

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-
}
53+
private CreateSnapshotResponse createTestSnapshot(CreateSnapshotRequest createSnapshotRequest) throws IOException {
54+
// assumes the repository already exists
5755

56+
return execute(createSnapshotRequest, highLevelClient().snapshot()::createSnapshot,
57+
highLevelClient().snapshot()::createSnapshotAsync);
58+
}
5859

5960
public void testCreateRepository() throws IOException {
6061
PutRepositoryResponse response = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
@@ -119,16 +120,33 @@ public void testVerifyRepository() throws IOException {
119120
assertThat(response.getNodes().size(), equalTo(1));
120121
}
121122

123+
public void testCreateSnapshot() throws IOException {
124+
String repository = "test_repository";
125+
assertTrue(createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}").isAcknowledged());
126+
127+
String snapshot = "test_snapshot";
128+
CreateSnapshotRequest request = new CreateSnapshotRequest(repository, snapshot);
129+
boolean waitForCompletion = randomBoolean();
130+
request.waitForCompletion(waitForCompletion);
131+
request.partial(randomBoolean());
132+
request.includeGlobalState(randomBoolean());
133+
134+
CreateSnapshotResponse response = createTestSnapshot(request);
135+
assertEquals(waitForCompletion ? RestStatus.OK : RestStatus.ACCEPTED, response.status());
136+
}
137+
122138
public void testDeleteSnapshot() throws IOException {
123139
String repository = "test_repository";
124140
String snapshot = "test_snapshot";
125141

126142
PutRepositoryResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
127143
assertTrue(putRepositoryResponse.isAcknowledged());
128144

129-
Response putSnapshotResponse = createTestSnapshot(repository, snapshot);
145+
CreateSnapshotRequest createSnapshotRequest = new CreateSnapshotRequest(repository, snapshot);
146+
createSnapshotRequest.waitForCompletion(true);
147+
CreateSnapshotResponse createSnapshotResponse = createTestSnapshot(createSnapshotRequest);
130148
// 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());
149+
assertEquals(RestStatus.OK, createSnapshotResponse.status());
132150

133151
DeleteSnapshotRequest request = new DeleteSnapshotRequest(repository, snapshot);
134152
DeleteSnapshotResponse response = execute(request, highLevelClient().snapshot()::delete, highLevelClient().snapshot()::deleteAsync);

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

+89
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
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.create.CreateSnapshotRequest;
33+
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
34+
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
35+
import org.elasticsearch.action.support.IndicesOptions;
3236
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
3337
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
3438
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
@@ -41,6 +45,7 @@
4145
import org.elasticsearch.common.unit.TimeValue;
4246
import org.elasticsearch.common.xcontent.XContentType;
4347
import org.elasticsearch.repositories.fs.FsRepository;
48+
import org.elasticsearch.rest.RestStatus;
4449

4550
import java.io.IOException;
4651
import java.util.HashMap;
@@ -367,6 +372,90 @@ public void onFailure(Exception e) {
367372
}
368373
}
369374

375+
public void testSnapshotCreate() throws IOException {
376+
RestHighLevelClient client = highLevelClient();
377+
378+
CreateIndexRequest createIndexRequest = new CreateIndexRequest("test-index0");
379+
client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
380+
createIndexRequest = new CreateIndexRequest("test-index1");
381+
client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
382+
383+
createTestRepositories();
384+
385+
// tag::create-snapshot-request
386+
CreateSnapshotRequest request = new CreateSnapshotRequest();
387+
// end::create-snapshot-request
388+
389+
// tag::create-snapshot-request-repositoryName
390+
request.repository(repositoryName); // <1>
391+
// end::create-snapshot-request-repositoryName
392+
// tag::create-snapshot-request-snapshotName
393+
request.snapshot(snapshotName); // <1>
394+
// end::create-snapshot-request-snapshotName
395+
// tag::create-snapshot-request-indices
396+
request.indices("test-index0", "test-index1"); // <1>
397+
// end::create-snapshot-request-indices
398+
// tag::create-snapshot-request-indicesOptions
399+
request.indicesOptions(IndicesOptions.fromOptions(false, false, true, true)); // <1>
400+
// end::create-snapshot-request-indicesOptions
401+
// tag::create-snapshot-request-partial
402+
request.partial(false); // <1>
403+
// end::create-snapshot-request-partial
404+
// tag::create-snapshot-request-includeGlobalState
405+
request.includeGlobalState(true); // <1>
406+
// end::create-snapshot-request-includeGlobalState
407+
408+
// tag::create-snapshot-request-masterTimeout
409+
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
410+
request.masterNodeTimeout("1m"); // <2>
411+
// end::create-snapshot-request-masterTimeout
412+
// tag::create-snapshot-request-waitForCompletion
413+
request.waitForCompletion(true); // <1>
414+
// end::create-snapshot-request-waitForCompletion
415+
416+
// tag::create-snapshot-execute
417+
CreateSnapshotResponse response = client.snapshot().createSnapshot(request, RequestOptions.DEFAULT);
418+
// end::create-snapshot-execute
419+
420+
// tag::create-snapshot-response
421+
RestStatus status = response.status(); // <1>
422+
// end::create-snapshot-response
423+
424+
assertEquals(RestStatus.OK, status);
425+
}
426+
427+
public void testSnapshotCreateAsync() throws InterruptedException {
428+
RestHighLevelClient client = highLevelClient();
429+
{
430+
CreateSnapshotRequest request = new CreateSnapshotRequest(repositoryName, snapshotName);
431+
432+
// tag::create-snapshot-execute-listener
433+
ActionListener<CreateSnapshotResponse> listener =
434+
new ActionListener<CreateSnapshotResponse>() {
435+
@Override
436+
public void onResponse(CreateSnapshotResponse createSnapshotResponse) {
437+
// <1>
438+
}
439+
440+
@Override
441+
public void onFailure(Exception exception) {
442+
// <2>
443+
}
444+
};
445+
// end::create-snapshot-execute-listener
446+
447+
// Replace the empty listener by a blocking listener in test
448+
final CountDownLatch latch = new CountDownLatch(1);
449+
listener = new LatchedActionListener<>(listener, latch);
450+
451+
// tag::create-snapshot-execute-async
452+
client.snapshot().createSnapshotAsync(request, RequestOptions.DEFAULT, listener); // <1>
453+
// end::create-snapshot-execute-async
454+
455+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
456+
}
457+
}
458+
370459
public void testSnapshotDeleteSnapshot() throws IOException {
371460
RestHighLevelClient client = highLevelClient();
372461

0 commit comments

Comments
 (0)