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 a5a6b9f7bd271..de61d07e34ed0 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
@@ -32,6 +32,7 @@
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
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.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
@@ -711,6 +712,19 @@ static Request createRepository(PutRepositoryRequest putRepositoryRequest) throw
return request;
}
+ static Request verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest) {
+ String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot")
+ .addPathPart(verifyRepositoryRequest.name())
+ .addPathPartAsIs("_verify")
+ .build();
+ Request request = new Request(HttpPost.METHOD_NAME, endpoint);
+
+ Params parameters = new Params(request);
+ parameters.withMasterTimeout(verifyRepositoryRequest.masterNodeTimeout());
+ parameters.withTimeout(verifyRepositoryRequest.timeout());
+ return request;
+ }
+
static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) throws IOException {
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addPathPart(putIndexTemplateRequest.name()).build();
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
index aec94586bee30..0b65b5b5d299d 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
@@ -25,6 +25,8 @@
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
+import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
+import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRestResponse;
import java.io.IOException;
@@ -90,4 +92,28 @@ public void createRepositoryAsync(PutRepositoryRequest putRepositoryRequest,
restHighLevelClient.performRequestAsyncAndParseEntity(putRepositoryRequest, RequestConverters::createRepository,
PutRepositoryResponse::fromXContent, listener, emptySet(), headers);
}
+
+ /**
+ * Verifies a snapshot repository.
+ *
+ * See Snapshot and Restore
+ * API on elastic.co
+ */
+ public VerifyRepositoryRestResponse verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest, Header... headers)
+ throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository,
+ VerifyRepositoryRestResponse::fromXContent, emptySet(), headers);
+ }
+
+ /**
+ * Asynchronously verifies a snapshot repository.
+ *
+ * See Snapshot and Restore
+ * API on elastic.co
+ */
+ public void verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryRequest,
+ ActionListener listener, Header... headers) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository,
+ VerifyRepositoryRestResponse::fromXContent, listener, emptySet(), headers);
+ }
}
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 4a0276e74d228..62d76029668b0 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
@@ -32,6 +32,7 @@
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
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.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
@@ -1566,6 +1567,21 @@ public void testCreateRepository() throws IOException {
assertToXContentBody(putRepositoryRequest, request.getEntity());
}
+ public void testVerifyRepository() throws IOException {
+ Map expectedParams = new HashMap<>();
+ String repository = "repo";
+ String endpoint = "/_snapshot/" + repository + "/_verify";
+
+ VerifyRepositoryRequest verifyRepositoryRequest = new VerifyRepositoryRequest(repository);
+ setRandomMasterTimeout(verifyRepositoryRequest, expectedParams);
+ setRandomTimeout(verifyRepositoryRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
+
+ Request request = RequestConverters.verifyRepository(verifyRepositoryRequest);
+ assertThat(endpoint, equalTo(request.getEndpoint()));
+ assertThat(HttpPost.METHOD_NAME, equalTo(request.getMethod()));
+ assertThat(expectedParams, equalTo(request.getParameters()));
+ }
+
public void testPutTemplateRequest() throws Exception {
Map names = new HashMap<>();
names.put("log", "log");
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java
index 1d0ea953cd5c1..18d7f00df8e18 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
@@ -24,6 +24,8 @@
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
+import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
+import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRestResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.rest.RestStatus;
@@ -48,6 +50,16 @@ public void testCreateRepository() throws IOException {
assertTrue(response.isAcknowledged());
}
+ public void testVerifyRepository() throws IOException {
+ PutRepositoryResponse putRepositoryResponse = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
+ assertTrue(putRepositoryResponse.isAcknowledged());
+
+ VerifyRepositoryRequest request = new VerifyRepositoryRequest("test");
+ VerifyRepositoryRestResponse response = execute(request, highLevelClient().snapshot()::verifyRepository,
+ highLevelClient().snapshot()::verifyRepositoryAsync);
+ assertThat(response.nodes().size(), equalTo(1));
+ }
+
public void testModulesGetRepositoriesUsingParams() throws IOException {
String testRepository = "test";
assertTrue(createTestRepository(testRepository, FsRepository.TYPE, "{\"location\": \".\"}").isAcknowledged());
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
index c57f8e2a2fbd5..c007287f78d74 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
@@ -25,6 +25,8 @@
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
+import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
+import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRestResponse;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
@@ -64,6 +66,66 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
private static final String repositoryName = "test_repository";
+ public void testSnapshotVerifyRepository() throws IOException {
+ RestHighLevelClient client = highLevelClient();
+ createTestRepositories();
+
+ // tag::verify-repository-request
+ VerifyRepositoryRequest request = new VerifyRepositoryRequest(repositoryName);
+ // end::verify-repository-request
+
+ // tag::verify-repository-request-masterTimeout
+ request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
+ request.masterNodeTimeout("1m"); // <2>
+ // end::verify-repository-request-masterTimeout
+ // tag::verify-repository-request-timeout
+ request.timeout(TimeValue.timeValueMinutes(1)); // <1>
+ request.timeout("1m"); // <2>
+ // end::verify-repository-request-timeout
+
+ // tag::verify-repository-execute
+ VerifyRepositoryRestResponse response = client.snapshot().verifyRepository(request);
+ // end::verify-repository-execute
+
+ // tag::verify-repository-response
+ List repositoryMetaDataResponse = response.nodes();
+ // end::verify-repository-response
+ assertThat(1, equalTo(repositoryMetaDataResponse.size()));
+ assertThat("node-0", equalTo(repositoryMetaDataResponse.get(0).getName()));
+ }
+
+ public void testSnapshotVerifyRepositoryAsync() throws InterruptedException {
+ RestHighLevelClient client = highLevelClient();
+ {
+ VerifyRepositoryRequest request = new VerifyRepositoryRequest(repositoryName);
+
+ // tag::verify-repository-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(VerifyRepositoryRestResponse verifyRepositoryRestResponse) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::verify-repository-execute-listener
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ // tag::verify-repository-execute-async
+ client.snapshot().verifyRepositoryAsync(request, listener); // <1>
+ // end::verify-repository-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+ }
+
public void testSnapshotCreateRepository() throws IOException {
RestHighLevelClient client = highLevelClient();
diff --git a/docs/java-rest/high-level/snapshot/verify_repository.asciidoc b/docs/java-rest/high-level/snapshot/verify_repository.asciidoc
new file mode 100644
index 0000000000000..a9ccf4edb3182
--- /dev/null
+++ b/docs/java-rest/high-level/snapshot/verify_repository.asciidoc
@@ -0,0 +1,81 @@
+[[java-rest-high-snapshot-verify-repository]]
+=== Snapshot Verify Repository API
+
+The Snapshot Verify Repository API allows to verify a registered repository.
+
+[[java-rest-high-snapshot-verify-repository-request]]
+==== Snapshot Verify Repository Request
+
+A `VerifyRepositoryRequest`:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[verify-repository-request]
+--------------------------------------------------
+
+==== Optional Arguments
+The following arguments can optionally be provided:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-repository-request-timeout]
+--------------------------------------------------
+<1> Timeout to wait for the all the nodes to acknowledge the settings were applied
+as a `TimeValue`
+<2> Timeout to wait for the all the nodes to acknowledge the settings were applied
+as a `String`
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[verify-repository-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-verify-repository-sync]]
+==== Synchronous Execution
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[verify-repository-execute]
+--------------------------------------------------
+
+[[java-rest-high-snapshot-verify-repository-async]]
+==== Asynchronous Execution
+
+The asynchronous execution of a snapshot verify repository requires both the
+`VerifyRepositoryRequest` instance and an `ActionListener` instance to be
+passed to the asynchronous method:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[verify-repository-execute-async]
+--------------------------------------------------
+<1> The `VerifyRepositoryRequest` to execute and the `ActionListener`
+to use when the execution completes
+
+The asynchronous method does not block and returns immediately. Once it is
+completed the `ActionListener` is called back using the `onResponse` method
+if the execution successfully completed or using the `onFailure` method if
+it failed.
+
+A typical listener for `VerifyRepositoryRestResponse` looks like:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[verify-repository-execute-listener]
+--------------------------------------------------
+<1> Called when the execution is successfully completed. The response is
+provided as an argument
+<2> Called in case of a failure. The raised exception is provided as an argument
+
+[[java-rest-high-cluster-verify-repository-response]]
+==== Snapshot Verify Repository Response
+
+The returned `VerifyRepositoryRestResponse` allows to retrieve information about the
+executed operation as follows:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[verify-repository-response]
+--------------------------------------------------
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index b00047359a5d7..882af0268c10d 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -114,6 +114,10 @@ include::cluster/list_tasks.asciidoc[]
The Java High Level REST Client supports the following Snapshot APIs:
* <>
+* <>
+* <>
+
include::snapshot/get_repository.asciidoc[]
include::snapshot/create_repository.asciidoc[]
+include::snapshot/verify_repository.asciidoc[]
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/verify/VerifyRepositoryRestResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/verify/VerifyRepositoryRestResponse.java
new file mode 100644
index 0000000000000..87635ed11e8cc
--- /dev/null
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/verify/VerifyRepositoryRestResponse.java
@@ -0,0 +1,149 @@
+/*
+ * 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.repositories.verify;
+
+import org.elasticsearch.action.ActionResponse;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.io.stream.Streamable;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+public class VerifyRepositoryRestResponse implements ToXContentObject {
+
+ public static class NodeView implements ToXContentObject {
+ private static final ObjectParser.NamedObjectParser PARSER;
+ static {
+ ObjectParser parser = new ObjectParser<>("nodes");
+ parser.declareString(NodeView::setName, new ParseField(Fields.NAME));
+ PARSER = (XContentParser p, Void v, String name )-> parser.parse(p, new NodeView(name), null);
+ }
+
+ final String nodeId;
+ String name;
+
+ public NodeView(String nodeId) { this.nodeId = nodeId; }
+
+ public NodeView(String nodeId, String name) {
+ this(nodeId);
+ this.name = name;
+ }
+
+ void setName(String name) { this.name = name; }
+
+ public String getName() { return name; }
+
+ public String getNodeId() { return nodeId; }
+
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject(nodeId);
+ builder.field(Fields.NAME, name);
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ NodeView other = (NodeView) obj;
+ return Objects.equals(nodeId, other.nodeId) &&
+ Objects.equals(name, other.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nodeId, name);
+ }
+ }
+
+ private static final ObjectParser PARSER =
+ new ObjectParser<>(VerifyRepositoryRestResponse.class.getName(), VerifyRepositoryRestResponse::new);
+ static {
+ PARSER.declareNamedObjects(VerifyRepositoryRestResponse::nodes, NodeView.PARSER, new ParseField("nodes"));
+ }
+
+ private List nodes = new ArrayList<>();
+
+ VerifyRepositoryRestResponse() {
+ }
+
+ public List nodes() {
+ return nodes;
+ }
+
+ void nodes(List nodes) {
+ this.nodes = nodes;
+ }
+
+ static final class Fields {
+ static final String NODES = "nodes";
+ static final String NAME = "name";
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.startObject(Fields.NODES);
+ for (NodeView node : nodes) {
+ node.toXContent(builder, params);
+ }
+ builder.endObject();
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return Strings.toString(this);
+ }
+
+ public static VerifyRepositoryRestResponse fromXContent(XContentParser parser) {
+ return PARSER.apply(parser, null);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ VerifyRepositoryRestResponse other = (VerifyRepositoryRestResponse) obj;
+ return nodes.equals(other.nodes);
+ }
+
+ @Override
+ public int hashCode() {
+ return nodes.hashCode();
+ }
+}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/verify/VerifyRepositoryRestResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/verify/VerifyRepositoryRestResponseTests.java
new file mode 100644
index 0000000000000..b9d6f323edeb2
--- /dev/null
+++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/verify/VerifyRepositoryRestResponseTests.java
@@ -0,0 +1,48 @@
+/*
+ * 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.repositories.verify;
+
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.AbstractXContentTestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class VerifyRepositoryRestResponseTests extends AbstractXContentTestCase {
+
+ @Override
+ protected VerifyRepositoryRestResponse doParseInstance(XContentParser parser) throws IOException {
+ return VerifyRepositoryRestResponse.fromXContent(parser);
+ }
+
+ @Override
+ protected boolean supportsUnknownFields() {
+ return false;
+ }
+
+ @Override
+ protected VerifyRepositoryRestResponse createTestInstance() {
+ VerifyRepositoryRestResponse response = new VerifyRepositoryRestResponse();
+ List nodes = new ArrayList<>();
+ nodes.add(new VerifyRepositoryRestResponse.NodeView("node-id", "node-name"));
+ response.nodes(nodes);
+ return response;
+ }
+}