REST high-level client: add support for Rollover Index API (#28698)

Relates to #27205
This commit is contained in:
Luca Cavanna 2018-02-20 15:58:58 +01:00 committed by GitHub
parent 94594f19ab
commit 8bbb3c9ffa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 1026 additions and 370 deletions

View File

@ -35,6 +35,8 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
@ -272,7 +274,7 @@ public final class IndicesClient {
* Splits an index using the Split Index API
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html">
* Shrink Index API on elastic.co</a>
* Split Index API on elastic.co</a>
*/
public ResizeResponse split(ResizeRequest resizeRequest, Header... headers) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(resizeRequest, Request::split, ResizeResponse::fromXContent,
@ -289,4 +291,26 @@ public final class IndicesClient {
restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, Request::split, ResizeResponse::fromXContent,
listener, emptySet(), headers);
}
/**
* Rolls over an index using the Rollover Index API
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-rollover-index.html">
* Rollover Index API on elastic.co</a>
*/
public RolloverResponse rollover(RolloverRequest rolloverRequest, Header... headers) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(rolloverRequest, Request::rollover, RolloverResponse::fromXContent,
emptySet(), headers);
}
/**
* Asynchronously rolls over an index using the Rollover Index API
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-rollover-index.html">
* Rollover Index API on elastic.co</a>
*/
public void rolloverAsync(RolloverRequest rolloverRequest, ActionListener<RolloverResponse> listener, Header... headers) {
restHighLevelClient.performRequestAsyncAndParseEntity(rolloverRequest, Request::rollover, RolloverResponse::fromXContent,
listener, emptySet(), headers);
}
}

View File

@ -38,6 +38,7 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
import org.elasticsearch.action.bulk.BulkRequest;
@ -498,11 +499,10 @@ public final class Request {
}
static Request rankEval(RankEvalRequest rankEvalRequest) throws IOException {
// TODO maybe indices should be propery of RankEvalRequest and not of the spec
// TODO maybe indices should be property of RankEvalRequest and not of the spec
List<String> indices = rankEvalRequest.getRankEvalSpec().getIndices();
String endpoint = endpoint(indices.toArray(new String[indices.size()]), Strings.EMPTY_ARRAY, "_rank_eval");
HttpEntity entity = null;
entity = createEntity(rankEvalRequest.getRankEvalSpec(), REQUEST_BODY_CONTENT_TYPE);
HttpEntity entity = createEntity(rankEvalRequest.getRankEvalSpec(), REQUEST_BODY_CONTENT_TYPE);
return new Request(HttpGet.METHOD_NAME, endpoint, Collections.emptyMap(), entity);
}
@ -542,6 +542,19 @@ public final class Request {
return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity);
}
static Request rollover(RolloverRequest rolloverRequest) throws IOException {
Params params = Params.builder();
params.withTimeout(rolloverRequest.timeout());
params.withMasterTimeout(rolloverRequest.masterNodeTimeout());
params.withWaitForActiveShards(rolloverRequest.getCreateIndexRequest().waitForActiveShards());
if (rolloverRequest.isDryRun()) {
params.putParam("dry_run", Boolean.TRUE.toString());
}
String endpoint = buildEndpoint(rolloverRequest.getAlias(), "_rollover", rolloverRequest.getNewIndexName());
HttpEntity entity = createEntity(rolloverRequest, REQUEST_BODY_CONTENT_TYPE);
return new Request(HttpPost.METHOD_NAME, endpoint, params.getParams(), entity);
}
private static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException {
BytesRef source = XContentHelper.toXContent(toXContent, xContentType, false).toBytesRef();
return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType));

View File

@ -39,11 +39,18 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
@ -435,4 +442,57 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
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")));
RolloverRequest rolloverRequest = new RolloverRequest("alias", "test_new");
rolloverRequest.addMaxIndexDocsCondition(1);
{
RolloverResponse rolloverResponse = execute(rolloverRequest, highLevelClient().indices()::rollover,
highLevelClient().indices()::rolloverAsync);
assertFalse(rolloverResponse.isRolledOver());
assertFalse(rolloverResponse.isDryRun());
Map<String, Boolean> conditionStatus = rolloverResponse.getConditionStatus();
assertEquals(1, conditionStatus.size());
assertFalse(conditionStatus.get("[max_docs: 1]"));
assertEquals("test", rolloverResponse.getOldIndex());
assertEquals("test_new", rolloverResponse.getNewIndex());
}
highLevelClient().index(new IndexRequest("test", "type", "1").source("field", "value"));
highLevelClient().index(new IndexRequest("test", "type", "2").source("field", "value")
.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL));
//without the refresh the rollover may not happen as the number of docs seen may be off
{
rolloverRequest.addMaxIndexAgeCondition(new TimeValue(1));
rolloverRequest.dryRun(true);
RolloverResponse rolloverResponse = execute(rolloverRequest, highLevelClient().indices()::rollover,
highLevelClient().indices()::rolloverAsync);
assertFalse(rolloverResponse.isRolledOver());
assertTrue(rolloverResponse.isDryRun());
Map<String, Boolean> conditionStatus = rolloverResponse.getConditionStatus();
assertEquals(2, conditionStatus.size());
assertTrue(conditionStatus.get("[max_docs: 1]"));
assertTrue(conditionStatus.get("[max_age: 1ms]"));
assertEquals("test", rolloverResponse.getOldIndex());
assertEquals("test_new", rolloverResponse.getNewIndex());
}
{
rolloverRequest.dryRun(false);
rolloverRequest.addMaxIndexSizeCondition(new ByteSizeValue(1, ByteSizeUnit.MB));
RolloverResponse rolloverResponse = execute(rolloverRequest, highLevelClient().indices()::rollover,
highLevelClient().indices()::rolloverAsync);
assertTrue(rolloverResponse.isRolledOver());
assertFalse(rolloverResponse.isDryRun());
Map<String, Boolean> conditionStatus = rolloverResponse.getConditionStatus();
assertEquals(3, conditionStatus.size());
assertTrue(conditionStatus.get("[max_docs: 1]"));
assertTrue(conditionStatus.get("[max_age: 1ms]"));
assertFalse(conditionStatus.get("[max_size: 1mb]"));
assertEquals("test", rolloverResponse.getOldIndex());
assertEquals("test_new", rolloverResponse.getNewIndex());
}
}
}

View File

@ -40,6 +40,7 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
import org.elasticsearch.action.bulk.BulkRequest;
@ -74,6 +75,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.RandomCreateIndexGenerator;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.rankeval.PrecisionAtK;
@ -1116,11 +1118,9 @@ public class RequestTests extends ESTestCase {
if (randomBoolean()) {
randomAliases(createIndexRequest);
}
setRandomWaitForActiveShards(createIndexRequest::waitForActiveShards, expectedParams);
resizeRequest.setTargetIndex(createIndexRequest);
} else {
setRandomWaitForActiveShards(resizeRequest::setWaitForActiveShards, expectedParams);
}
setRandomWaitForActiveShards(resizeRequest::setWaitForActiveShards, expectedParams);
Request request = function.apply(resizeRequest);
assertEquals(HttpPut.METHOD_NAME, request.getMethod());
@ -1144,6 +1144,44 @@ public class RequestTests extends ESTestCase {
assertEquals(expectedParams, expectedRequest.getParameters());
}
public void testRollover() throws IOException {
RolloverRequest rolloverRequest = new RolloverRequest(randomAlphaOfLengthBetween(3, 10),
randomBoolean() ? null : randomAlphaOfLengthBetween(3, 10));
Map<String, String> expectedParams = new HashMap<>();
setRandomTimeout(rolloverRequest::timeout, rolloverRequest.timeout(), expectedParams);
setRandomMasterTimeout(rolloverRequest, expectedParams);
if (randomBoolean()) {
rolloverRequest.dryRun(randomBoolean());
if (rolloverRequest.isDryRun()) {
expectedParams.put("dry_run", "true");
}
}
if (randomBoolean()) {
rolloverRequest.addMaxIndexAgeCondition(new TimeValue(randomNonNegativeLong()));
}
if (randomBoolean()) {
String type = randomAlphaOfLengthBetween(3, 10);
rolloverRequest.getCreateIndexRequest().mapping(type, RandomCreateIndexGenerator.randomMapping(type));
}
if (randomBoolean()) {
RandomCreateIndexGenerator.randomAliases(rolloverRequest.getCreateIndexRequest());
}
if (randomBoolean()) {
rolloverRequest.getCreateIndexRequest().settings(RandomCreateIndexGenerator.randomIndexSettings());
}
setRandomWaitForActiveShards(rolloverRequest.getCreateIndexRequest()::waitForActiveShards, expectedParams);
Request request = Request.rollover(rolloverRequest);
if (rolloverRequest.getNewIndexName() == null) {
assertEquals("/" + rolloverRequest.getAlias() + "/_rollover", request.getEndpoint());
} else {
assertEquals("/" + rolloverRequest.getAlias() + "/_rollover/" + rolloverRequest.getNewIndexName(), request.getEndpoint());
}
assertEquals(HttpPost.METHOD_NAME, request.getMethod());
assertToXContentBody(rolloverRequest, request.getEntity());
assertEquals(expectedParams, request.getParameters());
}
private static void assertToXContentBody(ToXContent expectedBody, HttpEntity actualEntity) throws IOException {
BytesReference expectedBytes = XContentHelper.toXContent(expectedBody, REQUEST_BODY_CONTENT_TYPE, false);
assertEquals(XContentType.JSON.mediaTypeWithoutParameters(), actualEntity.getContentType().getValue());

View File

@ -38,6 +38,8 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
@ -46,6 +48,8 @@ import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -731,7 +735,6 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
public void testUpdateAliases() throws Exception {
RestHighLevelClient client = highLevelClient();
@ -811,12 +814,12 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
public void testShrinkIndex() throws Exception {
RestHighLevelClient client = highLevelClient();
{
Map<String, Object> nodes = getAsMap("_nodes");
@SuppressWarnings("unchecked")
String firstNode = ((Map<String, Object>) nodes.get("nodes")).keySet().iterator().next();
createIndex("source_index", Settings.builder().put("index.number_of_shards", 4).put("index.number_of_replicas", 0).build());
updateIndexSettings("source_index", Settings.builder().put("index.routing.allocation.require._name", firstNode)
@ -836,8 +839,8 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
request.masterNodeTimeout("1m"); // <2>
// end::shrink-index-request-masterTimeout
// tag::shrink-index-request-waitForActiveShards
request.getTargetIndexRequest().waitForActiveShards(2); // <1>
request.getTargetIndexRequest().waitForActiveShards(ActiveShardCount.DEFAULT); // <2>
request.setWaitForActiveShards(2); // <1>
request.setWaitForActiveShards(ActiveShardCount.DEFAULT); // <2>
// end::shrink-index-request-waitForActiveShards
// tag::shrink-index-request-settings
request.getTargetIndexRequest().settings(Settings.builder().put("index.number_of_shards", 2)); // <1>
@ -882,7 +885,6 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
@SuppressWarnings({"unchecked", "rawtypes"})
public void testSplitIndex() throws Exception {
RestHighLevelClient client = highLevelClient();
@ -906,8 +908,8 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
request.masterNodeTimeout("1m"); // <2>
// end::split-index-request-masterTimeout
// tag::split-index-request-waitForActiveShards
request.getTargetIndexRequest().waitForActiveShards(2); // <1>
request.getTargetIndexRequest().waitForActiveShards(ActiveShardCount.DEFAULT); // <2>
request.setWaitForActiveShards(2); // <1>
request.setWaitForActiveShards(ActiveShardCount.DEFAULT); // <2>
// end::split-index-request-waitForActiveShards
// tag::split-index-request-settings
request.getTargetIndexRequest().settings(Settings.builder().put("index.number_of_shards", 4)); // <1>
@ -951,4 +953,89 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
public void testRolloverIndex() throws Exception {
RestHighLevelClient client = highLevelClient();
{
client.indices().create(new CreateIndexRequest("index-1").alias(new Alias("alias")));
}
// tag::rollover-request
RolloverRequest request = new RolloverRequest("alias", "index-2"); // <1>
request.addMaxIndexAgeCondition(new TimeValue(7, TimeUnit.DAYS)); // <2>
request.addMaxIndexDocsCondition(1000); // <3>
request.addMaxIndexSizeCondition(new ByteSizeValue(5, ByteSizeUnit.GB)); // <4>
// end::rollover-request
// tag::rollover-request-timeout
request.timeout(TimeValue.timeValueMinutes(2)); // <1>
request.timeout("2m"); // <2>
// end::rollover-request-timeout
// tag::rollover-request-masterTimeout
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
request.masterNodeTimeout("1m"); // <2>
// end::rollover-request-masterTimeout
// tag::rollover-request-dryRun
request.dryRun(true); // <1>
// end::rollover-request-dryRun
// tag::rollover-request-waitForActiveShards
request.getCreateIndexRequest().waitForActiveShards(2); // <1>
request.getCreateIndexRequest().waitForActiveShards(ActiveShardCount.DEFAULT); // <2>
// end::rollover-request-waitForActiveShards
// tag::rollover-request-settings
request.getCreateIndexRequest().settings(Settings.builder().put("index.number_of_shards", 4)); // <1>
// end::rollover-request-settings
// tag::rollover-request-mapping
request.getCreateIndexRequest().mapping("type", "field", "type=keyword"); // <1>
// end::rollover-request-mapping
// tag::rollover-request-alias
request.getCreateIndexRequest().alias(new Alias("another_alias")); // <1>
// end::rollover-request-alias
// tag::rollover-execute
RolloverResponse rolloverResponse = client.indices().rollover(request);
// end::rollover-execute
// tag::rollover-response
boolean acknowledged = rolloverResponse.isAcknowledged(); // <1>
boolean shardsAcked = rolloverResponse.isShardsAcknowledged(); // <2>
String oldIndex = rolloverResponse.getOldIndex(); // <3>
String newIndex = rolloverResponse.getNewIndex(); // <4>
boolean isRolledOver = rolloverResponse.isRolledOver(); // <5>
boolean isDryRun = rolloverResponse.isDryRun(); // <6>
Map<String, Boolean> conditionStatus = rolloverResponse.getConditionStatus();// <7>
// end::rollover-response
assertFalse(acknowledged);
assertFalse(shardsAcked);
assertEquals("index-1", oldIndex);
assertEquals("index-2", newIndex);
assertFalse(isRolledOver);
assertTrue(isDryRun);
assertEquals(3, conditionStatus.size());
// tag::rollover-execute-listener
ActionListener<RolloverResponse> listener = new ActionListener<RolloverResponse>() {
@Override
public void onResponse(RolloverResponse rolloverResponse) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::rollover-execute-listener
// Replace the empty listener by a blocking listener in test
final CountDownLatch latch = new CountDownLatch(1);
listener = new LatchedActionListener<>(listener, latch);
// tag::rollover-execute-async
client.indices().rolloverAsync(request,listener); // <1>
// end::rollover-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}

View File

@ -21,6 +21,7 @@ include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[create-index-reque
--------------------------------------------------
<1> Settings for this index
[[java-rest-high-create-index-request-mappings]]
==== Index mappings
An index may be created with mappings for its document types
@ -98,9 +99,9 @@ include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[create-index-reque
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[create-index-request-waitForActiveShards]
--------------------------------------------------
<1> The number of active shard copies to wait for before the create index API returns a
response, as an `int`.
response, as an `int`
<2> The number of active shard copies to wait for before the create index API returns a
response, as an `ActiveShardCount`.
response, as an `ActiveShardCount`
[[java-rest-high-create-index-sync]]
==== Synchronous Execution

View File

@ -41,7 +41,7 @@ include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[exists-alias-reque
--------------------------------------------------
<1> The `local` flag (defaults to `false`) controls whether the aliases need
to be looked up in the local cluster state or in the cluster state held by
the elected master node.
the elected master node
[[java-rest-high-exists-alias-sync]]
==== Synchronous Execution

View File

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

View File

@ -0,0 +1,131 @@
[[java-rest-high-rollover-index]]
=== Rollover Index API
[[java-rest-high-rollover-request]]
==== Rollover Request
The Rollover Index API requires a `RolloverRequest` instance.
A `RolloverRequest` requires two string arguments at construction time, and
one or more conditions that determine when the index has to be rolled over:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-request]
--------------------------------------------------
<1> The alias (first argument) that points to the index to rollover, and
optionally the name of the new index in case the rollover operation is performed
<2> Condition on the age of the index
<3> Condition on the number of documents in the index
<4> Condition on the size of the index
==== Optional arguments
The following arguments can optionally be provided:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-request-dryRun]
--------------------------------------------------
<1> Whether the rollover should be performed (default) or only simulated
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-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}/IndicesClientDocumentationIT.java[rollover-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}/IndicesClientDocumentationIT.java[rollover-request-waitForActiveShards]
--------------------------------------------------
<1> The number of active shard copies to wait for before the rollover index API
returns a response, as an `int`
<2> The number of active shard copies to wait for before the rollover index API
returns a response, as an `ActiveShardCount`
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-request-settings]
--------------------------------------------------
<1> Add the settings to apply to the new index, which include the number of
shards to create for it
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-request-mapping]
--------------------------------------------------
<1> Add the mappings to associate the new index with. See <<java-rest-high-create-index-request-mappings>>
for examples on the different ways to provide mappings
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-request-alias]
--------------------------------------------------
<1> Add the aliases to associate the new index with
[[java-rest-high-rollover-sync]]
==== Synchronous Execution
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-execute]
--------------------------------------------------
[[java-rest-high-rollover-async]]
==== Asynchronous Execution
The asynchronous execution of a rollover request requires both the `RolloverRequest`
instance and an `ActionListener` instance to be passed to the asynchronous
method:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-execute-async]
--------------------------------------------------
<1> The `RolloverRequest` 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 `RolloverResponse` looks like:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-execute-listener]
--------------------------------------------------
<1> Called when the execution is successfully completed. The response is
provided as an argument
<2> Called in case of failure. The raised exception is provided as an argument
[[java-rest-high-rollover-response]]
==== Rollover Response
The returned `RolloverResponse` allows to retrieve information about the
executed operation as follows:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[rollover-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
<3> The name of the old index, eventually rolled over
<4> The name of the new index
<5> Whether the index has been rolled over
<6> Whether the operation was performed or it was a dry run
<7> The different conditions and whether they were matched or not

View File

@ -38,22 +38,22 @@ include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[split-index-reques
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[split-index-request-waitForActiveShards]
--------------------------------------------------
<1> The number of active shard copies to wait for before the split index API
returns a response, as an `int`.
returns a response, as an `int`
<2> The number of active shard copies to wait for before the split index API
returns a response, as an `ActiveShardCount`.
returns a response, as an `ActiveShardCount`
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[split-index-request-settings]
--------------------------------------------------
<1> The settings to apply to the target index, which include the number of
shards to create for it.
shards to create for it
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[split-index-request-aliases]
--------------------------------------------------
<1> The aliases to associate the target index with.
<1> The aliases to associate the target index with
[[java-rest-high-split-index-sync]]
==== Synchronous Execution

View File

@ -52,6 +52,7 @@ Index Management::
* <<java-rest-high-close-index>>
* <<java-rest-high-shrink-index>>
* <<java-rest-high-split-index>>
* <<java-rest-high-rollover-index>>
Mapping Management::
* <<java-rest-high-put-mapping>>
@ -67,6 +68,7 @@ include::indices/open_index.asciidoc[]
include::indices/close_index.asciidoc[]
include::indices/shrink_index.asciidoc[]
include::indices/split_index.asciidoc[]
include::indices/rollover.asciidoc[]
include::indices/put_mapping.asciidoc[]
include::indices/update_aliases.asciidoc[]
include::indices/exists_alias.asciidoc[]

View File

@ -36,7 +36,6 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.DeprecationHandler;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
@ -57,9 +56,9 @@ import java.util.Objects;
import java.util.Set;
import static org.elasticsearch.action.ValidateActions.addValidationError;
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
import static org.elasticsearch.common.settings.Settings.readSettingsFromStream;
import static org.elasticsearch.common.settings.Settings.writeSettingsToStream;
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
/**
* A request to create an index. Best created with {@link org.elasticsearch.client.Requests#createIndexRequest(String)}.
@ -72,7 +71,7 @@ import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
*/
public class CreateIndexRequest extends AcknowledgedRequest<CreateIndexRequest> implements IndicesRequest, ToXContentObject {
private static final ParseField MAPPINGS = new ParseField("mappings");
public static final ParseField MAPPINGS = new ParseField("mappings");
public static final ParseField SETTINGS = new ParseField("settings");
public static final ParseField ALIASES = new ParseField("aliases");
@ -525,7 +524,12 @@ public class CreateIndexRequest extends AcknowledgedRequest<CreateIndexRequest>
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
innerToXContent(builder, params);
builder.endObject();
return builder;
}
public XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(SETTINGS.getPreferredName());
settings.toXContent(builder, params);
builder.endObject();
@ -545,8 +549,6 @@ public class CreateIndexRequest extends AcknowledgedRequest<CreateIndexRequest>
for (Map.Entry<String, IndexMetaData.Custom> entry : customs.entrySet()) {
builder.field(entry.getKey(), entry.getValue(), params);
}
builder.endObject();
return builder;
}
}

View File

@ -20,7 +20,7 @@
package org.elasticsearch.action.admin.indices.create;
import org.elasticsearch.Version;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.support.master.ShardsAcknowledgedResponse;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -37,9 +37,8 @@ import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constru
/**
* A response for a create index action.
*/
public class CreateIndexResponse extends AcknowledgedResponse implements ToXContentObject {
public class CreateIndexResponse extends ShardsAcknowledgedResponse implements ToXContentObject {
private static final ParseField SHARDS_ACKNOWLEDGED = new ParseField("shards_acknowledged");
private static final ParseField INDEX = new ParseField("index");
private static final ConstructingObjectParser<CreateIndexResponse, Void> PARSER = new ConstructingObjectParser<>("create_index",
@ -50,22 +49,17 @@ public class CreateIndexResponse extends AcknowledgedResponse implements ToXCont
}
protected static <T extends CreateIndexResponse> void declareFields(ConstructingObjectParser<T, Void> objectParser) {
declareAcknowledgedField(objectParser);
objectParser.declareField(constructorArg(), (parser, context) -> parser.booleanValue(), SHARDS_ACKNOWLEDGED,
ObjectParser.ValueType.BOOLEAN);
objectParser.declareField(constructorArg(), (parser, context) -> parser.text(), INDEX, ObjectParser.ValueType.STRING);
declareAcknowledgedAndShardsAcknowledgedFields(objectParser);
objectParser.declareField(constructorArg(), (parser, context) -> parser.textOrNull(), INDEX, ObjectParser.ValueType.STRING_OR_NULL);
}
private boolean shardsAcknowledged;
private String index;
protected CreateIndexResponse() {
}
protected CreateIndexResponse(boolean acknowledged, boolean shardsAcknowledged, String index) {
super(acknowledged);
assert acknowledged || shardsAcknowledged == false; // if its not acknowledged, then shardsAcknowledged should be false too
this.shardsAcknowledged = shardsAcknowledged;
super(acknowledged, shardsAcknowledged);
this.index = index;
}
@ -73,7 +67,7 @@ public class CreateIndexResponse extends AcknowledgedResponse implements ToXCont
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
readAcknowledged(in);
shardsAcknowledged = in.readBoolean();
readShardsAcknowledged(in);
if (in.getVersion().onOrAfter(Version.V_5_6_0)) {
index = in.readString();
}
@ -83,35 +77,22 @@ public class CreateIndexResponse extends AcknowledgedResponse implements ToXCont
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
writeAcknowledged(out);
out.writeBoolean(shardsAcknowledged);
writeShardsAcknowledged(out);
if (out.getVersion().onOrAfter(Version.V_5_6_0)) {
out.writeString(index);
}
}
/**
* Returns true if the requisite number of shards were started before
* returning from the index creation operation. If {@link #isAcknowledged()}
* is false, then this also returns false.
*/
public boolean isShardsAcknowledged() {
return shardsAcknowledged;
}
public String index() {
return index;
}
public void addCustomFields(XContentBuilder builder) throws IOException {
builder.field(SHARDS_ACKNOWLEDGED.getPreferredName(), isShardsAcknowledged());
builder.field(INDEX.getPreferredName(), index());
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
addAcknowledgedField(builder);
addCustomFields(builder);
addShardsAcknowledgedField(builder);
builder.field(INDEX.getPreferredName(), index());
builder.endObject();
return builder;
}

View File

@ -68,7 +68,7 @@ public class DeleteIndexResponse extends AcknowledgedResponse implements ToXCont
return builder;
}
public static DeleteIndexResponse fromXContent(XContentParser parser) throws IOException {
public static DeleteIndexResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}
}

View File

@ -20,54 +20,33 @@
package org.elasticsearch.action.admin.indices.open;
import org.elasticsearch.Version;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.action.support.master.ShardsAcknowledgedResponse;
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.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
/**
* A response for a open index action.
*/
public class OpenIndexResponse extends AcknowledgedResponse implements ToXContentObject {
private static final String SHARDS_ACKNOWLEDGED = "shards_acknowledged";
private static final ParseField SHARDS_ACKNOWLEDGED_PARSER = new ParseField(SHARDS_ACKNOWLEDGED);
public class OpenIndexResponse extends ShardsAcknowledgedResponse implements ToXContentObject {
private static final ConstructingObjectParser<OpenIndexResponse, Void> PARSER = new ConstructingObjectParser<>("open_index", true,
args -> new OpenIndexResponse((boolean) args[0], (boolean) args[1]));
static {
declareAcknowledgedField(PARSER);
PARSER.declareField(constructorArg(), (parser, context) -> parser.booleanValue(), SHARDS_ACKNOWLEDGED_PARSER,
ObjectParser.ValueType.BOOLEAN);
declareAcknowledgedAndShardsAcknowledgedFields(PARSER);
}
private boolean shardsAcknowledged;
OpenIndexResponse() {
}
OpenIndexResponse(boolean acknowledged, boolean shardsAcknowledged) {
super(acknowledged);
assert acknowledged || shardsAcknowledged == false; // if its not acknowledged, then shards acked should be false too
this.shardsAcknowledged = shardsAcknowledged;
}
/**
* Returns true if the requisite number of shards were started before
* returning from the indices opening operation. If {@link #isAcknowledged()}
* is false, then this also returns false.
*/
public boolean isShardsAcknowledged() {
return shardsAcknowledged;
super(acknowledged, shardsAcknowledged);
}
@Override
@ -75,7 +54,7 @@ public class OpenIndexResponse extends AcknowledgedResponse implements ToXConten
super.readFrom(in);
readAcknowledged(in);
if (in.getVersion().onOrAfter(Version.V_6_1_0)) {
shardsAcknowledged = in.readBoolean();
readShardsAcknowledged(in);
}
}
@ -84,7 +63,7 @@ public class OpenIndexResponse extends AcknowledgedResponse implements ToXConten
super.writeTo(out);
writeAcknowledged(out);
if (out.getVersion().onOrAfter(Version.V_6_1_0)) {
out.writeBoolean(shardsAcknowledged);
writeShardsAcknowledged(out);
}
}
@ -92,12 +71,12 @@ public class OpenIndexResponse extends AcknowledgedResponse implements ToXConten
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
addAcknowledgedField(builder);
builder.field(SHARDS_ACKNOWLEDGED, isShardsAcknowledged());
addShardsAcknowledgedField(builder);
builder.endObject();
return builder;
}
public static OpenIndexResponse fromXContent(XContentParser parser) throws IOException {
public static OpenIndexResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}
}

View File

@ -20,30 +20,16 @@
package org.elasticsearch.action.admin.indices.rollover;
import org.elasticsearch.Version;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.NamedWriteable;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContentFragment;
import java.util.Set;
import java.util.Objects;
/**
* Base class for rollover request conditions
*/
public abstract class Condition<T> implements NamedWriteable {
public static ObjectParser<Set<Condition>, Void> PARSER = new ObjectParser<>("conditions", null);
static {
PARSER.declareString((conditions, s) ->
conditions.add(new MaxAgeCondition(TimeValue.parseTimeValue(s, MaxAgeCondition.NAME))),
new ParseField(MaxAgeCondition.NAME));
PARSER.declareLong((conditions, value) ->
conditions.add(new MaxDocsCondition(value)), new ParseField(MaxDocsCondition.NAME));
PARSER.declareString((conditions, s) ->
conditions.add(new MaxSizeCondition(ByteSizeValue.parseBytesSizeValue(s, MaxSizeCondition.NAME))),
new ParseField(MaxSizeCondition.NAME));
}
public abstract class Condition<T> implements NamedWriteable, ToXContentFragment {
protected T value;
protected final String name;
@ -62,6 +48,24 @@ public abstract class Condition<T> implements NamedWriteable {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Condition<?> condition = (Condition<?>) o;
return Objects.equals(value, condition.value) &&
Objects.equals(name, condition.name);
}
@Override
public int hashCode() {
return Objects.hash(value, name);
}
@Override
public final String toString() {
return "[" + name + ": " + value + "]";

View File

@ -22,6 +22,7 @@ package org.elasticsearch.action.admin.indices.rollover;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
@ -55,6 +56,12 @@ public class MaxAgeCondition extends Condition<TimeValue> {
@Override
public void writeTo(StreamOutput out) throws IOException {
//TODO here we should just use TimeValue#writeTo and same for de-serialization in the constructor, we lose information this way
out.writeLong(value.getMillis());
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return builder.field(NAME, value.getStringRep());
}
}

View File

@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.rollover;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
@ -55,4 +56,9 @@ public class MaxDocsCondition extends Condition<Long> {
public void writeTo(StreamOutput out) throws IOException {
out.writeLong(value);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return builder.field(NAME, value);
}
}

View File

@ -24,6 +24,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
@ -61,6 +62,12 @@ public class MaxSizeCondition extends Condition<ByteSizeValue> {
@Override
public void writeTo(StreamOutput out) throws IOException {
//TODO here we should just use ByteSizeValue#writeTo and same for de-serialization in the constructor
out.writeVLong(value.getBytes());
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return builder.field(NAME, value.getStringRep());
}
}

View File

@ -21,7 +21,6 @@ package org.elasticsearch.action.admin.indices.rollover;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.common.ParseField;
@ -30,40 +29,57 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
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.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static org.elasticsearch.action.ValidateActions.addValidationError;
/**
* Request class to swap index under an alias upon satisfying conditions
*/
public class RolloverRequest extends AcknowledgedRequest<RolloverRequest> implements IndicesRequest {
public class RolloverRequest extends AcknowledgedRequest<RolloverRequest> implements IndicesRequest, ToXContentObject {
private static final ObjectParser<RolloverRequest, Void> PARSER = new ObjectParser<>("rollover");
private static final ObjectParser<Map<String, Condition>, Void> CONDITION_PARSER = new ObjectParser<>("conditions");
private static final ParseField CONDITIONS = new ParseField("conditions");
private static final ParseField MAX_AGE_CONDITION = new ParseField(MaxAgeCondition.NAME);
private static final ParseField MAX_DOCS_CONDITION = new ParseField(MaxDocsCondition.NAME);
private static final ParseField MAX_SIZE_CONDITION = new ParseField(MaxSizeCondition.NAME);
public static final ObjectParser<RolloverRequest, Void> PARSER = new ObjectParser<>("conditions", null);
static {
PARSER.declareField((parser, request, context) -> Condition.PARSER.parse(parser, request.conditions, null),
new ParseField("conditions"), ObjectParser.ValueType.OBJECT);
CONDITION_PARSER.declareString((conditions, s) ->
conditions.put(MaxAgeCondition.NAME, new MaxAgeCondition(TimeValue.parseTimeValue(s, MaxAgeCondition.NAME))),
MAX_AGE_CONDITION);
CONDITION_PARSER.declareLong((conditions, value) ->
conditions.put(MaxDocsCondition.NAME, new MaxDocsCondition(value)), MAX_DOCS_CONDITION);
CONDITION_PARSER.declareString((conditions, s) ->
conditions.put(MaxSizeCondition.NAME, new MaxSizeCondition(ByteSizeValue.parseBytesSizeValue(s, MaxSizeCondition.NAME))),
MAX_SIZE_CONDITION);
PARSER.declareField((parser, request, context) -> CONDITION_PARSER.parse(parser, request.conditions, null),
CONDITIONS, ObjectParser.ValueType.OBJECT);
PARSER.declareField((parser, request, context) -> request.createIndexRequest.settings(parser.map()),
new ParseField("settings"), ObjectParser.ValueType.OBJECT);
CreateIndexRequest.SETTINGS, ObjectParser.ValueType.OBJECT);
PARSER.declareField((parser, request, context) -> {
for (Map.Entry<String, Object> mappingsEntry : parser.map().entrySet()) {
request.createIndexRequest.mapping(mappingsEntry.getKey(),
(Map<String, Object>) mappingsEntry.getValue());
request.createIndexRequest.mapping(mappingsEntry.getKey(), (Map<String, Object>) mappingsEntry.getValue());
}
}, new ParseField("mappings"), ObjectParser.ValueType.OBJECT);
}, CreateIndexRequest.MAPPINGS, ObjectParser.ValueType.OBJECT);
PARSER.declareField((parser, request, context) -> request.createIndexRequest.aliases(parser.map()),
new ParseField("aliases"), ObjectParser.ValueType.OBJECT);
CreateIndexRequest.ALIASES, ObjectParser.ValueType.OBJECT);
}
private String alias;
private String newIndexName;
private boolean dryRun;
private Set<Condition> conditions = new HashSet<>(2);
private Map<String, Condition> conditions = new HashMap<>(2);
//the index name "_na_" is never read back, what matters are settings, mappings and aliases
private CreateIndexRequest createIndexRequest = new CreateIndexRequest("_na_");
RolloverRequest() {}
@ -75,13 +91,10 @@ public class RolloverRequest extends AcknowledgedRequest<RolloverRequest> implem
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = createIndexRequest == null ? null : createIndexRequest.validate();
ActionRequestValidationException validationException = createIndexRequest.validate();
if (alias == null) {
validationException = addValidationError("index alias is missing", validationException);
}
if (createIndexRequest == null) {
validationException = addValidationError("create index request is missing", validationException);
}
return validationException;
}
@ -93,7 +106,8 @@ public class RolloverRequest extends AcknowledgedRequest<RolloverRequest> implem
dryRun = in.readBoolean();
int size = in.readVInt();
for (int i = 0; i < size; i++) {
this.conditions.add(in.readNamedWriteable(Condition.class));
Condition condition = in.readNamedWriteable(Condition.class);
this.conditions.put(condition.name, condition);
}
createIndexRequest = new CreateIndexRequest();
createIndexRequest.readFrom(in);
@ -106,7 +120,7 @@ public class RolloverRequest extends AcknowledgedRequest<RolloverRequest> implem
out.writeOptionalString(newIndexName);
out.writeBoolean(dryRun);
out.writeVInt(conditions.size());
for (Condition condition : conditions) {
for (Condition condition : conditions.values()) {
if (condition.includedInVersion(out.getVersion())) {
out.writeNamedWriteable(condition);
}
@ -148,76 +162,75 @@ public class RolloverRequest extends AcknowledgedRequest<RolloverRequest> implem
* Adds condition to check if the index is at least <code>age</code> old
*/
public void addMaxIndexAgeCondition(TimeValue age) {
this.conditions.add(new MaxAgeCondition(age));
MaxAgeCondition maxAgeCondition = new MaxAgeCondition(age);
if (this.conditions.containsKey(maxAgeCondition.name)) {
throw new IllegalArgumentException(maxAgeCondition.name + " condition is already set");
}
this.conditions.put(maxAgeCondition.name, maxAgeCondition);
}
/**
* Adds condition to check if the index has at least <code>numDocs</code>
*/
public void addMaxIndexDocsCondition(long numDocs) {
this.conditions.add(new MaxDocsCondition(numDocs));
MaxDocsCondition maxDocsCondition = new MaxDocsCondition(numDocs);
if (this.conditions.containsKey(maxDocsCondition.name)) {
throw new IllegalArgumentException(maxDocsCondition.name + " condition is already set");
}
this.conditions.put(maxDocsCondition.name, maxDocsCondition);
}
/**
* Adds a size-based condition to check if the index size is at least <code>size</code>.
*/
public void addMaxIndexSizeCondition(ByteSizeValue size) {
this.conditions.add(new MaxSizeCondition(size));
MaxSizeCondition maxSizeCondition = new MaxSizeCondition(size);
if (this.conditions.containsKey(maxSizeCondition.name)) {
throw new IllegalArgumentException(maxSizeCondition + " condition is already set");
}
this.conditions.put(maxSizeCondition.name, maxSizeCondition);
}
/**
* Sets rollover index creation request to override index settings when
* the rolled over index has to be created
*/
public void setCreateIndexRequest(CreateIndexRequest createIndexRequest) {
this.createIndexRequest = Objects.requireNonNull(createIndexRequest, "create index request must not be null");;
}
boolean isDryRun() {
public boolean isDryRun() {
return dryRun;
}
Set<Condition> getConditions() {
Map<String, Condition> getConditions() {
return conditions;
}
String getAlias() {
public String getAlias() {
return alias;
}
String getNewIndexName() {
public String getNewIndexName() {
return newIndexName;
}
CreateIndexRequest getCreateIndexRequest() {
/**
* Returns the inner {@link CreateIndexRequest}. Allows to configure mappings, settings and aliases for the new index.
*/
public CreateIndexRequest getCreateIndexRequest() {
return createIndexRequest;
}
/**
* Sets the number of shard copies that should be active for creation of the
* new rollover index to return. Defaults to {@link ActiveShardCount#DEFAULT}, which will
* wait for one shard copy (the primary) to become active. Set this value to
* {@link ActiveShardCount#ALL} to wait for all shards (primary and all replicas) to be active
* before returning. Otherwise, use {@link ActiveShardCount#from(int)} to set this value to any
* non-negative integer, up to the number of copies per shard (number of replicas + 1),
* to wait for the desired amount of shard copies to become active before returning.
* Index creation will only wait up until the timeout value for the number of shard copies
* to be active before returning. Check {@link RolloverResponse#isShardsAcknowledged()} to
* determine if the requisite shard copies were all started before returning or timing out.
*
* @param waitForActiveShards number of active shard copies to wait on
*/
public void setWaitForActiveShards(ActiveShardCount waitForActiveShards) {
this.createIndexRequest.waitForActiveShards(waitForActiveShards);
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
createIndexRequest.innerToXContent(builder, params);
builder.startObject(CONDITIONS.getPreferredName());
for (Condition condition : conditions.values()) {
condition.toXContent(builder, params);
}
builder.endObject();
builder.endObject();
return builder;
}
/**
* A shortcut for {@link #setWaitForActiveShards(ActiveShardCount)} where the numerical
* shard count is passed in, instead of having to first call {@link ActiveShardCount#from(int)}
* to get the ActiveShardCount.
*/
public void setWaitForActiveShards(final int waitForActiveShards) {
setWaitForActiveShards(ActiveShardCount.from(waitForActiveShards));
public void fromXContent(XContentParser parser) throws IOException {
PARSER.parse(parser, this, null);
}
}

View File

@ -93,7 +93,7 @@ public class RolloverRequestBuilder extends MasterNodeOperationRequestBuilder<Ro
* @param waitForActiveShards number of active shard copies to wait on
*/
public RolloverRequestBuilder waitForActiveShards(ActiveShardCount waitForActiveShards) {
this.request.setWaitForActiveShards(waitForActiveShards);
this.request.getCreateIndexRequest().waitForActiveShards(waitForActiveShards);
return this;
}

View File

@ -19,51 +19,62 @@
package org.elasticsearch.action.admin.indices.rollover;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.support.master.ShardsAcknowledgedResponse;
import org.elasticsearch.common.ParseField;
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.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.AbstractMap;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.Objects;
public final class RolloverResponse extends ActionResponse implements ToXContentObject {
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
private static final String NEW_INDEX = "new_index";
private static final String OLD_INDEX = "old_index";
private static final String DRY_RUN = "dry_run";
private static final String ROLLED_OVER = "rolled_over";
private static final String CONDITIONS = "conditions";
private static final String ACKNOWLEDGED = "acknowledged";
private static final String SHARDS_ACKED = "shards_acknowledged";
public final class RolloverResponse extends ShardsAcknowledgedResponse implements ToXContentObject {
private static final ParseField NEW_INDEX = new ParseField("new_index");
private static final ParseField OLD_INDEX = new ParseField("old_index");
private static final ParseField DRY_RUN = new ParseField("dry_run");
private static final ParseField ROLLED_OVER = new ParseField("rolled_over");
private static final ParseField CONDITIONS = new ParseField("conditions");
@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<RolloverResponse, Void> PARSER = new ConstructingObjectParser<>("rollover",
true, args -> new RolloverResponse((String) args[0], (String) args[1], (Map<String,Boolean>) args[2],
(Boolean)args[3], (Boolean)args[4], (Boolean) args[5], (Boolean) args[6]));
static {
PARSER.declareField(constructorArg(), (parser, context) -> parser.text(), OLD_INDEX, ObjectParser.ValueType.STRING);
PARSER.declareField(constructorArg(), (parser, context) -> parser.text(), NEW_INDEX, ObjectParser.ValueType.STRING);
PARSER.declareObject(constructorArg(), (parser, context) -> parser.map(), CONDITIONS);
PARSER.declareField(constructorArg(), (parser, context) -> parser.booleanValue(), DRY_RUN, ObjectParser.ValueType.BOOLEAN);
PARSER.declareField(constructorArg(), (parser, context) -> parser.booleanValue(), ROLLED_OVER, ObjectParser.ValueType.BOOLEAN);
declareAcknowledgedAndShardsAcknowledgedFields(PARSER);
}
private String oldIndex;
private String newIndex;
private Set<Map.Entry<String, Boolean>> conditionStatus;
private Map<String, Boolean> conditionStatus;
private boolean dryRun;
private boolean rolledOver;
private boolean acknowledged;
private boolean shardsAcknowledged;
RolloverResponse() {
}
RolloverResponse(String oldIndex, String newIndex, Set<Condition.Result> conditionResults,
boolean dryRun, boolean rolledOver, boolean acknowledged, boolean shardsAcknowledged) {
RolloverResponse(String oldIndex, String newIndex, Map<String, Boolean> conditionResults,
boolean dryRun, boolean rolledOver, boolean acknowledged, boolean shardsAcknowledged) {
super(acknowledged, shardsAcknowledged);
this.oldIndex = oldIndex;
this.newIndex = newIndex;
this.dryRun = dryRun;
this.rolledOver = rolledOver;
this.acknowledged = acknowledged;
this.shardsAcknowledged = shardsAcknowledged;
this.conditionStatus = conditionResults.stream()
.map(result -> new AbstractMap.SimpleEntry<>(result.condition.toString(), result.matched))
.collect(Collectors.toSet());
this.conditionStatus = conditionResults;
}
/**
@ -83,7 +94,7 @@ public final class RolloverResponse extends ActionResponse implements ToXContent
/**
* Returns the statuses of all the request conditions
*/
public Set<Map.Entry<String, Boolean>> getConditionStatus() {
public Map<String, Boolean> getConditionStatus() {
return conditionStatus;
}
@ -101,42 +112,20 @@ public final class RolloverResponse extends ActionResponse implements ToXContent
return rolledOver;
}
/**
* Returns true if the creation of the new rollover index and switching of the
* alias to the newly created index was successful, and returns false otherwise.
* If {@link #isDryRun()} is true, then this will also return false. If this
* returns false, then {@link #isShardsAcknowledged()} will also return false.
*/
public boolean isAcknowledged() {
return acknowledged;
}
/**
* Returns true if the requisite number of shards were started in the newly
* created rollover index before returning. If {@link #isAcknowledged()} is
* false, then this will also return false.
*/
public boolean isShardsAcknowledged() {
return shardsAcknowledged;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
oldIndex = in.readString();
newIndex = in.readString();
int conditionSize = in.readVInt();
Set<Map.Entry<String, Boolean>> conditions = new HashSet<>(conditionSize);
conditionStatus = new HashMap<>(conditionSize);
for (int i = 0; i < conditionSize; i++) {
String condition = in.readString();
boolean satisfied = in.readBoolean();
conditions.add(new AbstractMap.SimpleEntry<>(condition, satisfied));
conditionStatus.put(in.readString(), in.readBoolean());
}
conditionStatus = conditions;
dryRun = in.readBoolean();
rolledOver = in.readBoolean();
acknowledged = in.readBoolean();
shardsAcknowledged = in.readBoolean();
readAcknowledged(in);
readShardsAcknowledged(in);
}
@Override
@ -145,31 +134,58 @@ public final class RolloverResponse extends ActionResponse implements ToXContent
out.writeString(oldIndex);
out.writeString(newIndex);
out.writeVInt(conditionStatus.size());
for (Map.Entry<String, Boolean> entry : conditionStatus) {
for (Map.Entry<String, Boolean> entry : conditionStatus.entrySet()) {
out.writeString(entry.getKey());
out.writeBoolean(entry.getValue());
}
out.writeBoolean(dryRun);
out.writeBoolean(rolledOver);
out.writeBoolean(acknowledged);
out.writeBoolean(shardsAcknowledged);
writeAcknowledged(out);
writeShardsAcknowledged(out);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(OLD_INDEX, oldIndex);
builder.field(NEW_INDEX, newIndex);
builder.field(ROLLED_OVER, rolledOver);
builder.field(DRY_RUN, dryRun);
builder.field(ACKNOWLEDGED, acknowledged);
builder.field(SHARDS_ACKED, shardsAcknowledged);
builder.startObject(CONDITIONS);
for (Map.Entry<String, Boolean> entry : conditionStatus) {
builder.field(OLD_INDEX.getPreferredName(), oldIndex);
builder.field(NEW_INDEX.getPreferredName(), newIndex);
builder.field(ROLLED_OVER.getPreferredName(), rolledOver);
builder.field(DRY_RUN.getPreferredName(), dryRun);
addAcknowledgedField(builder);
addShardsAcknowledgedField(builder);
builder.startObject(CONDITIONS.getPreferredName());
for (Map.Entry<String, Boolean> entry : conditionStatus.entrySet()) {
builder.field(entry.getKey(), entry.getValue());
}
builder.endObject();
builder.endObject();
return builder;
}
public static RolloverResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RolloverResponse that = (RolloverResponse) o;
return isAcknowledged() == that.isAcknowledged() &&
isShardsAcknowledged() == that.isShardsAcknowledged() &&
dryRun == that.dryRun &&
rolledOver == that.rolledOver &&
Objects.equals(oldIndex, that.oldIndex) &&
Objects.equals(newIndex, that.newIndex) &&
Objects.equals(conditionStatus, that.conditionStatus);
}
@Override
public int hashCode() {
return Objects.hash(isAcknowledged(), isShardsAcknowledged(), oldIndex, newIndex, conditionStatus, dryRun, rolledOver);
}
}

View File

@ -51,9 +51,10 @@ import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -122,7 +123,7 @@ public class TransportRolloverAction extends TransportMasterNodeAction<RolloverR
new ActionListener<IndicesStatsResponse>() {
@Override
public void onResponse(IndicesStatsResponse statsResponse) {
final Set<Condition.Result> conditionResults = evaluateConditions(rolloverRequest.getConditions(),
final Map<String, Boolean> conditionResults = evaluateConditions(rolloverRequest.getConditions().values(),
metaData.index(sourceIndexName), statsResponse);
if (rolloverRequest.isDryRun()) {
@ -130,7 +131,7 @@ public class TransportRolloverAction extends TransportMasterNodeAction<RolloverR
new RolloverResponse(sourceIndexName, rolloverIndexName, conditionResults, true, false, false, false));
return;
}
if (conditionResults.size() == 0 || conditionResults.stream().anyMatch(result -> result.matched)) {
if (conditionResults.size() == 0 || conditionResults.values().stream().anyMatch(result -> result)) {
CreateIndexClusterStateUpdateRequest updateRequest = prepareCreateIndexRequest(unresolvedName, rolloverIndexName,
rolloverRequest);
createIndexService.createIndex(updateRequest, ActionListener.wrap(createIndexClusterStateUpdateResponse -> {
@ -197,17 +198,17 @@ public class TransportRolloverAction extends TransportMasterNodeAction<RolloverR
}
}
static Set<Condition.Result> evaluateConditions(final Set<Condition> conditions,
final DocsStats docsStats, final IndexMetaData metaData) {
static Map<String, Boolean> evaluateConditions(final Collection<Condition> conditions,
final DocsStats docsStats, final IndexMetaData metaData) {
final long numDocs = docsStats == null ? 0 : docsStats.getCount();
final long indexSize = docsStats == null ? 0 : docsStats.getTotalSizeInBytes();
final Condition.Stats stats = new Condition.Stats(numDocs, metaData.getCreationDate(), new ByteSizeValue(indexSize));
return conditions.stream()
.map(condition -> condition.evaluate(stats))
.collect(Collectors.toSet());
.collect(Collectors.toMap(result -> result.condition.toString(), result -> result.matched));
}
static Set<Condition.Result> evaluateConditions(final Set<Condition> conditions, final IndexMetaData metaData,
static Map<String, Boolean> evaluateConditions(final Collection<Condition> conditions, final IndexMetaData metaData,
final IndicesStatsResponse statsResponse) {
return evaluateConditions(conditions, statsResponse.getPrimaries().getDocs(), metaData);
}

View File

@ -62,14 +62,14 @@ public abstract class AcknowledgedResponse extends ActionResponse {
}
/**
* Reads the timeout value
* Reads the acknowledged value
*/
protected void readAcknowledged(StreamInput in) throws IOException {
acknowledged = in.readBoolean();
}
/**
* Writes the timeout value
* Writes the acknowledged value
*/
protected void writeAcknowledged(StreamOutput out) throws IOException {
out.writeBoolean(acknowledged);

View File

@ -0,0 +1,76 @@
/*
* 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.support.master;
import org.elasticsearch.common.ParseField;
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.ObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
public abstract class ShardsAcknowledgedResponse extends AcknowledgedResponse {
private static final ParseField SHARDS_ACKNOWLEDGED = new ParseField("shards_acknowledged");
protected static <T extends ShardsAcknowledgedResponse> void declareAcknowledgedAndShardsAcknowledgedFields(
ConstructingObjectParser<T, Void> objectParser) {
declareAcknowledgedField(objectParser);
objectParser.declareField(constructorArg(), (parser, context) -> parser.booleanValue(), SHARDS_ACKNOWLEDGED,
ObjectParser.ValueType.BOOLEAN);
}
private boolean shardsAcknowledged;
protected ShardsAcknowledgedResponse() {
}
protected ShardsAcknowledgedResponse(boolean acknowledged, boolean shardsAcknowledged) {
super(acknowledged);
assert acknowledged || shardsAcknowledged == false; // if it's not acknowledged, then shards acked should be false too
this.shardsAcknowledged = shardsAcknowledged;
}
/**
* Returns true if the requisite number of shards were started before
* returning from the index creation operation. If {@link #isAcknowledged()}
* is false, then this also returns false.
*/
public boolean isShardsAcknowledged() {
return shardsAcknowledged;
}
protected void readShardsAcknowledged(StreamInput in) throws IOException {
shardsAcknowledged = in.readBoolean();
}
protected void writeShardsAcknowledged(StreamOutput out) throws IOException {
out.writeBoolean(shardsAcknowledged);
}
protected void addShardsAcknowledgedField(XContentBuilder builder) throws IOException {
builder.field(SHARDS_ACKNOWLEDGED.getPreferredName(), isShardsAcknowledged());
}
}

View File

@ -28,6 +28,7 @@ import java.io.IOException;
import static org.elasticsearch.rest.RestStatus.OK;
//TODO once all the responses that use this class implement ToXContent we can move to RestToXContentListener and remove this class
public class AcknowledgedRestListener<T extends AcknowledgedResponse> extends RestBuilderListener<T> {
public AcknowledgedRestListener(RestChannel channel) {
@ -36,7 +37,6 @@ public class AcknowledgedRestListener<T extends AcknowledgedResponse> extends Re
@Override
public RestResponse buildResponse(T response, XContentBuilder builder) throws Exception {
// TODO - Once AcknowledgedResponse implements ToXContent, this method should be updated to call response.toXContent.
builder.startObject()
.field(Fields.ACKNOWLEDGED, response.isAcknowledged());
addCustomFields(builder, response);

View File

@ -20,15 +20,13 @@
package org.elasticsearch.rest.action.admin.indices;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.AcknowledgedRestListener;
import org.elasticsearch.rest.action.RestToXContentListener;
import java.io.IOException;
@ -52,11 +50,6 @@ public class RestCreateIndexAction extends BaseRestHandler {
createIndexRequest.timeout(request.paramAsTime("timeout", createIndexRequest.timeout()));
createIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", createIndexRequest.masterNodeTimeout()));
createIndexRequest.waitForActiveShards(ActiveShardCount.parseString(request.param("wait_for_active_shards")));
return channel -> client.admin().indices().create(createIndexRequest, new AcknowledgedRestListener<CreateIndexResponse>(channel) {
@Override
public void addCustomFields(XContentBuilder builder, CreateIndexResponse response) throws IOException {
response.addCustomFields(builder);
}
});
return channel -> client.admin().indices().create(createIndexRequest, new RestToXContentListener<>(channel));
}
}

View File

@ -27,7 +27,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.AcknowledgedRestListener;
import org.elasticsearch.rest.action.RestToXContentListener;
import java.io.IOException;
@ -49,6 +49,6 @@ public class RestDeleteIndexAction extends BaseRestHandler {
deleteIndexRequest.timeout(request.paramAsTime("timeout", deleteIndexRequest.timeout()));
deleteIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", deleteIndexRequest.masterNodeTimeout()));
deleteIndexRequest.indicesOptions(IndicesOptions.fromRequest(request, deleteIndexRequest.indicesOptions()));
return channel -> client.admin().indices().delete(deleteIndexRequest, new AcknowledgedRestListener<>(channel));
return channel -> client.admin().indices().delete(deleteIndexRequest, new RestToXContentListener<>(channel));
}
}

View File

@ -20,17 +20,15 @@
package org.elasticsearch.rest.action.admin.indices;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.AcknowledgedRestListener;
import org.elasticsearch.rest.action.RestToXContentListener;
import java.io.IOException;
@ -56,11 +54,6 @@ public class RestOpenIndexAction extends BaseRestHandler {
if (waitForActiveShards != null) {
openIndexRequest.waitForActiveShards(ActiveShardCount.parseString(waitForActiveShards));
}
return channel -> client.admin().indices().open(openIndexRequest, new AcknowledgedRestListener<OpenIndexResponse>(channel) {
@Override
protected void addCustomFields(XContentBuilder builder, OpenIndexResponse response) throws IOException {
builder.field("shards_acknowledged", response.isShardsAcknowledged());
}
});
return channel -> client.admin().indices().open(openIndexRequest, new RestToXContentListener<>(channel));
}
}

View File

@ -45,11 +45,12 @@ public class RestRolloverIndexAction extends BaseRestHandler {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
RolloverRequest rolloverIndexRequest = new RolloverRequest(request.param("index"), request.param("new_index"));
request.applyContentParser(parser -> RolloverRequest.PARSER.parse(parser, rolloverIndexRequest, null));
request.applyContentParser(rolloverIndexRequest::fromXContent);
rolloverIndexRequest.dryRun(request.paramAsBoolean("dry_run", false));
rolloverIndexRequest.timeout(request.paramAsTime("timeout", rolloverIndexRequest.timeout()));
rolloverIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", rolloverIndexRequest.masterNodeTimeout()));
rolloverIndexRequest.setWaitForActiveShards(ActiveShardCount.parseString(request.param("wait_for_active_shards")));
rolloverIndexRequest.getCreateIndexRequest().waitForActiveShards(
ActiveShardCount.parseString(request.param("wait_for_active_shards")));
return channel -> client.admin().indices().rolloverIndex(rolloverIndexRequest, new RestToXContentListener<>(channel));
}
}

View File

@ -20,16 +20,14 @@
package org.elasticsearch.rest.action.admin.indices;
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.AcknowledgedRestListener;
import org.elasticsearch.rest.action.RestToXContentListener;
import java.io.IOException;
@ -47,23 +45,12 @@ public class RestShrinkIndexAction extends BaseRestHandler {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
if (request.param("target") == null) {
throw new IllegalArgumentException("no target index");
}
if (request.param("index") == null) {
throw new IllegalArgumentException("no source index");
}
ResizeRequest shrinkIndexRequest = new ResizeRequest(request.param("target"), request.param("index"));
shrinkIndexRequest.setResizeType(ResizeType.SHRINK);
request.applyContentParser(shrinkIndexRequest::fromXContent);
shrinkIndexRequest.timeout(request.paramAsTime("timeout", shrinkIndexRequest.timeout()));
shrinkIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", shrinkIndexRequest.masterNodeTimeout()));
shrinkIndexRequest.setWaitForActiveShards(ActiveShardCount.parseString(request.param("wait_for_active_shards")));
return channel -> client.admin().indices().resizeIndex(shrinkIndexRequest, new AcknowledgedRestListener<ResizeResponse>(channel) {
@Override
public void addCustomFields(XContentBuilder builder, ResizeResponse response) throws IOException {
response.addCustomFields(builder);
}
});
return channel -> client.admin().indices().resizeIndex(shrinkIndexRequest, new RestToXContentListener<>(channel));
}
}

View File

@ -20,16 +20,14 @@
package org.elasticsearch.rest.action.admin.indices;
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.AcknowledgedRestListener;
import org.elasticsearch.rest.action.RestToXContentListener;
import java.io.IOException;
@ -47,23 +45,12 @@ public class RestSplitIndexAction extends BaseRestHandler {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
if (request.param("target") == null) {
throw new IllegalArgumentException("no target index");
}
if (request.param("index") == null) {
throw new IllegalArgumentException("no source index");
}
ResizeRequest shrinkIndexRequest = new ResizeRequest(request.param("target"), request.param("index"));
shrinkIndexRequest.setResizeType(ResizeType.SPLIT);
request.applyContentParser(shrinkIndexRequest::fromXContent);
shrinkIndexRequest.timeout(request.paramAsTime("timeout", shrinkIndexRequest.timeout()));
shrinkIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", shrinkIndexRequest.masterNodeTimeout()));
shrinkIndexRequest.setWaitForActiveShards(ActiveShardCount.parseString(request.param("wait_for_active_shards")));
return channel -> client.admin().indices().resizeIndex(shrinkIndexRequest, new AcknowledgedRestListener<ResizeResponse>(channel) {
@Override
public void addCustomFields(XContentBuilder builder, ResizeResponse response) throws IOException {
response.addCustomFields(builder);
}
});
return channel -> client.admin().indices().resizeIndex(shrinkIndexRequest, new RestToXContentListener<>(channel));
}
}

View File

@ -26,11 +26,14 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.RandomCreateIndexGenerator;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
import java.io.IOException;
import java.util.Map;
@ -119,17 +122,22 @@ public class CreateIndexRequestTests extends ESTestCase {
assertMappingsEqual(createIndexRequest.mappings(), parsedCreateIndexRequest.mappings());
assertAliasesEqual(createIndexRequest.aliases(), parsedCreateIndexRequest.aliases());
assertEquals(createIndexRequest.settings(), parsedCreateIndexRequest.settings());
BytesReference finalBytes = toShuffledXContent(parsedCreateIndexRequest, xContentType, EMPTY_PARAMS, humanReadable);
ElasticsearchAssertions.assertToXContentEquivalent(originalBytes, finalBytes, xContentType);
}
private void assertMappingsEqual(Map<String, String> expected, Map<String, String> actual) throws IOException {
public static void assertMappingsEqual(Map<String, String> expected, Map<String, String> actual) throws IOException {
assertEquals(expected.keySet(), actual.keySet());
for (Map.Entry<String, String> expectedEntry : expected.entrySet()) {
String expectedValue = expectedEntry.getValue();
String actualValue = actual.get(expectedEntry.getKey());
XContentParser expectedJson = createParser(XContentType.JSON.xContent(), expectedValue);
XContentParser actualJson = createParser(XContentType.JSON.xContent(), actualValue);
assertEquals(expectedJson.mapOrdered(), actualJson.mapOrdered());
XContentParser expectedJson = JsonXContent.jsonXContent.createParser(NamedXContentRegistry.EMPTY,
LoggingDeprecationHandler.INSTANCE, expectedValue);
XContentParser actualJson = JsonXContent.jsonXContent.createParser(NamedXContentRegistry.EMPTY,
LoggingDeprecationHandler.INSTANCE, actualValue);
assertEquals(expectedJson.map(), actualJson.map());
}
}

View File

@ -27,6 +27,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
@ -76,6 +77,18 @@ public class CreateIndexResponseTests extends ESTestCase {
assertEquals("{\"acknowledged\":true,\"shards_acknowledged\":false,\"index\":\"index_name\"}", output);
}
public void testToAndFromXContentIndexNull() throws IOException {
CreateIndexResponse response = new CreateIndexResponse(true, false, null);
String output = Strings.toString(response);
assertEquals("{\"acknowledged\":true,\"shards_acknowledged\":false,\"index\":null}", output);
try (XContentParser parser = createParser(JsonXContent.jsonXContent, output)) {
CreateIndexResponse parsedResponse = CreateIndexResponse.fromXContent(parser);
assertNull(parsedResponse.index());
assertTrue(parsedResponse.isAcknowledged());
assertFalse(parsedResponse.isShardsAcknowledged());
}
}
public void testToAndFromXContent() throws IOException {
doFromXContentTestWithRandomFields(false);
}

View File

@ -23,12 +23,13 @@ import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;
import static org.hamcrest.Matchers.equalTo;
public class ConditionTests extends ESTestCase {
public void testMaxAge() throws Exception {
public void testMaxAge() {
final MaxAgeCondition maxAgeCondition = new MaxAgeCondition(TimeValue.timeValueHours(1));
long indexCreatedMatch = System.currentTimeMillis() - TimeValue.timeValueMinutes(61).getMillis();
@ -42,7 +43,7 @@ public class ConditionTests extends ESTestCase {
assertThat(evaluate.matched, equalTo(false));
}
public void testMaxDocs() throws Exception {
public void testMaxDocs() {
final MaxDocsCondition maxDocsCondition = new MaxDocsCondition(100L);
long maxDocsMatch = randomIntBetween(100, 1000);
@ -56,7 +57,7 @@ public class ConditionTests extends ESTestCase {
assertThat(evaluate.matched, equalTo(false));
}
public void testMaxSize() throws Exception {
public void testMaxSize() {
MaxSizeCondition maxSizeCondition = new MaxSizeCondition(new ByteSizeValue(randomIntBetween(10, 20), ByteSizeUnit.MB));
Condition.Result result = maxSizeCondition.evaluate(new Condition.Stats(randomNonNegativeLong(), randomNonNegativeLong(),
@ -72,7 +73,21 @@ public class ConditionTests extends ESTestCase {
assertThat(result.matched, equalTo(true));
}
private ByteSizeValue randomByteSize() {
public void testEqualsAndHashCode() {
MaxDocsCondition maxDocsCondition = new MaxDocsCondition(randomLong());
EqualsHashCodeTestUtils.checkEqualsAndHashCode(maxDocsCondition, condition -> new MaxDocsCondition(condition.value),
condition -> new MaxDocsCondition(randomLong()));
MaxSizeCondition maxSizeCondition = new MaxSizeCondition(randomByteSize());
EqualsHashCodeTestUtils.checkEqualsAndHashCode(maxSizeCondition, condition -> new MaxSizeCondition(condition.value),
condition -> new MaxSizeCondition(randomByteSize()));
MaxAgeCondition maxAgeCondition = new MaxAgeCondition(new TimeValue(randomNonNegativeLong()));
EqualsHashCodeTestUtils.checkEqualsAndHashCode(maxAgeCondition, condition -> new MaxAgeCondition(condition.value),
condition -> new MaxAgeCondition(new TimeValue(randomNonNegativeLong())));
}
private static ByteSizeValue randomByteSize() {
return new ByteSizeValue(randomNonNegativeLong(), ByteSizeUnit.BYTES);
}
}

View File

@ -37,15 +37,12 @@ import org.joda.time.format.DateTimeFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST)
@ -143,12 +140,8 @@ public class RolloverIT extends ESIntegTestCase {
assertThat(response.isDryRun(), equalTo(false));
assertThat(response.isRolledOver(), equalTo(false));
assertThat(response.getConditionStatus().size(), equalTo(2));
assertThat(response.getConditionStatus(), everyItem(hasProperty("value", is(false))));
Set<String> conditions = response.getConditionStatus().stream()
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
assertThat(response.getConditionStatus().values(), everyItem(is(false)));
Set<String> conditions = response.getConditionStatus().keySet();
assertThat(conditions, containsInAnyOrder(
new MaxSizeCondition(new ByteSizeValue(10, ByteSizeUnit.MB)).toString(),
new MaxAgeCondition(TimeValue.timeValueHours(4)).toString()));

View File

@ -19,6 +19,10 @@
package org.elasticsearch.action.admin.indices.rollover;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestTests;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
@ -29,15 +33,22 @@ import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.RandomCreateIndexGenerator;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.XContentTestUtils;
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
import org.junit.Before;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.Map;
import java.util.function.Consumer;
import static org.elasticsearch.common.xcontent.ToXContent.EMPTY_PARAMS;
import static org.hamcrest.Matchers.equalTo;
public class RolloverRequestTests extends ESTestCase {
@ -61,23 +72,15 @@ public class RolloverRequestTests extends ESTestCase {
.field("max_size", "45gb")
.endObject()
.endObject();
RolloverRequest.PARSER.parse(createParser(builder), request, null);
Set<Condition> conditions = request.getConditions();
request.fromXContent(createParser(builder));
Map<String, Condition> conditions = request.getConditions();
assertThat(conditions.size(), equalTo(3));
for (Condition condition : conditions) {
if (condition instanceof MaxAgeCondition) {
MaxAgeCondition maxAgeCondition = (MaxAgeCondition) condition;
assertThat(maxAgeCondition.value.getMillis(), equalTo(TimeValue.timeValueHours(24 * 10).getMillis()));
} else if (condition instanceof MaxDocsCondition) {
MaxDocsCondition maxDocsCondition = (MaxDocsCondition) condition;
assertThat(maxDocsCondition.value, equalTo(100L));
} else if (condition instanceof MaxSizeCondition) {
MaxSizeCondition maxSizeCondition = (MaxSizeCondition) condition;
assertThat(maxSizeCondition.value.getBytes(), equalTo(ByteSizeUnit.GB.toBytes(45)));
} else {
fail("unexpected condition " + condition);
}
}
MaxAgeCondition maxAgeCondition = (MaxAgeCondition)conditions.get(MaxAgeCondition.NAME);
assertThat(maxAgeCondition.value.getMillis(), equalTo(TimeValue.timeValueHours(24 * 10).getMillis()));
MaxDocsCondition maxDocsCondition = (MaxDocsCondition)conditions.get(MaxDocsCondition.NAME);
assertThat(maxDocsCondition.value, equalTo(100L));
MaxSizeCondition maxSizeCondition = (MaxSizeCondition)conditions.get(MaxSizeCondition.NAME);
assertThat(maxSizeCondition.value.getBytes(), equalTo(ByteSizeUnit.GB.toBytes(45)));
}
public void testParsingWithIndexSettings() throws Exception {
@ -105,8 +108,8 @@ public class RolloverRequestTests extends ESTestCase {
.startObject("alias1").endObject()
.endObject()
.endObject();
RolloverRequest.PARSER.parse(createParser(builder), request, null);
Set<Condition> conditions = request.getConditions();
request.fromXContent(createParser(builder));
Map<String, Condition> conditions = request.getConditions();
assertThat(conditions.size(), equalTo(2));
assertThat(request.getCreateIndexRequest().mappings().size(), equalTo(1));
assertThat(request.getCreateIndexRequest().aliases().size(), equalTo(1));
@ -126,19 +129,92 @@ public class RolloverRequestTests extends ESTestCase {
cloneRequest.readFrom(in);
assertThat(cloneRequest.getNewIndexName(), equalTo(originalRequest.getNewIndexName()));
assertThat(cloneRequest.getAlias(), equalTo(originalRequest.getAlias()));
List<String> originalConditions = originalRequest.getConditions().stream()
.map(Condition::toString)
.sorted()
.collect(Collectors.toList());
List<String> cloneConditions = cloneRequest.getConditions().stream()
.map(Condition::toString)
.sorted()
.collect(Collectors.toList());
assertThat(originalConditions, equalTo(cloneConditions));
for (Map.Entry<String, Condition> entry : cloneRequest.getConditions().entrySet()) {
Condition condition = originalRequest.getConditions().get(entry.getKey());
//here we compare the string representation as there is some information loss when serializing
//and de-serializing MaxAgeCondition
assertEquals(condition.toString(), entry.getValue().toString());
}
}
}
}
public void testToAndFromXContent() throws IOException {
RolloverRequest rolloverRequest = createTestItem();
final XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean();
BytesReference originalBytes = toShuffledXContent(rolloverRequest, xContentType, EMPTY_PARAMS, humanReadable);
RolloverRequest parsedRolloverRequest = new RolloverRequest();
parsedRolloverRequest.fromXContent(createParser(xContentType.xContent(), originalBytes));
CreateIndexRequest createIndexRequest = rolloverRequest.getCreateIndexRequest();
CreateIndexRequest parsedCreateIndexRequest = parsedRolloverRequest.getCreateIndexRequest();
CreateIndexRequestTests.assertMappingsEqual(createIndexRequest.mappings(), parsedCreateIndexRequest.mappings());
CreateIndexRequestTests.assertAliasesEqual(createIndexRequest.aliases(), parsedCreateIndexRequest.aliases());
assertEquals(createIndexRequest.settings(), parsedCreateIndexRequest.settings());
assertEquals(rolloverRequest.getConditions(), parsedRolloverRequest.getConditions());
BytesReference finalBytes = toShuffledXContent(parsedRolloverRequest, xContentType, EMPTY_PARAMS, humanReadable);
ElasticsearchAssertions.assertToXContentEquivalent(originalBytes, finalBytes, xContentType);
}
public void testUnknownFields() throws IOException {
final RolloverRequest request = new RolloverRequest();
XContentType xContentType = randomFrom(XContentType.values());
final XContentBuilder builder = XContentFactory.contentBuilder(xContentType);
builder.startObject();
{
builder.startObject("conditions");
builder.field("max_age", "10d");
builder.endObject();
}
builder.endObject();
BytesReference mutated = XContentTestUtils.insertRandomFields(xContentType, builder.bytes(), null, random());
expectThrows(ParsingException.class, () -> request.fromXContent(createParser(xContentType.xContent(), mutated)));
}
public void testSameConditionCanOnlyBeAddedOnce() {
RolloverRequest rolloverRequest = new RolloverRequest();
Consumer<RolloverRequest> rolloverRequestConsumer = randomFrom(conditionsGenerator);
rolloverRequestConsumer.accept(rolloverRequest);
expectThrows(IllegalArgumentException.class, () -> rolloverRequestConsumer.accept(rolloverRequest));
}
public void testValidation() {
RolloverRequest rolloverRequest = new RolloverRequest();
assertNotNull(rolloverRequest.getCreateIndexRequest());
ActionRequestValidationException validationException = rolloverRequest.validate();
assertNotNull(validationException);
assertEquals(1, validationException.validationErrors().size());
assertEquals("index alias is missing", validationException.validationErrors().get(0));
}
private static List<Consumer<RolloverRequest>> conditionsGenerator = new ArrayList<>();
static {
conditionsGenerator.add((request) -> request.addMaxIndexDocsCondition(randomNonNegativeLong()));
conditionsGenerator.add((request) -> request.addMaxIndexSizeCondition(new ByteSizeValue(randomNonNegativeLong())));
conditionsGenerator.add((request) -> request.addMaxIndexAgeCondition(new TimeValue(randomNonNegativeLong())));
}
private static RolloverRequest createTestItem() throws IOException {
RolloverRequest rolloverRequest = new RolloverRequest();
if (randomBoolean()) {
String type = randomAlphaOfLengthBetween(3, 10);
rolloverRequest.getCreateIndexRequest().mapping(type, RandomCreateIndexGenerator.randomMapping(type));
}
if (randomBoolean()) {
RandomCreateIndexGenerator.randomAliases(rolloverRequest.getCreateIndexRequest());
}
if (randomBoolean()) {
rolloverRequest.getCreateIndexRequest().settings(RandomCreateIndexGenerator.randomIndexSettings());
}
int numConditions = randomIntBetween(0, 3);
List<Consumer<RolloverRequest>> conditions = randomSubsetOf(numConditions, conditionsGenerator);
for (Consumer<RolloverRequest> consumer : conditions) {
consumer.accept(rolloverRequest);
}
return rolloverRequest;
}
}

View File

@ -0,0 +1,132 @@
/*
* 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.indices.rollover;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class RolloverResponseTests extends AbstractStreamableXContentTestCase<RolloverResponse> {
@Override
protected RolloverResponse createTestInstance() {
boolean acknowledged = randomBoolean();
boolean shardsAcknowledged = acknowledged && randomBoolean();
return new RolloverResponse(randomAlphaOfLengthBetween(3, 10),
randomAlphaOfLengthBetween(3, 10), randomResults(true), randomBoolean(), randomBoolean(), acknowledged, shardsAcknowledged);
}
private static Map<String, Boolean> randomResults(boolean allowNoItems) {
Map<String, Boolean> results = new HashMap<>();
int numResults = randomIntBetween(allowNoItems ? 0 : 1, 3);
List<Supplier<Condition<?>>> conditions = randomSubsetOf(numResults, conditionSuppliers);
for (Supplier<Condition<?>> condition : conditions) {
Condition<?> cond = condition.get();
results.put(cond.name, randomBoolean());
}
return results;
}
private static final List<Supplier<Condition<?>>> conditionSuppliers = new ArrayList<>();
static {
conditionSuppliers.add(() -> new MaxAgeCondition(new TimeValue(randomNonNegativeLong())));
conditionSuppliers.add(() -> new MaxDocsCondition(randomNonNegativeLong()));
conditionSuppliers.add(() -> new MaxDocsCondition(randomNonNegativeLong()));
}
@Override
protected RolloverResponse createBlankInstance() {
return new RolloverResponse();
}
@Override
protected RolloverResponse doParseInstance(XContentParser parser) {
return RolloverResponse.fromXContent(parser);
}
@Override
protected Predicate<String> getRandomFieldsExcludeFilter() {
return field -> field.startsWith("conditions");
}
@Override
protected EqualsHashCodeTestUtils.MutateFunction<RolloverResponse> getMutateFunction() {
return response -> {
int i = randomIntBetween(0, 6);
switch(i) {
case 0:
return new RolloverResponse(response.getOldIndex() + randomAlphaOfLengthBetween(2, 5),
response.getNewIndex(), response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 1:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex() + randomAlphaOfLengthBetween(2, 5),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 2:
Map<String, Boolean> results;
if (response.getConditionStatus().isEmpty()) {
results = randomResults(false);
} else {
results = new HashMap<>(response.getConditionStatus().size());
List<String> keys = randomSubsetOf(randomIntBetween(1, response.getConditionStatus().size()),
response.getConditionStatus().keySet());
for (Map.Entry<String, Boolean> entry : response.getConditionStatus().entrySet()) {
boolean value = keys.contains(entry.getKey()) ? entry.getValue() == false : entry.getValue();
results.put(entry.getKey(), value);
}
}
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(), results, response.isDryRun(),
response.isRolledOver(), response.isAcknowledged(), response.isShardsAcknowledged());
case 3:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun() == false, response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 4:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver() == false,
response.isAcknowledged(), response.isShardsAcknowledged());
case 5: {
boolean acknowledged = response.isAcknowledged() == false;
boolean shardsAcknowledged = acknowledged && response.isShardsAcknowledged();
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
acknowledged, shardsAcknowledged);
}
case 6: {
boolean shardsAcknowledged = response.isShardsAcknowledged() == false;
boolean acknowledged = shardsAcknowledged || response.isAcknowledged();
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
acknowledged, shardsAcknowledged);
}
default:
throw new UnsupportedOperationException();
}
};
}
}

View File

@ -44,6 +44,7 @@ import org.mockito.ArgumentCaptor;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import static org.elasticsearch.action.admin.indices.rollover.TransportRolloverAction.evaluateConditions;
@ -58,7 +59,7 @@ import static org.mockito.Mockito.when;
public class TransportRolloverActionTests extends ESTestCase {
public void testDocStatsSelectionFromPrimariesOnly() throws Exception {
public void testDocStatsSelectionFromPrimariesOnly() {
long docsInPrimaryShards = 100;
long docsInShards = 200;
@ -70,7 +71,7 @@ public class TransportRolloverActionTests extends ESTestCase {
assertEquals(docsInPrimaryShards, argument.getValue().numDocs);
}
public void testEvaluateConditions() throws Exception {
public void testEvaluateConditions() {
MaxDocsCondition maxDocsCondition = new MaxDocsCondition(100L);
MaxAgeCondition maxAgeCondition = new MaxAgeCondition(TimeValue.timeValueHours(2));
MaxSizeCondition maxSizeCondition = new MaxSizeCondition(new ByteSizeValue(randomIntBetween(10, 100), ByteSizeUnit.MB));
@ -89,29 +90,29 @@ public class TransportRolloverActionTests extends ESTestCase {
.settings(settings)
.build();
final Set<Condition> conditions = Sets.newHashSet(maxDocsCondition, maxAgeCondition, maxSizeCondition);
Set<Condition.Result> results = evaluateConditions(conditions,
Map<String, Boolean> results = evaluateConditions(conditions,
new DocsStats(matchMaxDocs, 0L, ByteSizeUnit.MB.toBytes(120)), metaData);
assertThat(results.size(), equalTo(3));
for (Condition.Result result : results) {
assertThat(result.matched, equalTo(true));
for (Boolean matched : results.values()) {
assertThat(matched, equalTo(true));
}
results = evaluateConditions(conditions, new DocsStats(notMatchMaxDocs, 0, notMatchMaxSize.getBytes()), metaData);
assertThat(results.size(), equalTo(3));
for (Condition.Result result : results) {
if (result.condition instanceof MaxAgeCondition) {
assertThat(result.matched, equalTo(true));
} else if (result.condition instanceof MaxDocsCondition) {
assertThat(result.matched, equalTo(false));
} else if (result.condition instanceof MaxSizeCondition) {
assertThat(result.matched, equalTo(false));
for (Map.Entry<String, Boolean> entry : results.entrySet()) {
if (entry.getKey().equals(maxAgeCondition.toString())) {
assertThat(entry.getValue(), equalTo(true));
} else if (entry.getKey().equals(maxDocsCondition.toString())) {
assertThat(entry.getValue(), equalTo(false));
} else if (entry.getKey().equals(maxSizeCondition.toString())) {
assertThat(entry.getValue(), equalTo(false));
} else {
fail("unknown condition result found " + result.condition);
fail("unknown condition result found " + entry.getKey());
}
}
}
public void testEvaluateWithoutDocStats() throws Exception {
public void testEvaluateWithoutDocStats() {
MaxDocsCondition maxDocsCondition = new MaxDocsCondition(randomNonNegativeLong());
MaxAgeCondition maxAgeCondition = new MaxAgeCondition(TimeValue.timeValueHours(randomIntBetween(1, 3)));
MaxSizeCondition maxSizeCondition = new MaxSizeCondition(new ByteSizeValue(randomNonNegativeLong()));
@ -128,23 +129,23 @@ public class TransportRolloverActionTests extends ESTestCase {
.creationDate(System.currentTimeMillis() - TimeValue.timeValueHours(randomIntBetween(5, 10)).getMillis())
.settings(settings)
.build();
Set<Condition.Result> results = evaluateConditions(conditions, null, metaData);
Map<String, Boolean> results = evaluateConditions(conditions, null, metaData);
assertThat(results.size(), equalTo(3));
for (Condition.Result result : results) {
if (result.condition instanceof MaxAgeCondition) {
assertThat(result.matched, equalTo(true));
} else if (result.condition instanceof MaxDocsCondition) {
assertThat(result.matched, equalTo(false));
} else if (result.condition instanceof MaxSizeCondition) {
assertThat(result.matched, equalTo(false));
for (Map.Entry<String, Boolean> entry : results.entrySet()) {
if (entry.getKey().equals(maxAgeCondition.toString())) {
assertThat(entry.getValue(), equalTo(true));
} else if (entry.getKey().equals(maxDocsCondition.toString())) {
assertThat(entry.getValue(), equalTo(false));
} else if (entry.getKey().equals(maxSizeCondition.toString())) {
assertThat(entry.getValue(), equalTo(false));
} else {
fail("unknown condition result found " + result.condition);
fail("unknown condition result found " + entry.getKey());
}
}
}
public void testCreateUpdateAliasRequest() throws Exception {
public void testCreateUpdateAliasRequest() {
String sourceAlias = randomAlphaOfLength(10);
String sourceIndex = randomAlphaOfLength(10);
String targetIndex = randomAlphaOfLength(10);
@ -171,7 +172,7 @@ public class TransportRolloverActionTests extends ESTestCase {
assertTrue(foundRemove);
}
public void testValidation() throws Exception {
public void testValidation() {
String index1 = randomAlphaOfLength(10);
String alias = randomAlphaOfLength(10);
String index2 = randomAlphaOfLength(10);
@ -206,7 +207,7 @@ public class TransportRolloverActionTests extends ESTestCase {
TransportRolloverAction.validate(metaData, new RolloverRequest(alias, randomAlphaOfLength(10)));
}
public void testGenerateRolloverIndexName() throws Exception {
public void testGenerateRolloverIndexName() {
String invalidIndexName = randomAlphaOfLength(10) + "A";
IndexNameExpressionResolver indexNameExpressionResolver = new IndexNameExpressionResolver(Settings.EMPTY);
expectThrows(IllegalArgumentException.class, () ->
@ -224,12 +225,12 @@ public class TransportRolloverActionTests extends ESTestCase {
indexNameExpressionResolver));
}
public void testCreateIndexRequest() throws Exception {
public void testCreateIndexRequest() {
String alias = randomAlphaOfLength(10);
String rolloverIndex = randomAlphaOfLength(10);
final RolloverRequest rolloverRequest = new RolloverRequest(alias, randomAlphaOfLength(10));
final ActiveShardCount activeShardCount = randomBoolean() ? ActiveShardCount.ALL : ActiveShardCount.ONE;
rolloverRequest.setWaitForActiveShards(activeShardCount);
rolloverRequest.getCreateIndexRequest().waitForActiveShards(activeShardCount);
final Settings settings = Settings.builder()
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
.put(IndexMetaData.SETTING_INDEX_UUID, UUIDs.randomBase64UUID())
@ -244,7 +245,7 @@ public class TransportRolloverActionTests extends ESTestCase {
assertThat(createIndexRequest.cause(), equalTo("rollover_index"));
}
public void testRejectDuplicateAlias() throws Exception {
public void testRejectDuplicateAlias() {
final IndexTemplateMetaData template = IndexTemplateMetaData.builder("test-template")
.patterns(Arrays.asList("foo-*", "bar-*"))
.putAlias(AliasMetaData.builder("foo-write")).putAlias(AliasMetaData.builder("bar-write"))
@ -271,7 +272,7 @@ public class TransportRolloverActionTests extends ESTestCase {
return response;
}
private IndexMetaData createMetaData() {
private static IndexMetaData createMetaData() {
final Settings settings = Settings.builder()
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
.put(IndexMetaData.SETTING_INDEX_UUID, UUIDs.randomBase64UUID())
@ -284,7 +285,7 @@ public class TransportRolloverActionTests extends ESTestCase {
.build();
}
private Condition createTestCondition() {
private static Condition createTestCondition() {
final Condition condition = mock(Condition.class);
when(condition.evaluate(any())).thenReturn(new Condition.Result(condition, true));
return condition;

View File

@ -28,6 +28,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.RandomCreateIndexGenerator;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
import java.io.IOException;
@ -76,6 +77,9 @@ public class ResizeRequestTests extends ESTestCase {
CreateIndexRequestTests.assertAliasesEqual(resizeRequest.getTargetIndexRequest().aliases(),
parsedResizeRequest.getTargetIndexRequest().aliases());
assertEquals(resizeRequest.getTargetIndexRequest().settings(), parsedResizeRequest.getTargetIndexRequest().settings());
BytesReference finalBytes = toShuffledXContent(parsedResizeRequest, xContentType, EMPTY_PARAMS, humanReadable);
ElasticsearchAssertions.assertToXContentEquivalent(originalBytes, finalBytes, xContentType);
}
private static ResizeRequest createTestItem() {

View File

@ -76,7 +76,7 @@ public final class RandomCreateIndexGenerator {
return builder.build();
}
private static XContentBuilder randomMapping(String type) throws IOException {
public static XContentBuilder randomMapping(String type) throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject().startObject(type);

View File

@ -58,7 +58,7 @@ public abstract class AbstractStreamableTestCase<T extends Streamable> extends E
}
/**
* Returns a {@link MutateFunction} that can be used to make create a copy
* Returns a {@link MutateFunction} that can be used to create a copy
* of the given instance that is different to this instance. This defaults
* to null.
*/
@ -71,7 +71,7 @@ public abstract class AbstractStreamableTestCase<T extends Streamable> extends E
* Tests that the equals and hashcode methods are consistent and copied
* versions of the instance have are equal.
*/
public void testEqualsAndHashcode() throws IOException {
public void testEqualsAndHashcode() {
for (int runs = 0; runs < NUMBER_OF_TEST_RUNS; runs++) {
EqualsHashCodeTestUtils.checkEqualsAndHashCode(createTestInstance(), getCopyFunction(), getMutateFunction());
}

View File

@ -27,6 +27,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
import java.util.function.Predicate;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
@ -44,7 +45,7 @@ public abstract class AbstractStreamableXContentTestCase<T extends ToXContent &
BytesReference withRandomFields;
if (supportsUnknownFields()) {
// we add a few random fields to check that parser is lenient on new fields
withRandomFields = XContentTestUtils.insertRandomFields(xContentType, shuffled, null, random());
withRandomFields = XContentTestUtils.insertRandomFields(xContentType, shuffled, getRandomFieldsExcludeFilter(), random());
} else {
withRandomFields = shuffled;
}
@ -74,6 +75,10 @@ public abstract class AbstractStreamableXContentTestCase<T extends ToXContent &
return true;
}
protected Predicate<String> getRandomFieldsExcludeFilter() {
return field -> false;
}
private T parseInstance(XContentParser parser) throws IOException {
T parsedInstance = doParseInstance(parser);
assertNull(parser.nextToken());