From 7b46b5fb65122b420a7ce2ff88fa3f7ccd02d85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Thu, 3 Jan 2019 15:56:17 +0100 Subject: [PATCH 01/10] Support 'include_type_name' in RestGetIndicesAction 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. --- .../elasticsearch/client/IndicesClientIT.java | 23 +++---- .../IndicesClientDocumentationIT.java | 8 +-- .../rest-api-spec/api/indices.get.json | 4 ++ .../test/indices.get/10_basic.yml | 29 +++++++++ .../admin/indices/get/GetIndexResponse.java | 53 +++++++++++++--- .../admin/indices/RestGetIndicesAction.java | 9 +++ .../admin/indices/RestGetMappingAction.java | 3 +- .../indices/get/GetIndexResponseTests.java | 31 +++++++++- .../mapping/get/GetMappingsResponseTests.java | 23 ++++--- .../indices/RestGetIndicesActionTests.java | 60 +++++++++++++++++++ 10 files changed, 210 insertions(+), 33 deletions(-) create mode 100644 server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesActionTests.java 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 a639a09b3cc53..92d7e94394594 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 @@ -89,6 +89,7 @@ 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 void testCreateIndex() throws IOException { 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 void testCreateIndex() throws IOException { Map 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 void testGetIndex() throws IOException { .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 void testGetIndex() throws IOException { 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) o).get("field-1"), instanceOf(Map.class)); @@ -370,7 +371,7 @@ public void testGetIndexWithDefaults() throws IOException { .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 void testGetIndexWithDefaults() throws IOException { 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) o).get("field-1"), instanceOf(Map.class)); Map fieldMapping = (Map) ((Map) o).get("field-1"); @@ -408,7 +409,7 @@ public void testPutMapping() throws IOException { 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 void testPutMapping() throws IOException { assertTrue(putMappingResponse.isAcknowledged()); Map 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 void testGetMapping() throws IOException { assertTrue(putMappingResponse.isAcknowledged()); Map 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) 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 3ff4466649ff2..8f9d8a069fd48 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 @@ -70,15 +70,15 @@ 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 void testGetIndex() throws Exception { 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 void testGetIndex() throws Exception { // tag::get-index-response ImmutableOpenMap indexMappings = getIndexResponse.getMappings().get("index"); // <1> - Map indexTypeMappings = indexMappings.get("doc").getSourceAsMap(); // <2> + Map indexTypeMappings = indexMappings.get("_doc").getSourceAsMap(); // <2> List indexAliases = getIndexResponse.getAliases().get("index"); // <3> String numberOfShardsString = getIndexResponse.getSetting("index", "index.number_of_shards"); // <4> Settings indexSettings = getIndexResponse.getSettings().get("index"); // <5> diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.get.json b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.get.json index 6474b8acf5298..76e6ed00feb26 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.get.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.get.json @@ -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)" diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml index 6301087f48902..ef028dcdf67e8 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml @@ -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": diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java index e2b72077b7f21..e6a809918e71c 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java @@ -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.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,6 +43,7 @@ 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; @@ -249,15 +252,29 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws } builder.endObject(); - builder.startObject("mappings"); ImmutableOpenMap indexMappings = mappings.get(index); - if (indexMappings != null) { - for (final ObjectObjectCursor typeEntry : indexMappings) { - builder.field(typeEntry.key); - builder.map(typeEntry.value.sourceAsMap()); + boolean includeTypeName = params.paramAsBoolean("include_type_name", false); + if (includeTypeName) { + builder.startObject("mappings"); + if (indexMappings != null) { + for (final ObjectObjectCursor typeEntry : indexMappings) { + builder.field(typeEntry.key); + builder.map(typeEntry.value.sourceAsMap()); + } + } + builder.endObject(); + } else { + if (indexMappings != null && indexMappings.size() > 0) { + builder.field("mappings"); + for (final ObjectObjectCursor typeEntry : indexMappings) { + builder.map(typeEntry.value.sourceAsMap()); + } + } else { + // we always want to output a mappings object, even if empty + builder.startObject("mappings"); + builder.endObject(); } } - builder.endObject(); builder.startObject("settings"); Settings indexSettings = settings.get(index); @@ -291,6 +308,16 @@ private static List parseAliases(XContentParser parser) throws IO } private static ImmutableOpenMap parseMappings(XContentParser parser) throws IOException { + ImmutableOpenMap.Builder indexMappings = ImmutableOpenMap.builder(); + // We start at START_OBJECT since parseIndexEntry ensures that + Map map = parser.map(); + if (map.isEmpty() == false) { + indexMappings.put(MapperService.SINGLE_MAPPING_NAME, new MappingMetaData(MapperService.SINGLE_MAPPING_NAME, map)); + } + return indexMappings.build(); + } + + private static ImmutableOpenMap parseMappingsWithTypes(XContentParser parser) throws IOException { ImmutableOpenMap.Builder indexMappings = ImmutableOpenMap.builder(); // We start at START_OBJECT since parseIndexEntry ensures that while (parser.nextToken() != Token.END_OBJECT) { @@ -306,7 +333,7 @@ private static ImmutableOpenMap parseMappings(XContentP return indexMappings.build(); } - private static IndexEntry parseIndexEntry(XContentParser parser) throws IOException { + private static IndexEntry parseIndexEntry(XContentParser parser, boolean legacyWithTypes) throws IOException { List indexAliases = null; ImmutableOpenMap indexMappings = null; Settings indexSettings = null; @@ -321,7 +348,11 @@ private static IndexEntry parseIndexEntry(XContentParser parser) throws IOExcept indexAliases = parseAliases(parser); break; case "mappings": - indexMappings = parseMappings(parser); + if (legacyWithTypes) { + indexMappings = parseMappingsWithTypes(parser); + } else { + indexMappings = parseMappings(parser); + } break; case "settings": indexSettings = Settings.fromXContent(parser); @@ -355,6 +386,10 @@ private static class IndexEntry { } public static GetIndexResponse fromXContent(XContentParser parser) throws IOException { + return fromXContent(parser, false); + } + + public static GetIndexResponse fromXContent(XContentParser parser, boolean legacyWithTypes) throws IOException { ImmutableOpenMap.Builder> aliases = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder> mappings = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder settings = ImmutableOpenMap.builder(); @@ -372,7 +407,7 @@ public static GetIndexResponse fromXContent(XContentParser parser) throws IOExce // we assume this is an index entry String indexName = parser.currentName(); indices.add(indexName); - IndexEntry indexEntry = parseIndexEntry(parser); + IndexEntry indexEntry = parseIndexEntry(parser, legacyWithTypes); // make the order deterministic CollectionUtil.timSort(indexEntry.indexAliases, Comparator.comparing(AliasMetaData::alias)); aliases.put(indexName, Collections.unmodifiableList(indexEntry.indexAliases)); diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java index 04fae0f30f6bf..614fe492171bf 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java @@ -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; @@ -41,6 +43,9 @@ */ 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."; public RestGetIndicesAction( final Settings settings, @@ -58,6 +63,10 @@ public String getName() { @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")) { + deprecationLogger.deprecatedAndMaybeLog("get_indices_with_types", TYPES_DEPRECATION_MESSAGE); + } final GetIndexRequest getIndexRequest = new GetIndexRequest(); getIndexRequest.indices(indices); getIndexRequest.indicesOptions(IndicesOptions.fromRequest(request, getIndexRequest.indicesOptions())); diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetMappingAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetMappingAction.java index aca6235420cca..15a503fe55efb 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetMappingAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetMappingAction.java @@ -20,8 +20,9 @@ package org.elasticsearch.rest.action.admin.indices; import com.carrotsearch.hppc.cursors.ObjectCursor; -import org.apache.logging.log4j.Logger; + import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse; import org.elasticsearch.action.support.IndicesOptions; diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java index 3991442fd5b87..38377f6fef18c 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java @@ -31,7 +31,11 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.IndexScopedSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; 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.AbstractStreamableXContentTestCase; import org.junit.Assert; @@ -72,6 +76,10 @@ protected GetIndexResponse createBlankInstance() { @Override protected GetIndexResponse createTestInstance() { + return createTestInstance(false); + } + + private GetIndexResponse createTestInstance(boolean randomTypeName) { String[] indices = generateRandomStringArray(5, 5, false, false); ImmutableOpenMap.Builder> mappings = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder> aliases = ImmutableOpenMap.builder(); @@ -80,7 +88,9 @@ protected GetIndexResponse createTestInstance() { 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 aliasMetaDataList = new ArrayList<>(); int aliasesNum = randomIntBetween(0, 3); @@ -191,4 +201,23 @@ public void testCanOutput622Response() throws IOException { Assert.assertEquals(TEST_6_3_0_RESPONSE_BYTES, base64OfResponse); } + /** + * test that the old response format with types can still be parsed with the special parser method + * when output is rendered with types + */ + public void testFromXContentWithTypes() throws IOException { + GetIndexResponse testInstance = this.createTestInstance(true); + try (XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent())) { + // this renders the response in the "old" format with types + testInstance.toXContent(builder, new ToXContent.MapParams(Collections.singletonMap("include_type_name", "true"))); + BytesReference bytes = BytesReference.bytes(builder); + XContentParser parser = createParser(JsonXContent.jsonXContent, bytes); + // this parses the output expecting the "old" format with types + GetIndexResponse parsedInstance = GetIndexResponse.fromXContent(parser, true); + assertNotSame(parsedInstance, testInstance); + assertEquals(testInstance, parsedInstance); + assertEquals(testInstance.hashCode(), parsedInstance.hashCode()); + } + } + } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/get/GetMappingsResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/get/GetMappingsResponseTests.java index beae91df77e3d..481d05ea8cc07 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/get/GetMappingsResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/get/GetMappingsResponseTests.java @@ -24,6 +24,7 @@ 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 @@ protected GetMappingsResponse mutateInstance(GetMappingsResponse instance) throw public static ImmutableOpenMap createMappingsForIndex() { // rarely have no types int typeCount = rarely() ? 0 : scaledRandomIntBetween(1, 3); + return createMappingsForIndex(typeCount, true); + } + + public static ImmutableOpenMap createMappingsForIndex(int typeCount, boolean randomTypeName) { List typeMappings = new ArrayList<>(typeCount); for (int i = 0; i < typeCount; i++) { - Map mappings = new HashMap<>(); if (rarely() == false) { // rarely have no fields + Map 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 typeBuilder = ImmutableOpenMap.builder(); diff --git a/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesActionTests.java b/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesActionTests.java new file mode 100644 index 0000000000000..95b813741c275 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesActionTests.java @@ -0,0 +1,60 @@ +/* + * 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.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 params = new HashMap<>(); + params.put("include_type_name", 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)); + } +} From 4a07eedd570d5e3ac17d4be6965726c549c643da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Fri, 4 Jan 2019 20:25:58 +0100 Subject: [PATCH 02/10] iter --- .../action/admin/indices/RestGetIndicesAction.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java index 614fe492171bf..67cf10577c5f4 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java @@ -33,7 +33,10 @@ 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; @@ -47,6 +50,9 @@ public class RestGetIndicesAction extends BaseRestHandler { 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 allowedResponseParameters = Collections.unmodifiableSet(Stream + .concat(Collections.singleton("include_type_name").stream(), Settings.FORMAT_PARAMS.stream()).collect(Collectors.toSet())); + public RestGetIndicesAction( final Settings settings, final RestController controller) { @@ -77,9 +83,12 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC 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 responseParams() { - return Settings.FORMAT_PARAMS; + return allowedResponseParameters; } - } From e9f9f64bdeb5c1d6455cfe752f9cd4f955ac5811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Mon, 7 Jan 2019 11:24:29 +0100 Subject: [PATCH 03/10] Use constant --- .../action/admin/indices/get/GetIndexResponse.java | 3 ++- .../main/java/org/elasticsearch/rest/BaseRestHandler.java | 2 +- .../rest/action/admin/indices/RestGetIndicesAction.java | 2 +- .../action/admin/indices/get/GetIndexResponseTests.java | 6 ++++-- .../action/admin/indices/RestGetIndicesActionTests.java | 3 ++- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java index e6a809918e71c..12733b08b923e 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java @@ -47,6 +47,7 @@ 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. @@ -253,7 +254,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.endObject(); ImmutableOpenMap indexMappings = mappings.get(index); - boolean includeTypeName = params.paramAsBoolean("include_type_name", false); + boolean includeTypeName = params.paramAsBoolean(INCLUDE_TYPE_NAME_PARAMETER, false); if (includeTypeName) { builder.startObject("mappings"); if (indexMappings != null) { diff --git a/server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java b/server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java index 4611fd69b2bf8..963c8089f342b 100644 --- a/server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java +++ b/server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java @@ -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 diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java index 67cf10577c5f4..50fc80fe7d963 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java @@ -70,7 +70,7 @@ public String getName() { 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")) { + if (request.hasParam(INCLUDE_TYPE_NAME_PARAMETER)) { deprecationLogger.deprecatedAndMaybeLog("get_indices_with_types", TYPES_DEPRECATION_MESSAGE); } final GetIndexRequest getIndexRequest = new GetIndexRequest(); diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java index 38377f6fef18c..e754761996060 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java @@ -49,9 +49,11 @@ import java.util.List; import java.util.function.Predicate; +import static org.elasticsearch.action.admin.indices.get.GetIndexResponse.fromXContent; import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS; import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS; import static org.elasticsearch.index.IndexSettings.INDEX_REFRESH_INTERVAL_SETTING; +import static org.elasticsearch.rest.BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER; public class GetIndexResponseTests extends AbstractStreamableXContentTestCase { @@ -209,11 +211,11 @@ public void testFromXContentWithTypes() throws IOException { GetIndexResponse testInstance = this.createTestInstance(true); try (XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent())) { // this renders the response in the "old" format with types - testInstance.toXContent(builder, new ToXContent.MapParams(Collections.singletonMap("include_type_name", "true"))); + testInstance.toXContent(builder, new ToXContent.MapParams(Collections.singletonMap(INCLUDE_TYPE_NAME_PARAMETER, "true"))); BytesReference bytes = BytesReference.bytes(builder); XContentParser parser = createParser(JsonXContent.jsonXContent, bytes); // this parses the output expecting the "old" format with types - GetIndexResponse parsedInstance = GetIndexResponse.fromXContent(parser, true); + GetIndexResponse parsedInstance = fromXContent(parser, true); assertNotSame(parsedInstance, testInstance); assertEquals(testInstance, parsedInstance); assertEquals(testInstance.hashCode(), parsedInstance.hashCode()); diff --git a/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesActionTests.java b/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesActionTests.java index 95b813741c275..5f157cd298d4d 100644 --- a/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesActionTests.java +++ b/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesActionTests.java @@ -30,6 +30,7 @@ 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 { @@ -39,7 +40,7 @@ public class RestGetIndicesActionTests extends ESTestCase { */ public void testIncludeTypeNamesWarning() throws IOException { Map params = new HashMap<>(); - params.put("include_type_name", randomFrom("true", "false")); + params.put(INCLUDE_TYPE_NAME_PARAMETER, randomFrom("true", "false")); RestRequest request = new FakeRestRequest.Builder(xContentRegistry()) .withMethod(RestRequest.Method.GET) .withPath("/some_index") From e3988b7912bf20ad5d68248ef3a9e963d23326eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Mon, 7 Jan 2019 22:14:33 +0100 Subject: [PATCH 04/10] iter --- .../action/admin/indices/get/GetIndexResponse.java | 5 ++--- .../rest/action/admin/indices/RestGetIndicesAction.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java index 12733b08b923e..0ef710801f0aa 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java @@ -310,7 +310,6 @@ private static List parseAliases(XContentParser parser) throws IO private static ImmutableOpenMap parseMappings(XContentParser parser) throws IOException { ImmutableOpenMap.Builder indexMappings = ImmutableOpenMap.builder(); - // We start at START_OBJECT since parseIndexEntry ensures that Map map = parser.map(); if (map.isEmpty() == false) { indexMappings.put(MapperService.SINGLE_MAPPING_NAME, new MappingMetaData(MapperService.SINGLE_MAPPING_NAME, map)); @@ -334,7 +333,7 @@ private static ImmutableOpenMap parseMappingsWithTypes( return indexMappings.build(); } - private static IndexEntry parseIndexEntry(XContentParser parser, boolean legacyWithTypes) throws IOException { + private static IndexEntry parseIndexEntry(XContentParser parser, boolean includeTypeName) throws IOException { List indexAliases = null; ImmutableOpenMap indexMappings = null; Settings indexSettings = null; @@ -349,7 +348,7 @@ private static IndexEntry parseIndexEntry(XContentParser parser, boolean legacyW indexAliases = parseAliases(parser); break; case "mappings": - if (legacyWithTypes) { + if (includeTypeName) { indexMappings = parseMappingsWithTypes(parser); } else { indexMappings = parseMappings(parser); diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java index 50fc80fe7d963..9f9575057b4be 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java @@ -51,7 +51,7 @@ public class RestGetIndicesAction extends BaseRestHandler { + "The parameter will be removed in the next major version."; private static final Set allowedResponseParameters = Collections.unmodifiableSet(Stream - .concat(Collections.singleton("include_type_name").stream(), Settings.FORMAT_PARAMS.stream()).collect(Collectors.toSet())); + .concat(Collections.singleton(INCLUDE_TYPE_NAME_PARAMETER).stream(), Settings.FORMAT_PARAMS.stream()).collect(Collectors.toSet())); public RestGetIndicesAction( final Settings settings, From d16903036524e264ced3fadd040aaa04d7900820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Mon, 7 Jan 2019 22:16:00 +0100 Subject: [PATCH 05/10] Remove parsing with types --- .../admin/indices/get/GetIndexResponse.java | 30 ++----------------- .../indices/get/GetIndexResponseTests.java | 26 ---------------- 2 files changed, 3 insertions(+), 53 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java index 0ef710801f0aa..e6938e4b8fb3a 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java @@ -317,23 +317,7 @@ private static ImmutableOpenMap parseMappings(XContentP return indexMappings.build(); } - private static ImmutableOpenMap parseMappingsWithTypes(XContentParser parser) throws IOException { - ImmutableOpenMap.Builder 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(); - } - } - return indexMappings.build(); - } - - private static IndexEntry parseIndexEntry(XContentParser parser, boolean includeTypeName) throws IOException { + private static IndexEntry parseIndexEntry(XContentParser parser) throws IOException { List indexAliases = null; ImmutableOpenMap indexMappings = null; Settings indexSettings = null; @@ -348,11 +332,7 @@ private static IndexEntry parseIndexEntry(XContentParser parser, boolean include indexAliases = parseAliases(parser); break; case "mappings": - if (includeTypeName) { - indexMappings = parseMappingsWithTypes(parser); - } else { - indexMappings = parseMappings(parser); - } + indexMappings = parseMappings(parser); break; case "settings": indexSettings = Settings.fromXContent(parser); @@ -386,10 +366,6 @@ private static class IndexEntry { } public static GetIndexResponse fromXContent(XContentParser parser) throws IOException { - return fromXContent(parser, false); - } - - public static GetIndexResponse fromXContent(XContentParser parser, boolean legacyWithTypes) throws IOException { ImmutableOpenMap.Builder> aliases = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder> mappings = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder settings = ImmutableOpenMap.builder(); @@ -407,7 +383,7 @@ public static GetIndexResponse fromXContent(XContentParser parser, boolean legac // we assume this is an index entry String indexName = parser.currentName(); indices.add(indexName); - IndexEntry indexEntry = parseIndexEntry(parser, legacyWithTypes); + IndexEntry indexEntry = parseIndexEntry(parser); // make the order deterministic CollectionUtil.timSort(indexEntry.indexAliases, Comparator.comparing(AliasMetaData::alias)); aliases.put(indexName, Collections.unmodifiableList(indexEntry.indexAliases)); diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java index e754761996060..3b979ccd1ced6 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java @@ -31,11 +31,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.ToXContent; -import org.elasticsearch.common.xcontent.XContentBuilder; 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.AbstractStreamableXContentTestCase; import org.junit.Assert; @@ -49,11 +45,9 @@ import java.util.List; import java.util.function.Predicate; -import static org.elasticsearch.action.admin.indices.get.GetIndexResponse.fromXContent; import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS; import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS; import static org.elasticsearch.index.IndexSettings.INDEX_REFRESH_INTERVAL_SETTING; -import static org.elasticsearch.rest.BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER; public class GetIndexResponseTests extends AbstractStreamableXContentTestCase { @@ -202,24 +196,4 @@ public void testCanOutput622Response() throws IOException { Assert.assertEquals(TEST_6_3_0_RESPONSE_BYTES, base64OfResponse); } - - /** - * test that the old response format with types can still be parsed with the special parser method - * when output is rendered with types - */ - public void testFromXContentWithTypes() throws IOException { - GetIndexResponse testInstance = this.createTestInstance(true); - try (XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent())) { - // this renders the response in the "old" format with types - testInstance.toXContent(builder, new ToXContent.MapParams(Collections.singletonMap(INCLUDE_TYPE_NAME_PARAMETER, "true"))); - BytesReference bytes = BytesReference.bytes(builder); - XContentParser parser = createParser(JsonXContent.jsonXContent, bytes); - // this parses the output expecting the "old" format with types - GetIndexResponse parsedInstance = fromXContent(parser, true); - assertNotSame(parsedInstance, testInstance); - assertEquals(testInstance, parsedInstance); - assertEquals(testInstance.hashCode(), parsedInstance.hashCode()); - } - } - } From 296f2bcd50433401f29513b49162499e92ee8e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Mon, 7 Jan 2019 23:06:12 +0100 Subject: [PATCH 06/10] change mapping toXContent --- .../admin/indices/get/GetIndexResponse.java | 19 +++++++++++-------- .../admin/indices/RestGetIndicesAction.java | 5 +++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java index e6938e4b8fb3a..bc832467d03fa 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java @@ -265,15 +265,18 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws } builder.endObject(); } else { - if (indexMappings != null && indexMappings.size() > 0) { - builder.field("mappings"); - for (final ObjectObjectCursor typeEntry : indexMappings) { - builder.map(typeEntry.value.sourceAsMap()); + MappingMetaData mappings = null; + for (final ObjectObjectCursor typeEntry : indexMappings) { + 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()); } - } else { - // we always want to output a mappings object, even if empty - builder.startObject("mappings"); - builder.endObject(); } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java index 9f9575057b4be..f38df9326949f 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java @@ -50,8 +50,9 @@ public class RestGetIndicesAction extends BaseRestHandler { 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 allowedResponseParameters = Collections.unmodifiableSet(Stream - .concat(Collections.singleton(INCLUDE_TYPE_NAME_PARAMETER).stream(), Settings.FORMAT_PARAMS.stream()).collect(Collectors.toSet())); + private static final Set allowedResponseParameters = Collections + .unmodifiableSet(Stream.concat(Collections.singleton(INCLUDE_TYPE_NAME_PARAMETER).stream(), Settings.FORMAT_PARAMS.stream()) + .collect(Collectors.toSet())); public RestGetIndicesAction( final Settings settings, From 06cc067bcf0891b64f88aa75be49e91e5f051a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Tue, 8 Jan 2019 00:08:53 +0100 Subject: [PATCH 07/10] Fix failing yaml test --- .../main/resources/rest-api-spec/test/indices.get/10_basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml index ef028dcdf67e8..6350504fd92b2 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml @@ -92,7 +92,7 @@ setup: - is_true: test_index.aliases - is_true: test_index.settings - is_true: test_index_2.settings - - is_true: test_index_2.mappings + - is_false: test_index_2.mappings - is_true: test_index_2.aliases --- From 9cb40f2744e2fae12ab16ea2c96a0d0235870ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Tue, 8 Jan 2019 18:55:44 +0100 Subject: [PATCH 08/10] Revert changes in yaml tests --- .../test/indices.get/10_basic.yml | 2 +- .../admin/indices/get/GetIndexResponse.java | 27 +++++++++++-------- .../indices/get/GetIndexResponseTests.java | 6 +---- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml index 6350504fd92b2..ef028dcdf67e8 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml @@ -92,7 +92,7 @@ setup: - is_true: test_index.aliases - is_true: test_index.settings - is_true: test_index_2.settings - - is_false: test_index_2.mappings + - is_true: test_index_2.mappings - is_true: test_index_2.aliases --- diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java index bc832467d03fa..f619b88a6d9eb 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java @@ -265,17 +265,22 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws } builder.endObject(); } else { - MappingMetaData mappings = null; - for (final ObjectObjectCursor typeEntry : indexMappings) { - 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()); + if (indexMappings.size() == 0) { + // special case where there are no index mappings at all, we still want to output an empty object + builder.startObject("mappings").endObject(); + } else { + MappingMetaData mappings = null; + for (final ObjectObjectCursor typeEntry : indexMappings) { + 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()); + } } } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java index 3b979ccd1ced6..a8f3c2e2f8044 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java @@ -72,10 +72,6 @@ protected GetIndexResponse createBlankInstance() { @Override protected GetIndexResponse createTestInstance() { - return createTestInstance(false); - } - - private GetIndexResponse createTestInstance(boolean randomTypeName) { String[] indices = generateRandomStringArray(5, 5, false, false); ImmutableOpenMap.Builder> mappings = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder> aliases = ImmutableOpenMap.builder(); @@ -86,7 +82,7 @@ private GetIndexResponse createTestInstance(boolean randomTypeName) { for (String index: indices) { // rarely have no types int typeCount = rarely() ? 0 : 1; - mappings.put(index, GetMappingsResponseTests.createMappingsForIndex(typeCount, randomTypeName)); + mappings.put(index, GetMappingsResponseTests.createMappingsForIndex(typeCount, false)); List aliasMetaDataList = new ArrayList<>(); int aliasesNum = randomIntBetween(0, 3); From 52ffb4bded135e55d0c76e92a1c7bc9ffd4c7ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Tue, 8 Jan 2019 21:44:39 +0100 Subject: [PATCH 09/10] iter --- .../admin/indices/get/GetIndexResponse.java | 25 ++++++++----------- .../indices/get/GetIndexResponseTests.java | 13 +++++++++- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java index f619b88a6d9eb..c7e64143f9c9a 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java @@ -265,23 +265,18 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws } builder.endObject(); } else { - if (indexMappings.size() == 0) { - // special case where there are no index mappings at all, we still want to output an empty object + MappingMetaData mappings = null; + for (final ObjectObjectCursor typeEntry : indexMappings) { + 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 { - MappingMetaData mappings = null; - for (final ObjectObjectCursor typeEntry : indexMappings) { - 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.field("mappings", mappings.sourceAsMap()); } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java index a8f3c2e2f8044..af3ab33e915db 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java @@ -32,6 +32,7 @@ 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 @@ protected GetIndexResponse createBlankInstance() { @Override protected GetIndexResponse createTestInstance() { + return createTestInstance(randomBoolean()); + } + + private GetIndexResponse createTestInstance(boolean randomTypeName) { String[] indices = generateRandomStringArray(5, 5, false, false); ImmutableOpenMap.Builder> mappings = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder> aliases = ImmutableOpenMap.builder(); @@ -82,7 +87,7 @@ protected GetIndexResponse createTestInstance() { for (String index: indices) { // rarely have no types int typeCount = rarely() ? 0 : 1; - mappings.put(index, GetMappingsResponseTests.createMappingsForIndex(typeCount, false)); + mappings.put(index, GetMappingsResponseTests.createMappingsForIndex(typeCount, randomTypeName)); List aliasMetaDataList = new ArrayList<>(); int aliasesNum = randomIntBetween(0, 3); @@ -105,6 +110,12 @@ protected GetIndexResponse createTestInstance() { ); } + @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 getRandomFieldsExcludeFilter() { //we do not want to add new fields at the root (index-level), or inside the blocks From 585ed20468ed2243ca9595e392fb80273eb1b862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Wed, 9 Jan 2019 11:19:06 +0100 Subject: [PATCH 10/10] Add Skipping types section to get-indices docs --- docs/reference/indices/get-index.asciidoc | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/docs/reference/indices/get-index.asciidoc b/docs/reference/indices/get-index.asciidoc index ffa512dca6363..8e254a576c11d 100644 --- a/docs/reference/indices/get-index.asciidoc +++ b/docs/reference/indices/get-index.asciidoc @@ -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/]