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 42791b719c4e..6fa3a66a79ca 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 @@ -24,7 +24,6 @@ import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse; -import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.FlushResponse; @@ -47,6 +46,8 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.core.ShardsAcknowledgedResponse; import org.elasticsearch.client.indices.AnalyzeRequest; import org.elasticsearch.client.indices.AnalyzeResponse; +import org.elasticsearch.client.indices.CloseIndexRequest; +import org.elasticsearch.client.indices.CloseIndexResponse; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.FreezeIndexRequest; @@ -471,9 +472,9 @@ public final class IndicesClient { * @return the response * @throws IOException in case there is a problem sending the request or parsing back the response */ - public AcknowledgedResponse close(CloseIndexRequest closeIndexRequest, RequestOptions options) throws IOException { + public CloseIndexResponse close(CloseIndexRequest closeIndexRequest, RequestOptions options) throws IOException { return restHighLevelClient.performRequestAndParseEntity(closeIndexRequest, IndicesRequestConverters::closeIndex, options, - AcknowledgedResponse::fromXContent, emptySet()); + CloseIndexResponse::fromXContent, emptySet()); } /** @@ -484,9 +485,9 @@ public final class IndicesClient { * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion */ - public void closeAsync(CloseIndexRequest closeIndexRequest, RequestOptions options, ActionListener listener) { + public void closeAsync(CloseIndexRequest closeIndexRequest, RequestOptions options, ActionListener listener) { restHighLevelClient.performRequestAsyncAndParseEntity(closeIndexRequest, IndicesRequestConverters::closeIndex, options, - AcknowledgedResponse::fromXContent, listener, emptySet()); + CloseIndexResponse::fromXContent, listener, emptySet()); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java index 7de53510b508..c0b2f565e534 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java @@ -27,7 +27,6 @@ import org.apache.http.client.methods.HttpPut; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; -import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; @@ -41,6 +40,7 @@ import org.elasticsearch.action.admin.indices.shrink.ResizeType; import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest; import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest; import org.elasticsearch.client.indices.AnalyzeRequest; +import org.elasticsearch.client.indices.CloseIndexRequest; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.FreezeIndexRequest; import org.elasticsearch.client.indices.GetFieldMappingsRequest; diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CloseIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CloseIndexRequest.java new file mode 100644 index 000000000000..e3ce4be9259f --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CloseIndexRequest.java @@ -0,0 +1,113 @@ +/* + * 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.client.indices; + +import org.elasticsearch.action.admin.indices.open.OpenIndexResponse; +import org.elasticsearch.action.support.ActiveShardCount; +import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.client.TimedRequest; +import org.elasticsearch.client.Validatable; +import org.elasticsearch.client.ValidationException; + +import java.util.Optional; + +/** + * A request to close an index. + */ +public class CloseIndexRequest extends TimedRequest implements Validatable { + + private String[] indices; + private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpen(); + private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT; + + /** + * Creates a new close index request + * + * @param indices the indices to close + */ + public CloseIndexRequest(String... indices) { + this.indices = indices; + } + + /** + * Returns the indices to close + */ + public String[] indices() { + return indices; + } + + /** + * Specifies what type of requested indices to ignore and how to deal with wildcard expressions. + * For example indices that don't exist. + * + * @return the current behaviour when it comes to index names and wildcard indices expressions + */ + public IndicesOptions indicesOptions() { + return indicesOptions; + } + + /** + * Specifies what type of requested indices to ignore and how to deal with wildcard expressions. + * For example indices that don't exist. + * + * @param indicesOptions the desired behaviour regarding indices to ignore and wildcard indices expressions + */ + public CloseIndexRequest indicesOptions(IndicesOptions indicesOptions) { + this.indicesOptions = indicesOptions; + return this; + } + + /** + * Returns the wait for active shard count or null if the default should be used + */ + public ActiveShardCount waitForActiveShards() { + return waitForActiveShards; + } + + /** + * Sets the number of shard copies that should be active for indices opening 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. + * Indices opening will only wait up until the timeout value for the number of shard copies + * to be active before returning. Check {@link OpenIndexResponse#isShardsAcknowledged()} to + * determine if the requisite shard copies were all started before returning or timing out. + * + * @param waitForActiveShards number of active shard copies to wait on + */ + public CloseIndexRequest waitForActiveShards(ActiveShardCount waitForActiveShards) { + this.waitForActiveShards = waitForActiveShards; + return this; + } + + @Override + public Optional validate() { + if (indices == null || indices.length == 0) { + ValidationException validationException = new ValidationException(); + validationException.addValidationError("index is missing"); + return Optional.of(validationException); + } else { + return Optional.empty(); + } + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CloseIndexResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CloseIndexResponse.java new file mode 100644 index 000000000000..7416f139d009 --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CloseIndexResponse.java @@ -0,0 +1,213 @@ +/* + * 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.client.indices; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.support.DefaultShardOperationFailedException; +import org.elasticsearch.action.support.master.ShardsAcknowledgedResponse; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentParserUtils; + +import java.util.List; +import java.util.Objects; + +import static java.util.Collections.emptyList; +import static java.util.Collections.unmodifiableList; +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; +import static org.elasticsearch.common.xcontent.ObjectParser.ValueType; + +public class CloseIndexResponse extends ShardsAcknowledgedResponse { + + @SuppressWarnings("unchecked") + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("close_index_response", + true, args -> { + boolean acknowledged = (boolean) args[0]; + boolean shardsAcknowledged = args[1] != null ? (boolean) args[1] : acknowledged; + List indices = args[2] != null ? (List) args[2] : emptyList(); + return new CloseIndexResponse(acknowledged, shardsAcknowledged, indices); + }); + + static { + declareAcknowledgedField(PARSER); + PARSER.declareField(optionalConstructorArg(), (parser, context) -> parser.booleanValue(), SHARDS_ACKNOWLEDGED, ValueType.BOOLEAN); + PARSER.declareNamedObjects(optionalConstructorArg(), (p, c, name) -> IndexResult.fromXContent(p, name), new ParseField("indices")); + } + + private final List indices; + + public CloseIndexResponse(final boolean acknowledged, final boolean shardsAcknowledged, final List indices) { + super(acknowledged, shardsAcknowledged); + this.indices = unmodifiableList(Objects.requireNonNull(indices)); + } + + public List getIndices() { + return indices; + } + + public static CloseIndexResponse fromXContent(final XContentParser parser) { + return PARSER.apply(parser, null); + } + + public static class IndexResult { + + @SuppressWarnings("unchecked") + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("index_result", true, + (args, index) -> { + Exception exception = (Exception) args[1]; + if (exception != null) { + assert (boolean) args[0] == false; + return new IndexResult(index, exception); + } + ShardResult[] shardResults = args[2] != null ? ((List) args[2]).toArray(new ShardResult[0]) : null; + if (shardResults != null) { + assert (boolean) args[0] == false; + return new IndexResult(index, shardResults); + } + assert (boolean) args[0]; + return new IndexResult(index); + }); + static { + PARSER.declareBoolean(optionalConstructorArg(), new ParseField("closed")); + PARSER.declareObject(optionalConstructorArg(), (p, c) -> { + XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, p.currentToken(), p::getTokenLocation); + XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, p.nextToken(), p::getTokenLocation); + Exception e = ElasticsearchException.failureFromXContent(p); + XContentParserUtils.ensureExpectedToken(XContentParser.Token.END_OBJECT, p.nextToken(), p::getTokenLocation); + return e; + }, new ParseField("exception")); + PARSER.declareNamedObjects(optionalConstructorArg(), + (p, c, id) -> ShardResult.fromXContent(p, id), new ParseField("failedShards")); + } + + private final String index; + private final @Nullable Exception exception; + private final @Nullable ShardResult[] shards; + + IndexResult(final String index) { + this(index, null, null); + } + + IndexResult(final String index, final Exception failure) { + this(index, Objects.requireNonNull(failure), null); + } + + IndexResult(final String index, final ShardResult[] shards) { + this(index, null, Objects.requireNonNull(shards)); + } + + private IndexResult(final String index, @Nullable final Exception exception, @Nullable final ShardResult[] shards) { + this.index = Objects.requireNonNull(index); + this.exception = exception; + this.shards = shards; + } + + public String getIndex() { + return index; + } + + public @Nullable Exception getException() { + return exception; + } + + public @Nullable ShardResult[] getShards() { + return shards; + } + + public boolean hasFailures() { + if (exception != null) { + return true; + } + if (shards != null) { + for (ShardResult shard : shards) { + if (shard.hasFailures()) { + return true; + } + } + } + return false; + } + + static IndexResult fromXContent(final XContentParser parser, final String name) { + return PARSER.apply(parser, name); + } + } + + public static class ShardResult { + + @SuppressWarnings("unchecked") + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("shard_result", true, + (arg, id) -> { + Failure[] failures = arg[0] != null ? ((List) arg[0]).toArray(new Failure[0]) : new Failure[0]; + return new ShardResult(Integer.parseInt(id), failures); + }); + + static { + PARSER.declareObjectArray(optionalConstructorArg(), (p, c) -> Failure.PARSER.apply(p, null), new ParseField("failures")); + } + + private final int id; + private final Failure[] failures; + + ShardResult(final int id, final Failure[] failures) { + this.id = id; + this.failures = failures; + } + + public boolean hasFailures() { + return failures != null && failures.length > 0; + } + + public int getId() { + return id; + } + + public Failure[] getFailures() { + return failures; + } + + static ShardResult fromXContent(final XContentParser parser, final String id) { + return PARSER.apply(parser, id); + } + + public static class Failure extends DefaultShardOperationFailedException { + + static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("failure", true, + arg -> new Failure((String) arg[0], (int) arg[1], (Throwable) arg[2], (String) arg[3])); + + static { + declareFields(PARSER); + PARSER.declareStringOrNull(optionalConstructorArg(), new ParseField("node")); + } + + private @Nullable String nodeId; + + Failure(final String index, final int shardId, final Throwable reason, final String nodeId) { + super(index, shardId, reason); + this.nodeId = nodeId; + } + + public String getNodeId() { + return nodeId; + } + } + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/FreezeIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/FreezeIndexRequest.java index d78f2d533ab8..7e7a9d090949 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/FreezeIndexRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/FreezeIndexRequest.java @@ -70,7 +70,7 @@ public final class FreezeIndexRequest extends TimedRequest { } /** - * Returns the wait for active shard cound or null if the default should be used + * Returns the wait for active shard count or null if the default should be used */ public ActiveShardCount getWaitForActiveShards() { return waitForActiveShards; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java index dbcab4d1b2ce..790c3c9a955b 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java @@ -23,7 +23,6 @@ import org.apache.http.util.EntityUtils; import org.apache.logging.log4j.message.ParameterizedMessage; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; -import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; @@ -49,6 +48,7 @@ import org.elasticsearch.client.ccr.ResumeFollowRequest; import org.elasticsearch.client.ccr.UnfollowRequest; import org.elasticsearch.client.core.AcknowledgedResponse; import org.elasticsearch.client.core.BroadcastResponse; +import org.elasticsearch.client.indices.CloseIndexRequest; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.common.xcontent.XContentHelper; 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 a050693e04c0..a3c40d6a9d7c 100644 --- 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 @@ -30,7 +30,6 @@ import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasA import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse; -import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.FlushResponse; @@ -58,6 +57,8 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.core.ShardsAcknowledgedResponse; import org.elasticsearch.client.indices.AnalyzeRequest; import org.elasticsearch.client.indices.AnalyzeResponse; +import org.elasticsearch.client.indices.CloseIndexRequest; +import org.elasticsearch.client.indices.CloseIndexResponse; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.FreezeIndexRequest; @@ -81,6 +82,7 @@ import org.elasticsearch.client.indices.rollover.RolloverResponse; import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.ValidationException; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.settings.Setting; @@ -127,6 +129,7 @@ import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -872,20 +875,29 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { } public void testCloseExistingIndex() throws IOException { - String index = "index"; - createIndex(index, Settings.EMPTY); - Response response = client().performRequest(new Request(HttpGet.METHOD_NAME, index + "/_search")); - assertThat(response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); + final String[] indices = new String[randomIntBetween(1, 5)]; + for (int i = 0; i < indices.length; i++) { + String index = "index-" + i; + createIndex(index, Settings.EMPTY); + indices[i] = index; + } - CloseIndexRequest closeIndexRequest = new CloseIndexRequest(index); - AcknowledgedResponse closeIndexResponse = execute(closeIndexRequest, highLevelClient().indices()::close, - highLevelClient().indices()::closeAsync); + CloseIndexRequest closeIndexRequest = new CloseIndexRequest(indices); + CloseIndexResponse closeIndexResponse = execute(closeIndexRequest, + highLevelClient().indices()::close, highLevelClient().indices()::closeAsync); assertTrue(closeIndexResponse.isAcknowledged()); + assertTrue(closeIndexResponse.isShardsAcknowledged()); + assertThat(closeIndexResponse.getIndices(), notNullValue()); + assertThat(closeIndexResponse.getIndices(), hasSize(indices.length)); + closeIndexResponse.getIndices().forEach(indexResult -> { + assertThat(indexResult.getIndex(), startsWith("index-")); + assertThat(indexResult.hasFailures(), is(false)); - ResponseException exception = expectThrows(ResponseException.class, - () -> client().performRequest(new Request(HttpGet.METHOD_NAME, index + "/_search"))); - assertThat(exception.getResponse().getStatusLine().getStatusCode(), equalTo(RestStatus.BAD_REQUEST.getStatus())); - assertThat(exception.getMessage().contains(index), equalTo(true)); + ResponseException exception = expectThrows(ResponseException.class, + () -> client().performRequest(new Request(HttpGet.METHOD_NAME, indexResult.getIndex() + "/_search"))); + assertThat(exception.getResponse().getStatusLine().getStatusCode(), equalTo(RestStatus.BAD_REQUEST.getStatus())); + assertThat(exception.getMessage().contains(indexResult.getIndex()), equalTo(true)); + }); } public void testCloseNonExistentIndex() throws IOException { @@ -898,6 +910,14 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertEquals(RestStatus.NOT_FOUND, exception.status()); } + public void testCloseEmptyOrNullIndex() { + String[] indices = randomBoolean() ? Strings.EMPTY_ARRAY : null; + CloseIndexRequest closeIndexRequest = new CloseIndexRequest(indices); + org.elasticsearch.client.ValidationException exception = expectThrows(org.elasticsearch.client.ValidationException.class, + () -> execute(closeIndexRequest, highLevelClient().indices()::close, highLevelClient().indices()::closeAsync)); + assertThat(exception.validationErrors().get(0), equalTo("index is missing")); + } + public void testRefresh() throws IOException { { String index = "index"; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java index d0f417763579..a8728b90023f 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java @@ -30,7 +30,6 @@ import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; -import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; @@ -45,6 +44,7 @@ import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplat import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest; import org.elasticsearch.action.support.master.AcknowledgedRequest; import org.elasticsearch.client.indices.AnalyzeRequest; +import org.elasticsearch.client.indices.CloseIndexRequest; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.GetFieldMappingsRequest; import org.elasticsearch.client.indices.GetIndexRequest; @@ -603,7 +603,8 @@ public class IndicesRequestConvertersTests extends ESTestCase { CloseIndexRequest closeIndexRequest = new CloseIndexRequest(indices); Map expectedParams = new HashMap<>(); - RequestConvertersTests.setRandomTimeout(closeIndexRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); + RequestConvertersTests.setRandomTimeout(timeout -> closeIndexRequest.setTimeout(TimeValue.parseTimeValue(timeout, "test")), + AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); RequestConvertersTests.setRandomMasterTimeout(closeIndexRequest, expectedParams); RequestConvertersTests.setRandomIndicesOptions(closeIndexRequest::indicesOptions, closeIndexRequest::indicesOptions, expectedParams); @@ -616,12 +617,6 @@ public class IndicesRequestConvertersTests extends ESTestCase { Assert.assertThat(request.getEntity(), nullValue()); } - public void testCloseIndexEmptyIndices() { - String[] indices = ESTestCase.randomBoolean() ? null : Strings.EMPTY_ARRAY; - ActionRequestValidationException validationException = new CloseIndexRequest(indices).validate(); - Assert.assertNotNull(validationException); - } - public void testRefresh() { String[] indices = ESTestCase.randomBoolean() ? null : RequestConvertersTests.randomIndicesNames(0, 5); RefreshRequest refreshRequest; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java index 0c05b79f1413..b78507112b79 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java @@ -24,7 +24,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.LatchedActionListener; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; -import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.client.ESRestHighLevelClientTestCase; @@ -53,6 +52,7 @@ import org.elasticsearch.client.ccr.ResumeFollowRequest; import org.elasticsearch.client.ccr.UnfollowRequest; import org.elasticsearch.client.core.AcknowledgedResponse; import org.elasticsearch.client.core.BroadcastResponse; +import org.elasticsearch.client.indices.CloseIndexRequest; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.common.xcontent.XContentHelper; 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 f878f0f6f7d8..ddd9241a4931 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 @@ -28,7 +28,6 @@ import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasA import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse; -import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.FlushResponse; @@ -62,6 +61,8 @@ import org.elasticsearch.client.core.BroadcastResponse.Shards; import org.elasticsearch.client.core.ShardsAcknowledgedResponse; import org.elasticsearch.client.indices.AnalyzeRequest; import org.elasticsearch.client.indices.AnalyzeResponse; +import org.elasticsearch.client.indices.CloseIndexRequest; +import org.elasticsearch.client.indices.CloseIndexResponse; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.DetailAnalyzeResponse; @@ -1458,12 +1459,10 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase // end::close-index-request // tag::close-index-request-timeout - request.timeout(TimeValue.timeValueMinutes(2)); // <1> - request.timeout("2m"); // <2> + request.setTimeout(TimeValue.timeValueMinutes(2)); // <1> // end::close-index-request-timeout // tag::close-index-request-masterTimeout - request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1> - request.masterNodeTimeout("1m"); // <2> + request.setMasterTimeout(TimeValue.timeValueMinutes(1)); // <1> // end::close-index-request-masterTimeout // tag::close-index-request-indicesOptions @@ -1480,10 +1479,9 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase assertTrue(acknowledged); // tag::close-index-execute-listener - ActionListener listener = - new ActionListener() { + ActionListener listener = new ActionListener<>() { @Override - public void onResponse(AcknowledgedResponse closeIndexResponse) { + public void onResponse(CloseIndexResponse closeIndexResponse) { // <1> } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CloseIndexRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CloseIndexRequestTests.java new file mode 100644 index 000000000000..5b59e107570d --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CloseIndexRequestTests.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.client.indices; + +import org.elasticsearch.action.support.ActiveShardCount; +import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.client.TimedRequest; +import org.elasticsearch.client.ValidationException; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.test.ESTestCase; + +import java.util.Optional; + +import static org.hamcrest.Matchers.equalTo; + +public class CloseIndexRequestTests extends ESTestCase { + + public void testIndices() { + String[] indices = generateRandomStringArray(5, 5, false, true); + CloseIndexRequest request = new CloseIndexRequest(indices); + assertArrayEquals(indices, request.indices()); + } + + public void testValidate() { + String[] indices = randomBoolean() ? null : Strings.EMPTY_ARRAY; + CloseIndexRequest request = new CloseIndexRequest(indices); + Optional validation = request.validate(); + assertTrue(validation.isPresent()); + assertThat(validation.get().validationErrors().get(0), equalTo("index is missing")); + } + + public void testIndicesOptions() { + IndicesOptions indicesOptions = IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()); + CloseIndexRequest request = new CloseIndexRequest().indicesOptions(indicesOptions); + assertEquals(indicesOptions, request.indicesOptions()); + } + + public void testWaitForActiveShards() { + final CloseIndexRequest request = new CloseIndexRequest("index"); + final int count = randomIntBetween(0, 10); + request.waitForActiveShards(ActiveShardCount.from(count)); + assertEquals(request.waitForActiveShards(), ActiveShardCount.from(count)); + } + + public void testTimeout() { + final CloseIndexRequest request = new CloseIndexRequest("index"); + assertEquals(request.timeout(), TimedRequest.DEFAULT_ACK_TIMEOUT); + assertEquals(request.masterNodeTimeout(), TimedRequest.DEFAULT_MASTER_NODE_TIMEOUT); + + final TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(0, 1000)); + request.setTimeout(timeout); + + final TimeValue masterTimeout = TimeValue.timeValueSeconds(randomIntBetween(0,1000)); + request.setMasterTimeout(masterTimeout); + + assertEquals(request.timeout(), timeout); + assertEquals(request.masterNodeTimeout(), masterTimeout); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CloseIndexResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CloseIndexResponseTests.java new file mode 100644 index 000000000000..b66927eff447 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CloseIndexResponseTests.java @@ -0,0 +1,221 @@ +/* + * 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.client.indices; + +import org.elasticsearch.ElasticsearchStatusException; +import org.elasticsearch.action.support.master.AcknowledgedResponse; +import org.elasticsearch.action.support.master.ShardsAcknowledgedResponse; +import org.elasticsearch.client.AbstractResponseTestCase; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.XContent; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.Index; +import org.elasticsearch.index.IndexNotFoundException; +import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.transport.ActionNotFoundTransportException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; + +public class CloseIndexResponseTests extends + AbstractResponseTestCase { + + @Override + protected org.elasticsearch.action.admin.indices.close.CloseIndexResponse createServerTestInstance() { + boolean acknowledged = true; + final String[] indicesNames = generateRandomStringArray(10, 10, false, true); + + final List indexResults = new ArrayList<>(); + for (String indexName : indicesNames) { + final Index index = new Index(indexName, randomAlphaOfLength(5)); + if (randomBoolean()) { + indexResults.add(new org.elasticsearch.action.admin.indices.close.CloseIndexResponse.IndexResult(index)); + } else { + if (randomBoolean()) { + acknowledged = false; + Exception exception = randomFrom(new IndexNotFoundException(index), new ActionNotFoundTransportException("test")); + indexResults.add(new org.elasticsearch.action.admin.indices.close.CloseIndexResponse.IndexResult(index, exception)); + } else { + final int nbShards = randomIntBetween(1, 5); + org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult[] shards = + new org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult[nbShards]; + for (int i = 0; i < nbShards; i++) { + org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult.Failure[] failures = null; + if (randomBoolean()) { + acknowledged = false; + int nbFailures = randomIntBetween(1, 3); + failures = new org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult.Failure[nbFailures]; + for (int j = 0; j < failures.length; j++) { + String nodeId = null; + if (frequently()) { + nodeId = randomAlphaOfLength(5); + } + failures[j] = newFailure(indexName, i, nodeId); + } + } + shards[i] = new org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult(i, failures); + } + indexResults.add(new org.elasticsearch.action.admin.indices.close.CloseIndexResponse.IndexResult(index, shards)); + } + } + } + + final boolean shardsAcknowledged = acknowledged ? randomBoolean() : false; + return new org.elasticsearch.action.admin.indices.close.CloseIndexResponse(acknowledged, shardsAcknowledged, indexResults); + } + + @Override + protected CloseIndexResponse doParseToClientInstance(final XContentParser parser) throws IOException { + return CloseIndexResponse.fromXContent(parser); + } + + @Override + protected void assertInstances(final org.elasticsearch.action.admin.indices.close.CloseIndexResponse serverInstance, + final CloseIndexResponse clientInstance) { + assertNotSame(serverInstance, clientInstance); + assertThat(clientInstance.isAcknowledged(), equalTo(serverInstance.isAcknowledged())); + assertThat(clientInstance.isShardsAcknowledged(), equalTo(serverInstance.isShardsAcknowledged())); + + assertThat(clientInstance.getIndices(), hasSize(serverInstance.getIndices().size())); + serverInstance.getIndices().forEach(expectedIndexResult -> { + List actualIndexResults = clientInstance.getIndices().stream() + .filter(result -> result.getIndex().equals(expectedIndexResult.getIndex().getName())) + .collect(Collectors.toList()); + assertThat(actualIndexResults, hasSize(1)); + + final CloseIndexResponse.IndexResult actualIndexResult = actualIndexResults.get(0); + assertThat(actualIndexResult.hasFailures(), equalTo(expectedIndexResult.hasFailures())); + + if (expectedIndexResult.hasFailures() == false) { + assertThat(actualIndexResult.getException(), nullValue()); + assertThat(actualIndexResult.getShards(), nullValue()); + } + if (expectedIndexResult.getException() != null) { + assertThat(actualIndexResult.hasFailures(), is(true)); + assertThat(actualIndexResult.getShards(), nullValue()); + assertThat(actualIndexResult.getException(), notNullValue()); + assertThat(actualIndexResult.getException().getMessage(), containsString(expectedIndexResult.getException().getMessage())); + } + if (expectedIndexResult.getShards() != null) { + assertThat(actualIndexResult.getException(), nullValue()); + + List failedShardResults = + Arrays.stream(expectedIndexResult.getShards()) + .filter(org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult::hasFailures) + .collect(Collectors.toList()); + + if (failedShardResults.isEmpty()) { + assertThat(actualIndexResult.hasFailures(), is(false)); + assertThat(actualIndexResult.getShards(), nullValue()); + return; + } + + assertThat(actualIndexResult.hasFailures(), is(true)); + assertThat(actualIndexResult.getShards(), notNullValue()); + assertThat(actualIndexResult.getShards().length, equalTo(failedShardResults.size())); + + failedShardResults.forEach(failedShardResult -> { + List actualShardResults = Arrays.stream(actualIndexResult.getShards()) + .filter(result -> result.getId() == failedShardResult.getId()) + .collect(Collectors.toList()); + assertThat(actualShardResults, hasSize(1)); + + final CloseIndexResponse.ShardResult actualShardResult = actualShardResults.get(0); + assertThat(actualShardResult.hasFailures(), is(true)); + assertThat(actualShardResult.getFailures(), notNullValue()); + assertThat(actualShardResult.getFailures().length, equalTo(failedShardResult.getFailures().length)); + + for (int i = 0; i < failedShardResult.getFailures().length; i++) { + org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult.Failure expectedFailure = + failedShardResult.getFailures()[i]; + CloseIndexResponse.ShardResult.Failure actualFailure = actualShardResult.getFailures()[i]; + assertThat(actualFailure.getNodeId(), equalTo(expectedFailure.getNodeId())); + assertThat(actualFailure.index(), equalTo(expectedFailure.index())); + assertThat(actualFailure.shardId(), equalTo(expectedFailure.shardId())); + assertThat(actualFailure.getCause().getMessage(), containsString(expectedFailure.getCause().getMessage())); + } + }); + } + }); + } + + public final void testBwcFromXContent() throws IOException { + { + final boolean acknowledged = randomBoolean(); + final AcknowledgedResponse expected = new AcknowledgedResponse(acknowledged); + + final XContentType xContentType = randomFrom(XContentType.values()); + final BytesReference bytes = toShuffledXContent(expected, xContentType, getParams(), randomBoolean()); + final XContent xContent = XContentFactory.xContent(xContentType); + final XContentParser parser = xContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + bytes.streamInput()); + + final CloseIndexResponse actual = doParseToClientInstance(parser); + assertThat(actual, notNullValue()); + assertThat(actual.isAcknowledged(), equalTo(expected.isAcknowledged())); + assertThat(actual.isShardsAcknowledged(), equalTo(expected.isAcknowledged())); + assertThat(actual.getIndices(), hasSize(0)); + } + { + final boolean acknowledged = randomBoolean(); + final boolean shardsAcknowledged = acknowledged ? randomBoolean() : false; + final ShardsAcknowledgedResponse expected = new ShardsAcknowledgedResponse(acknowledged, shardsAcknowledged){}; + + final XContentType xContentType = randomFrom(XContentType.values()); + final BytesReference bytes = toShuffledXContent(expected, xContentType, getParams(), randomBoolean()); + final XContent xContent = XContentFactory.xContent(xContentType); + final XContentParser parser = xContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + bytes.streamInput()); + + final CloseIndexResponse actual = doParseToClientInstance(parser); + assertThat(actual, notNullValue()); + assertThat(actual.isAcknowledged(), equalTo(expected.isAcknowledged())); + assertThat(actual.isShardsAcknowledged(), equalTo(expected.isShardsAcknowledged())); + assertThat(actual.getIndices(), hasSize(0)); + } + } + + private org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult.Failure newFailure(final String indexName, + final int shard, + final String nodeId) { + Exception exception = randomFrom(new IndexNotFoundException(indexName), + new ActionNotFoundTransportException("test"), + new IOException("boom", new NullPointerException()), + new ElasticsearchStatusException("something", RestStatus.TOO_MANY_REQUESTS)); + return new org.elasticsearch.action.admin.indices.close.CloseIndexResponse.ShardResult.Failure(indexName, shard, exception, nodeId); + } +} diff --git a/docs/java-rest/high-level/indices/close_index.asciidoc b/docs/java-rest/high-level/indices/close_index.asciidoc index fa3d7513ca0e..6d6fb917c794 100644 --- a/docs/java-rest/high-level/indices/close_index.asciidoc +++ b/docs/java-rest/high-level/indices/close_index.asciidoc @@ -27,15 +27,12 @@ include-tagged::{doc-tests-file}[{api}-request-timeout] -------------------------------------------------- <1> Timeout to wait for the all the nodes to acknowledge the index is closed as a `TimeValue` -<2> Timeout to wait for the all the nodes to acknowledge the index is closed -as a `String` ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- include-tagged::{doc-tests-file}[{api}-request-masterTimeout] -------------------------------------------------- <1> Timeout to connect to the master node as a `TimeValue` -<2> Timeout to connect to the master node as a `String` ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java index d2a0e1631806..fcf1446e53c4 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java @@ -179,8 +179,7 @@ public abstract class AbstractObjectParser declareField(consumer, XContentParser::booleanValue, field, ValueType.BOOLEAN); } - public void declareObjectArray(BiConsumer> consumer, ContextParser objectParser, - ParseField field) { + public void declareObjectArray(BiConsumer> consumer, ContextParser objectParser, ParseField field) { declareFieldArray(consumer, (p, c) -> objectParser.parse(p, c), field, ValueType.OBJECT_ARRAY); } diff --git a/server/src/main/java/org/elasticsearch/action/support/DefaultShardOperationFailedException.java b/server/src/main/java/org/elasticsearch/action/support/DefaultShardOperationFailedException.java index f8a3baf96e2a..cfdc463892f1 100644 --- a/server/src/main/java/org/elasticsearch/action/support/DefaultShardOperationFailedException.java +++ b/server/src/main/java/org/elasticsearch/action/support/DefaultShardOperationFailedException.java @@ -45,10 +45,14 @@ public class DefaultShardOperationFailedException extends ShardOperationFailedEx public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( "failures", true, arg -> new DefaultShardOperationFailedException((String) arg[0], (int) arg[1] ,(Throwable) arg[2])); + protected static void declareFields(ConstructingObjectParser objectParser) { + objectParser.declareString(constructorArg(), new ParseField(INDEX)); + objectParser.declareInt(constructorArg(), new ParseField(SHARD_ID)); + objectParser.declareObject(constructorArg(), (p, c) -> ElasticsearchException.fromXContent(p), new ParseField(REASON)); + } + static { - PARSER.declareString(constructorArg(), new ParseField(INDEX)); - PARSER.declareInt(constructorArg(), new ParseField(SHARD_ID)); - PARSER.declareObject(constructorArg(), (p, c) -> ElasticsearchException.fromXContent(p), new ParseField(REASON)); + declareFields(PARSER); } protected DefaultShardOperationFailedException() {} 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 index e088f4414a21..3c2f7efec0c2 100644 --- a/server/src/main/java/org/elasticsearch/action/support/master/ShardsAcknowledgedResponse.java +++ b/server/src/main/java/org/elasticsearch/action/support/master/ShardsAcknowledgedResponse.java @@ -33,7 +33,7 @@ import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constru public abstract class ShardsAcknowledgedResponse extends AcknowledgedResponse { - private static final ParseField SHARDS_ACKNOWLEDGED = new ParseField("shards_acknowledged"); + protected static final ParseField SHARDS_ACKNOWLEDGED = new ParseField("shards_acknowledged"); protected static void declareAcknowledgedAndShardsAcknowledgedFields( ConstructingObjectParser objectParser) { diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponseTests.java index 01fc1c0343e2..a767868c48bf 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponseTests.java @@ -27,13 +27,14 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.AbstractWireSerializingTestCase; import org.elasticsearch.transport.ActionNotFoundTransportException; import java.io.IOException; @@ -51,7 +52,80 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -public class CloseIndexResponseTests extends ESTestCase { +public class CloseIndexResponseTests extends AbstractWireSerializingTestCase { + + @Override + protected CloseIndexResponse createTestInstance() { + return randomResponse(); + } + + @Override + protected Writeable.Reader instanceReader() { + return CloseIndexResponse::new; + } + + @Override + protected void assertEqualInstances(CloseIndexResponse expected, CloseIndexResponse actual) { + assertNotSame(expected, actual); + assertThat(actual.isAcknowledged(), equalTo(expected.isAcknowledged())); + assertThat(actual.isShardsAcknowledged(), equalTo(expected.isShardsAcknowledged())); + + for (int i = 0; i < expected.getIndices().size(); i++) { + CloseIndexResponse.IndexResult expectedIndexResult = expected.getIndices().get(i); + CloseIndexResponse.IndexResult actualIndexResult = actual.getIndices().get(i); + assertNotSame(expectedIndexResult, actualIndexResult); + assertThat(actualIndexResult.getIndex(), equalTo(expectedIndexResult.getIndex())); + assertThat(actualIndexResult.hasFailures(), equalTo(expectedIndexResult.hasFailures())); + + if (expectedIndexResult.hasFailures() == false) { + assertThat(actualIndexResult.getException(), nullValue()); + if (actualIndexResult.getShards() != null) { + assertThat(Arrays.stream(actualIndexResult.getShards()) + .allMatch(shardResult -> shardResult.hasFailures() == false), is(true)); + } + } + + if (expectedIndexResult.getException() != null) { + assertThat(actualIndexResult.getShards(), nullValue()); + assertThat(actualIndexResult.getException(), notNullValue()); + assertThat(actualIndexResult.getException().getMessage(), equalTo(expectedIndexResult.getException().getMessage())); + assertThat(actualIndexResult.getException().getClass(), equalTo(expectedIndexResult.getException().getClass())); + assertArrayEquals(actualIndexResult.getException().getStackTrace(), expectedIndexResult.getException().getStackTrace()); + } else { + assertThat(actualIndexResult.getException(), nullValue()); + } + + if (expectedIndexResult.getShards() != null) { + assertThat(actualIndexResult.getShards().length, equalTo(expectedIndexResult.getShards().length)); + + for (int j = 0; j < expectedIndexResult.getShards().length; j++) { + CloseIndexResponse.ShardResult expectedShardResult = expectedIndexResult.getShards()[j]; + CloseIndexResponse.ShardResult actualShardResult = actualIndexResult.getShards()[j]; + assertThat(actualShardResult.getId(), equalTo(expectedShardResult.getId())); + assertThat(actualShardResult.hasFailures(), equalTo(expectedShardResult.hasFailures())); + + if (expectedShardResult.hasFailures()) { + assertThat(actualShardResult.getFailures().length, equalTo(expectedShardResult.getFailures().length)); + + for (int k = 0; k < expectedShardResult.getFailures().length; k++) { + CloseIndexResponse.ShardResult.Failure expectedFailure = expectedShardResult.getFailures()[k]; + CloseIndexResponse.ShardResult.Failure actualFailure = actualShardResult.getFailures()[k]; + assertThat(actualFailure.getNodeId(), equalTo(expectedFailure.getNodeId())); + assertThat(actualFailure.index(), equalTo(expectedFailure.index())); + assertThat(actualFailure.shardId(), equalTo(expectedFailure.shardId())); + assertThat(actualFailure.getCause().getMessage(), equalTo(expectedFailure.getCause().getMessage())); + assertThat(actualFailure.getCause().getClass(), equalTo(expectedFailure.getCause().getClass())); + assertArrayEquals(actualFailure.getCause().getStackTrace(), expectedFailure.getCause().getStackTrace()); + } + } else { + assertThat(actualShardResult.getFailures(), nullValue()); + } + } + } else { + assertThat(actualIndexResult.getShards(), nullValue()); + } + } + } /** * Test that random responses can be written to xcontent without errors. @@ -85,18 +159,6 @@ public class CloseIndexResponseTests extends ESTestCase { Strings.toString(closeIndexResponse)); } - public void testSerialization() throws Exception { - final CloseIndexResponse response = randomResponse(); - try (BytesStreamOutput out = new BytesStreamOutput()) { - response.writeTo(out); - - try (StreamInput in = out.bytes().streamInput()) { - final CloseIndexResponse deserializedResponse = new CloseIndexResponse(in); - assertCloseIndexResponse(deserializedResponse, response); - } - } - } - public void testBwcSerialization() throws Exception { { final CloseIndexResponse response = randomResponse(); @@ -150,7 +212,7 @@ public class CloseIndexResponseTests extends ESTestCase { final List indexResults = new ArrayList<>(); for (String indexName : indicesNames) { - final Index index = new Index(indexName, "_na_"); + final Index index = new Index(indexName, randomAlphaOfLength(5)); if (randomBoolean()) { indexResults.add(new CloseIndexResponse.IndexResult(index)); } else { @@ -178,7 +240,6 @@ public class CloseIndexResponseTests extends ESTestCase { indexResults.add(new CloseIndexResponse.IndexResult(index, shards)); } } - } final boolean shardsAcknowledged = acknowledged ? randomBoolean() : false; @@ -191,64 +252,4 @@ public class CloseIndexResponseTests extends ESTestCase { new ActionNotFoundTransportException("test"), new NoShardAvailableActionException(new ShardId(index, id))); } - - private static void assertCloseIndexResponse(final CloseIndexResponse actual, final CloseIndexResponse expected) { - assertThat(actual.isAcknowledged(), equalTo(expected.isAcknowledged())); - assertThat(actual.isShardsAcknowledged(), equalTo(expected.isShardsAcknowledged())); - - for (int i = 0; i < expected.getIndices().size(); i++) { - CloseIndexResponse.IndexResult expectedIndexResult = expected.getIndices().get(i); - CloseIndexResponse.IndexResult actualIndexResult = actual.getIndices().get(i); - assertThat(actualIndexResult.getIndex(), equalTo(expectedIndexResult.getIndex())); - assertThat(actualIndexResult.hasFailures(), equalTo(expectedIndexResult.hasFailures())); - - if (expectedIndexResult.hasFailures() == false) { - assertThat(actualIndexResult.getException(), nullValue()); - if (actualIndexResult.getShards() != null) { - assertThat(Arrays.stream(actualIndexResult.getShards()) - .allMatch(shardResult -> shardResult.hasFailures() == false), is(true)); - } - } - - if (expectedIndexResult.getException() != null) { - assertThat(actualIndexResult.getShards(), nullValue()); - assertThat(actualIndexResult.getException(), notNullValue()); - assertThat(actualIndexResult.getException().getMessage(), equalTo(expectedIndexResult.getException().getMessage())); - assertThat(actualIndexResult.getException().getClass(), equalTo(expectedIndexResult.getException().getClass())); - assertArrayEquals(actualIndexResult.getException().getStackTrace(), expectedIndexResult.getException().getStackTrace()); - } else { - assertThat(actualIndexResult.getException(), nullValue()); - } - - if (expectedIndexResult.getShards() != null) { - assertThat(actualIndexResult.getShards().length, equalTo(expectedIndexResult.getShards().length)); - - for (int j = 0; j < expectedIndexResult.getShards().length; j++) { - CloseIndexResponse.ShardResult expectedShardResult = expectedIndexResult.getShards()[j]; - CloseIndexResponse.ShardResult actualShardResult = actualIndexResult.getShards()[j]; - assertThat(actualShardResult.getId(), equalTo(expectedShardResult.getId())); - assertThat(actualShardResult.hasFailures(), equalTo(expectedShardResult.hasFailures())); - - if (expectedShardResult.hasFailures()) { - assertThat(actualShardResult.getFailures().length, equalTo(expectedShardResult.getFailures().length)); - - for (int k = 0; k < expectedShardResult.getFailures().length; k++) { - CloseIndexResponse.ShardResult.Failure expectedFailure = expectedShardResult.getFailures()[k]; - CloseIndexResponse.ShardResult.Failure actualFailure = actualShardResult.getFailures()[k]; - assertThat(actualFailure.getNodeId(), equalTo(expectedFailure.getNodeId())); - assertThat(actualFailure.index(), equalTo(expectedFailure.index())); - assertThat(actualFailure.shardId(), equalTo(expectedFailure.shardId())); - assertThat(actualFailure.getCause().getMessage(), equalTo(expectedFailure.getCause().getMessage())); - assertThat(actualFailure.getCause().getClass(), equalTo(expectedFailure.getCause().getClass())); - assertArrayEquals(actualFailure.getCause().getStackTrace(), expectedFailure.getCause().getStackTrace()); - } - } else { - assertThat(actualShardResult.getFailures(), nullValue()); - } - } - } else { - assertThat(actualIndexResult.getShards(), nullValue()); - } - } - } }