Add Get Snapshots High Level REST API (#31537)
With this commit we add the get snapshots API to the Java high level REST client. Relates #27205
This commit is contained in:
parent
d0c276c456
commit
9ac81a1322
|
@ -38,6 +38,7 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequ
|
|||
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
|
||||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
|
||||
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;
|
||||
|
@ -894,6 +895,26 @@ final class RequestConverters {
|
|||
return request;
|
||||
}
|
||||
|
||||
static Request getSnapshots(GetSnapshotsRequest getSnapshotsRequest) {
|
||||
EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPartAsIs("_snapshot")
|
||||
.addPathPart(getSnapshotsRequest.repository());
|
||||
String endpoint;
|
||||
if (getSnapshotsRequest.snapshots().length == 0) {
|
||||
endpoint = endpointBuilder.addPathPart("_all").build();
|
||||
} else {
|
||||
endpoint = endpointBuilder.addCommaSeparatedPathParts(getSnapshotsRequest.snapshots()).build();
|
||||
}
|
||||
|
||||
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
|
||||
|
||||
Params parameters = new Params(request);
|
||||
parameters.withMasterTimeout(getSnapshotsRequest.masterNodeTimeout());
|
||||
parameters.putParam("ignore_unavailable", Boolean.toString(getSnapshotsRequest.ignoreUnavailable()));
|
||||
parameters.putParam("verbose", Boolean.toString(getSnapshotsRequest.verbose()));
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
static Request deleteSnapshot(DeleteSnapshotRequest deleteSnapshotRequest) {
|
||||
String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot")
|
||||
.addPathPart(deleteSnapshotRequest.repository())
|
||||
|
|
|
@ -32,6 +32,8 @@ import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotReq
|
|||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -190,6 +192,35 @@ public final class SnapshotClient {
|
|||
CreateSnapshotResponse::fromXContent, listener, emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get snapshots.
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
|
||||
* API on elastic.co</a>
|
||||
*
|
||||
* @param getSnapshotsRequest 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 GetSnapshotsResponse get(GetSnapshotsRequest getSnapshotsRequest, RequestOptions options) throws IOException {
|
||||
return restHighLevelClient.performRequestAndParseEntity(getSnapshotsRequest, RequestConverters::getSnapshots, options,
|
||||
GetSnapshotsResponse::fromXContent, emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously get snapshots.
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
|
||||
* API on elastic.co</a>
|
||||
*
|
||||
* @param getSnapshotsRequest 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 getAsync(GetSnapshotsRequest getSnapshotsRequest, RequestOptions options, ActionListener<GetSnapshotsResponse> listener) {
|
||||
restHighLevelClient.performRequestAsyncAndParseEntity(getSnapshotsRequest, RequestConverters::getSnapshots, options,
|
||||
GetSnapshotsResponse::fromXContent, listener, emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a snapshot.
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
|
||||
|
|
|
@ -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.snapshots.create.CreateSnapshotRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
|
||||
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
|
||||
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
|
@ -2011,6 +2012,58 @@ public class RequestConvertersTests extends ESTestCase {
|
|||
assertToXContentBody(createSnapshotRequest, request.getEntity());
|
||||
}
|
||||
|
||||
public void testGetSnapshots() {
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
String repository = randomIndicesNames(1, 1)[0];
|
||||
String snapshot1 = "snapshot1-" + randomAlphaOfLengthBetween(2, 5).toLowerCase(Locale.ROOT);
|
||||
String snapshot2 = "snapshot2-" + randomAlphaOfLengthBetween(2, 5).toLowerCase(Locale.ROOT);
|
||||
|
||||
String endpoint = String.format(Locale.ROOT, "/_snapshot/%s/%s,%s", repository, snapshot1, snapshot2);
|
||||
|
||||
GetSnapshotsRequest getSnapshotsRequest = new GetSnapshotsRequest();
|
||||
getSnapshotsRequest.repository(repository);
|
||||
getSnapshotsRequest.snapshots(Arrays.asList(snapshot1, snapshot2).toArray(new String[0]));
|
||||
setRandomMasterTimeout(getSnapshotsRequest, expectedParams);
|
||||
|
||||
boolean ignoreUnavailable = randomBoolean();
|
||||
getSnapshotsRequest.ignoreUnavailable(ignoreUnavailable);
|
||||
expectedParams.put("ignore_unavailable", Boolean.toString(ignoreUnavailable));
|
||||
|
||||
boolean verbose = randomBoolean();
|
||||
getSnapshotsRequest.verbose(verbose);
|
||||
expectedParams.put("verbose", Boolean.toString(verbose));
|
||||
|
||||
Request request = RequestConverters.getSnapshots(getSnapshotsRequest);
|
||||
assertThat(endpoint, equalTo(request.getEndpoint()));
|
||||
assertThat(HttpGet.METHOD_NAME, equalTo(request.getMethod()));
|
||||
assertThat(expectedParams, equalTo(request.getParameters()));
|
||||
assertNull(request.getEntity());
|
||||
}
|
||||
|
||||
public void testGetAllSnapshots() {
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
String repository = randomIndicesNames(1, 1)[0];
|
||||
|
||||
String endpoint = String.format(Locale.ROOT, "/_snapshot/%s/_all", repository);
|
||||
|
||||
GetSnapshotsRequest getSnapshotsRequest = new GetSnapshotsRequest(repository);
|
||||
setRandomMasterTimeout(getSnapshotsRequest, expectedParams);
|
||||
|
||||
boolean ignoreUnavailable = randomBoolean();
|
||||
getSnapshotsRequest.ignoreUnavailable(ignoreUnavailable);
|
||||
expectedParams.put("ignore_unavailable", Boolean.toString(ignoreUnavailable));
|
||||
|
||||
boolean verbose = randomBoolean();
|
||||
getSnapshotsRequest.verbose(verbose);
|
||||
expectedParams.put("verbose", Boolean.toString(verbose));
|
||||
|
||||
Request request = RequestConverters.getSnapshots(getSnapshotsRequest);
|
||||
assertThat(endpoint, equalTo(request.getEndpoint()));
|
||||
assertThat(HttpGet.METHOD_NAME, equalTo(request.getMethod()));
|
||||
assertThat(expectedParams, equalTo(request.getParameters()));
|
||||
assertNull(request.getEntity());
|
||||
}
|
||||
|
||||
public void testDeleteSnapshot() {
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
String repository = randomIndicesNames(1, 1)[0];
|
||||
|
|
|
@ -32,12 +32,16 @@ import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotReq
|
|||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.repositories.fs.FsRepository;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class SnapshotIT extends ESRestHighLevelClientTestCase {
|
||||
|
@ -135,6 +139,40 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
|
|||
assertEquals(waitForCompletion ? RestStatus.OK : RestStatus.ACCEPTED, response.status());
|
||||
}
|
||||
|
||||
public void testGetSnapshots() throws IOException {
|
||||
String repository = "test_repository";
|
||||
String snapshot1 = "test_snapshot1";
|
||||
String snapshot2 = "test_snapshot2";
|
||||
|
||||
PutRepositoryResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
|
||||
assertTrue(putRepositoryResponse.isAcknowledged());
|
||||
|
||||
CreateSnapshotRequest createSnapshotRequest1 = new CreateSnapshotRequest(repository, snapshot1);
|
||||
createSnapshotRequest1.waitForCompletion(true);
|
||||
CreateSnapshotResponse putSnapshotResponse1 = createTestSnapshot(createSnapshotRequest1);
|
||||
CreateSnapshotRequest createSnapshotRequest2 = new CreateSnapshotRequest(repository, snapshot2);
|
||||
createSnapshotRequest2.waitForCompletion(true);
|
||||
CreateSnapshotResponse putSnapshotResponse2 = createTestSnapshot(createSnapshotRequest2);
|
||||
// check that the request went ok without parsing JSON here. When using the high level client, check acknowledgement instead.
|
||||
assertEquals(RestStatus.OK, putSnapshotResponse1.status());
|
||||
assertEquals(RestStatus.OK, putSnapshotResponse2.status());
|
||||
|
||||
GetSnapshotsRequest request;
|
||||
if (randomBoolean()) {
|
||||
request = new GetSnapshotsRequest(repository);
|
||||
} else if (randomBoolean()) {
|
||||
request = new GetSnapshotsRequest(repository, new String[] {"_all"});
|
||||
|
||||
} else {
|
||||
request = new GetSnapshotsRequest(repository, new String[] {snapshot1, snapshot2});
|
||||
}
|
||||
GetSnapshotsResponse response = execute(request, highLevelClient().snapshot()::get, highLevelClient().snapshot()::getAsync);
|
||||
|
||||
assertEquals(2, response.getSnapshots().size());
|
||||
assertThat(response.getSnapshots().stream().map((s) -> s.snapshotId().getName()).collect(Collectors.toList()),
|
||||
contains("test_snapshot1", "test_snapshot2"));
|
||||
}
|
||||
|
||||
public void testDeleteSnapshot() throws IOException {
|
||||
String repository = "test_repository";
|
||||
String snapshot = "test_snapshot";
|
||||
|
|
|
@ -31,6 +31,8 @@ import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyReposito
|
|||
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
||||
|
@ -46,6 +48,7 @@ import org.elasticsearch.common.unit.TimeValue;
|
|||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.repositories.fs.FsRepository;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.snapshots.SnapshotInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
@ -456,6 +459,76 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
|
|||
}
|
||||
}
|
||||
|
||||
public void testSnapshotGetSnapshots() throws IOException {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
createTestRepositories();
|
||||
createTestSnapshots();
|
||||
|
||||
// tag::get-snapshots-request
|
||||
GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName);
|
||||
// end::get-snapshots-request
|
||||
|
||||
// tag::get-snapshots-request-snapshots
|
||||
String[] snapshots = { snapshotName };
|
||||
request.snapshots(snapshots); // <1>
|
||||
// end::get-snapshots-request-snapshots
|
||||
|
||||
// tag::get-snapshots-request-masterTimeout
|
||||
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
|
||||
request.masterNodeTimeout("1m"); // <2>
|
||||
// end::get-snapshots-request-masterTimeout
|
||||
|
||||
// tag::get-snapshots-request-verbose
|
||||
request.verbose(true); // <1>
|
||||
// end::get-snapshots-request-verbose
|
||||
|
||||
// tag::get-snapshots-request-ignore-unavailable
|
||||
request.ignoreUnavailable(false); // <1>
|
||||
// end::get-snapshots-request-ignore-unavailable
|
||||
|
||||
// tag::get-snapshots-execute
|
||||
GetSnapshotsResponse response = client.snapshot().get(request, RequestOptions.DEFAULT);
|
||||
// end::get-snapshots-execute
|
||||
|
||||
// tag::get-snapshots-response
|
||||
List<SnapshotInfo> snapshotsInfos = response.getSnapshots(); // <1>
|
||||
// end::get-snapshots-response
|
||||
assertEquals(1, snapshotsInfos.size());
|
||||
}
|
||||
|
||||
public void testSnapshotGetSnapshotsAsync() throws InterruptedException {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
{
|
||||
GetSnapshotsRequest request = new GetSnapshotsRequest();
|
||||
|
||||
// tag::get-snapshots-execute-listener
|
||||
ActionListener<GetSnapshotsResponse> listener =
|
||||
new ActionListener<GetSnapshotsResponse>() {
|
||||
@Override
|
||||
public void onResponse(GetSnapshotsResponse deleteSnapshotResponse) {
|
||||
// <1>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
// <2>
|
||||
}
|
||||
};
|
||||
// end::get-snapshots-execute-listener
|
||||
|
||||
// Replace the empty listener by a blocking listener in test
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
listener = new LatchedActionListener<>(listener, latch);
|
||||
|
||||
// tag::get-snapshots-execute-async
|
||||
client.snapshot().getAsync(request, RequestOptions.DEFAULT, listener); // <1>
|
||||
// end::get-snapshots-execute-async
|
||||
|
||||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSnapshotDeleteSnapshot() throws IOException {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
[[java-rest-high-snapshot-get-snapshots]]
|
||||
=== Get Snapshots API
|
||||
|
||||
Use the Get Snapshot API to get snapshots.
|
||||
|
||||
[[java-rest-high-snapshot-get-snapshots-request]]
|
||||
==== Get Snapshots Request
|
||||
|
||||
A `GetSnapshotsRequest`:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request]
|
||||
--------------------------------------------------
|
||||
|
||||
==== Required Arguments
|
||||
The following arguments are mandatory:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request-repositoryName]
|
||||
--------------------------------------------------
|
||||
<1> The name of the repository.
|
||||
|
||||
==== Optional Arguments
|
||||
The following arguments are optional:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request-snapshots]
|
||||
--------------------------------------------------
|
||||
<1> An array of snapshots to get. Otherwise it will return all snapshots for a repository.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request-masterTimeout]
|
||||
--------------------------------------------------
|
||||
<1> Timeout to connect to the master node as a `TimeValue`.
|
||||
<2> Timeout to connect to the master node as a `String`.
|
||||
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request-verbose]
|
||||
--------------------------------------------------
|
||||
<1> `Boolean` indicating if the response should be verbose.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request-ignore-unavailable]
|
||||
--------------------------------------------------
|
||||
<1> `Boolean` indicating if unavailable snapshots should be ignored. Otherwise the request will
|
||||
fail if any of the snapshots are unavailable.
|
||||
|
||||
[[java-rest-high-snapshot-get-snapshots-sync]]
|
||||
==== Synchronous Execution
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-execute]
|
||||
--------------------------------------------------
|
||||
|
||||
[[java-rest-high-snapshot-get-snapshots-async]]
|
||||
==== Asynchronous Execution
|
||||
|
||||
The asynchronous execution of a get snapshots request requires both the
|
||||
`GetSnapshotsRequest` instance and an `ActionListener` instance to be
|
||||
passed as arguments to the asynchronous method:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-execute-async]
|
||||
--------------------------------------------------
|
||||
<1> The `GetSnapshotsRequest` 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 with the `onResponse` method
|
||||
if the execution is successful or the `onFailure` method if the execution
|
||||
failed.
|
||||
|
||||
A typical listener for `GetSnapshotsResponse` looks like:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-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-snapshot-get-snapshots-response]]
|
||||
==== Get Snapshots Response
|
||||
|
||||
Use the `GetSnapshotsResponse` to retrieve information about the evaluated
|
||||
request:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-response]
|
||||
--------------------------------------------------
|
||||
<1> Indicates the node has started the request.
|
|
@ -143,6 +143,7 @@ The Java High Level REST Client supports the following Snapshot APIs:
|
|||
* <<java-rest-high-snapshot-delete-repository>>
|
||||
* <<java-rest-high-snapshot-verify-repository>>
|
||||
* <<java-rest-high-snapshot-create-snapshot>>
|
||||
* <<java-rest-high-snapshot-get-snapshots>>
|
||||
* <<java-rest-high-snapshot-delete-snapshot>>
|
||||
|
||||
include::snapshot/get_repository.asciidoc[]
|
||||
|
@ -150,6 +151,7 @@ include::snapshot/create_repository.asciidoc[]
|
|||
include::snapshot/delete_repository.asciidoc[]
|
||||
include::snapshot/verify_repository.asciidoc[]
|
||||
include::snapshot/create_snapshot.asciidoc[]
|
||||
include::snapshot/get_snapshots.asciidoc[]
|
||||
include::snapshot/delete_snapshot.asciidoc[]
|
||||
|
||||
== Tasks APIs
|
||||
|
|
|
@ -20,23 +20,37 @@
|
|||
package org.elasticsearch.action.admin.cluster.snapshots.get;
|
||||
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
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 org.elasticsearch.snapshots.SnapshotInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Get snapshots response
|
||||
*/
|
||||
public class GetSnapshotsResponse extends ActionResponse implements ToXContentObject {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ConstructingObjectParser<GetSnapshotsResponse, Void> GET_SNAPSHOT_PARSER =
|
||||
new ConstructingObjectParser<>(GetSnapshotsResponse.class.getName(), true,
|
||||
(args) -> new GetSnapshotsResponse((List<SnapshotInfo>) args[0]));
|
||||
|
||||
static {
|
||||
GET_SNAPSHOT_PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> SnapshotInfo.SNAPSHOT_INFO_PARSER.apply(p, c).build(), new ParseField("snapshots"));
|
||||
}
|
||||
|
||||
private List<SnapshotInfo> snapshots = Collections.emptyList();
|
||||
|
||||
GetSnapshotsResponse() {
|
||||
|
@ -87,4 +101,20 @@ public class GetSnapshotsResponse extends ActionResponse implements ToXContentOb
|
|||
return builder;
|
||||
}
|
||||
|
||||
public static GetSnapshotsResponse fromXContent(XContentParser parser) throws IOException {
|
||||
return GET_SNAPSHOT_PARSER.parse(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
GetSnapshotsResponse that = (GetSnapshotsResponse) o;
|
||||
return Objects.equals(snapshots, that.snapshots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(snapshots);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,15 +31,12 @@ import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
|||
import org.elasticsearch.common.joda.Joda;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser.Token;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -84,7 +81,7 @@ public final class SnapshotInfo implements Comparable<SnapshotInfo>, ToXContent,
|
|||
private static final Comparator<SnapshotInfo> COMPARATOR =
|
||||
Comparator.comparing(SnapshotInfo::startTime).thenComparing(SnapshotInfo::snapshotId);
|
||||
|
||||
private static final class SnapshotInfoBuilder {
|
||||
public static final class SnapshotInfoBuilder {
|
||||
private String snapshotName = null;
|
||||
private String snapshotUUID = null;
|
||||
private String state = null;
|
||||
|
@ -137,23 +134,8 @@ public final class SnapshotInfo implements Comparable<SnapshotInfo>, ToXContent,
|
|||
this.version = version;
|
||||
}
|
||||
|
||||
private void setShardFailures(XContentParser parser) {
|
||||
if (shardFailures == null) {
|
||||
shardFailures = new ArrayList<>();
|
||||
}
|
||||
|
||||
try {
|
||||
if (parser.currentToken() == Token.START_ARRAY) {
|
||||
parser.nextToken();
|
||||
}
|
||||
|
||||
while (parser.currentToken() != Token.END_ARRAY) {
|
||||
shardFailures.add(SnapshotShardFailure.fromXContent(parser));
|
||||
parser.nextToken();
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
throw new UncheckedIOException(exception);
|
||||
}
|
||||
private void setShardFailures(List<SnapshotShardFailure> shardFailures) {
|
||||
this.shardFailures = shardFailures;
|
||||
}
|
||||
|
||||
private void ignoreVersion(String version) {
|
||||
|
@ -172,7 +154,7 @@ public final class SnapshotInfo implements Comparable<SnapshotInfo>, ToXContent,
|
|||
// ignore extra field
|
||||
}
|
||||
|
||||
private SnapshotInfo build() {
|
||||
public SnapshotInfo build() {
|
||||
SnapshotId snapshotId = new SnapshotId(snapshotName, snapshotUUID);
|
||||
|
||||
if (indices == null) {
|
||||
|
@ -219,11 +201,11 @@ public final class SnapshotInfo implements Comparable<SnapshotInfo>, ToXContent,
|
|||
}
|
||||
}
|
||||
|
||||
private static final ObjectParser<SnapshotInfoBuilder, Void> SNAPSHOT_INFO_PARSER =
|
||||
new ObjectParser<>(SnapshotInfoBuilder.class.getName(), SnapshotInfoBuilder::new);
|
||||
public static final ObjectParser<SnapshotInfoBuilder, Void> SNAPSHOT_INFO_PARSER =
|
||||
new ObjectParser<>(SnapshotInfoBuilder.class.getName(), true, SnapshotInfoBuilder::new);
|
||||
|
||||
private static final ObjectParser<ShardStatsBuilder, Void> SHARD_STATS_PARSER =
|
||||
new ObjectParser<>(ShardStatsBuilder.class.getName(), ShardStatsBuilder::new);
|
||||
new ObjectParser<>(ShardStatsBuilder.class.getName(), true, ShardStatsBuilder::new);
|
||||
|
||||
static {
|
||||
SNAPSHOT_INFO_PARSER.declareString(SnapshotInfoBuilder::setSnapshotName, new ParseField(SNAPSHOT));
|
||||
|
@ -236,8 +218,8 @@ public final class SnapshotInfo implements Comparable<SnapshotInfo>, ToXContent,
|
|||
SNAPSHOT_INFO_PARSER.declareObject(SnapshotInfoBuilder::setShardStatsBuilder, SHARD_STATS_PARSER, new ParseField(SHARDS));
|
||||
SNAPSHOT_INFO_PARSER.declareBoolean(SnapshotInfoBuilder::setIncludeGlobalState, new ParseField(INCLUDE_GLOBAL_STATE));
|
||||
SNAPSHOT_INFO_PARSER.declareInt(SnapshotInfoBuilder::setVersion, new ParseField(VERSION_ID));
|
||||
SNAPSHOT_INFO_PARSER.declareField(
|
||||
SnapshotInfoBuilder::setShardFailures, parser -> parser, new ParseField(FAILURES), ValueType.OBJECT_ARRAY_OR_STRING);
|
||||
SNAPSHOT_INFO_PARSER.declareObjectArray(SnapshotInfoBuilder::setShardFailures, SnapshotShardFailure.SNAPSHOT_SHARD_FAILURE_PARSER,
|
||||
new ParseField(FAILURES));
|
||||
SNAPSHOT_INFO_PARSER.declareString(SnapshotInfoBuilder::ignoreVersion, new ParseField(VERSION));
|
||||
SNAPSHOT_INFO_PARSER.declareString(SnapshotInfoBuilder::ignoreStartTime, new ParseField(START_TIME));
|
||||
SNAPSHOT_INFO_PARSER.declareString(SnapshotInfoBuilder::ignoreEndTime, new ParseField(END_TIME));
|
||||
|
@ -521,7 +503,7 @@ public final class SnapshotInfo implements Comparable<SnapshotInfo>, ToXContent,
|
|||
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
|
||||
// write snapshot info to repository snapshot blob format
|
||||
if (CONTEXT_MODE_SNAPSHOT.equals(params.param(CONTEXT_MODE_PARAM))) {
|
||||
return toXContentSnapshot(builder, params);
|
||||
return toXContentInternal(builder, params);
|
||||
}
|
||||
|
||||
final boolean verbose = params.paramAsBoolean("verbose", GetSnapshotsRequest.DEFAULT_VERBOSE_MODE);
|
||||
|
@ -576,7 +558,7 @@ public final class SnapshotInfo implements Comparable<SnapshotInfo>, ToXContent,
|
|||
return builder;
|
||||
}
|
||||
|
||||
private XContentBuilder toXContentSnapshot(final XContentBuilder builder, final ToXContent.Params params) throws IOException {
|
||||
private XContentBuilder toXContentInternal(final XContentBuilder builder, final ToXContent.Params params) throws IOException {
|
||||
builder.startObject(SNAPSHOT);
|
||||
builder.field(NAME, snapshotId.getName());
|
||||
builder.field(UUID, snapshotId.getUUID());
|
||||
|
@ -609,22 +591,12 @@ public final class SnapshotInfo implements Comparable<SnapshotInfo>, ToXContent,
|
|||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a SnapshotInfo from external x-content. It does not
|
||||
* handle x-content written with the internal version.
|
||||
*/
|
||||
public static SnapshotInfo fromXContent(final XContentParser parser) throws IOException {
|
||||
parser.nextToken(); // // move to '{'
|
||||
|
||||
if (parser.currentToken() != Token.START_OBJECT) {
|
||||
throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "], expected ['{']");
|
||||
}
|
||||
|
||||
SnapshotInfo snapshotInfo = SNAPSHOT_INFO_PARSER.apply(parser, null).build();
|
||||
|
||||
if (parser.currentToken() != Token.END_OBJECT) {
|
||||
throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "], expected ['}']");
|
||||
}
|
||||
|
||||
parser.nextToken(); // move past '}'
|
||||
|
||||
return snapshotInfo;
|
||||
return SNAPSHOT_INFO_PARSER.parse(parser, null).build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,8 +23,10 @@ import org.elasticsearch.ElasticsearchParseException;
|
|||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -60,11 +62,23 @@ public class SnapshotShardFailure implements ShardOperationFailedException {
|
|||
* @param reason failure reason
|
||||
*/
|
||||
public SnapshotShardFailure(@Nullable String nodeId, ShardId shardId, String reason) {
|
||||
this(nodeId, shardId, reason, RestStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new snapshot shard failure object
|
||||
*
|
||||
* @param nodeId node where failure occurred
|
||||
* @param shardId shard id
|
||||
* @param reason failure reason
|
||||
* @param status rest status
|
||||
*/
|
||||
private SnapshotShardFailure(@Nullable String nodeId, ShardId shardId, String reason, RestStatus status) {
|
||||
assert reason != null;
|
||||
this.nodeId = nodeId;
|
||||
this.shardId = shardId;
|
||||
this.reason = reason;
|
||||
assert reason != null;
|
||||
status = RestStatus.INTERNAL_SERVER_ERROR;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,7 +114,7 @@ public class SnapshotShardFailure implements ShardOperationFailedException {
|
|||
/**
|
||||
* Returns REST status corresponding to this failure
|
||||
*
|
||||
* @return REST status
|
||||
* @return REST STATUS
|
||||
*/
|
||||
@Override
|
||||
public RestStatus status() {
|
||||
|
@ -173,6 +187,57 @@ public class SnapshotShardFailure implements ShardOperationFailedException {
|
|||
builder.endObject();
|
||||
}
|
||||
|
||||
static final ConstructingObjectParser<SnapshotShardFailure, Void> SNAPSHOT_SHARD_FAILURE_PARSER =
|
||||
new ConstructingObjectParser<>("shard_failure", true, SnapshotShardFailure::constructSnapshotShardFailure);
|
||||
|
||||
static {
|
||||
SNAPSHOT_SHARD_FAILURE_PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("index"));
|
||||
SNAPSHOT_SHARD_FAILURE_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("index_uuid"));
|
||||
SNAPSHOT_SHARD_FAILURE_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("node_id"));
|
||||
// Workaround for https://github.com/elastic/elasticsearch/issues/25878
|
||||
// Some old snapshot might still have null in shard failure reasons
|
||||
SNAPSHOT_SHARD_FAILURE_PARSER.declareStringOrNull(ConstructingObjectParser.optionalConstructorArg(), new ParseField("reason"));
|
||||
SNAPSHOT_SHARD_FAILURE_PARSER.declareInt(ConstructingObjectParser.constructorArg(), new ParseField("shard_id"));
|
||||
SNAPSHOT_SHARD_FAILURE_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("status"));
|
||||
}
|
||||
|
||||
private static SnapshotShardFailure constructSnapshotShardFailure(Object[] args) {
|
||||
String index = (String) args[0];
|
||||
String indexUuid = (String) args[1];
|
||||
String nodeId = (String) args[2];
|
||||
String reason = (String) args[3];
|
||||
Integer intShardId = (Integer) args[4];
|
||||
String status = (String) args[5];
|
||||
|
||||
if (index == null) {
|
||||
throw new ElasticsearchParseException("index name was not set");
|
||||
}
|
||||
if (intShardId == null) {
|
||||
throw new ElasticsearchParseException("index shard was not set");
|
||||
}
|
||||
|
||||
ShardId shardId = new ShardId(index, indexUuid != null ? indexUuid : IndexMetaData.INDEX_UUID_NA_VALUE, intShardId);
|
||||
|
||||
// Workaround for https://github.com/elastic/elasticsearch/issues/25878
|
||||
// Some old snapshot might still have null in shard failure reasons
|
||||
String nonNullReason;
|
||||
if (reason != null) {
|
||||
nonNullReason = reason;
|
||||
} else {
|
||||
nonNullReason = "";
|
||||
}
|
||||
|
||||
|
||||
RestStatus restStatus;
|
||||
if (status != null) {
|
||||
restStatus = RestStatus.valueOf(status);
|
||||
} else {
|
||||
restStatus = RestStatus.INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
return new SnapshotShardFailure(nodeId, shardId, nonNullReason, restStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes snapshot failure information from JSON
|
||||
*
|
||||
|
@ -180,56 +245,7 @@ public class SnapshotShardFailure implements ShardOperationFailedException {
|
|||
* @return snapshot failure information
|
||||
*/
|
||||
public static SnapshotShardFailure fromXContent(XContentParser parser) throws IOException {
|
||||
SnapshotShardFailure snapshotShardFailure = new SnapshotShardFailure();
|
||||
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
String index = null;
|
||||
String index_uuid = IndexMetaData.INDEX_UUID_NA_VALUE;
|
||||
int shardId = -1;
|
||||
if (token == XContentParser.Token.START_OBJECT) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
String currentFieldName = parser.currentName();
|
||||
token = parser.nextToken();
|
||||
if (token.isValue()) {
|
||||
if ("index".equals(currentFieldName)) {
|
||||
index = parser.text();
|
||||
} else if ("index_uuid".equals(currentFieldName)) {
|
||||
index_uuid = parser.text();
|
||||
} else if ("node_id".equals(currentFieldName)) {
|
||||
snapshotShardFailure.nodeId = parser.text();
|
||||
} else if ("reason".equals(currentFieldName)) {
|
||||
// Workaround for https://github.com/elastic/elasticsearch/issues/25878
|
||||
// Some old snapshot might still have null in shard failure reasons
|
||||
snapshotShardFailure.reason = parser.textOrNull();
|
||||
} else if ("shard_id".equals(currentFieldName)) {
|
||||
shardId = parser.intValue();
|
||||
} else if ("status".equals(currentFieldName)) {
|
||||
snapshotShardFailure.status = RestStatus.valueOf(parser.text());
|
||||
} else {
|
||||
throw new ElasticsearchParseException("unknown parameter [{}]", currentFieldName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchParseException("unexpected token [{}]", token);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchParseException("unexpected token [{}]", token);
|
||||
}
|
||||
if (index == null) {
|
||||
throw new ElasticsearchParseException("index name was not set");
|
||||
}
|
||||
if (shardId == -1) {
|
||||
throw new ElasticsearchParseException("index shard was not set");
|
||||
}
|
||||
snapshotShardFailure.shardId = new ShardId(index, index_uuid, shardId);
|
||||
// Workaround for https://github.com/elastic/elasticsearch/issues/25878
|
||||
// Some old snapshot might still have null in shard failure reasons
|
||||
if (snapshotShardFailure.reason == null) {
|
||||
snapshotShardFailure.reason = "";
|
||||
}
|
||||
return snapshotShardFailure;
|
||||
return SNAPSHOT_SHARD_FAILURE_PARSER.parse(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.get;
|
||||
|
||||
import org.elasticsearch.common.UUIDs;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.snapshots.SnapshotId;
|
||||
import org.elasticsearch.snapshots.SnapshotInfo;
|
||||
import org.elasticsearch.snapshots.SnapshotShardFailure;
|
||||
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class GetSnapshotsResponseTests extends AbstractStreamableXContentTestCase<GetSnapshotsResponse> {
|
||||
|
||||
@Override
|
||||
protected GetSnapshotsResponse doParseInstance(XContentParser parser) throws IOException {
|
||||
return GetSnapshotsResponse.fromXContent(parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GetSnapshotsResponse createBlankInstance() {
|
||||
return new GetSnapshotsResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GetSnapshotsResponse createTestInstance() {
|
||||
ArrayList<SnapshotInfo> snapshots = new ArrayList<>();
|
||||
for (int i = 0; i < randomIntBetween(5, 10); ++i) {
|
||||
SnapshotId snapshotId = new SnapshotId("snapshot " + i, UUIDs.base64UUID());
|
||||
String reason = randomBoolean() ? null : "reason";
|
||||
ShardId shardId = new ShardId("index", UUIDs.base64UUID(), 2);
|
||||
List<SnapshotShardFailure> shardFailures = Collections.singletonList(new SnapshotShardFailure("node-id", shardId, "reason"));
|
||||
snapshots.add(new SnapshotInfo(snapshotId, Arrays.asList("indice1", "indice2"), System.currentTimeMillis(), reason,
|
||||
System.currentTimeMillis(), randomIntBetween(2, 3), shardFailures, randomBoolean()));
|
||||
|
||||
}
|
||||
return new GetSnapshotsResponse(snapshots);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue