Add Delete Snapshot High Level REST API

With this commit we add the delete snapshot API to the Java high level
REST client.

Relates #27205
Relates #31393
This commit is contained in:
Daniel Mitterdorfer 2018-06-20 16:42:50 +02:00 committed by GitHub
parent db1b97fd85
commit 90d62e6e4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 287 additions and 0 deletions

View File

@ -39,6 +39,7 @@ import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyReposito
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
@ -844,6 +845,18 @@ final class RequestConverters {
return request; return request;
} }
static Request deleteSnapshot(DeleteSnapshotRequest deleteSnapshotRequest) {
String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot")
.addPathPart(deleteSnapshotRequest.repository())
.addPathPart(deleteSnapshotRequest.snapshot())
.build();
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
Params parameters = new Params(request);
parameters.withMasterTimeout(deleteSnapshotRequest.masterNodeTimeout());
return request;
}
static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) throws IOException { static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) throws IOException {
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addPathPart(putIndexTemplateRequest.name()).build(); String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addPathPart(putIndexTemplateRequest.name()).build();
Request request = new Request(HttpPut.METHOD_NAME, endpoint); Request request = new Request(HttpPut.METHOD_NAME, endpoint);

View File

@ -28,6 +28,8 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequ
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse; 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.VerifyRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse; 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 java.io.IOException; import java.io.IOException;
@ -161,4 +163,34 @@ public final class SnapshotClient {
restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository, options, restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository, options,
VerifyRepositoryResponse::fromXContent, listener, emptySet()); VerifyRepositoryResponse::fromXContent, listener, emptySet());
} }
/**
* Deletes a snapshot.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
* API on elastic.co</a>
*
* @param deleteSnapshotRequest 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 DeleteSnapshotResponse delete(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
DeleteSnapshotResponse::fromXContent, emptySet());
}
/**
* Asynchronously deletes a snapshot.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
* API on elastic.co</a>
*
* @param deleteSnapshotRequest 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 deleteAsync(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options,
ActionListener<DeleteSnapshotResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
DeleteSnapshotResponse::fromXContent, listener, emptySet());
}
} }

View File

@ -37,6 +37,7 @@ import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRe
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.admin.indices.alias.Alias;
@ -1857,6 +1858,25 @@ public class RequestConvertersTests extends ESTestCase {
assertThat(expectedParams, equalTo(request.getParameters())); assertThat(expectedParams, equalTo(request.getParameters()));
} }
public void testDeleteSnapshot() {
Map<String, String> expectedParams = new HashMap<>();
String repository = randomIndicesNames(1, 1)[0];
String snapshot = "snapshot-" + randomAlphaOfLengthBetween(2, 5).toLowerCase(Locale.ROOT);
String endpoint = String.format(Locale.ROOT, "/_snapshot/%s/%s", repository, snapshot);
DeleteSnapshotRequest deleteSnapshotRequest = new DeleteSnapshotRequest();
deleteSnapshotRequest.repository(repository);
deleteSnapshotRequest.snapshot(snapshot);
setRandomMasterTimeout(deleteSnapshotRequest, expectedParams);
Request request = RequestConverters.deleteSnapshot(deleteSnapshotRequest);
assertThat(endpoint, equalTo(request.getEndpoint()));
assertThat(HttpDelete.METHOD_NAME, equalTo(request.getMethod()));
assertThat(expectedParams, equalTo(request.getParameters()));
assertNull(request.getEntity());
}
public void testPutTemplateRequest() throws Exception { public void testPutTemplateRequest() throws Exception {
Map<String, String> names = new HashMap<>(); Map<String, String> names = new HashMap<>();
names.put("log", "log"); names.put("log", "log");

View File

@ -28,11 +28,14 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequ
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse; 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.VerifyRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse; 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.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.repositories.fs.FsRepository; import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import java.io.IOException; import java.io.IOException;
import java.util.Locale;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@ -46,6 +49,13 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
highLevelClient().snapshot()::createRepositoryAsync); highLevelClient().snapshot()::createRepositoryAsync);
} }
private Response createTestSnapshot(String repository, String snapshot) throws IOException {
Request createSnapshot = new Request("put", String.format(Locale.ROOT, "_snapshot/%s/%s", repository, snapshot));
createSnapshot.addParameter("wait_for_completion", "true");
return highLevelClient().getLowLevelClient().performRequest(createSnapshot);
}
public void testCreateRepository() throws IOException { public void testCreateRepository() throws IOException {
PutRepositoryResponse response = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}"); PutRepositoryResponse response = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
assertTrue(response.isAcknowledged()); assertTrue(response.isAcknowledged());
@ -108,4 +118,21 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
highLevelClient().snapshot()::verifyRepositoryAsync); highLevelClient().snapshot()::verifyRepositoryAsync);
assertThat(response.getNodes().size(), equalTo(1)); assertThat(response.getNodes().size(), equalTo(1));
} }
public void testDeleteSnapshot() 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());
DeleteSnapshotRequest request = new DeleteSnapshotRequest(repository, snapshot);
DeleteSnapshotResponse response = execute(request, highLevelClient().snapshot()::delete, highLevelClient().snapshot()::deleteAsync);
assertTrue(response.isAcknowledged());
}
} }

View File

@ -29,8 +29,12 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequ
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse; 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.VerifyRepositoryRequest;
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse; 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.client.ESRestHighLevelClientTestCase; import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.metadata.RepositoryMetaData; import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -41,6 +45,7 @@ import org.elasticsearch.repositories.fs.FsRepository;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -69,6 +74,8 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
private static final String repositoryName = "test_repository"; private static final String repositoryName = "test_repository";
private static final String snapshotName = "test_snapshot";
public void testSnapshotCreateRepository() throws IOException { public void testSnapshotCreateRepository() throws IOException {
RestHighLevelClient client = highLevelClient(); RestHighLevelClient client = highLevelClient();
@ -360,10 +367,76 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
} }
} }
public void testSnapshotDeleteSnapshot() throws IOException {
RestHighLevelClient client = highLevelClient();
createTestRepositories();
createTestSnapshots();
// tag::delete-snapshot-request
DeleteSnapshotRequest request = new DeleteSnapshotRequest(repositoryName);
request.snapshot(snapshotName);
// end::delete-snapshot-request
// tag::delete-snapshot-request-masterTimeout
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
request.masterNodeTimeout("1m"); // <2>
// end::delete-snapshot-request-masterTimeout
// tag::delete-snapshot-execute
DeleteSnapshotResponse response = client.snapshot().delete(request, RequestOptions.DEFAULT);
// end::delete-snapshot-execute
// tag::delete-snapshot-response
boolean acknowledged = response.isAcknowledged(); // <1>
// end::delete-snapshot-response
assertTrue(acknowledged);
}
public void testSnapshotDeleteSnapshotAsync() throws InterruptedException {
RestHighLevelClient client = highLevelClient();
{
DeleteSnapshotRequest request = new DeleteSnapshotRequest();
// tag::delete-snapshot-execute-listener
ActionListener<DeleteSnapshotResponse> listener =
new ActionListener<DeleteSnapshotResponse>() {
@Override
public void onResponse(DeleteSnapshotResponse deleteSnapshotResponse) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::delete-snapshot-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-snapshot-execute-async
client.snapshot().deleteAsync(request, RequestOptions.DEFAULT, listener); // <1>
// end::delete-snapshot-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
private void createTestRepositories() throws IOException { private void createTestRepositories() throws IOException {
PutRepositoryRequest request = new PutRepositoryRequest(repositoryName); PutRepositoryRequest request = new PutRepositoryRequest(repositoryName);
request.type(FsRepository.TYPE); request.type(FsRepository.TYPE);
request.settings("{\"location\": \".\"}", XContentType.JSON); request.settings("{\"location\": \".\"}", XContentType.JSON);
assertTrue(highLevelClient().snapshot().createRepository(request, RequestOptions.DEFAULT).isAcknowledged()); assertTrue(highLevelClient().snapshot().createRepository(request, RequestOptions.DEFAULT).isAcknowledged());
} }
private void createTestSnapshots() throws IOException {
Request createSnapshot = new Request("put", String.format(Locale.ROOT, "_snapshot/%s/%s", repositoryName, snapshotName));
createSnapshot.addParameter("wait_for_completion", "true");
Response response = highLevelClient().getLowLevelClient().performRequest(createSnapshot);
// check that the request went ok without parsing JSON here. When using the high level client, check acknowledgement instead.
assertEquals(200, response.getStatusLine().getStatusCode());
}
} }

View File

@ -0,0 +1,73 @@
[[java-rest-high-snapshot-delete-snapshot]]
=== Delete Snapshot API
The Delete Snapshot API allows to delete a snapshot.
[[java-rest-high-snapshot-delete-snapshot-request]]
==== Delete Snapshot Request
A `DeleteSnapshotRequest`:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-request]
--------------------------------------------------
==== Optional Arguments
The following arguments can optionally be provided:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-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-delete-snapshot-sync]]
==== Synchronous Execution
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-execute]
--------------------------------------------------
[[java-rest-high-snapshot-delete-snapshot-async]]
==== Asynchronous Execution
The asynchronous execution of a delete snapshot request requires both the
`DeleteSnapshotRequest` 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-snapshot-execute-async]
--------------------------------------------------
<1> The `DeleteSnapshotRequest` 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 `DeleteSnapshotResponse` looks like:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-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-cluster-delete-snapshot-response]]
==== Delete Snapshot Response
The returned `DeleteSnapshotResponse` allows to retrieve information about the
executed operation as follows:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[delete-snapshot-response]
--------------------------------------------------
<1> Indicates the node has acknowledged the request

View File

@ -136,11 +136,13 @@ The Java High Level REST Client supports the following Snapshot APIs:
* <<java-rest-high-snapshot-create-repository>> * <<java-rest-high-snapshot-create-repository>>
* <<java-rest-high-snapshot-delete-repository>> * <<java-rest-high-snapshot-delete-repository>>
* <<java-rest-high-snapshot-verify-repository>> * <<java-rest-high-snapshot-verify-repository>>
* <<java-rest-high-snapshot-delete-snapshot>>
include::snapshot/get_repository.asciidoc[] include::snapshot/get_repository.asciidoc[]
include::snapshot/create_repository.asciidoc[] include::snapshot/create_repository.asciidoc[]
include::snapshot/delete_repository.asciidoc[] include::snapshot/delete_repository.asciidoc[]
include::snapshot/verify_repository.asciidoc[] include::snapshot/verify_repository.asciidoc[]
include::snapshot/delete_snapshot.asciidoc[]
== Tasks APIs == Tasks APIs

View File

@ -20,6 +20,7 @@
package org.elasticsearch.action.admin.cluster.snapshots.delete; package org.elasticsearch.action.admin.cluster.snapshots.delete;
import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.xcontent.XContentParser;
/** /**
* Delete snapshot response * Delete snapshot response
@ -32,4 +33,9 @@ public class DeleteSnapshotResponse extends AcknowledgedResponse {
DeleteSnapshotResponse(boolean acknowledged) { DeleteSnapshotResponse(boolean acknowledged) {
super(acknowledged); super(acknowledged);
} }
public static DeleteSnapshotResponse fromXContent(XContentParser parser) {
return new DeleteSnapshotResponse(parseAcknowledged(parser));
}
} }

View File

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