Support 'include_type_name' in RestGetIndicesAction (#37149)

This change adds support for the 'include_type_name' parameter for the
indices.get API. This parameter, which defaults to `false` starting in 7.0,
changes the response to not include the indices type names any longer.

If the parameter is set in the request, we additionally emit a deprecation
warning since using the parameter should be only temporarily necessary while
adapting to the new response format and we will remove it with the next major
version.
This commit is contained in:
Christoph Büscher 2019-01-09 14:17:17 +01:00 committed by GitHub
parent 84d520b0e5
commit c149bb8cc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 251 additions and 42 deletions

View File

@ -89,6 +89,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
@ -209,7 +210,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
mappingBuilder.startObject().startObject("properties").startObject("field");
mappingBuilder.field("type", "text");
mappingBuilder.endObject().endObject().endObject();
createIndexRequest.mapping("type_name", mappingBuilder);
createIndexRequest.mapping(MapperService.SINGLE_MAPPING_NAME, mappingBuilder);
CreateIndexResponse createIndexResponse =
execute(createIndexRequest, highLevelClient().indices()::create, highLevelClient().indices()::createAsync);
@ -226,7 +227,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
Map<String, Object> term = (Map) filter.get("term");
assertEquals(2016, term.get("year"));
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.type_name.properties.field.type", getIndexResponse));
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.properties.field.type", getIndexResponse));
}
}
@ -340,7 +341,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
.put(SETTING_NUMBER_OF_SHARDS, 1)
.put(SETTING_NUMBER_OF_REPLICAS, 0)
.build();
String mappings = "\"type-1\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
String mappings = "\"_doc\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
createIndex(indexName, basicSettings, mappings);
GetIndexRequest getIndexRequest = new GetIndexRequest()
@ -353,8 +354,8 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS));
assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS));
assertNotNull(getIndexResponse.getMappings().get(indexName));
assertNotNull(getIndexResponse.getMappings().get(indexName).get("type-1"));
Object o = getIndexResponse.getMappings().get(indexName).get("type-1").getSourceAsMap().get("properties");
assertNotNull(getIndexResponse.getMappings().get(indexName).get("_doc"));
Object o = getIndexResponse.getMappings().get(indexName).get("_doc").getSourceAsMap().get("properties");
assertThat(o, instanceOf(Map.class));
//noinspection unchecked
assertThat(((Map<String, Object>) o).get("field-1"), instanceOf(Map.class));
@ -370,7 +371,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
.put(SETTING_NUMBER_OF_SHARDS, 1)
.put(SETTING_NUMBER_OF_REPLICAS, 0)
.build();
String mappings = "\"type-1\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
String mappings = "\"_doc\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
createIndex(indexName, basicSettings, mappings);
GetIndexRequest getIndexRequest = new GetIndexRequest()
@ -384,8 +385,8 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS));
assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS));
assertNotNull(getIndexResponse.getMappings().get(indexName));
assertNotNull(getIndexResponse.getMappings().get(indexName).get("type-1"));
Object o = getIndexResponse.getMappings().get(indexName).get("type-1").getSourceAsMap().get("properties");
assertNotNull(getIndexResponse.getMappings().get(indexName).get("_doc"));
Object o = getIndexResponse.getMappings().get(indexName).get("_doc").getSourceAsMap().get("properties");
assertThat(o, instanceOf(Map.class));
assertThat(((Map<String, Object>) o).get("field-1"), instanceOf(Map.class));
Map<String, Object> fieldMapping = (Map<String, Object>) ((Map<String, Object>) o).get("field-1");
@ -408,7 +409,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
createIndex(indexName, Settings.EMPTY);
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
putMappingRequest.type("type_name");
putMappingRequest.type("_doc");
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
mappingBuilder.startObject().startObject("properties").startObject("field");
mappingBuilder.field("type", "text");
@ -420,7 +421,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
assertTrue(putMappingResponse.isAcknowledged());
Map<String, Object> getIndexResponse = getAsMap(indexName);
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.type_name.properties.field.type", getIndexResponse));
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.properties.field.type", getIndexResponse));
}
public void testGetMapping() throws IOException {
@ -440,7 +441,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
assertTrue(putMappingResponse.isAcknowledged());
Map<String, Object> getIndexResponse = getAsMap(indexName);
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings._doc.properties.field.type", getIndexResponse));
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.properties.field.type", getIndexResponse));
GetMappingsRequest request = new GetMappingsRequest()
.indices(indexName)

View File

@ -70,15 +70,15 @@ import org.elasticsearch.action.support.DefaultShardOperationFailedException;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.indices.FreezeIndexRequest;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.SyncedFlushResponse;
import org.elasticsearch.client.core.ShardsAcknowledgedResponse;
import org.elasticsearch.client.indices.FreezeIndexRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.UnfreezeIndexRequest;
import org.elasticsearch.client.core.ShardsAcknowledgedResponse;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData;
@ -1249,7 +1249,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
Settings settings = Settings.builder().put("number_of_shards", 3).build();
String mappings = "{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
CreateIndexResponse createIndexResponse = client.indices().create(
new CreateIndexRequest("index", settings).mapping("doc", mappings, XContentType.JSON),
new CreateIndexRequest("index", settings).mapping("_doc", mappings, XContentType.JSON),
RequestOptions.DEFAULT);
assertTrue(createIndexResponse.isAcknowledged());
}
@ -1272,7 +1272,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
// tag::get-index-response
ImmutableOpenMap<String, MappingMetaData> indexMappings = getIndexResponse.getMappings().get("index"); // <1>
Map<String, Object> indexTypeMappings = indexMappings.get("doc").getSourceAsMap(); // <2>
Map<String, Object> indexTypeMappings = indexMappings.get("_doc").getSourceAsMap(); // <2>
List<AliasMetaData> indexAliases = getIndexResponse.getAliases().get("index"); // <3>
String numberOfShardsString = getIndexResponse.getSetting("index", "index.number_of_shards"); // <4>
Settings indexSettings = getIndexResponse.getSettings().get("index"); // <5>

View File

@ -15,3 +15,63 @@ alias or wildcard expression is required.
The get index API can also be applied to more than one index, or on
all indices by using `_all` or `*` as index.
[float]
=== Skipping types
Types are scheduled to be fully removed in Elasticsearch 8.0 and will not appear
in requests or responses anymore. You can opt in for this future behaviour by
setting `include_type_name=false` in the request, which will return mappings
directly under `mappings` without keying by the type name.
Here is an example:
[source,js]
--------------------------------------------------
PUT test?include_type_name=false
{
"mappings": {
"properties": {
"foo": {
"type": "keyword"
}
}
}
}
GET test?include_type_name=false
--------------------------------------------------
// CONSOLE
which returns
[source,js]
--------------------------------------------------
{
"test": {
"aliases": {},
"mappings": {
"properties": {
"foo": {
"type": "keyword"
}
}
},
"settings": {
"index": {
"creation_date": "1547028674905",
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "u1YpkPqLSqGIn3kNAvY8cA",
"version": {
"created": ...
},
"provided_name": "test"
}
}
}
}
--------------------------------------------------
// TESTRESPONSE[s/1547028674905/$body.test.settings.index.creation_date/]
// TESTRESPONSE[s/u1YpkPqLSqGIn3kNAvY8cA/$body.test.settings.index.uuid/]
// TESTRESPONSE[s/"created": \.\.\./"created": $body.test.settings.index.version.created/]

View File

@ -13,6 +13,10 @@
}
},
"params":{
"include_type_name": {
"type" : "boolean",
"description" : "Whether to add the type name to the response (default: false)"
},
"local":{
"type":"boolean",
"description":"Return local information, do not retrieve the state from master node (default: false)"

View File

@ -52,6 +52,35 @@ setup:
- is_true: test_index.settings
- is_true: test_index.mappings
---
"Test include_type_name":
- skip:
version: " - 6.99.99"
reason: the include_type_name parameter is not backported to pre 7.0 versions yet
- do:
indices.get:
include_type_name: true
index: test_index
- is_true: test_index.mappings
- is_true: test_index.mappings.type_1
- do:
indices.get:
include_type_name: false
index: test_index
- is_true: test_index.mappings
- is_false: test_index.mappings.type_1
- do:
indices.get:
index: test_index
- is_true: test_index.mappings
- is_false: test_index.mappings.type_1
---
"Get index infos should work for wildcards":

View File

@ -20,6 +20,7 @@
package org.elasticsearch.action.admin.indices.get;
import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
import org.apache.lucene.util.CollectionUtil;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionResponse;
@ -34,6 +35,7 @@ import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import org.elasticsearch.index.mapper.MapperService;
import java.io.IOException;
import java.util.ArrayList;
@ -41,9 +43,11 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
import static org.elasticsearch.rest.BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER;
/**
* A response for a get index action.
@ -249,15 +253,32 @@ public class GetIndexResponse extends ActionResponse implements ToXContentObject
}
builder.endObject();
builder.startObject("mappings");
ImmutableOpenMap<String, MappingMetaData> indexMappings = mappings.get(index);
if (indexMappings != null) {
boolean includeTypeName = params.paramAsBoolean(INCLUDE_TYPE_NAME_PARAMETER, false);
if (includeTypeName) {
builder.startObject("mappings");
if (indexMappings != null) {
for (final ObjectObjectCursor<String, MappingMetaData> typeEntry : indexMappings) {
builder.field(typeEntry.key);
builder.map(typeEntry.value.sourceAsMap());
}
}
builder.endObject();
} else {
MappingMetaData mappings = null;
for (final ObjectObjectCursor<String, MappingMetaData> typeEntry : indexMappings) {
builder.field(typeEntry.key);
builder.map(typeEntry.value.sourceAsMap());
if (typeEntry.key.equals(MapperService.DEFAULT_MAPPING) == false) {
assert mappings == null;
mappings = typeEntry.value;
}
}
if (mappings == null) {
// no mappings yet
builder.startObject("mappings").endObject();
} else {
builder.field("mappings", mappings.sourceAsMap());
}
}
builder.endObject();
builder.startObject("settings");
Settings indexSettings = settings.get(index);
@ -292,16 +313,9 @@ public class GetIndexResponse extends ActionResponse implements ToXContentObject
private static ImmutableOpenMap<String, MappingMetaData> parseMappings(XContentParser parser) throws IOException {
ImmutableOpenMap.Builder<String, MappingMetaData> indexMappings = ImmutableOpenMap.builder();
// We start at START_OBJECT since parseIndexEntry ensures that
while (parser.nextToken() != Token.END_OBJECT) {
ensureExpectedToken(Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);
parser.nextToken();
if (parser.currentToken() == Token.START_OBJECT) {
String mappingType = parser.currentName();
indexMappings.put(mappingType, new MappingMetaData(mappingType, parser.map()));
} else if (parser.currentToken() == Token.START_ARRAY) {
parser.skipChildren();
}
Map<String, Object> map = parser.map();
if (map.isEmpty() == false) {
indexMappings.put(MapperService.SINGLE_MAPPING_NAME, new MappingMetaData(MapperService.SINGLE_MAPPING_NAME, map));
}
return indexMappings.build();
}

View File

@ -62,7 +62,7 @@ public abstract class BaseRestHandler extends AbstractComponent implements RestH
* Parameter that controls whether certain REST apis should include type names in their requests or responses.
* Note: Support for this parameter will be removed after the transition perido to typeless APIs.
*/
protected static final String INCLUDE_TYPE_NAME_PARAMETER = "include_type_name";
public static final String INCLUDE_TYPE_NAME_PARAMETER = "include_type_name";
protected BaseRestHandler(Settings settings) {
// TODO drop settings from ctor

View File

@ -20,10 +20,12 @@
package org.elasticsearch.rest.action.admin.indices;
import org.apache.logging.log4j.LogManager;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
@ -31,7 +33,10 @@ import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestToXContentListener;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestRequest.Method.HEAD;
@ -41,6 +46,13 @@ import static org.elasticsearch.rest.RestRequest.Method.HEAD;
*/
public class RestGetIndicesAction extends BaseRestHandler {
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(LogManager.getLogger(RestGetIndicesAction.class));
static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Using `include_type_name` in get indices requests is deprecated. "
+ "The parameter will be removed in the next major version.";
private static final Set<String> allowedResponseParameters = Collections
.unmodifiableSet(Stream.concat(Collections.singleton(INCLUDE_TYPE_NAME_PARAMETER).stream(), Settings.FORMAT_PARAMS.stream())
.collect(Collectors.toSet()));
public RestGetIndicesAction(
final Settings settings,
@ -58,6 +70,10 @@ public class RestGetIndicesAction extends BaseRestHandler {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
String[] indices = Strings.splitStringByCommaToArray(request.param("index"));
// starting with 7.0 we don't include types by default in the response
if (request.hasParam(INCLUDE_TYPE_NAME_PARAMETER)) {
deprecationLogger.deprecatedAndMaybeLog("get_indices_with_types", TYPES_DEPRECATION_MESSAGE);
}
final GetIndexRequest getIndexRequest = new GetIndexRequest();
getIndexRequest.indices(indices);
getIndexRequest.indicesOptions(IndicesOptions.fromRequest(request, getIndexRequest.indicesOptions()));
@ -68,9 +84,12 @@ public class RestGetIndicesAction extends BaseRestHandler {
return channel -> client.admin().indices().getIndex(getIndexRequest, new RestToXContentListener<>(channel));
}
/**
* Parameters used for controlling the response and thus might not be consumed during
* preparation of the request execution in {@link BaseRestHandler#prepareRequest(RestRequest, NodeClient)}.
*/
@Override
protected Set<String> responseParams() {
return Settings.FORMAT_PARAMS;
return allowedResponseParameters;
}
}

View File

@ -32,6 +32,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.IndexScopedSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.RandomCreateIndexGenerator;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.junit.Assert;
@ -72,6 +73,10 @@ public class GetIndexResponseTests extends AbstractStreamableXContentTestCase<Ge
@Override
protected GetIndexResponse createTestInstance() {
return createTestInstance(randomBoolean());
}
private GetIndexResponse createTestInstance(boolean randomTypeName) {
String[] indices = generateRandomStringArray(5, 5, false, false);
ImmutableOpenMap.Builder<String, ImmutableOpenMap<String, MappingMetaData>> mappings = ImmutableOpenMap.builder();
ImmutableOpenMap.Builder<String, List<AliasMetaData>> aliases = ImmutableOpenMap.builder();
@ -80,7 +85,9 @@ public class GetIndexResponseTests extends AbstractStreamableXContentTestCase<Ge
IndexScopedSettings indexScopedSettings = IndexScopedSettings.DEFAULT_SCOPED_SETTINGS;
boolean includeDefaults = randomBoolean();
for (String index: indices) {
mappings.put(index, GetMappingsResponseTests.createMappingsForIndex());
// rarely have no types
int typeCount = rarely() ? 0 : 1;
mappings.put(index, GetMappingsResponseTests.createMappingsForIndex(typeCount, randomTypeName));
List<AliasMetaData> aliasMetaDataList = new ArrayList<>();
int aliasesNum = randomIntBetween(0, 3);
@ -103,6 +110,12 @@ public class GetIndexResponseTests extends AbstractStreamableXContentTestCase<Ge
);
}
@Override
protected GetIndexResponse createXContextTestInstance(XContentType xContentType) {
// don't use random type names for XContent roundtrip tests because we cannot parse them back anymore
return createTestInstance(false);
}
@Override
protected Predicate<String> getRandomFieldsExcludeFilter() {
//we do not want to add new fields at the root (index-level), or inside the blocks
@ -190,5 +203,4 @@ public class GetIndexResponseTests extends AbstractStreamableXContentTestCase<Ge
Assert.assertEquals(TEST_6_3_0_RESPONSE_BYTES, base64OfResponse);
}
}

View File

@ -24,6 +24,7 @@ import com.carrotsearch.hppc.cursors.ObjectCursor;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;
@ -84,22 +85,30 @@ public class GetMappingsResponseTests extends AbstractStreamableXContentTestCase
public static ImmutableOpenMap<String, MappingMetaData> createMappingsForIndex() {
// rarely have no types
int typeCount = rarely() ? 0 : scaledRandomIntBetween(1, 3);
return createMappingsForIndex(typeCount, true);
}
public static ImmutableOpenMap<String, MappingMetaData> createMappingsForIndex(int typeCount, boolean randomTypeName) {
List<MappingMetaData> typeMappings = new ArrayList<>(typeCount);
for (int i = 0; i < typeCount; i++) {
Map<String, Object> mappings = new HashMap<>();
if (rarely() == false) { // rarely have no fields
Map<String, Object> mappings = new HashMap<>();
mappings.put("field-" + i, randomFieldMapping());
if (randomBoolean()) {
mappings.put("field2-" + i, randomFieldMapping());
}
}
try {
MappingMetaData mmd = new MappingMetaData("type-" + randomAlphaOfLength(5), mappings);
typeMappings.add(mmd);
} catch (IOException e) {
fail("shouldn't have failed " + e);
try {
String typeName = MapperService.SINGLE_MAPPING_NAME;
if (randomTypeName) {
typeName = "type-" + randomAlphaOfLength(5);
}
MappingMetaData mmd = new MappingMetaData(typeName, mappings);
typeMappings.add(mmd);
} catch (IOException e) {
fail("shouldn't have failed " + e);
}
}
}
ImmutableOpenMap.Builder<String, MappingMetaData> typeBuilder = ImmutableOpenMap.builder();

View File

@ -0,0 +1,61 @@
/*
* 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.rest.action.admin.indices;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.rest.FakeRestRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.elasticsearch.rest.BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER;
import static org.mockito.Mockito.mock;
public class RestGetIndicesActionTests extends ESTestCase {
/**
* Test that setting the "include_type_name" parameter raises a warning
*/
public void testIncludeTypeNamesWarning() throws IOException {
Map<String, String> params = new HashMap<>();
params.put(INCLUDE_TYPE_NAME_PARAMETER, randomFrom("true", "false"));
RestRequest request = new FakeRestRequest.Builder(xContentRegistry())
.withMethod(RestRequest.Method.GET)
.withPath("/some_index")
.withParams(params)
.build();
RestGetIndicesAction handler = new RestGetIndicesAction(Settings.EMPTY, mock(RestController.class));
handler.prepareRequest(request, mock(NodeClient.class));
assertWarnings(RestGetIndicesAction.TYPES_DEPRECATION_MESSAGE);
// the same request without the parameter should pass without warning
request = new FakeRestRequest.Builder(xContentRegistry())
.withMethod(RestRequest.Method.GET)
.withPath("/some_index")
.build();
handler.prepareRequest(request, mock(NodeClient.class));
}
}