Add Delete Repository High Level REST API (#30666)

This commit adds Delete Repository, the associated docs and tests for
the high level REST API client. It also cleans up a seemingly innocuous
line in the RestDeleteRepositoryAction and some naming in SnapshotIT.

Relates #27205
This commit is contained in:
Michael Basnight 2018-05-21 19:52:21 -05:00 committed by GitHub
parent 3ce2297dc1
commit c6be3b4e5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 288 additions and 10 deletions

View File

@ -30,6 +30,7 @@ import org.apache.http.entity.ContentType;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
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.settings.ClusterUpdateSettingsRequest;
@ -711,6 +712,16 @@ final class RequestConverters {
return request;
}
static Request deleteRepository(DeleteRepositoryRequest deleteRepositoryRequest) {
String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot").addPathPart(deleteRepositoryRequest.name()).build();
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
Params parameters = new Params(request);
parameters.withMasterTimeout(deleteRepositoryRequest.masterNodeTimeout());
parameters.withTimeout(deleteRepositoryRequest.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);

View File

@ -21,6 +21,8 @@ package org.elasticsearch.client;
import org.apache.http.Header;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
@ -90,4 +92,28 @@ public final class SnapshotClient {
restHighLevelClient.performRequestAsyncAndParseEntity(putRepositoryRequest, RequestConverters::createRepository,
PutRepositoryResponse::fromXContent, listener, emptySet(), headers);
}
/**
* Deletes 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 DeleteRepositoryResponse deleteRepository(DeleteRepositoryRequest deleteRepositoryRequest, Header... headers)
throws IOException {
return restHighLevelClient.performRequestAndParseEntity(deleteRepositoryRequest, RequestConverters::deleteRepository,
DeleteRepositoryResponse::fromXContent, emptySet(), headers);
}
/**
* Asynchronously deletes 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 deleteRepositoryAsync(DeleteRepositoryRequest deleteRepositoryRequest,
ActionListener<DeleteRepositoryResponse> listener, Header... headers) {
restHighLevelClient.performRequestAsyncAndParseEntity(deleteRepositoryRequest, RequestConverters::deleteRepository,
DeleteRepositoryResponse::fromXContent, listener, emptySet(), headers);
}
}

View File

@ -30,6 +30,7 @@ import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
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.settings.ClusterUpdateSettingsRequest;
@ -1546,7 +1547,7 @@ public class RequestConvertersTests extends ESTestCase {
}
public void testCreateRepository() throws IOException {
String repository = "repo";
String repository = randomIndicesNames(1, 1)[0];
String endpoint = "/_snapshot/" + repository;
Path repositoryLocation = PathUtils.get(".");
PutRepositoryRequest putRepositoryRequest = new PutRepositoryRequest(repository);
@ -1555,10 +1556,10 @@ public class RequestConvertersTests extends ESTestCase {
putRepositoryRequest.settings(
Settings.builder()
.put(FsRepository.LOCATION_SETTING.getKey(), repositoryLocation)
.put(FsRepository.COMPRESS_SETTING.getKey(), randomBoolean())
.put(FsRepository.CHUNK_SIZE_SETTING.getKey(), randomIntBetween(100, 1000), ByteSizeUnit.BYTES)
.build());
.put(FsRepository.LOCATION_SETTING.getKey(), repositoryLocation)
.put(FsRepository.COMPRESS_SETTING.getKey(), randomBoolean())
.put(FsRepository.CHUNK_SIZE_SETTING.getKey(), randomIntBetween(100, 1000), ByteSizeUnit.BYTES)
.build());
Request request = RequestConverters.createRepository(putRepositoryRequest);
assertThat(endpoint, equalTo(request.getEndpoint()));
@ -1566,6 +1567,24 @@ public class RequestConvertersTests extends ESTestCase {
assertToXContentBody(putRepositoryRequest, request.getEntity());
}
public void testDeleteRepository() {
Map<String, String> expectedParams = new HashMap<>();
String repository = randomIndicesNames(1, 1)[0];
StringBuilder endpoint = new StringBuilder("/_snapshot/" + repository);
DeleteRepositoryRequest deleteRepositoryRequest = new DeleteRepositoryRequest();
deleteRepositoryRequest.name(repository);
setRandomMasterTimeout(deleteRepositoryRequest, expectedParams);
setRandomTimeout(deleteRepositoryRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
Request request = RequestConverters.deleteRepository(deleteRepositoryRequest);
assertThat(endpoint.toString(), equalTo(request.getEndpoint()));
assertThat(HttpDelete.METHOD_NAME, equalTo(request.getMethod()));
assertThat(expectedParams, equalTo(request.getParameters()));
assertNull(request.getEntity());
}
public void testPutTemplateRequest() throws Exception {
Map<String, String> names = new HashMap<>();
names.put("log", "log");

View File

@ -19,7 +19,11 @@
package org.elasticsearch.client;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
@ -29,6 +33,7 @@ import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.rest.RestStatus;
import java.io.IOException;
import java.util.Collections;
import static org.hamcrest.Matchers.equalTo;
@ -40,7 +45,6 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
request.type(type);
return execute(request, highLevelClient().snapshot()::createRepository,
highLevelClient().snapshot()::createRepositoryAsync);
}
public void testCreateRepository() throws IOException {
@ -48,7 +52,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
assertTrue(response.isAcknowledged());
}
public void testModulesGetRepositoriesUsingParams() throws IOException {
public void testSnapshotGetRepositoriesUsingParams() throws IOException {
String testRepository = "test";
assertTrue(createTestRepository(testRepository, FsRepository.TYPE, "{\"location\": \".\"}").isAcknowledged());
assertTrue(createTestRepository("other", FsRepository.TYPE, "{\"location\": \".\"}").isAcknowledged());
@ -60,7 +64,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
assertThat(1, equalTo(response.repositories().size()));
}
public void testModulesGetDefaultRepositories() throws IOException {
public void testSnapshotGetDefaultRepositories() throws IOException {
assertTrue(createTestRepository("other", FsRepository.TYPE, "{\"location\": \".\"}").isAcknowledged());
assertTrue(createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}").isAcknowledged());
@ -69,7 +73,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
assertThat(2, equalTo(response.repositories().size()));
}
public void testModulesGetRepositoriesNonExistent() throws IOException {
public void testSnapshotGetRepositoriesNonExistent() {
String repository = "doesnotexist";
GetRepositoriesRequest request = new GetRepositoriesRequest(new String[]{repository});
ElasticsearchException exception = expectThrows(ElasticsearchException.class, () -> execute(request,
@ -79,4 +83,23 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
assertThat(exception.getMessage(), equalTo(
"Elasticsearch exception [type=repository_missing_exception, reason=[" + repository + "] missing]"));
}
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));
GetRepositoriesRequest request = new GetRepositoriesRequest();
GetRepositoriesResponse response = execute(request, highLevelClient().snapshot()::getRepositories,
highLevelClient().snapshot()::getRepositoriesAsync);
assertThat(1, equalTo(response.repositories().size()));
DeleteRepositoryRequest deleteRequest = new DeleteRepositoryRequest(repository);
DeleteRepositoryResponse deleteResponse = execute(deleteRequest, highLevelClient().snapshot()::deleteRepository,
highLevelClient().snapshot()::deleteRepositoryAsync);
assertTrue(deleteResponse.isAcknowledged());
}
}

View File

@ -21,6 +21,8 @@ package org.elasticsearch.client.documentation;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.LatchedActionListener;
import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
@ -235,6 +237,66 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
}
}
public void testSnapshotDeleteRepository() throws IOException {
RestHighLevelClient client = highLevelClient();
createTestRepositories();
// tag::delete-repository-request
DeleteRepositoryRequest request = new DeleteRepositoryRequest(repositoryName);
// end::delete-repository-request
// tag::delete-repository-request-masterTimeout
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
request.masterNodeTimeout("1m"); // <2>
// end::delete-repository-request-masterTimeout
// tag::delete-repository-request-timeout
request.timeout(TimeValue.timeValueMinutes(1)); // <1>
request.timeout("1m"); // <2>
// end::delete-repository-request-timeout
// tag::delete-repository-execute
DeleteRepositoryResponse response = client.snapshot().deleteRepository(request);
// end::delete-repository-execute
// tag::delete-repository-response
boolean acknowledged = response.isAcknowledged(); // <1>
// end::delete-repository-response
assertTrue(acknowledged);
}
public void testSnapshotDeleteRepositoryAsync() throws InterruptedException {
RestHighLevelClient client = highLevelClient();
{
DeleteRepositoryRequest request = new DeleteRepositoryRequest();
// tag::delete-repository-execute-listener
ActionListener<DeleteRepositoryResponse> listener =
new ActionListener<DeleteRepositoryResponse>() {
@Override
public void onResponse(DeleteRepositoryResponse deleteRepositoryResponse) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::delete-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::delete-repository-execute-async
client.snapshot().deleteRepositoryAsync(request, listener); // <1>
// end::delete-repository-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
private void createTestRepositories() throws IOException {
PutRepositoryRequest request = new PutRepositoryRequest(repositoryName);
request.type(FsRepository.TYPE);

View File

@ -0,0 +1,82 @@
[[java-rest-high-snapshot-delete-repository]]
=== Snapshot Delete Repository API
The Snapshot Delete Repository API allows to delete a registered repository.
[[java-rest-high-snapshot-delete-repository-request]]
==== Snapshot Delete Repository Request
A `DeleteRepositoryRequest`:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-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[delete-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-delete-repository-sync]]
==== Synchronous Execution
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-repository-execute]
--------------------------------------------------
[[java-rest-high-snapshot-delete-repository-async]]
==== Asynchronous Execution
The asynchronous execution of a snapshot delete repository requires both the
`DeleteRepositoryRequest` instance and an `ActionListener` instance to be
passed to the asynchronous method:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-repository-execute-async]
--------------------------------------------------
<1> The `DeleteRepositoryRequest` 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 `DeleteRepositoryResponse` looks like:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-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-delete-repository-response]]
==== Snapshot Delete Repository Response
The returned `DeleteRepositoryResponse` allows to retrieve information about the
executed operation as follows:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-repository-response]
--------------------------------------------------
<1> Indicates the node has acknowledged the request

View File

@ -114,6 +114,9 @@ include::cluster/list_tasks.asciidoc[]
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>>
include::snapshot/get_repository.asciidoc[]
include::snapshot/create_repository.asciidoc[]
include::snapshot/delete_repository.asciidoc[]

View File

@ -22,6 +22,9 @@ package org.elasticsearch.action.admin.cluster.repositories.delete;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
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.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
@ -30,6 +33,13 @@ import java.io.IOException;
*/
public class DeleteRepositoryResponse extends AcknowledgedResponse {
private static final ConstructingObjectParser<DeleteRepositoryResponse, Void> PARSER =
new ConstructingObjectParser<>("delete_repository", true, args -> new DeleteRepositoryResponse((boolean) args[0]));
static {
declareAcknowledgedField(PARSER);
}
DeleteRepositoryResponse() {
}
@ -49,4 +59,7 @@ public class DeleteRepositoryResponse extends AcknowledgedResponse {
writeAcknowledged(out);
}
public static DeleteRepositoryResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}
}

View File

@ -49,7 +49,6 @@ public class RestDeleteRepositoryAction extends BaseRestHandler {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
DeleteRepositoryRequest deleteRepositoryRequest = deleteRepositoryRequest(request.param("repository"));
deleteRepositoryRequest.masterNodeTimeout(request.paramAsTime("master_timeout", deleteRepositoryRequest.masterNodeTimeout()));
deleteRepositoryRequest.timeout(request.paramAsTime("timeout", deleteRepositoryRequest.timeout()));
deleteRepositoryRequest.masterNodeTimeout(request.paramAsTime("master_timeout", deleteRepositoryRequest.masterNodeTimeout()));
return channel -> client.admin().cluster().deleteRepository(deleteRepositoryRequest, new RestToXContentListener<>(channel));

View File

@ -0,0 +1,40 @@
/*
* 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.delete;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
public class DeleteRepositoryResponseTests extends AbstractStreamableXContentTestCase<DeleteRepositoryResponse> {
@Override
protected DeleteRepositoryResponse doParseInstance(XContentParser parser) {
return DeleteRepositoryResponse.fromXContent(parser);
}
@Override
protected DeleteRepositoryResponse createBlankInstance() {
return new DeleteRepositoryResponse();
}
@Override
protected DeleteRepositoryResponse createTestInstance() {
return new DeleteRepositoryResponse(randomBoolean());
}
}