Selaa lähdekoodia

IndexTemplateMetaData.mappings() should return a single object (#52961)

Currently it returns a map, but that map can only ever hold one set of mappings so
it makes sense to change the signature here.

Relates to #41059
Alan Woodward 5 vuotta sitten
vanhempi
commit
a76df695f9

+ 5 - 3
client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexTemplatesResponseTests.java

@@ -110,8 +110,7 @@ public class GetIndexTemplatesResponseTests extends ESTestCase {
                     assertThat(result.order(), equalTo(esIMD.order()));
                     assertThat(result.version(), equalTo(esIMD.version()));
 
-                    assertThat(esIMD.mappings().size(), equalTo(1));
-                    BytesArray mappingSource = new BytesArray(esIMD.mappings().valuesIt().next().uncompressed());
+                    BytesArray mappingSource = new BytesArray(esIMD.mappings().uncompressed());
                     Map<String, Object> expectedMapping =
                         XContentHelper.convertToMap(mappingSource, true, xContentBuilder.contentType()).v2();
                     assertThat(result.mappings().sourceAsMap(), equalTo(expectedMapping.get("_doc")));
@@ -205,7 +204,10 @@ public class GetIndexTemplatesResponseTests extends ESTestCase {
             serverTemplateBuilder.order(clientITMD.order());
             serverTemplateBuilder.version(clientITMD.version());
             if (clientITMD.mappings() != null) {
-                serverTemplateBuilder.putMapping(MapperService.SINGLE_MAPPING_NAME, clientITMD.mappings().source());
+                // The client-side mappings never include a wrapping type, but server-side mappings
+                // for index templates still do so we need to wrap things here
+                String mappings = "{\"" + MapperService.SINGLE_MAPPING_NAME + "\": " + clientITMD.mappings().source().string() + "}";
+                serverTemplateBuilder.putMapping(MapperService.SINGLE_MAPPING_NAME, mappings);
             }
             serverIndexTemplates.add(serverTemplateBuilder.build());
 

+ 1 - 25
server/src/main/java/org/elasticsearch/cluster/ClusterState.java

@@ -46,7 +46,6 @@ import org.elasticsearch.common.UUIDs;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.bytes.BytesReference;
 import org.elasticsearch.common.collect.ImmutableOpenMap;
-import org.elasticsearch.common.compress.CompressedXContent;
 import org.elasticsearch.common.io.stream.BytesStreamOutput;
 import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
 import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
@@ -430,30 +429,7 @@ public class ClusterState implements ToXContentFragment, Diffable<ClusterState>
             builder.startObject("templates");
             for (ObjectCursor<IndexTemplateMetaData> cursor : metaData().templates().values()) {
                 IndexTemplateMetaData templateMetaData = cursor.value;
-                builder.startObject(templateMetaData.name());
-
-                builder.field("index_patterns", templateMetaData.patterns());
-                builder.field("order", templateMetaData.order());
-
-                builder.startObject("settings");
-                Settings settings = templateMetaData.settings();
-                settings.toXContent(builder, params);
-                builder.endObject();
-
-                builder.startObject("mappings");
-                for (ObjectObjectCursor<String, CompressedXContent> cursor1 : templateMetaData.mappings()) {
-                    Map<String, Object> mapping = XContentHelper.convertToMap(new BytesArray(cursor1.value.uncompressed()), false).v2();
-                    if (mapping.size() == 1 && mapping.containsKey(cursor1.key)) {
-                        // the type name is the root value, reduce it
-                        mapping = (Map<String, Object>) mapping.get(cursor1.key);
-                    }
-                    builder.field(cursor1.key);
-                    builder.map(mapping);
-                }
-                builder.endObject();
-
-
-                builder.endObject();
+                IndexTemplateMetaData.Builder.toXContentWithTypes(templateMetaData, builder, params);
             }
             builder.endObject();
 

+ 35 - 44
server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java

@@ -38,8 +38,10 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
 import org.elasticsearch.common.xcontent.XContentHelper;
 import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
 
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -132,12 +134,15 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
         return this.settings;
     }
 
-    public ImmutableOpenMap<String, CompressedXContent> mappings() {
-        return this.mappings;
+    public CompressedXContent mappings() {
+        if (this.mappings.isEmpty()) {
+            return null;
+        }
+        return this.mappings.iterator().next().value;
     }
 
-    public ImmutableOpenMap<String, CompressedXContent> getMappings() {
-        return this.mappings;
+    public CompressedXContent getMappings() {
+        return this.mappings();
     }
 
     public ImmutableOpenMap<String, AliasMetaData> aliases() {
@@ -219,6 +224,19 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
         out.writeOptionalVInt(version);
     }
 
+    @Override
+    public String toString() {
+        try {
+            XContentBuilder builder = JsonXContent.contentBuilder();
+            builder.startObject();
+            IndexTemplateMetaData.Builder.toXContentWithTypes(this, builder, ToXContent.EMPTY_PARAMS);
+            builder.endObject();
+            return Strings.toString(builder);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
     public static class Builder {
 
         private static final Set<String> VALID_FIELDS = Sets.newHashSet(
@@ -251,7 +269,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
             patterns(indexTemplateMetaData.patterns());
             settings(indexTemplateMetaData.settings());
 
-            mappings = ImmutableOpenMap.builder(indexTemplateMetaData.mappings());
+            mappings = ImmutableOpenMap.builder(indexTemplateMetaData.mappings);
             aliases = ImmutableOpenMap.builder(indexTemplateMetaData.aliases());
         }
 
@@ -371,41 +389,18 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
             indexTemplateMetaData.settings().toXContent(builder, params);
             builder.endObject();
 
-            if (params.paramAsBoolean("reduce_mappings", false)) {
-                // The parameter include_type_name is only ever used in the REST API, where reduce_mappings is
-                // always set to true. We therefore only check for include_type_name in this branch.
-                if (includeTypeName == false) {
-                    Map<String, Object> documentMapping = null;
-                    for (ObjectObjectCursor<String, CompressedXContent> cursor : indexTemplateMetaData.mappings()) {
-                        assert documentMapping == null;
-                        byte[] mappingSource = cursor.value.uncompressed();
-                        Map<String, Object> mapping = XContentHelper.convertToMap(new BytesArray(mappingSource), true).v2();
-                        documentMapping = reduceMapping(cursor.key, mapping);
-                    }
+            includeTypeName &= (params.paramAsBoolean("reduce_mappings", false) == false);
 
-                    if (documentMapping != null) {
-                        builder.field("mappings", documentMapping);
-                    } else {
-                        builder.startObject("mappings").endObject();
-                    }
-                } else {
-                    builder.startObject("mappings");
-                    for (ObjectObjectCursor<String, CompressedXContent> cursor : indexTemplateMetaData.mappings()) {
-                        byte[] mappingSource = cursor.value.uncompressed();
-                        Map<String, Object> mapping = XContentHelper.convertToMap(new BytesArray(mappingSource), true).v2();
-                        mapping = reduceMapping(cursor.key, mapping);
-                        builder.field(cursor.key);
-                        builder.map(mapping);
-                    }
-                    builder.endObject();
+            CompressedXContent m = indexTemplateMetaData.mappings();
+            if (m != null) {
+                Map<String, Object> documentMapping = XContentHelper.convertToMap(new BytesArray(m.uncompressed()), true).v2();
+                if (includeTypeName == false) {
+                    documentMapping = reduceMapping(documentMapping);
                 }
+                builder.field("mappings");
+                builder.map(documentMapping);
             } else {
-                builder.startArray("mappings");
-                for (ObjectObjectCursor<String, CompressedXContent> cursor : indexTemplateMetaData.mappings()) {
-                    byte[] data = cursor.value.uncompressed();
-                    builder.map(XContentHelper.convertToMap(new BytesArray(data), true).v2());
-                }
-                builder.endArray();
+                builder.startObject("mappings").endObject();
             }
 
             builder.startObject("aliases");
@@ -416,13 +411,9 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
         }
 
         @SuppressWarnings("unchecked")
-        private static Map<String, Object> reduceMapping(String type, Map<String, Object> mapping) {
-            if (mapping.size() == 1 && mapping.containsKey(type)) {
-                // the type name is the root value, reduce it
-                return (Map<String, Object>) mapping.get(type);
-            } else {
-                return mapping;
-            }
+        private static Map<String, Object> reduceMapping(Map<String, Object> mapping) {
+            assert mapping.keySet().size() == 1;
+            return (Map<String, Object>) mapping.values().iterator().next();
         }
 
         public static IndexTemplateMetaData fromXContent(XContentParser parser, String templateName) throws IOException {

+ 4 - 8
server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java

@@ -414,15 +414,11 @@ public class MetaDataCreateIndexService {
         Map<String, Object> mappings = MapperService.parseMapping(xContentRegistry, mappingsJson);
         // apply templates, merging the mappings into the request mapping if exists
         for (IndexTemplateMetaData template : templates) {
-            for (ObjectObjectCursor<String, CompressedXContent> cursor : template.mappings()) {
-                String mappingString = cursor.value.string();
-                // Templates are wrapped with their _type names, which for pre-8x templates may not
-                // be _doc.  For now, we unwrap them based on the _type name, and then re-wrap with
-                // _doc
-                // TODO in 9x these will all have a _type of _doc so no re-wrapping will be necessary
-                Map<String, Object> templateMapping = MapperService.parseMapping(xContentRegistry, mappingString);
+            CompressedXContent mapping = template.mappings();
+            if (mapping != null) {
+                Map<String, Object> templateMapping = MapperService.parseMapping(xContentRegistry, mapping.string());
                 assert templateMapping.size() == 1 : templateMapping;
-                assert cursor.key.equals(templateMapping.keySet().iterator().next()) : cursor.key + " != " + templateMapping;
+                // pre-8x templates may have a wrapper type other than _doc, so we re-wrap things here
                 templateMapping = Collections.singletonMap(MapperService.SINGLE_MAPPING_NAME,
                     templateMapping.values().iterator().next());
                 if (mappings.isEmpty()) {

+ 1 - 3
server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java

@@ -35,14 +35,12 @@ import org.elasticsearch.test.ESTestCase;
 import java.util.Arrays;
 import java.util.Collections;
 
-import static java.util.Collections.singletonMap;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.Matchers.contains;
 
 public class IndexTemplateMetaDataTests extends ESTestCase {
 
     public void testIndexTemplateMetaDataXContentRoundTrip() throws Exception {
-        ToXContent.Params params = new ToXContent.MapParams(singletonMap("reduce_mappings", "true"));
 
         String template = "{\"index_patterns\" : [ \".test-*\" ],\"order\" : 1000," +
             "\"settings\" : {\"number_of_shards\" : 1,\"number_of_replicas\" : 0}," +
@@ -62,7 +60,7 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
         final BytesReference templateBytesRoundTrip;
         try (XContentBuilder builder = XContentBuilder.builder(JsonXContent.jsonXContent)) {
             builder.startObject();
-            IndexTemplateMetaData.Builder.toXContentWithTypes(indexTemplateMetaData, builder, params);
+            IndexTemplateMetaData.Builder.toXContentWithTypes(indexTemplateMetaData, builder, ToXContent.EMPTY_PARAMS);
             builder.endObject();
             templateBytesRoundTrip = BytesReference.bytes(builder);
         }

+ 3 - 5
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/template/TemplateUtils.java

@@ -14,7 +14,6 @@ import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.bytes.BytesReference;
-import org.elasticsearch.common.collect.ImmutableOpenMap;
 import org.elasticsearch.common.compress.CompressedXContent;
 import org.elasticsearch.common.io.Streams;
 import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
@@ -161,14 +160,13 @@ public class TemplateUtils {
         if (templateMeta == null) {
             return false;
         }
-        ImmutableOpenMap<String, CompressedXContent> mappings = templateMeta.getMappings();
+        CompressedXContent mappings = templateMeta.getMappings();
         // check all mappings contain correct version in _meta
         // we have to parse the source here which is annoying
-        for (Object typeMapping : mappings.values().toArray()) {
-            CompressedXContent typeMappingXContent = (CompressedXContent) typeMapping;
+        if (mappings != null) {
             try {
                 Map<String, Object> typeMappingMap = convertToMap(
-                    new BytesArray(typeMappingXContent.uncompressed()), false,
+                    new BytesArray(mappings.uncompressed()), false,
                     XContentType.JSON).v2();
                 // should always contain one entry with key = typename
                 assert (typeMappingMap.size() == 1);

+ 1 - 3
x-pack/plugin/logstash/src/main/java/org/elasticsearch/xpack/logstash/Logstash.java

@@ -11,7 +11,6 @@ import org.elasticsearch.action.ActionRequest;
 import org.elasticsearch.action.ActionResponse;
 import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.index.mapper.MapperService;
 import org.elasticsearch.indices.SystemIndexDescriptor;
 import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.plugins.SystemIndexPlugin;
@@ -56,8 +55,7 @@ public class Logstash extends Plugin implements SystemIndexPlugin {
             templates.keySet().removeIf(OLD_LOGSTASH_INDEX_NAME::equals);
             TemplateUtils.loadTemplateIntoMap("/" + LOGSTASH_TEMPLATE_FILE_NAME + ".json", templates, LOGSTASH_INDEX_TEMPLATE_NAME,
                     Version.CURRENT.toString(), TEMPLATE_VERSION_VARIABLE, LogManager.getLogger(Logstash.class));
-            //internal representation of typeless templates requires the default "_doc" type, which is also required for internal templates
-            assert templates.get(LOGSTASH_INDEX_TEMPLATE_NAME).mappings().get(MapperService.SINGLE_MAPPING_NAME) != null;
+            assert templates.get(LOGSTASH_INDEX_TEMPLATE_NAME).mappings() != null;
             return templates;
         };
     }

+ 1 - 1
x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterResourceIntegTests.java

@@ -194,7 +194,7 @@ public class LocalExporterResourceIntegTests extends LocalExporterIntegTestCase
         final String name = MonitoringTemplateUtils.templateName(system.getSystem());
 
         for (IndexTemplateMetaData template : client().admin().indices().prepareGetTemplates(name).get().getIndexTemplates()) {
-            final String docMapping = template.getMappings().get("_doc").toString();
+            final String docMapping = template.getMappings().toString();
 
             assertThat(docMapping, notNullValue());
             assertThat(docMapping, containsString("test"));

+ 2 - 2
x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/persistence/TransformInternalIndex.java

@@ -362,7 +362,7 @@ public final class TransformInternalIndex {
         // Installing the template involves communication with the master node, so it's more expensive but much rarer
         try {
             IndexTemplateMetaData indexTemplateMetaData = getIndexTemplateMetaData();
-            BytesReference jsonMappings = new BytesArray(indexTemplateMetaData.mappings().get(SINGLE_MAPPING_NAME).uncompressed());
+            BytesReference jsonMappings = new BytesArray(indexTemplateMetaData.mappings().uncompressed());
             PutIndexTemplateRequest request = new PutIndexTemplateRequest(TransformInternalIndexConstants.LATEST_INDEX_VERSIONED_NAME)
                 .patterns(indexTemplateMetaData.patterns())
                 .version(indexTemplateMetaData.version())
@@ -396,7 +396,7 @@ public final class TransformInternalIndex {
         // Installing the template involves communication with the master node, so it's more expensive but much rarer
         try {
             IndexTemplateMetaData indexTemplateMetaData = getAuditIndexTemplateMetaData();
-            BytesReference jsonMappings = new BytesArray(indexTemplateMetaData.mappings().get(SINGLE_MAPPING_NAME).uncompressed());
+            BytesReference jsonMappings = new BytesArray(indexTemplateMetaData.mappings().uncompressed());
             PutIndexTemplateRequest request = new PutIndexTemplateRequest(TransformInternalIndexConstants.AUDIT_INDEX).patterns(
                 indexTemplateMetaData.patterns()
             )