Skip to content

Add Clone Index API #44267

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

Merged
merged 4 commits into from
Jul 25, 2019
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -909,6 +909,33 @@ public void splitAsync(ResizeRequest resizeRequest, RequestOptions options, Acti
ResizeResponse::fromXContent, listener, emptySet());
}

/**
* Clones an index using the Clone Index API.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clone-index.html">
* Clone Index API on elastic.co</a>
* @param resizeRequest 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 ResizeResponse clone(ResizeRequest resizeRequest, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(resizeRequest, IndicesRequestConverters::clone, options,
ResizeResponse::fromXContent, emptySet());
}

/**
* Asynchronously clones an index using the Clone Index API.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clone-index.html">
* Clone Index API on elastic.co</a>
* @param resizeRequest 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 cloneAsync(ResizeRequest resizeRequest, RequestOptions options, ActionListener<ResizeResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, IndicesRequestConverters::clone, options,
ResizeResponse::fromXContent, listener, emptySet());
}

/**
* Rolls over an index using the Rollover Index API.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-rollover-index.html">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,13 @@ static Request shrink(ResizeRequest resizeRequest) throws IOException {
return resize(resizeRequest);
}

static Request clone(ResizeRequest resizeRequest) throws IOException {
if (resizeRequest.getResizeType() != ResizeType.CLONE) {
throw new IllegalArgumentException("Wrong resize type [" + resizeRequest.getResizeType() + "] for indices clone request");
}
return resize(resizeRequest);
}

private static Request resize(ResizeRequest resizeRequest) throws IOException {
String endpoint = new RequestConverters.EndpointBuilder().addPathPart(resizeRequest.getSourceIndex())
.addPathPartAsIs("_" + resizeRequest.getResizeType().name().toLowerCase(Locale.ROOT))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,30 @@ public void testSplit() throws IOException {
assertNotNull(aliasData);
}

@SuppressWarnings("unchecked")
public void testClone() throws IOException {
createIndex("source", Settings.builder().put("index.number_of_shards", 2).put("index.number_of_replicas", 0)
.put("index.number_of_routing_shards", 4).build());
updateIndexSettings("source", Settings.builder().put("index.blocks.write", true));

ResizeRequest resizeRequest = new ResizeRequest("target", "source");
resizeRequest.setResizeType(ResizeType.CLONE);
Settings targetSettings = Settings.builder().put("index.number_of_shards", 2).put("index.number_of_replicas", 0).build();
resizeRequest.setTargetIndex(new org.elasticsearch.action.admin.indices.create.CreateIndexRequest("target")
.settings(targetSettings)
.alias(new Alias("alias")));
ResizeResponse resizeResponse = execute(resizeRequest, highLevelClient().indices()::clone, highLevelClient().indices()::cloneAsync);
assertTrue(resizeResponse.isAcknowledged());
assertTrue(resizeResponse.isShardsAcknowledged());
Map<String, Object> getIndexResponse = getAsMap("target");
Map<String, Object> indexSettings = (Map<String, Object>)XContentMapValues.extractValue("target.settings.index", getIndexResponse);
assertNotNull(indexSettings);
assertEquals("2", indexSettings.get("number_of_shards"));
assertEquals("0", indexSettings.get("number_of_replicas"));
Map<String, Object> aliasData = (Map<String, Object>)XContentMapValues.extractValue("target.aliases.alias", getIndexResponse);
assertNotNull(aliasData);
}

public void testRollover() throws IOException {
highLevelClient().indices().create(new CreateIndexRequest("test").alias(new Alias("alias")), RequestOptions.DEFAULT);
RolloverRequest rolloverRequest = new RolloverRequest("alias", "test_new");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -830,18 +830,33 @@ public void testSplit() throws IOException {

public void testSplitWrongResizeType() {
ResizeRequest resizeRequest = new ResizeRequest("target", "source");
resizeRequest.setResizeType(ResizeType.SHRINK);
ResizeType wrongType = randomFrom(ResizeType.SHRINK, ResizeType.CLONE);
resizeRequest.setResizeType(wrongType);
IllegalArgumentException iae = LuceneTestCase.expectThrows(IllegalArgumentException.class, ()
-> IndicesRequestConverters.split(resizeRequest));
Assert.assertEquals("Wrong resize type [SHRINK] for indices split request", iae.getMessage());
Assert.assertEquals("Wrong resize type [" + wrongType.name() + "] for indices split request", iae.getMessage());
}

public void testClone() throws IOException {
resizeTest(ResizeType.CLONE, IndicesRequestConverters::clone);
}

public void testCloneWrongResizeType() {
ResizeRequest resizeRequest = new ResizeRequest("target", "source");
ResizeType wrongType = randomFrom(ResizeType.SHRINK, ResizeType.SPLIT);
resizeRequest.setResizeType(wrongType);
IllegalArgumentException iae = LuceneTestCase.expectThrows(IllegalArgumentException.class, ()
-> IndicesRequestConverters.clone(resizeRequest));
Assert.assertEquals("Wrong resize type [" + wrongType.name() + "] for indices clone request", iae.getMessage());
}

public void testShrinkWrongResizeType() {
ResizeRequest resizeRequest = new ResizeRequest("target", "source");
resizeRequest.setResizeType(ResizeType.SPLIT);
ResizeType wrongType = randomFrom(ResizeType.SPLIT, ResizeType.CLONE);
resizeRequest.setResizeType(wrongType);
IllegalArgumentException iae = LuceneTestCase.expectThrows(IllegalArgumentException.class, ()
-> IndicesRequestConverters.shrink(resizeRequest));
Assert.assertEquals("Wrong resize type [SPLIT] for indices shrink request", iae.getMessage());
Assert.assertEquals("Wrong resize type [" + wrongType.name() + "] for indices shrink request", iae.getMessage());
}

public void testShrink() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1808,6 +1808,75 @@ public void onFailure(Exception e) {
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}

public void testCloneIndex() throws Exception {
RestHighLevelClient client = highLevelClient();

{
createIndex("source_index", Settings.builder().put("index.number_of_shards", 2).put("index.number_of_replicas", 0).build());
updateIndexSettings("source_index", Settings.builder().put("index.blocks.write", true));
}

// tag::clone-index-request
ResizeRequest request = new ResizeRequest("target_index","source_index"); // <1>
request.setResizeType(ResizeType.CLONE); // <2>
// end::clone-index-request

// tag::clone-index-request-timeout
request.timeout(TimeValue.timeValueMinutes(2)); // <1>
request.timeout("2m"); // <2>
// end::clone-index-request-timeout
// tag::clone-index-request-masterTimeout
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
request.masterNodeTimeout("1m"); // <2>
// end::clone-index-request-masterTimeout
// tag::clone-index-request-waitForActiveShards
request.setWaitForActiveShards(2); // <1>
request.setWaitForActiveShards(ActiveShardCount.DEFAULT); // <2>
// end::clone-index-request-waitForActiveShards
// tag::clone-index-request-settings
request.getTargetIndexRequest().settings(Settings.builder()
.put("index.number_of_shards", 2)); // <1>
// end::clone-index-request-settings
// tag::clone-index-request-aliases
request.getTargetIndexRequest().alias(new Alias("target_alias")); // <1>
// end::clone-index-request-aliases

// tag::clone-index-execute
ResizeResponse resizeResponse = client.indices().clone(request, RequestOptions.DEFAULT);
// end::clone-index-execute

// tag::clone-index-response
boolean acknowledged = resizeResponse.isAcknowledged(); // <1>
boolean shardsAcked = resizeResponse.isShardsAcknowledged(); // <2>
// end::clone-index-response
assertTrue(acknowledged);
assertTrue(shardsAcked);

// tag::clone-index-execute-listener
ActionListener<ResizeResponse> listener = new ActionListener<ResizeResponse>() {
@Override
public void onResponse(ResizeResponse resizeResponse) {
// <1>
}

@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::clone-index-execute-listener

// Replace the empty listener by a blocking listener in test
final CountDownLatch latch = new CountDownLatch(1);
listener = new LatchedActionListener<>(listener, latch);

// tag::clone-index-execute-async
client.indices().cloneAsync(request, RequestOptions.DEFAULT,listener); // <1>
// end::clone-index-execute-async

assertTrue(latch.await(30L, TimeUnit.SECONDS));
}

public void testRolloverIndex() throws Exception {
RestHighLevelClient client = highLevelClient();

Expand Down
80 changes: 80 additions & 0 deletions docs/java-rest/high-level/indices/clone_index.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
--
:api: clone-index
:request: ResizeRequest
:response: ResizeResponse
--

[id="{upid}-{api}"]
=== Clone Index API

[id="{upid}-{api}-request"]
==== Resize Request

The Clone Index API requires a +{request}+ instance.
A +{request}+ requires two string arguments:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-request]
--------------------------------------------------
<1> The target index (first argument) to clone the source index (second argument) into
<2> The resize type needs to be set to `CLONE`

==== Optional arguments
The following arguments can optionally be provided:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-request-timeout]
--------------------------------------------------
<1> Timeout to wait for the all the nodes to acknowledge the index is opened
as a `TimeValue`
<2> Timeout to wait for the all the nodes to acknowledge the index is opened
as a `String`

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-request-masterTimeout]
--------------------------------------------------
<1> Timeout to connect to the master node as a `TimeValue`
<2> Timeout to connect to the master node as a `String`

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-request-waitForActiveShards]
--------------------------------------------------
<1> The number of active shard copies to wait for before the clone index API
returns a response, as an `int`
<2> The number of active shard copies to wait for before the clone index API
returns a response, as an `ActiveShardCount`

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-request-settings]
--------------------------------------------------
<1> The settings to apply to the target index, which optionally include the
number of shards to create for it

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-request-aliases]
--------------------------------------------------
<1> The aliases to associate the target index with

include::../execution.asciidoc[]

[id="{upid}-{api}-response"]
==== Clone Index Response

The returned +{response}+ allows to retrieve information about the
executed operation as follows:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-response]
--------------------------------------------------
<1> Indicates whether all of the nodes have acknowledged the request
<2> Indicates whether the requisite number of shard copies were started for
each shard in the index before timing out


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 @@ -99,6 +99,7 @@ Index Management::
* <<{upid}-close-index>>
* <<{upid}-shrink-index>>
* <<{upid}-split-index>>
* <<{upid}-clone-index>>
* <<{upid}-refresh>>
* <<{upid}-flush>>
* <<{upid}-flush-synced>>
Expand Down Expand Up @@ -133,6 +134,7 @@ include::indices/open_index.asciidoc[]
include::indices/close_index.asciidoc[]
include::indices/shrink_index.asciidoc[]
include::indices/split_index.asciidoc[]
include::indices/clone_index.asciidoc[]
include::indices/refresh.asciidoc[]
include::indices/flush.asciidoc[]
include::indices/flush_synced.asciidoc[]
Expand Down
3 changes: 3 additions & 0 deletions docs/reference/indices.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ index settings, aliases, mappings, and index templates.
* <<indices-open-close>>
* <<indices-shrink-index>>
* <<indices-split-index>>
* <<indices-clone-index>>
* <<indices-rollover-index>>
* <<freeze-index-api>>
* <<unfreeze-index-api>>
Expand Down Expand Up @@ -72,6 +73,8 @@ include::indices/shrink-index.asciidoc[]

include::indices/split-index.asciidoc[]

include::indices/clone-index.asciidoc[]

include::indices/rollover-index.asciidoc[]

include::indices/apis/freeze.asciidoc[]
Expand Down
Loading