Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Verify Repository High Level REST API #30934

Merged
merged 5 commits into from
May 30, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
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;
Expand Down Expand Up @@ -747,6 +748,19 @@ static Request deleteRepository(DeleteRepositoryRequest deleteRepositoryRequest)
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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.VerifyRepositoryResponse;

import java.io.IOException;

Expand Down Expand Up @@ -116,4 +118,28 @@ public void deleteRepositoryAsync(DeleteRepositoryRequest deleteRepositoryReques
restHighLevelClient.performRequestAsyncAndParseEntity(deleteRepositoryRequest, RequestConverters::deleteRepository,
DeleteRepositoryResponse::fromXContent, listener, emptySet(), headers);
}

/**
* Verifies a snapshot repository.
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
* API on elastic.co</a>
*/
public VerifyRepositoryResponse verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest, Header... headers)
throws IOException {
return restHighLevelClient.performRequestAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository,
VerifyRepositoryResponse::fromXContent, emptySet(), headers);
}

/**
* Asynchronously verifies a snapshot repository.
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
* API on elastic.co</a>
*/
public void verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryRequest,
ActionListener<VerifyRepositoryResponse> listener, Header... headers) {
restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository,
VerifyRepositoryResponse::fromXContent, listener, emptySet(), headers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
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;
Expand Down Expand Up @@ -1632,6 +1633,21 @@ public void testDeleteRepository() {
assertNull(request.getEntity());
}

public void testVerifyRepository() {
Map<String, String> expectedParams = new HashMap<>();
String repository = randomIndicesNames(1, 1)[0];
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<String, String> names = new HashMap<>();
names.put("log", "log");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,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.VerifyRepositoryResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.rest.RestStatus;
Expand Down Expand Up @@ -86,10 +88,7 @@ public void testSnapshotGetRepositoriesNonExistent() {

public void testSnapshotDeleteRepository() throws IOException {
String repository = "test";
String repositorySettings = "{\"type\":\"fs\", \"settings\":{\"location\": \".\"}}";

highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/" + repository,
Collections.emptyMap(), new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));
assertTrue(createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}").isAcknowledged());

GetRepositoriesRequest request = new GetRepositoriesRequest();
GetRepositoriesResponse response = execute(request, highLevelClient().snapshot()::getRepositories,
Expand All @@ -102,4 +101,14 @@ public void testSnapshotDeleteRepository() throws IOException {

assertTrue(deleteResponse.isAcknowledged());
}

public void testVerifyRepository() throws IOException {
PutRepositoryResponse putRepositoryResponse = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
assertTrue(putRepositoryResponse.isAcknowledged());

VerifyRepositoryRequest request = new VerifyRepositoryRequest("test");
VerifyRepositoryResponse response = execute(request, highLevelClient().snapshot()::verifyRepository,
highLevelClient().snapshot()::verifyRepositoryAsync);
assertThat(response.getNodes().size(), equalTo(1));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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.VerifyRepositoryResponse;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
Expand Down Expand Up @@ -297,6 +299,66 @@ public void onFailure(Exception e) {
}
}

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
VerifyRepositoryResponse response = client.snapshot().verifyRepository(request);
// end::verify-repository-execute

// tag::verify-repository-response
List<VerifyRepositoryResponse.NodeView> repositoryMetaDataResponse = response.getNodes();
// 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<VerifyRepositoryResponse> listener =
new ActionListener<VerifyRepositoryResponse>() {
@Override
public void onResponse(VerifyRepositoryResponse 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));
}
}

private void createTestRepositories() throws IOException {
PutRepositoryRequest request = new PutRepositoryRequest(repositoryName);
request.type(FsRepository.TYPE);
Expand Down
81 changes: 81 additions & 0 deletions docs/java-rest/high-level/snapshot/verify_repository.asciidoc
Original file line number Diff line number Diff line change
@@ -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 `VerifyRepositoryResponse` 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 `VerifyRepositoryResponse` 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]
--------------------------------------------------
2 changes: 2 additions & 0 deletions docs/java-rest/high-level/supported-apis.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,12 @@ The Java High Level REST Client supports the following Snapshot APIs:
* <<java-rest-high-snapshot-get-repository>>
* <<java-rest-high-snapshot-create-repository>>
* <<java-rest-high-snapshot-delete-repository>>
* <<java-rest-high-snapshot-verify-repository>>

include::snapshot/get_repository.asciidoc[]
include::snapshot/create_repository.asciidoc[]
include::snapshot/delete_repository.asciidoc[]
include::snapshot/verify_repository.asciidoc[]

== Tasks APIs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
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.Arrays;
Expand Down Expand Up @@ -129,6 +130,12 @@ public int hashCode() {
private ClusterName clusterName;


private static final ObjectParser<VerifyRepositoryResponse, Void> PARSER =
new ObjectParser<>(VerifyRepositoryResponse.class.getName(), VerifyRepositoryResponse::new);
static {
PARSER.declareNamedObjects(VerifyRepositoryResponse::setNodes, NodeView.PARSER, new ParseField("nodes"));
}

VerifyRepositoryResponse() {
}

Expand Down Expand Up @@ -167,6 +174,10 @@ public ClusterName getClusterName() {
return clusterName;
}

protected void setNodes(List<NodeView> nodes) {
this.nodes = nodes.stream().map(n -> n.convertToDiscoveryNode()).collect(Collectors.toList());
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
Expand All @@ -187,8 +198,29 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
return builder;
}

public static VerifyRepositoryResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}

@Override
public String toString() {
return Strings.toString(this);
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
VerifyRepositoryResponse other = (VerifyRepositoryResponse) obj;
return nodes.equals(other.nodes);
}

@Override
public int hashCode() {
return nodes.hashCode();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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 VerifyRepositoryResponseTests extends AbstractXContentTestCase<VerifyRepositoryResponse> {

@Override
protected VerifyRepositoryResponse doParseInstance(XContentParser parser) {
return VerifyRepositoryResponse.fromXContent(parser);
}

@Override
protected boolean supportsUnknownFields() {
return false;
}

@Override
protected VerifyRepositoryResponse createTestInstance() {
VerifyRepositoryResponse response = new VerifyRepositoryResponse();
List<VerifyRepositoryResponse.NodeView> nodes = new ArrayList<>();
nodes.add(new VerifyRepositoryResponse.NodeView("node-id", "node-name"));
response.setNodes(nodes);
return response;
}
}