Adds snapshot clone REST tests and HLRC support for the API.
This commit is contained in:
parent
1287df4074
commit
1880bcdc09
|
@ -28,6 +28,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.repositories.verify.VerifyRepositoryResponse;
|
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
|
||||||
|
import org.elasticsearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
|
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
|
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
|
||||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
||||||
|
@ -236,6 +237,32 @@ public final class SnapshotClient {
|
||||||
CreateSnapshotResponse::fromXContent, listener, emptySet());
|
CreateSnapshotResponse::fromXContent, listener, emptySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clones a snapshot.
|
||||||
|
* <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 AcknowledgedResponse clone(CloneSnapshotRequest cloneSnapshotRequest, RequestOptions options)
|
||||||
|
throws IOException {
|
||||||
|
return restHighLevelClient.performRequestAndParseEntity(cloneSnapshotRequest, SnapshotRequestConverters::cloneSnapshot, options,
|
||||||
|
AcknowledgedResponse::fromXContent, emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously clones a snapshot.
|
||||||
|
* <p>
|
||||||
|
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
|
||||||
|
* API on elastic.co</a>
|
||||||
|
* @return cancellable that may be used to cancel the request
|
||||||
|
*/
|
||||||
|
public Cancellable cloneAsync(CloneSnapshotRequest cloneSnapshotRequest, RequestOptions options,
|
||||||
|
ActionListener<AcknowledgedResponse> listener) {
|
||||||
|
return restHighLevelClient.performRequestAsyncAndParseEntity(cloneSnapshotRequest,
|
||||||
|
SnapshotRequestConverters::cloneSnapshot, options,
|
||||||
|
AcknowledgedResponse::fromXContent, listener, emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get snapshots.
|
* Get snapshots.
|
||||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
|
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteReposito
|
||||||
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
|
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.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.snapshots.clone.CloneSnapshotRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
|
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
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.GetSnapshotsRequest;
|
||||||
|
@ -123,6 +124,21 @@ final class SnapshotRequestConverters {
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Request cloneSnapshot(CloneSnapshotRequest cloneSnapshotRequest) throws IOException {
|
||||||
|
String endpoint = new RequestConverters.EndpointBuilder().addPathPart("_snapshot")
|
||||||
|
.addPathPart(cloneSnapshotRequest.repository())
|
||||||
|
.addPathPart(cloneSnapshotRequest.source())
|
||||||
|
.addPathPart("_clone")
|
||||||
|
.addPathPart(cloneSnapshotRequest.target())
|
||||||
|
.build();
|
||||||
|
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
|
||||||
|
RequestConverters.Params params = new RequestConverters.Params();
|
||||||
|
params.withMasterTimeout(cloneSnapshotRequest.masterNodeTimeout());
|
||||||
|
request.addParameters(params.asMap());
|
||||||
|
request.setEntity(RequestConverters.createEntity(cloneSnapshotRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
static Request getSnapshots(GetSnapshotsRequest getSnapshotsRequest) {
|
static Request getSnapshots(GetSnapshotsRequest getSnapshotsRequest) {
|
||||||
RequestConverters.EndpointBuilder endpointBuilder = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot")
|
RequestConverters.EndpointBuilder endpointBuilder = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot")
|
||||||
.addPathPart(getSnapshotsRequest.repository());
|
.addPathPart(getSnapshotsRequest.repository());
|
||||||
|
|
|
@ -28,6 +28,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.repositories.verify.VerifyRepositoryResponse;
|
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
|
||||||
|
import org.elasticsearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
|
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
|
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
|
||||||
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
|
||||||
|
@ -351,6 +352,30 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
|
||||||
assertTrue(response.isAcknowledged());
|
assertTrue(response.isAcknowledged());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCloneSnapshot() throws IOException {
|
||||||
|
String repository = "test_repository";
|
||||||
|
String snapshot = "source_snapshot";
|
||||||
|
String targetSnapshot = "target_snapshot";
|
||||||
|
final String testIndex = "test_idx";
|
||||||
|
|
||||||
|
createIndex(testIndex, Settings.EMPTY);
|
||||||
|
assertTrue("index [" + testIndex + "] should have been created", indexExists(testIndex));
|
||||||
|
|
||||||
|
AcknowledgedResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
|
||||||
|
assertTrue(putRepositoryResponse.isAcknowledged());
|
||||||
|
|
||||||
|
CreateSnapshotRequest createSnapshotRequest = new CreateSnapshotRequest(repository, snapshot);
|
||||||
|
createSnapshotRequest.waitForCompletion(true);
|
||||||
|
|
||||||
|
CreateSnapshotResponse createSnapshotResponse = createTestSnapshot(createSnapshotRequest);
|
||||||
|
assertEquals(RestStatus.OK, createSnapshotResponse.status());
|
||||||
|
|
||||||
|
CloneSnapshotRequest request = new CloneSnapshotRequest(repository, snapshot, targetSnapshot, new String[]{testIndex});
|
||||||
|
AcknowledgedResponse response = execute(request, highLevelClient().snapshot()::clone, highLevelClient().snapshot()::cloneAsync);
|
||||||
|
|
||||||
|
assertTrue(response.isAcknowledged());
|
||||||
|
}
|
||||||
|
|
||||||
private static Map<String, Object> randomUserMetadata() {
|
private static Map<String, Object> randomUserMetadata() {
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"snapshot.clone":{
|
||||||
|
"documentation":{
|
||||||
|
"url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html",
|
||||||
|
"description":"Clones indices from one snapshot into another snapshot in the same repository."
|
||||||
|
},
|
||||||
|
"stability":"stable",
|
||||||
|
"url":{
|
||||||
|
"paths":[
|
||||||
|
{
|
||||||
|
"path":"/_snapshot/{repository}/{snapshot}/_clone/{target_snapshot}",
|
||||||
|
"methods":[
|
||||||
|
"PUT"
|
||||||
|
],
|
||||||
|
"parts":{
|
||||||
|
"repository":{
|
||||||
|
"type":"string",
|
||||||
|
"description":"A repository name"
|
||||||
|
},
|
||||||
|
"snapshot":{
|
||||||
|
"type":"string",
|
||||||
|
"description":"The name of the snapshot to clone from"
|
||||||
|
},
|
||||||
|
"target_snapshot":{
|
||||||
|
"type":"string",
|
||||||
|
"description":"The name of the cloned snapshot to create"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params":{
|
||||||
|
"master_timeout":{
|
||||||
|
"type":"time",
|
||||||
|
"description":"Explicit operation timeout for connection to master node"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body":{
|
||||||
|
"description":"The snapshot clone definition",
|
||||||
|
"required":true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
---
|
||||||
|
setup:
|
||||||
|
|
||||||
|
- do:
|
||||||
|
snapshot.create_repository:
|
||||||
|
repository: test_repo_create_1
|
||||||
|
body:
|
||||||
|
type: fs
|
||||||
|
settings:
|
||||||
|
location: "test_repo_create_1_loc"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.create:
|
||||||
|
index: test_index_1
|
||||||
|
body:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 1
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.create:
|
||||||
|
index: test_index_2
|
||||||
|
body:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 1
|
||||||
|
|
||||||
|
- do:
|
||||||
|
snapshot.create:
|
||||||
|
repository: test_repo_create_1
|
||||||
|
snapshot: test_snapshot
|
||||||
|
wait_for_completion: true
|
||||||
|
|
||||||
|
---
|
||||||
|
"Clone a snapshot":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.9.99"
|
||||||
|
reason: "Clone snapshot functionality was introduced in 7.10"
|
||||||
|
- do:
|
||||||
|
snapshot.clone:
|
||||||
|
repository: test_repo_create_1
|
||||||
|
snapshot: test_snapshot
|
||||||
|
target_snapshot: target_snapshot_1
|
||||||
|
body:
|
||||||
|
"indices": test_index_2
|
||||||
|
|
||||||
|
- match: { acknowledged: true }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
snapshot.delete:
|
||||||
|
repository: test_repo_create_1
|
||||||
|
snapshot: target_snapshot_1
|
||||||
|
|
||||||
|
- match: { acknowledged: true }
|
|
@ -23,14 +23,17 @@ import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
import org.elasticsearch.action.IndicesRequest;
|
import org.elasticsearch.action.IndicesRequest;
|
||||||
import org.elasticsearch.action.support.IndicesOptions;
|
import org.elasticsearch.action.support.IndicesOptions;
|
||||||
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
||||||
|
|
||||||
public class CloneSnapshotRequest extends MasterNodeRequest<CloneSnapshotRequest> implements IndicesRequest.Replaceable{
|
public class CloneSnapshotRequest extends MasterNodeRequest<CloneSnapshotRequest> implements IndicesRequest.Replaceable, ToXContentObject {
|
||||||
|
|
||||||
private final String repository;
|
private final String repository;
|
||||||
|
|
||||||
|
@ -139,4 +142,29 @@ public class CloneSnapshotRequest extends MasterNodeRequest<CloneSnapshotRequest
|
||||||
public String source() {
|
public String source() {
|
||||||
return this.source;
|
return this.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
|
builder.startObject();
|
||||||
|
builder.field("repository", repository);
|
||||||
|
builder.field("source", source);
|
||||||
|
builder.field("target", target);
|
||||||
|
if (indices != null) {
|
||||||
|
builder.startArray("indices");
|
||||||
|
for (String index : indices) {
|
||||||
|
builder.value(index);
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
|
}
|
||||||
|
if (indicesOptions != null) {
|
||||||
|
indicesOptions.toXContent(builder, params);
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Strings.toString(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue