From 8bbb3c9ffad66e599a17438a533be9356ea6d4a4 Mon Sep 17 00:00:00 2001 From: Luca Cavanna Date: Tue, 20 Feb 2018 15:58:58 +0100 Subject: [PATCH] REST high-level client: add support for Rollover Index API (#28698) Relates to #27205 --- .../elasticsearch/client/IndicesClient.java | 26 +++- .../org/elasticsearch/client/Request.java | 19 ++- .../elasticsearch/client/IndicesClientIT.java | 60 ++++++++ .../elasticsearch/client/RequestTests.java | 44 +++++- .../IndicesClientDocumentationIT.java | 101 ++++++++++++- .../high-level/indices/create_index.asciidoc | 5 +- .../high-level/indices/exists_alias.asciidoc | 2 +- .../high-level/indices/open_index.asciidoc | 4 +- .../high-level/indices/rollover.asciidoc | 131 ++++++++++++++++ .../high-level/indices/split_index.asciidoc | 8 +- .../high-level/supported-apis.asciidoc | 2 + .../indices/create/CreateIndexRequest.java | 12 +- .../indices/create/CreateIndexResponse.java | 37 ++--- .../indices/delete/DeleteIndexResponse.java | 2 +- .../admin/indices/open/OpenIndexResponse.java | 37 +---- .../admin/indices/rollover/Condition.java | 38 ++--- .../indices/rollover/MaxAgeCondition.java | 7 + .../indices/rollover/MaxDocsCondition.java | 6 + .../indices/rollover/MaxSizeCondition.java | 7 + .../indices/rollover/RolloverRequest.java | 131 ++++++++-------- .../rollover/RolloverRequestBuilder.java | 2 +- .../indices/rollover/RolloverResponse.java | 142 ++++++++++-------- .../rollover/TransportRolloverAction.java | 15 +- .../support/master/AcknowledgedResponse.java | 4 +- .../master/ShardsAcknowledgedResponse.java | 76 ++++++++++ .../rest/action/AcknowledgedRestListener.java | 2 +- .../admin/indices/RestCreateIndexAction.java | 11 +- .../admin/indices/RestDeleteIndexAction.java | 4 +- .../admin/indices/RestOpenIndexAction.java | 11 +- .../indices/RestRolloverIndexAction.java | 5 +- .../admin/indices/RestShrinkIndexAction.java | 17 +-- .../admin/indices/RestSplitIndexAction.java | 17 +-- .../create/CreateIndexRequestTests.java | 16 +- .../create/CreateIndexResponseTests.java | 13 ++ .../indices/rollover/ConditionTests.java | 23 ++- .../admin/indices/rollover/RolloverIT.java | 11 +- .../rollover/RolloverRequestTests.java | 136 +++++++++++++---- .../rollover/RolloverResponseTests.java | 132 ++++++++++++++++ .../TransportRolloverActionTests.java | 63 ++++---- .../indices/shrink/ResizeRequestTests.java | 4 + .../index/RandomCreateIndexGenerator.java | 2 +- .../test/AbstractStreamableTestCase.java | 4 +- .../AbstractStreamableXContentTestCase.java | 7 +- 43 files changed, 1026 insertions(+), 370 deletions(-) create mode 100644 docs/java-rest/high-level/indices/rollover.asciidoc create mode 100644 server/src/main/java/org/elasticsearch/action/support/master/ShardsAcknowledgedResponse.java create mode 100644 server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverResponseTests.java diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java index 98d6736f7864a..6968839d1ee42 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java @@ -35,6 +35,8 @@ 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 void shrinkAsync(ResizeRequest resizeRequest, ActionListener * See - * Shrink Index API on elastic.co + * Split Index API on elastic.co */ public ResizeResponse split(ResizeRequest resizeRequest, Header... headers) throws IOException { return restHighLevelClient.performRequestAndParseEntity(resizeRequest, Request::split, ResizeResponse::fromXContent, @@ -289,4 +291,26 @@ public void splitAsync(ResizeRequest resizeRequest, ActionListener + * See + * Rollover Index API on elastic.co + */ + 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 + *

+ * See + * Rollover Index API on elastic.co + */ + public void rolloverAsync(RolloverRequest rolloverRequest, ActionListener listener, Header... headers) { + restHighLevelClient.performRequestAsyncAndParseEntity(rolloverRequest, Request::rollover, RolloverResponse::fromXContent, + listener, emptySet(), headers); + } } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java index 246964f6f4855..fd849f5e47883 100755 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java @@ -38,6 +38,7 @@ 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 @@ static Request existsAlias(GetAliasesRequest getAliasesRequest) { } 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 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 @@ static Request clusterPutSettings(ClusterUpdateSettingsRequest clusterUpdateSett 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)); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java index b8c9f4e76c25e..fbc15b10a7488 100755 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java @@ -39,11 +39,18 @@ 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 void testSplit() throws IOException { Map aliasData = (Map)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 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 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 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()); + } + } } \ No newline at end of file diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java index 970eac8372604..71724cab82ec7 100755 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java @@ -40,6 +40,7 @@ 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.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 @@ private static void resizeTest(ResizeType resizeType, CheckedFunction 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()); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java index e30018abd4caa..cb262db1b379f 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java @@ -38,6 +38,8 @@ 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.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 void onFailure(Exception e) { } } - @SuppressWarnings({"unchecked", "rawtypes"}) public void testUpdateAliases() throws Exception { RestHighLevelClient client = highLevelClient(); @@ -811,12 +814,12 @@ public void onFailure(Exception e) { } } - @SuppressWarnings({"unchecked", "rawtypes"}) public void testShrinkIndex() throws Exception { RestHighLevelClient client = highLevelClient(); { Map nodes = getAsMap("_nodes"); + @SuppressWarnings("unchecked") String firstNode = ((Map) 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 void testShrinkIndex() throws Exception { 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 void onFailure(Exception e) { assertTrue(latch.await(30L, TimeUnit.SECONDS)); } - @SuppressWarnings({"unchecked", "rawtypes"}) public void testSplitIndex() throws Exception { RestHighLevelClient client = highLevelClient(); @@ -906,8 +908,8 @@ public void testSplitIndex() throws Exception { 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 void onFailure(Exception e) { 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 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 listener = new ActionListener() { + @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)); + } } diff --git a/docs/java-rest/high-level/indices/create_index.asciidoc b/docs/java-rest/high-level/indices/create_index.asciidoc index fa723d3158cf4..b68faa0dd7659 100644 --- a/docs/java-rest/high-level/indices/create_index.asciidoc +++ b/docs/java-rest/high-level/indices/create_index.asciidoc @@ -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 diff --git a/docs/java-rest/high-level/indices/exists_alias.asciidoc b/docs/java-rest/high-level/indices/exists_alias.asciidoc index 5042b8119a5b0..c92c526444f68 100644 --- a/docs/java-rest/high-level/indices/exists_alias.asciidoc +++ b/docs/java-rest/high-level/indices/exists_alias.asciidoc @@ -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 diff --git a/docs/java-rest/high-level/indices/open_index.asciidoc b/docs/java-rest/high-level/indices/open_index.asciidoc index 1123e62a7a228..1c690344577b8 100644 --- a/docs/java-rest/high-level/indices/open_index.asciidoc +++ b/docs/java-rest/high-level/indices/open_index.asciidoc @@ -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"] -------------------------------------------------- diff --git a/docs/java-rest/high-level/indices/rollover.asciidoc b/docs/java-rest/high-level/indices/rollover.asciidoc new file mode 100644 index 0000000000000..85a99eb002b6e --- /dev/null +++ b/docs/java-rest/high-level/indices/rollover.asciidoc @@ -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 <> +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 + + diff --git a/docs/java-rest/high-level/indices/split_index.asciidoc b/docs/java-rest/high-level/indices/split_index.asciidoc index 55081a1da37df..cdf59fd416fc4 100644 --- a/docs/java-rest/high-level/indices/split_index.asciidoc +++ b/docs/java-rest/high-level/indices/split_index.asciidoc @@ -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 diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 295de7689f7c1..9269da0923a56 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -52,6 +52,7 @@ Index Management:: * <> * <> * <> +* <> Mapping Management:: * <> @@ -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[] diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java index b92b87f05e561..e22a8be968ed1 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java @@ -36,7 +36,6 @@ 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.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 @@ */ public class CreateIndexRequest extends AcknowledgedRequest 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 void writeTo(StreamOutput out) throws IOException { @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 XContentBuilder toXContent(XContentBuilder builder, Params params) throws for (Map.Entry entry : customs.entrySet()) { builder.field(entry.getKey(), entry.getValue(), params); } - - builder.endObject(); return builder; } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java index be30a8c97b189..e5b7d323b5af9 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java @@ -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 @@ /** * 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 PARSER = new ConstructingObjectParser<>("create_index", @@ -50,22 +49,17 @@ public class CreateIndexResponse extends AcknowledgedResponse implements ToXCont } protected static void declareFields(ConstructingObjectParser 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 @@ protected CreateIndexResponse(boolean acknowledged, boolean shardsAcknowledged, 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 void readFrom(StreamInput in) throws IOException { 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; } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponse.java index 8217668e2177d..378f10bb8207e 100755 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponse.java @@ -68,7 +68,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws return builder; } - public static DeleteIndexResponse fromXContent(XContentParser parser) throws IOException { + public static DeleteIndexResponse fromXContent(XContentParser parser) { return PARSER.apply(parser, null); } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/open/OpenIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/open/OpenIndexResponse.java index 4e98c60265c76..5bc115eaf1ac5 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/open/OpenIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/open/OpenIndexResponse.java @@ -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 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 void readFrom(StreamInput in) throws IOException { super.readFrom(in); readAcknowledged(in); if (in.getVersion().onOrAfter(Version.V_6_1_0)) { - shardsAcknowledged = in.readBoolean(); + readShardsAcknowledged(in); } } @@ -84,7 +63,7 @@ public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); writeAcknowledged(out); if (out.getVersion().onOrAfter(Version.V_6_1_0)) { - out.writeBoolean(shardsAcknowledged); + writeShardsAcknowledged(out); } } @@ -92,12 +71,12 @@ public void writeTo(StreamOutput out) throws IOException { 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); } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/Condition.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/Condition.java index 83dc73f9e94b3..afbc9a554ed5e 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/Condition.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/Condition.java @@ -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 implements NamedWriteable { - - public static ObjectParser, 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 implements NamedWriteable, ToXContentFragment { protected T value; protected final String name; @@ -62,6 +48,24 @@ boolean includedInVersion(Version version) { 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 + "]"; diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxAgeCondition.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxAgeCondition.java index 9208193c9849e..c0b0d2a3297da 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxAgeCondition.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxAgeCondition.java @@ -22,6 +22,7 @@ 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 String getWriteableName() { @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()); + } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxDocsCondition.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxDocsCondition.java index 7c1f802389e54..8fddb870e59e9 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxDocsCondition.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxDocsCondition.java @@ -21,6 +21,7 @@ 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 String getWriteableName() { 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); + } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxSizeCondition.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxSizeCondition.java index 91b18bc050623..bb6f37634ce87 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxSizeCondition.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MaxSizeCondition.java @@ -24,6 +24,7 @@ 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 String getWriteableName() { @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()); + } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequest.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequest.java index 34d56239b5ce8..fe5ad65c4799b 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequest.java @@ -21,7 +21,6 @@ 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.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 implements IndicesRequest { +public class RolloverRequest extends AcknowledgedRequest implements IndicesRequest, ToXContentObject { + + private static final ObjectParser PARSER = new ObjectParser<>("rollover"); + private static final ObjectParser, 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 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 mappingsEntry : parser.map().entrySet()) { - request.createIndexRequest.mapping(mappingsEntry.getKey(), - (Map) mappingsEntry.getValue()); + request.createIndexRequest.mapping(mappingsEntry.getKey(), (Map) 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 conditions = new HashSet<>(2); + private Map 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 RolloverRequest(String alias, String newIndexName) { @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 void readFrom(StreamInput in) throws IOException { 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 void writeTo(StreamOutput out) throws IOException { 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 void dryRun(boolean dryRun) { * Adds condition to check if the index is at least age 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 numDocs */ 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 size. */ 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 getConditions() { + Map getConditions() { return conditions; } - String getAlias() { + public String getAlias() { return alias; } - String getNewIndexName() { + public String getNewIndexName() { return newIndexName; } - 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 + * Returns the inner {@link CreateIndexRequest}. Allows to configure mappings, settings and aliases for the new index. */ - public void setWaitForActiveShards(ActiveShardCount waitForActiveShards) { - this.createIndexRequest.waitForActiveShards(waitForActiveShards); + public CreateIndexRequest getCreateIndexRequest() { + return createIndexRequest; } - /** - * 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)); + @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; } + public void fromXContent(XContentParser parser) throws IOException { + PARSER.parse(parser, this, null); + } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequestBuilder.java index 818def9d19a09..be331547b2a20 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequestBuilder.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequestBuilder.java @@ -93,7 +93,7 @@ public RolloverRequestBuilder mapping(String type, String source) { * @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; } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverResponse.java index 7e2ec1677740d..58c84385f49fc 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/RolloverResponse.java @@ -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; - -public final class RolloverResponse extends ActionResponse implements ToXContentObject { - - 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"; +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; + +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 PARSER = new ConstructingObjectParser<>("rollover", + true, args -> new RolloverResponse((String) args[0], (String) args[1], (Map) 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> conditionStatus; + private Map conditionStatus; private boolean dryRun; private boolean rolledOver; - private boolean acknowledged; - private boolean shardsAcknowledged; RolloverResponse() { } - RolloverResponse(String oldIndex, String newIndex, Set conditionResults, - boolean dryRun, boolean rolledOver, boolean acknowledged, boolean shardsAcknowledged) { + RolloverResponse(String oldIndex, String newIndex, Map 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 String getNewIndex() { /** * Returns the statuses of all the request conditions */ - public Set> getConditionStatus() { + public Map getConditionStatus() { return conditionStatus; } @@ -101,42 +112,20 @@ public boolean isRolledOver() { 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> 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 void writeTo(StreamOutput out) throws IOException { out.writeString(oldIndex); out.writeString(newIndex); out.writeVInt(conditionStatus.size()); - for (Map.Entry entry : conditionStatus) { + for (Map.Entry 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 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 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); + } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java index ded01077da2af..a5385c42aa0af 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java @@ -51,9 +51,10 @@ 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 @@ protected void masterOperation(final RolloverRequest rolloverRequest, final Clus new ActionListener() { @Override public void onResponse(IndicesStatsResponse statsResponse) { - final Set conditionResults = evaluateConditions(rolloverRequest.getConditions(), + final Map conditionResults = evaluateConditions(rolloverRequest.getConditions().values(), metaData.index(sourceIndexName), statsResponse); if (rolloverRequest.isDryRun()) { @@ -130,7 +131,7 @@ public void onResponse(IndicesStatsResponse statsResponse) { 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 @@ static String generateRolloverIndexName(String sourceIndexName, IndexNameExpress } } - static Set evaluateConditions(final Set conditions, - final DocsStats docsStats, final IndexMetaData metaData) { + static Map evaluateConditions(final Collection 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 evaluateConditions(final Set conditions, final IndexMetaData metaData, + static Map evaluateConditions(final Collection conditions, final IndexMetaData metaData, final IndicesStatsResponse statsResponse) { return evaluateConditions(conditions, statsResponse.getPrimaries().getDocs(), metaData); } diff --git a/server/src/main/java/org/elasticsearch/action/support/master/AcknowledgedResponse.java b/server/src/main/java/org/elasticsearch/action/support/master/AcknowledgedResponse.java index 18cb416a763fe..343a76c81571f 100755 --- a/server/src/main/java/org/elasticsearch/action/support/master/AcknowledgedResponse.java +++ b/server/src/main/java/org/elasticsearch/action/support/master/AcknowledgedResponse.java @@ -62,14 +62,14 @@ public final boolean isAcknowledged() { } /** - * 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); diff --git a/server/src/main/java/org/elasticsearch/action/support/master/ShardsAcknowledgedResponse.java b/server/src/main/java/org/elasticsearch/action/support/master/ShardsAcknowledgedResponse.java new file mode 100644 index 0000000000000..c8672456acb33 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/action/support/master/ShardsAcknowledgedResponse.java @@ -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 void declareAcknowledgedAndShardsAcknowledgedFields( + ConstructingObjectParser 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()); + } +} diff --git a/server/src/main/java/org/elasticsearch/rest/action/AcknowledgedRestListener.java b/server/src/main/java/org/elasticsearch/rest/action/AcknowledgedRestListener.java index 9f08c43fa0f3f..7fce8b310678e 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/AcknowledgedRestListener.java +++ b/server/src/main/java/org/elasticsearch/rest/action/AcknowledgedRestListener.java @@ -28,6 +28,7 @@ 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 extends RestBuilderListener { public AcknowledgedRestListener(RestChannel channel) { @@ -36,7 +37,6 @@ public AcknowledgedRestListener(RestChannel channel) { @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); diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java index 0934d8557158b..201a3b66b086d 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java @@ -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 RestChannelConsumer prepareRequest(final RestRequest request, final NodeC 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(channel) { - @Override - public void addCustomFields(XContentBuilder builder, CreateIndexResponse response) throws IOException { - response.addCustomFields(builder); - } - }); + return channel -> client.admin().indices().create(createIndexRequest, new RestToXContentListener<>(channel)); } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexAction.java index d3f2566026151..f6c4c17857287 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexAction.java @@ -27,7 +27,7 @@ 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 RestChannelConsumer prepareRequest(final RestRequest request, final NodeC 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)); } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestOpenIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestOpenIndexAction.java index 73817c1565d4a..fcf2422be7c2b 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestOpenIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestOpenIndexAction.java @@ -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 RestChannelConsumer prepareRequest(final RestRequest request, final NodeC if (waitForActiveShards != null) { openIndexRequest.waitForActiveShards(ActiveShardCount.parseString(waitForActiveShards)); } - return channel -> client.admin().indices().open(openIndexRequest, new AcknowledgedRestListener(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)); } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java index bd31ec3a70cc9..489001bf2a14f 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java @@ -45,11 +45,12 @@ public String getName() { @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)); } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestShrinkIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestShrinkIndexAction.java index c72dad2654e61..be875dd0a55aa 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestShrinkIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestShrinkIndexAction.java @@ -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 String getName() { @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(channel) { - @Override - public void addCustomFields(XContentBuilder builder, ResizeResponse response) throws IOException { - response.addCustomFields(builder); - } - }); + return channel -> client.admin().indices().resizeIndex(shrinkIndexRequest, new RestToXContentListener<>(channel)); } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestSplitIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestSplitIndexAction.java index 9bd1711d15a6e..d465c4ebb749b 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestSplitIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestSplitIndexAction.java @@ -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 String getName() { @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(channel) { - @Override - public void addCustomFields(XContentBuilder builder, ResizeResponse response) throws IOException { - response.addCustomFields(builder); - } - }); + return channel -> client.admin().indices().resizeIndex(shrinkIndexRequest, new RestToXContentListener<>(channel)); } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java index acb7161fb5a1f..034570bbc5c11 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java @@ -26,11 +26,14 @@ 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 void testToAndFromXContent() throws IOException { 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 expected, Map actual) throws IOException { + public static void assertMappingsEqual(Map expected, Map actual) throws IOException { assertEquals(expected.keySet(), actual.keySet()); for (Map.Entry 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()); } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponseTests.java index 69238599194d3..358073db75154 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponseTests.java @@ -27,6 +27,7 @@ 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 void testToXContent() { 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); } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/ConditionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/ConditionTests.java index a4e6cdfade7ef..bc6e2d1b610ad 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/ConditionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/ConditionTests.java @@ -23,12 +23,13 @@ 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 void testMaxAge() throws Exception { 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 void testMaxDocs() throws Exception { 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 void testMaxSize() throws Exception { 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); } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverIT.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverIT.java index e2c31db81ce60..869bba452fefe 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverIT.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverIT.java @@ -37,15 +37,12 @@ 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 void testRolloverConditionsNotMet() throws Exception { 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 conditions = response.getConditionStatus().stream() - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); + assertThat(response.getConditionStatus().values(), everyItem(is(false))); + Set conditions = response.getConditionStatus().keySet(); assertThat(conditions, containsInAnyOrder( new MaxSizeCondition(new ByteSizeValue(10, ByteSizeUnit.MB)).toString(), new MaxAgeCondition(TimeValue.timeValueHours(4)).toString())); diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequestTests.java index 290ba79af0738..a2ef02af486a7 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverRequestTests.java @@ -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.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 void testConditionsParsing() throws Exception { .field("max_size", "45gb") .endObject() .endObject(); - RolloverRequest.PARSER.parse(createParser(builder), request, null); - Set conditions = request.getConditions(); + request.fromXContent(createParser(builder)); + Map 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 void testParsingWithIndexSettings() throws Exception { .startObject("alias1").endObject() .endObject() .endObject(); - RolloverRequest.PARSER.parse(createParser(builder), request, null); - Set conditions = request.getConditions(); + request.fromXContent(createParser(builder)); + Map 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 void testSerialize() throws Exception { cloneRequest.readFrom(in); assertThat(cloneRequest.getNewIndexName(), equalTo(originalRequest.getNewIndexName())); assertThat(cloneRequest.getAlias(), equalTo(originalRequest.getAlias())); + for (Map.Entry 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()); + } + } + } + } - List originalConditions = originalRequest.getConditions().stream() - .map(Condition::toString) - .sorted() - .collect(Collectors.toList()); + public void testToAndFromXContent() throws IOException { + RolloverRequest rolloverRequest = createTestItem(); - List cloneConditions = cloneRequest.getConditions().stream() - .map(Condition::toString) - .sorted() - .collect(Collectors.toList()); + final XContentType xContentType = randomFrom(XContentType.values()); + boolean humanReadable = randomBoolean(); + BytesReference originalBytes = toShuffledXContent(rolloverRequest, xContentType, EMPTY_PARAMS, humanReadable); - assertThat(originalConditions, equalTo(cloneConditions)); - } + 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 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> 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> conditions = randomSubsetOf(numConditions, conditionsGenerator); + for (Consumer consumer : conditions) { + consumer.accept(rolloverRequest); } + return rolloverRequest; } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverResponseTests.java new file mode 100644 index 0000000000000..2f76f0f7ea725 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/RolloverResponseTests.java @@ -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 { + + @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 randomResults(boolean allowNoItems) { + Map results = new HashMap<>(); + int numResults = randomIntBetween(allowNoItems ? 0 : 1, 3); + List>> conditions = randomSubsetOf(numResults, conditionSuppliers); + for (Supplier> condition : conditions) { + Condition cond = condition.get(); + results.put(cond.name, randomBoolean()); + } + return results; + } + + private static final List>> 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 getRandomFieldsExcludeFilter() { + return field -> field.startsWith("conditions"); + } + + @Override + protected EqualsHashCodeTestUtils.MutateFunction 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 results; + if (response.getConditionStatus().isEmpty()) { + results = randomResults(false); + } else { + results = new HashMap<>(response.getConditionStatus().size()); + List keys = randomSubsetOf(randomIntBetween(1, response.getConditionStatus().size()), + response.getConditionStatus().keySet()); + for (Map.Entry 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(); + } + }; + } +} diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java index 3366646e24a79..be88a69a8f4a3 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java @@ -44,6 +44,7 @@ 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 @@ public class TransportRolloverActionTests extends ESTestCase { - public void testDocStatsSelectionFromPrimariesOnly() throws Exception { + public void testDocStatsSelectionFromPrimariesOnly() { long docsInPrimaryShards = 100; long docsInShards = 200; @@ -70,7 +71,7 @@ public void testDocStatsSelectionFromPrimariesOnly() throws Exception { 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 void testEvaluateConditions() throws Exception { .settings(settings) .build(); final Set conditions = Sets.newHashSet(maxDocsCondition, maxAgeCondition, maxSizeCondition); - Set results = evaluateConditions(conditions, + Map 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 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 void testEvaluateWithoutDocStats() throws Exception { .creationDate(System.currentTimeMillis() - TimeValue.timeValueHours(randomIntBetween(5, 10)).getMillis()) .settings(settings) .build(); - Set results = evaluateConditions(conditions, null, metaData); + Map 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 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 void testCreateUpdateAliasRequest() throws Exception { 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 void testValidation() throws Exception { 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 void testGenerateRolloverIndexName() throws Exception { 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 void testCreateIndexRequest() throws Exception { 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 @@ private IndicesStatsResponse createIndicesStatResponse(long totalDocs, long prim 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 @@ private IndexMetaData createMetaData() { .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; diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/shrink/ResizeRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/shrink/ResizeRequestTests.java index 6061be3353929..77ead591a01f2 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/shrink/ResizeRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/shrink/ResizeRequestTests.java @@ -28,6 +28,7 @@ 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 void testToAndFromXContent() throws IOException { 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() { diff --git a/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java b/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java index ec3c9e4dbb430..3e42e3b304e00 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java +++ b/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java @@ -76,7 +76,7 @@ public static Settings randomIndexSettings() { 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); diff --git a/test/framework/src/main/java/org/elasticsearch/test/AbstractStreamableTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/AbstractStreamableTestCase.java index 39340117d9f30..fa0628b8536ab 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/AbstractStreamableTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/AbstractStreamableTestCase.java @@ -58,7 +58,7 @@ protected CopyFunction getCopyFunction() { } /** - * 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 @@ protected MutateFunction getMutateFunction() { * 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()); } diff --git a/test/framework/src/main/java/org/elasticsearch/test/AbstractStreamableXContentTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/AbstractStreamableXContentTestCase.java index 7a51c00ac144e..d36c58aa6f699 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/AbstractStreamableXContentTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/AbstractStreamableXContentTestCase.java @@ -27,6 +27,7 @@ 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 void testFromXContent() throws IOException { 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 @@ protected boolean supportsUnknownFields() { return true; } + protected Predicate getRandomFieldsExcludeFilter() { + return field -> false; + } + private T parseInstance(XContentParser parser) throws IOException { T parsedInstance = doParseInstance(parser); assertNull(parser.nextToken());