From 0f8f9c4382adc02a9df0ad354167530a78ff2710 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Mon, 18 Jun 2018 16:20:01 -0600 Subject: [PATCH 01/15] Work on request convertor --- .../client/RequestConverters.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) 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 ab85af9f1fd7e..c09786b75c2a4 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 @@ -37,6 +37,7 @@ 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.get.GetSnapshotsRequest; 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; @@ -842,6 +843,25 @@ static Request verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest) return request; } + static Request getSnapshots(GetSnapshotsRequest getSnapshotsRequest) { + String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot") + .addPathPart(getSnapshotsRequest.repository()) + .addCommaSeparatedPathParts(getSnapshotsRequest.snapshots()) + .build(); + + Request request = new Request(HttpGet.METHOD_NAME, endpoint); + + Params parameters = new Params(request); + parameters.withMasterTimeout(getSnapshotsRequest.masterNodeTimeout()); + if (getSnapshotsRequest.ignoreUnavailable()) { + parameters.putParam("ignore_unavailable", Boolean.TRUE.toString()); + } + if (getSnapshotsRequest.verbose() == false) { + parameters.putParam("verbose", Boolean.FALSE.toString()); + } + 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); From 70f79da005ed0d9ebd618d9b4c1de46b07fa0814 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Mon, 18 Jun 2018 16:37:47 -0600 Subject: [PATCH 02/15] Start on documentation --- .../high-level/snapshot/get-snapshot.asciidoc | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/java-rest/high-level/snapshot/get-snapshot.asciidoc diff --git a/docs/java-rest/high-level/snapshot/get-snapshot.asciidoc b/docs/java-rest/high-level/snapshot/get-snapshot.asciidoc new file mode 100644 index 0000000000000..5b6853c84453a --- /dev/null +++ b/docs/java-rest/high-level/snapshot/get-snapshot.asciidoc @@ -0,0 +1,89 @@ +[[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[create-snapshot-request] +-------------------------------------------------- + +==== Required Arguments +The following arguments are mandatory: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-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[create-snapshot-request-indices] +-------------------------------------------------- +<1> A list of snapshots to get. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-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-create-snapshot-sync]] +==== Synchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-execute] +-------------------------------------------------- + +[[java-rest-high-snapshot-create-snapshot-async]] +==== Asynchronous Execution + +The asynchronous execution of a create snapshot request requires both the +`CreateSnapshotRequest` 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[create-snapshot-execute-async] +-------------------------------------------------- +<1> The `CreateSnapshotRequest` 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 `CreateSnapshotResponse` looks like: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-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-snapshot-create-snapshot-response]] +==== Snapshot Create Response + +Use the `CreateSnapshotResponse` to retrieve information about the evaluated +request: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-response] +-------------------------------------------------- +<1> Indicates the node has started the request. \ No newline at end of file From df63a2466a62f49dbe2a2c872bb492095322e6fc Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Thu, 21 Jun 2018 15:19:44 -0600 Subject: [PATCH 03/15] Work on parsing --- .../elasticsearch/client/SnapshotClient.java | 31 +++++ .../client/RequestConvertersTests.java | 30 ++++ .../org/elasticsearch/client/SnapshotIT.java | 21 +++ .../snapshots/get/GetSnapshotsResponse.java | 19 +++ .../blobstore/BlobStoreRepository.java | 2 +- .../elasticsearch/snapshots/SnapshotInfo.java | 131 +++++++++++++++--- 6 files changed, 217 insertions(+), 17 deletions(-) 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 36b4f473ce82f..aa36c9160e726 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 @@ -30,6 +30,8 @@ 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.action.admin.cluster.snapshots.get.GetSnapshotsRequest; +import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse; import java.io.IOException; @@ -164,6 +166,35 @@ public void verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryReques VerifyRepositoryResponse::fromXContent, listener, emptySet()); } + /** + * Get snapshots. + * See Snapshot and Restore + * API on elastic.co + * + * @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 Snapshot and Restore + * API on elastic.co + * + * @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 listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(getSnapshotsRequest, RequestConverters::getSnapshots, options, + GetSnapshotsResponse::fromXContent, listener, emptySet()); + } + /** * Deletes a snapshot. * See Snapshot and Restore 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 eee37cea561b0..5a80c95d1b3b5 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 @@ -38,6 +38,8 @@ 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.snapshots.get.GetSnapshotsRequest; +import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse; import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; import org.elasticsearch.action.admin.indices.alias.Alias; @@ -1858,6 +1860,34 @@ public void testVerifyRepository() { assertThat(expectedParams, equalTo(request.getParameters())); } + public void testGetSnapshots() { + Map 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); + if (randomBoolean()) { + getSnapshotsRequest.ignoreUnavailable(true); + expectedParams.put("ignore_unavailable", Boolean.TRUE.toString()); + } + if (randomBoolean() == false) { + getSnapshotsRequest.verbose(false); + expectedParams.put("verbose", Boolean.FALSE.toString()); + } + + 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 expectedParams = new HashMap<>(); String repository = randomIndicesNames(1, 1)[0]; 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 f4d325e158bc5..a5798d8f91d22 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 @@ -30,11 +30,14 @@ 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.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.Arrays; import java.util.Locale; import static org.hamcrest.Matchers.equalTo; @@ -119,6 +122,24 @@ public void testVerifyRepository() throws IOException { assertThat(response.getNodes().size(), equalTo(1)); } + public void testGetSnapshots() 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()); + + GetSnapshotsRequest request = new GetSnapshotsRequest(repository, Arrays.asList(snapshot).toArray(new String[0])); + GetSnapshotsResponse response = execute(request, highLevelClient().snapshot()::get, highLevelClient().snapshot()::getAsync); + + fail(); +// assertTrue(response.isAcknowledged()); + } + public void testDeleteSnapshot() throws IOException { String repository = "test_repository"; String snapshot = "test_snapshot"; diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java index 0d1e5eda7f2d2..f561ab8c44020 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java @@ -25,6 +25,7 @@ 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; @@ -32,6 +33,8 @@ import java.util.Collections; import java.util.List; +import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; + /** * Get snapshots response */ @@ -87,4 +90,20 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par return builder; } + public static GetSnapshotsResponse fromXContent(XContentParser parser) throws IOException { + XContentParser.Token token = parser.nextToken(); + ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation); + ArrayList snapshots = new ArrayList<>(); + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + String currentFieldName = parser.currentName(); + if ("snapshots".equals(currentFieldName)) { + token = parser.nextToken(); + ensureExpectedToken(XContentParser.Token.START_ARRAY, token, parser::getTokenLocation); + while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { + snapshots.add(SnapshotInfo.fromXContent(parser)); + } + } + } + return new GetSnapshotsResponse(snapshots); + } } diff --git a/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java b/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java index 618dd3b8bc3b9..7905a87bed6a3 100644 --- a/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java +++ b/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java @@ -257,7 +257,7 @@ protected void doStart() { indexMetaDataFormat = new ChecksumBlobStoreFormat<>(INDEX_METADATA_CODEC, METADATA_NAME_FORMAT, IndexMetaData::fromXContent, namedXContentRegistry, isCompress()); snapshotFormat = new ChecksumBlobStoreFormat<>(SNAPSHOT_CODEC, SNAPSHOT_NAME_FORMAT, - SnapshotInfo::fromXContent, namedXContentRegistry, isCompress()); + SnapshotInfo::fromXContentSnapshot, namedXContentRegistry, isCompress()); } @Override diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java index 073007f4225df..b67406cb963f7 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java @@ -41,6 +41,8 @@ import java.util.List; import java.util.Objects; +import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; + /** * Information about a snapshot */ @@ -117,7 +119,7 @@ public SnapshotInfo(SnapshotId snapshotId, List indices, long startTime, public SnapshotInfo(SnapshotId snapshotId, List indices, long startTime, String reason, long endTime, int totalShards, List shardFailures, Boolean includeGlobalState) { this(snapshotId, indices, snapshotState(reason, shardFailures), reason, Version.CURRENT, - startTime, endTime, totalShards, totalShards - shardFailures.size(), shardFailures, includeGlobalState); + startTime, endTime, totalShards, totalShards - shardFailures.size(), shardFailures, includeGlobalState); } private SnapshotInfo(SnapshotId snapshotId, List indices, SnapshotState state, String reason, Version version, @@ -183,8 +185,8 @@ public SnapshotInfo(final StreamInput in) throws IOException { */ public static SnapshotInfo incompatible(SnapshotId snapshotId) { return new SnapshotInfo(snapshotId, Collections.emptyList(), SnapshotState.INCOMPATIBLE, - "the snapshot is incompatible with the current version of Elasticsearch and its exact version is unknown", - null, 0L, 0L, 0, 0, Collections.emptyList(), null); + "the snapshot is incompatible with the current version of Elasticsearch and its exact version is unknown", + null, 0L, 0L, 0, 0, Collections.emptyList(), null); } /** @@ -353,7 +355,7 @@ public RestStatus status() { return RestStatus.OK; } return RestStatus.status(successfulShards, totalShards, - shardFailures.toArray(new ShardOperationFailedException[shardFailures.size()])); + shardFailures.toArray(new ShardOperationFailedException[shardFailures.size()])); } @Override @@ -415,7 +417,104 @@ public XContentBuilder toXContent(final XContentBuilder builder, final Params pa return builder; } - private XContentBuilder toXContentSnapshot(final XContentBuilder builder, final ToXContent.Params params) throws IOException { + public static SnapshotInfo fromXContent(final XContentParser parser) throws IOException { + String name = null; + String uuid = null; + Version version = Version.CURRENT; + SnapshotState state = SnapshotState.IN_PROGRESS; + String reason = null; + List indices = Collections.emptyList(); + long startTime = 0; + long endTime = 0; + int totalShards = 0; + int successfulShards = 0; + Boolean includeGlobalState = null; + List shardFailures = Collections.emptyList(); + if (parser.currentToken() == null) { // fresh parser? move to the first token + parser.nextToken(); + } + XContentParser.Token token = parser.currentToken(); + ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation); + 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 (SNAPSHOT.equals(currentFieldName)) { + name = parser.text(); + } else if (UUID.equals(currentFieldName)) { + uuid = parser.text(); + } else if (VERSION_ID.equals(currentFieldName)) { + version = Version.fromId(parser.intValue()); + } else if (INCLUDE_GLOBAL_STATE.equals(currentFieldName)) { + includeGlobalState = parser.booleanValue(); + } else if (STATE.equals(currentFieldName)) { + state = SnapshotState.valueOf(parser.text()); + } else if (REASON.equals(currentFieldName)) { + reason = parser.text(); + } else if (START_TIME_IN_MILLIS.equals(currentFieldName)) { + startTime = parser.longValue(); + } else if (END_TIME_IN_MILLIS.equals(currentFieldName)) { + endTime = parser.longValue(); + } + } else if (token == XContentParser.Token.START_ARRAY) { + if (INDICES.equals(currentFieldName)) { + ArrayList indicesArray = new ArrayList<>(); + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + indicesArray.add(parser.text()); + } + indices = Collections.unmodifiableList(indicesArray); + } else if (FAILURES.equals(currentFieldName)) { + ArrayList shardFailureArrayList = new ArrayList<>(); + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + shardFailureArrayList.add(SnapshotShardFailure.fromXContent(parser)); + } + shardFailures = Collections.unmodifiableList(shardFailureArrayList); + } else { + // It was probably created by newer version - ignoring + parser.skipChildren(); + } + } else if (token == XContentParser.Token.START_OBJECT) { + if (SHARDS.equals(currentFieldName)) { + while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + token = parser.nextToken(); + if (token.isValue()) { + if (TOTAL.equals(currentFieldName)) { + totalShards = parser.intValue(); + } else if (SUCCESSFUL.equals(currentFieldName)) { + successfulShards = parser.intValue(); + } + } + } + } + } else { + // It was probably created by newer version - ignoring + parser.skipChildren(); + } + } + } + } + if (uuid == null) { + // the old format where there wasn't a UUID + uuid = name; + } + return new SnapshotInfo(new SnapshotId(name, uuid), + indices, + state, + reason, + version, + startTime, + endTime, + totalShards, + successfulShards, + shardFailures, + includeGlobalState); + } + + private XContentBuilder toXContentSnapshot(final XContentBuilder builder, final ToXContent.Params params) throws + IOException { builder.startObject(SNAPSHOT); builder.field(NAME, snapshotId.getName()); builder.field(UUID, snapshotId.getUUID()); @@ -453,7 +552,7 @@ private XContentBuilder toXContentSnapshot(final XContentBuilder builder, final * handle x-content written with the external version as external x-content * is only for display purposes and does not need to be parsed. */ - public static SnapshotInfo fromXContent(final XContentParser parser) throws IOException { + public static SnapshotInfo fromXContentSnapshot(final XContentParser parser) throws IOException { String name = null; String uuid = null; Version version = Version.CURRENT; @@ -534,16 +633,16 @@ public static SnapshotInfo fromXContent(final XContentParser parser) throws IOEx uuid = name; } return new SnapshotInfo(new SnapshotId(name, uuid), - indices, - state, - reason, - version, - startTime, - endTime, - totalShards, - successfulShards, - shardFailures, - includeGlobalState); + indices, + state, + reason, + version, + startTime, + endTime, + totalShards, + successfulShards, + shardFailures, + includeGlobalState); } @Override From 2915a380bdfdb9e177ee9011e5775287ec1e2821 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Thu, 21 Jun 2018 16:09:04 -0600 Subject: [PATCH 04/15] Implement tests --- .../client/RequestConverters.java | 12 +++++--- .../client/RequestConvertersTests.java | 25 +++++++++++++++- .../org/elasticsearch/client/SnapshotIT.java | 29 ++++++++++++++----- 3 files changed, 54 insertions(+), 12 deletions(-) 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 39deab2597bdf..34a3524b3df75 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 @@ -847,10 +847,14 @@ static Request verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest) } static Request getSnapshots(GetSnapshotsRequest getSnapshotsRequest) { - String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot") - .addPathPart(getSnapshotsRequest.repository()) - .addCommaSeparatedPathParts(getSnapshotsRequest.snapshots()) - .build(); + 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); 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 5a80c95d1b3b5..492e0cf65d70f 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 @@ -39,7 +39,6 @@ import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest; import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest; -import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse; import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; import org.elasticsearch.action.admin.indices.alias.Alias; @@ -1888,6 +1887,30 @@ public void testGetSnapshots() { assertNull(request.getEntity()); } + public void testGetAllSnapshots() { + Map 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); + if (randomBoolean()) { + getSnapshotsRequest.ignoreUnavailable(true); + expectedParams.put("ignore_unavailable", Boolean.TRUE.toString()); + } + if (randomBoolean() == false) { + getSnapshotsRequest.verbose(false); + expectedParams.put("verbose", Boolean.FALSE.toString()); + } + + 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 expectedParams = new HashMap<>(); String repository = randomIndicesNames(1, 1)[0]; 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 a5798d8f91d22..db8cd13c3547f 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 @@ -38,8 +38,11 @@ import java.io.IOException; import java.util.Arrays; +import java.util.Collections; import java.util.Locale; +import java.util.stream.Collectors; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; public class SnapshotIT extends ESRestHighLevelClientTestCase { @@ -124,20 +127,32 @@ public void testVerifyRepository() throws IOException { public void testGetSnapshots() throws IOException { String repository = "test_repository"; - String snapshot = "test_snapshot"; + String snapshot1 = "test_snapshot1"; + String snapshot2 = "test_snapshot2"; PutRepositoryResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}"); assertTrue(putRepositoryResponse.isAcknowledged()); - Response putSnapshotResponse = createTestSnapshot(repository, snapshot); + Response putSnapshotResponse1 = createTestSnapshot(repository, snapshot1); + Response putSnapshotResponse2 = createTestSnapshot(repository, snapshot2); // check that the request went ok without parsing JSON here. When using the high level client, check acknowledgement instead. - assertEquals(200, putSnapshotResponse.getStatusLine().getStatusCode()); - - GetSnapshotsRequest request = new GetSnapshotsRequest(repository, Arrays.asList(snapshot).toArray(new String[0])); + assertEquals(200, putSnapshotResponse1.getStatusLine().getStatusCode()); + assertEquals(200, putSnapshotResponse2.getStatusLine().getStatusCode()); + + GetSnapshotsRequest request; + if (randomBoolean()) { + request = new GetSnapshotsRequest(repository); + } else if (randomBoolean()) { + request = new GetSnapshotsRequest(repository, Collections.singletonList("_all").toArray(new String[0])); + + } else { + request = new GetSnapshotsRequest(repository, Arrays.asList(snapshot1, snapshot2).toArray(new String[0])); + } GetSnapshotsResponse response = execute(request, highLevelClient().snapshot()::get, highLevelClient().snapshot()::getAsync); - fail(); -// assertTrue(response.isAcknowledged()); + 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 { From 50a26e149f326a4fd6ac2683d392c033ec9038a0 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Fri, 22 Jun 2018 11:09:53 -0600 Subject: [PATCH 05/15] Add tests --- .../snapshots/get/GetSnapshotsResponse.java | 14 ++++ .../elasticsearch/snapshots/SnapshotInfo.java | 4 +- .../get/GetSnapshotsResponseTests.java | 67 +++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponseTests.java diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java index f561ab8c44020..594bb3cd4abe5 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; @@ -106,4 +107,17 @@ public static GetSnapshotsResponse fromXContent(XContentParser parser) throws IO } return new GetSnapshotsResponse(snapshots); } + + @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); + } } diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java index b67406cb963f7..e1c7db18a0e68 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java @@ -460,7 +460,7 @@ public static SnapshotInfo fromXContent(final XContentParser parser) throws IOEx } else if (token == XContentParser.Token.START_ARRAY) { if (INDICES.equals(currentFieldName)) { ArrayList indicesArray = new ArrayList<>(); - while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { indicesArray.add(parser.text()); } indices = Collections.unmodifiableList(indicesArray); @@ -476,7 +476,7 @@ public static SnapshotInfo fromXContent(final XContentParser parser) throws IOEx } } else if (token == XContentParser.Token.START_OBJECT) { if (SHARDS.equals(currentFieldName)) { - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); token = parser.nextToken(); diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponseTests.java new file mode 100644 index 0000000000000..90946b1f0246c --- /dev/null +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponseTests.java @@ -0,0 +1,67 @@ +/* + * 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 { + + @Override + protected GetSnapshotsResponse doParseInstance(XContentParser parser) throws IOException { + return GetSnapshotsResponse.fromXContent(parser); + } + + @Override + protected GetSnapshotsResponse createBlankInstance() { + return new GetSnapshotsResponse(); + } + + @Override + protected GetSnapshotsResponse createTestInstance() { + ArrayList 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 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); + } + + @Override + protected boolean supportsUnknownFields() { + return false; + } +} From d385f5c20dedcfd17ef38386566d5b993b553226 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Fri, 22 Jun 2018 11:43:54 -0600 Subject: [PATCH 06/15] Work on documentation --- .../SnapshotClientDocumentationIT.java | 75 +++++++++++++++++++ ...apshot.asciidoc => get_snapshots.asciidoc} | 50 ++++++++----- 2 files changed, 107 insertions(+), 18 deletions(-) rename docs/java-rest/high-level/snapshot/{get-snapshot.asciidoc => get_snapshots.asciidoc} (52%) 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 965f9641e48ad..17d20f8fb870e 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 @@ -31,6 +31,8 @@ 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.action.admin.cluster.snapshots.get.GetSnapshotsRequest; +import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse; import org.elasticsearch.client.ESRestHighLevelClientTestCase; import org.elasticsearch.client.Request; import org.elasticsearch.client.RequestOptions; @@ -41,8 +43,11 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.repositories.fs.FsRepository; +import org.elasticsearch.snapshots.SnapshotInfo; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -367,6 +372,76 @@ public void onFailure(Exception e) { } } + 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 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 listener = + new ActionListener() { + @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(); diff --git a/docs/java-rest/high-level/snapshot/get-snapshot.asciidoc b/docs/java-rest/high-level/snapshot/get_snapshots.asciidoc similarity index 52% rename from docs/java-rest/high-level/snapshot/get-snapshot.asciidoc rename to docs/java-rest/high-level/snapshot/get_snapshots.asciidoc index 5b6853c84453a..388a6904e1391 100644 --- a/docs/java-rest/high-level/snapshot/get-snapshot.asciidoc +++ b/docs/java-rest/high-level/snapshot/get_snapshots.asciidoc @@ -10,7 +10,7 @@ A `GetSnapshotsRequest`: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-request] +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request] -------------------------------------------------- ==== Required Arguments @@ -18,7 +18,7 @@ The following arguments are mandatory: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-request-repositoryName] +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request-repositoryName] -------------------------------------------------- <1> The name of the repository. @@ -27,37 +27,51 @@ The following arguments are optional: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-request-indices] +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-request-snapshots] -------------------------------------------------- -<1> A list of snapshots to get. +<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[create-snapshot-request-masterTimeout] +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`. -[[java-rest-high-snapshot-create-snapshot-sync]] + +["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[create-snapshot-execute] +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-execute] -------------------------------------------------- -[[java-rest-high-snapshot-create-snapshot-async]] +[[java-rest-high-snapshot-get-snapshots-async]] ==== Asynchronous Execution -The asynchronous execution of a create snapshot request requires both the -`CreateSnapshotRequest` instance and an `ActionListener` instance to be +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[create-snapshot-execute-async] +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-execute-async] -------------------------------------------------- -<1> The `CreateSnapshotRequest` to execute and the `ActionListener` to use when +<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 @@ -65,25 +79,25 @@ 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 `CreateSnapshotResponse` looks like: +A typical listener for `GetSnapshotsResponse` looks like: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-execute-listener] +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-create-snapshot-response]] -==== Snapshot Create Response +[[java-rest-high-snapshot-get-snapshots-response]] +==== Get Snapshots Response -Use the `CreateSnapshotResponse` to retrieve information about the evaluated +Use the `GetSnapshotsResponse` to retrieve information about the evaluated request: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-response] +include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[get-snapshots-response] -------------------------------------------------- <1> Indicates the node has started the request. \ No newline at end of file From 45f54e7e4f76b7ddaa692edb3b3005f5da21ee5e Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Tue, 26 Jun 2018 17:50:35 -0600 Subject: [PATCH 07/15] Changes from review --- .../client/RequestConvertersTests.java | 4 +- .../org/elasticsearch/client/SnapshotIT.java | 4 +- .../SnapshotClientDocumentationIT.java | 2 - .../high-level/supported-apis.asciidoc | 2 + .../elasticsearch/snapshots/SnapshotInfo.java | 152 +++++++----------- .../snapshots/SnapshotShardFailure.java | 120 ++++++++------ .../get/GetSnapshotsResponseTests.java | 5 - 7 files changed, 135 insertions(+), 154 deletions(-) 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 492e0cf65d70f..eb6a67c367186 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 @@ -1875,9 +1875,9 @@ public void testGetSnapshots() { getSnapshotsRequest.ignoreUnavailable(true); expectedParams.put("ignore_unavailable", Boolean.TRUE.toString()); } - if (randomBoolean() == false) { + if (randomBoolean()) { getSnapshotsRequest.verbose(false); - expectedParams.put("verbose", Boolean.FALSE.toString()); + expectedParams.put("verboseSnapshotIT.java", Boolean.FALSE.toString()); } Request request = RequestConverters.getSnapshots(getSnapshotsRequest); 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 db8cd13c3547f..f0b5ffc4455af 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 @@ -143,10 +143,10 @@ public void testGetSnapshots() throws IOException { if (randomBoolean()) { request = new GetSnapshotsRequest(repository); } else if (randomBoolean()) { - request = new GetSnapshotsRequest(repository, Collections.singletonList("_all").toArray(new String[0])); + request = new GetSnapshotsRequest(repository, new String[] {"_all"}); } else { - request = new GetSnapshotsRequest(repository, Arrays.asList(snapshot1, snapshot2).toArray(new String[0])); + request = new GetSnapshotsRequest(repository, new String[] {snapshot1, snapshot2}); } GetSnapshotsResponse response = execute(request, highLevelClient().snapshot()::get, highLevelClient().snapshot()::getAsync); 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 17d20f8fb870e..623f12def6b94 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 @@ -46,8 +46,6 @@ import org.elasticsearch.snapshots.SnapshotInfo; import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 727088aa5737f..d0e7fbeda585e 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -136,12 +136,14 @@ 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/get_snapshots.asciidoc[] include::snapshot/delete_snapshot.asciidoc[] == Tasks APIs diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java index e1c7db18a0e68..3fc50f6a8740e 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java @@ -23,12 +23,15 @@ import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest; 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.io.stream.Writeable; import org.elasticsearch.common.joda.FormatDateTimeFormatter; import org.elasticsearch.common.joda.Joda; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; @@ -41,8 +44,6 @@ import java.util.List; import java.util.Objects; -import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; - /** * Information about a snapshot */ @@ -417,102 +418,67 @@ public XContentBuilder toXContent(final XContentBuilder builder, final Params pa return builder; } - public static SnapshotInfo fromXContent(final XContentParser parser) throws IOException { - String name = null; - String uuid = null; - Version version = Version.CURRENT; - SnapshotState state = SnapshotState.IN_PROGRESS; - String reason = null; - List indices = Collections.emptyList(); - long startTime = 0; - long endTime = 0; - int totalShards = 0; - int successfulShards = 0; - Boolean includeGlobalState = null; - List shardFailures = Collections.emptyList(); - if (parser.currentToken() == null) { // fresh parser? move to the first token - parser.nextToken(); - } - XContentParser.Token token = parser.currentToken(); - ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation); - 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 (SNAPSHOT.equals(currentFieldName)) { - name = parser.text(); - } else if (UUID.equals(currentFieldName)) { - uuid = parser.text(); - } else if (VERSION_ID.equals(currentFieldName)) { - version = Version.fromId(parser.intValue()); - } else if (INCLUDE_GLOBAL_STATE.equals(currentFieldName)) { - includeGlobalState = parser.booleanValue(); - } else if (STATE.equals(currentFieldName)) { - state = SnapshotState.valueOf(parser.text()); - } else if (REASON.equals(currentFieldName)) { - reason = parser.text(); - } else if (START_TIME_IN_MILLIS.equals(currentFieldName)) { - startTime = parser.longValue(); - } else if (END_TIME_IN_MILLIS.equals(currentFieldName)) { - endTime = parser.longValue(); - } - } else if (token == XContentParser.Token.START_ARRAY) { - if (INDICES.equals(currentFieldName)) { - ArrayList indicesArray = new ArrayList<>(); - while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { - indicesArray.add(parser.text()); - } - indices = Collections.unmodifiableList(indicesArray); - } else if (FAILURES.equals(currentFieldName)) { - ArrayList shardFailureArrayList = new ArrayList<>(); - while (parser.nextToken() != XContentParser.Token.END_ARRAY) { - shardFailureArrayList.add(SnapshotShardFailure.fromXContent(parser)); - } - shardFailures = Collections.unmodifiableList(shardFailureArrayList); - } else { - // It was probably created by newer version - ignoring - parser.skipChildren(); - } - } else if (token == XContentParser.Token.START_OBJECT) { - if (SHARDS.equals(currentFieldName)) { - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = parser.currentName(); - token = parser.nextToken(); - if (token.isValue()) { - if (TOTAL.equals(currentFieldName)) { - totalShards = parser.intValue(); - } else if (SUCCESSFUL.equals(currentFieldName)) { - successfulShards = parser.intValue(); - } - } - } - } - } else { - // It was probably created by newer version - ignoring - parser.skipChildren(); - } - } - } - } + private static final ConstructingObjectParser SNAPSHOT_INFO_PARSER = + new ConstructingObjectParser<>("snapshot_info", true, SnapshotInfo::constructSnapshotInfo); + + private static final ObjectParser SHARDS_PARSER = new ObjectParser<>("shard_info", true, ShardInfo::new); + + static { + SHARDS_PARSER.declareInt((v, i) -> v.total = i, new ParseField(TOTAL)); + SHARDS_PARSER.declareInt((v, s) -> v.successful = s, new ParseField(SUCCESSFUL)); + + + SNAPSHOT_INFO_PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField(SNAPSHOT)); + SNAPSHOT_INFO_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField(UUID)); + SNAPSHOT_INFO_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField(VERSION)); + SNAPSHOT_INFO_PARSER.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), new ParseField(INCLUDE_GLOBAL_STATE)); + SNAPSHOT_INFO_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField(STATE)); + SNAPSHOT_INFO_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField(REASON)); + SNAPSHOT_INFO_PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), new ParseField(START_TIME_IN_MILLIS)); + SNAPSHOT_INFO_PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), new ParseField(END_TIME_IN_MILLIS)); + SNAPSHOT_INFO_PARSER.declareObjectArray(ConstructingObjectParser.optionalConstructorArg(), + SnapshotShardFailure.SNAPSHOT_SHARD_FAILURE_PARSER::apply, new ParseField(FAILURES)); + SNAPSHOT_INFO_PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), + SHARDS_PARSER::apply, new ParseField(SHARDS)); + SNAPSHOT_INFO_PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), new ParseField(INDICES)); + } + + @SuppressWarnings("unchecked") + private static SnapshotInfo constructSnapshotInfo(Object[] args) { + String snapshotName = (String) args[0]; + String uuid = (String) args[1]; + String version = (String) args[2]; + Boolean includeGlobalState = (Boolean) args[3]; + String state = (String) args[4]; + String reason = (String) args[5]; + Long startTime = (Long) args[6]; + Long endTime = (Long) args[7]; + List shardFailures = (List) args[8]; + ShardInfo shardInfo = (ShardInfo) args[9]; + List indices = (List) args[10]; + + // the old format where there wasn't a UUID if (uuid == null) { - // the old format where there wasn't a UUID - uuid = name; + uuid = snapshotName; } - return new SnapshotInfo(new SnapshotId(name, uuid), + + return new SnapshotInfo(new SnapshotId(snapshotName, uuid), indices, - state, + state != null ? SnapshotState.valueOf(state) : SnapshotState.IN_PROGRESS, reason, - version, - startTime, - endTime, - totalShards, - successfulShards, - shardFailures, + version != null ? Version.fromString(version) : Version.CURRENT, + startTime != null ? startTime : 0, + endTime != null ? endTime : 0, + shardInfo.total, + shardInfo.successful, + shardFailures != null ? shardFailures : Collections.emptyList(), includeGlobalState); } + public static SnapshotInfo fromXContent(final XContentParser parser) throws IOException { + return SNAPSHOT_INFO_PARSER.parse(parser, null); + } + private XContentBuilder toXContentSnapshot(final XContentBuilder builder, final ToXContent.Params params) throws IOException { builder.startObject(SNAPSHOT); @@ -706,4 +672,8 @@ private static SnapshotState snapshotState(final String reason, final List 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 (shardId == -1) { + if (intShardId == null) { throw new ElasticsearchParseException("index shard was not set"); } - snapshotShardFailure.shardId = new ShardId(index, index_uuid, shardId); + + 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 - if (snapshotShardFailure.reason == null) { - snapshotShardFailure.reason = ""; + 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 snapshotShardFailure; + + return new SnapshotShardFailure(nodeId, shardId, nonNullReason, restStatus); + } + + /** + * Deserializes snapshot failure information from JSON + * + * @param parser JSON parser + * @return snapshot failure information + */ + public static SnapshotShardFailure fromXContent(XContentParser parser) throws IOException { + return SNAPSHOT_SHARD_FAILURE_PARSER.parse(parser, null); } @Override diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponseTests.java index 90946b1f0246c..c5bd7d9f38ac1 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponseTests.java @@ -59,9 +59,4 @@ protected GetSnapshotsResponse createTestInstance() { } return new GetSnapshotsResponse(snapshots); } - - @Override - protected boolean supportsUnknownFields() { - return false; - } } From 987529023e32a87244264c2231700a9cb6a6ef46 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Tue, 26 Jun 2018 17:51:40 -0600 Subject: [PATCH 08/15] whitespace --- .../elasticsearch/snapshots/SnapshotInfo.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java index 3fc50f6a8740e..dd9bfd9ecf040 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java @@ -599,16 +599,16 @@ public static SnapshotInfo fromXContentSnapshot(final XContentParser parser) thr uuid = name; } return new SnapshotInfo(new SnapshotId(name, uuid), - indices, - state, - reason, - version, - startTime, - endTime, - totalShards, - successfulShards, - shardFailures, - includeGlobalState); + indices, + state, + reason, + version, + startTime, + endTime, + totalShards, + successfulShards, + shardFailures, + includeGlobalState); } @Override From 2f16ff0db2678e935acd354f287bc0d1a919a97b Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Tue, 26 Jun 2018 17:54:25 -0600 Subject: [PATCH 09/15] Changes from review --- .../java/org/elasticsearch/client/RequestConvertersTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0c40afa9ac41e..f8e3b5e2f74e0 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 @@ -1984,7 +1984,7 @@ public void testGetAllSnapshots() { getSnapshotsRequest.ignoreUnavailable(true); expectedParams.put("ignore_unavailable", Boolean.TRUE.toString()); } - if (randomBoolean() == false) { + if (randomBoolean()) { getSnapshotsRequest.verbose(false); expectedParams.put("verbose", Boolean.FALSE.toString()); } From 1479487f805803a262dcb1d63fa2a0822720a81a Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Tue, 26 Jun 2018 22:59:05 -0600 Subject: [PATCH 10/15] Fix checkstyle --- .../src/test/java/org/elasticsearch/client/SnapshotIT.java | 2 -- 1 file changed, 2 deletions(-) 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 f0b5ffc4455af..eec8778c0c35a 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 @@ -37,8 +37,6 @@ import org.elasticsearch.rest.RestStatus; import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; import java.util.Locale; import java.util.stream.Collectors; From 429f9acba57e150ff84e9cb39d38cb27ddb8a246 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 27 Jun 2018 08:14:34 -0600 Subject: [PATCH 11/15] Fix test --- .../java/org/elasticsearch/client/RequestConvertersTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f8e3b5e2f74e0..de132f212f1d4 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 @@ -1962,7 +1962,7 @@ public void testGetSnapshots() { } if (randomBoolean()) { getSnapshotsRequest.verbose(false); - expectedParams.put("verboseSnapshotIT.java", Boolean.FALSE.toString()); + expectedParams.put("verbose", Boolean.FALSE.toString()); } Request request = RequestConverters.getSnapshots(getSnapshotsRequest); From 5c61d106b4dabac9052946630fb9d32087232708 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 27 Jun 2018 09:24:36 -0600 Subject: [PATCH 12/15] Adjust comments --- .../java/org/elasticsearch/snapshots/SnapshotInfo.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java index dd9bfd9ecf040..e9bb3d7dc83e3 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java @@ -475,6 +475,10 @@ private static SnapshotInfo constructSnapshotInfo(Object[] args) { includeGlobalState); } + /** + * 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 { return SNAPSHOT_INFO_PARSER.parse(parser, null); } @@ -515,8 +519,7 @@ private XContentBuilder toXContentSnapshot(final XContentBuilder builder, final /** * This method creates a SnapshotInfo from internal x-content. It does not - * handle x-content written with the external version as external x-content - * is only for display purposes and does not need to be parsed. + * handle x-content written with the external version. */ public static SnapshotInfo fromXContentSnapshot(final XContentParser parser) throws IOException { String name = null; From 0058c83af6214859ef4b3da5347706f0b1748752 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 27 Jun 2018 12:11:05 -0600 Subject: [PATCH 13/15] Fix naming --- .../elasticsearch/snapshots/SnapshotInfo.java | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java index b88318b0afc63..a9667d85b6892 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java @@ -34,7 +34,6 @@ 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; @@ -504,7 +503,7 @@ public RestStatus status() { 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); @@ -559,7 +558,7 @@ public XContentBuilder toXContent(final XContentBuilder builder, final Params pa 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()); @@ -592,21 +591,11 @@ private XContentBuilder toXContentSnapshot(final XContentBuilder builder, final 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 { -// if (parser.currentToken() != Token.START_OBJECT) { -// parser.nextToken(); // // move to '{' -// } - -// if (parser.currentToken() != Token.START_OBJECT) { -// throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "], expected ['{']"); -// } - - // if (parser.currentToken() != Token.END_OBJECT) { -// throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "], expected ['}']"); -// } - -// parser.nextToken(); // move past '}' - return SNAPSHOT_INFO_PARSER.parse(parser, null).build(); } From 8cb968b28b782b37018ab9fceeee747a986d9e95 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 27 Jun 2018 14:33:44 -0600 Subject: [PATCH 14/15] Changes --- .../snapshots/get/GetSnapshotsResponse.java | 36 +++++++------------ .../elasticsearch/snapshots/SnapshotInfo.java | 6 ++-- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java index 60477b6119ab0..6f757cb60ca86 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java @@ -20,8 +20,10 @@ 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; @@ -34,13 +36,21 @@ import java.util.List; import java.util.Objects; -import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; - /** * Get snapshots response */ public class GetSnapshotsResponse extends ActionResponse implements ToXContentObject { + @SuppressWarnings("unchecked") + private static final ConstructingObjectParser GET_SNAPSHOT_PARSER = + new ConstructingObjectParser<>(GetSnapshotsResponse.class.getName(), true, + (args) -> new GetSnapshotsResponse((List) args[0])); + + static { + GET_SNAPSHOT_PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), + (p, c) -> SnapshotInfo.SNAPSHOT_INFO_PARSER.apply(p, c).build(), new ParseField("snapshots")); + } + private List snapshots = Collections.emptyList(); GetSnapshotsResponse() { @@ -92,27 +102,7 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par } public static GetSnapshotsResponse fromXContent(XContentParser parser) throws IOException { - XContentParser.Token token = parser.nextToken(); - ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation); - ArrayList snapshots = new ArrayList<>(); - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - String currentFieldName = parser.currentName(); - if ("snapshots".equals(currentFieldName)) { - token = parser.nextToken(); - ensureExpectedToken(XContentParser.Token.START_ARRAY, token, parser::getTokenLocation); - while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { - snapshots.add(SnapshotInfo.fromXContent(parser)); - } - } - } - - if (parser.currentToken() != XContentParser.Token.END_OBJECT) { - throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "], expected ['}']"); - } - - parser.nextToken(); // move past '}' - - return new GetSnapshotsResponse(snapshots); + return GET_SNAPSHOT_PARSER.parse(parser, null); } @Override diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java index a9667d85b6892..a1f56a1e47376 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java @@ -81,7 +81,7 @@ public final class SnapshotInfo implements Comparable, ToXContent, private static final Comparator 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; @@ -154,7 +154,7 @@ private void ignoreDurationInMillis(long durationInMillis) { // ignore extra field } - private SnapshotInfo build() { + public SnapshotInfo build() { SnapshotId snapshotId = new SnapshotId(snapshotName, snapshotUUID); if (indices == null) { @@ -201,7 +201,7 @@ private void ignoreFailedShards(int failedShards) { } } - private static final ObjectParser SNAPSHOT_INFO_PARSER = + public static final ObjectParser SNAPSHOT_INFO_PARSER = new ObjectParser<>(SnapshotInfoBuilder.class.getName(), true, SnapshotInfoBuilder::new); private static final ObjectParser SHARD_STATS_PARSER = From 4a6336495c3243142fec2c9b6d5b486d30d9f10e Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 27 Jun 2018 14:38:02 -0600 Subject: [PATCH 15/15] More changes --- .../client/RequestConverters.java | 9 ++---- .../client/RequestConvertersTests.java | 32 +++++++++---------- 2 files changed, 19 insertions(+), 22 deletions(-) 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 4792661c6855e..6e96ecd9c5cb5 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 @@ -909,12 +909,9 @@ static Request getSnapshots(GetSnapshotsRequest getSnapshotsRequest) { Params parameters = new Params(request); parameters.withMasterTimeout(getSnapshotsRequest.masterNodeTimeout()); - if (getSnapshotsRequest.ignoreUnavailable()) { - parameters.putParam("ignore_unavailable", Boolean.TRUE.toString()); - } - if (getSnapshotsRequest.verbose() == false) { - parameters.putParam("verbose", Boolean.FALSE.toString()); - } + parameters.putParam("ignore_unavailable", Boolean.toString(getSnapshotsRequest.ignoreUnavailable())); + parameters.putParam("verbose", Boolean.toString(getSnapshotsRequest.verbose())); + return request; } 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 ba128c7da171b..252caa457eeea 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 @@ -2024,14 +2024,14 @@ public void testGetSnapshots() { getSnapshotsRequest.repository(repository); getSnapshotsRequest.snapshots(Arrays.asList(snapshot1, snapshot2).toArray(new String[0])); setRandomMasterTimeout(getSnapshotsRequest, expectedParams); - if (randomBoolean()) { - getSnapshotsRequest.ignoreUnavailable(true); - expectedParams.put("ignore_unavailable", Boolean.TRUE.toString()); - } - if (randomBoolean()) { - getSnapshotsRequest.verbose(false); - expectedParams.put("verbose", Boolean.FALSE.toString()); - } + + 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())); @@ -2048,14 +2048,14 @@ public void testGetAllSnapshots() { GetSnapshotsRequest getSnapshotsRequest = new GetSnapshotsRequest(repository); setRandomMasterTimeout(getSnapshotsRequest, expectedParams); - if (randomBoolean()) { - getSnapshotsRequest.ignoreUnavailable(true); - expectedParams.put("ignore_unavailable", Boolean.TRUE.toString()); - } - if (randomBoolean()) { - getSnapshotsRequest.verbose(false); - expectedParams.put("verbose", Boolean.FALSE.toString()); - } + + 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()));