Browse Source

Revert "Clean up IndexTemplateMetaData xcontent serialization (#54003)"

This reverts commit 04c21affcf6b2215f22a690223ba1e520d3c6f9b.
Alan Woodward 5 years ago
parent
commit
8ee2ee529f

+ 6 - 1
server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java

@@ -22,6 +22,7 @@ import org.elasticsearch.action.ActionResponse;
 import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
 import org.elasticsearch.common.io.stream.StreamInput;
 import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.xcontent.ToXContent;
 import org.elasticsearch.common.xcontent.ToXContentObject;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 
@@ -30,6 +31,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
+import static java.util.Collections.singletonMap;
+
 public class GetIndexTemplatesResponse extends ActionResponse implements ToXContentObject {
 
     private final List<IndexTemplateMetaData> indexTemplates;
@@ -74,9 +77,11 @@ public class GetIndexTemplatesResponse extends ActionResponse implements ToXCont
 
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+        params = new ToXContent.DelegatingMapParams(singletonMap("reduce_mappings", "true"), params);
+
         builder.startObject();
         for (IndexTemplateMetaData indexTemplateMetaData : getIndexTemplates()) {
-            indexTemplateMetaData.toXContent(builder, params);
+            IndexTemplateMetaData.Builder.toXContent(indexTemplateMetaData, builder, params);
         }
         builder.endObject();
         return builder;

+ 2 - 3
server/src/main/java/org/elasticsearch/cluster/ClusterState.java

@@ -53,7 +53,6 @@ import org.elasticsearch.common.io.stream.StreamInput;
 import org.elasticsearch.common.io.stream.StreamOutput;
 import org.elasticsearch.common.io.stream.VersionedNamedWriteable;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.xcontent.ToXContent;
 import org.elasticsearch.common.xcontent.ToXContentFragment;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentHelper;
@@ -427,10 +426,10 @@ public class ClusterState implements ToXContentFragment, Diffable<ClusterState>
             coordinationMetaData().toXContent(builder, params);
             builder.endObject();
 
-            ToXContent.Params templateParams = new DelegatingMapParams(Map.of(IndexTemplateMetaData.INCLUDE_TYPE_NAME, "true"), params);
             builder.startObject("templates");
             for (ObjectCursor<IndexTemplateMetaData> cursor : metaData().templates().values()) {
-                cursor.value.toXContent(builder, templateParams);
+                IndexTemplateMetaData templateMetaData = cursor.value;
+                IndexTemplateMetaData.Builder.toXContentWithTypes(templateMetaData, builder, params);
             }
             builder.endObject();
 

+ 163 - 90
server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java

@@ -20,37 +20,36 @@ package org.elasticsearch.cluster.metadata;
 
 import com.carrotsearch.hppc.cursors.ObjectCursor;
 import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
+import org.elasticsearch.ElasticsearchParseException;
 import org.elasticsearch.cluster.AbstractDiffable;
 import org.elasticsearch.cluster.Diff;
 import org.elasticsearch.common.Nullable;
-import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.collect.ImmutableOpenMap;
+import org.elasticsearch.common.collect.MapBuilder;
 import org.elasticsearch.common.compress.CompressedXContent;
 import org.elasticsearch.common.io.stream.StreamInput;
 import org.elasticsearch.common.io.stream.StreamOutput;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.util.set.Sets;
-import org.elasticsearch.common.xcontent.ObjectParser;
 import org.elasticsearch.common.xcontent.ToXContent;
-import org.elasticsearch.common.xcontent.ToXContentFragment;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
 import org.elasticsearch.common.xcontent.XContentHelper;
-import org.elasticsearch.common.xcontent.XContentParseException;
 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;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
-public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaData> implements ToXContentFragment {
+public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaData> {
 
     private final String name;
 
@@ -229,7 +228,9 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
     public String toString() {
         try {
             XContentBuilder builder = JsonXContent.contentBuilder();
-            this.toXContent(builder, ToXContent.EMPTY_PARAMS);
+            builder.startObject();
+            IndexTemplateMetaData.Builder.toXContentWithTypes(this, builder, ToXContent.EMPTY_PARAMS);
+            builder.endObject();
             return Strings.toString(builder);
         } catch (IOException e) {
             throw new UncheckedIOException(e);
@@ -318,113 +319,185 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
             return this;
         }
 
-        public void putAliases(List<AliasMetaData> aliases) {
-            for (AliasMetaData alias : aliases) {
-                putAlias(alias);
-            }
-        }
-
         public IndexTemplateMetaData build() {
             return new IndexTemplateMetaData(name, order, version, indexPatterns, settings, mappings.build(), aliases.build());
         }
 
-    }
-
-    public static final String INCLUDE_TYPE_NAME = "include_type_name";
-    public static final String INCLUDE_TEMPLATE_NAME = "include_template_name";
-
-    @Override
-    public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
-
-        boolean includeTypeName = params.paramAsBoolean(INCLUDE_TYPE_NAME, false);
-        boolean includeTemplateName = params.paramAsBoolean(INCLUDE_TEMPLATE_NAME, true);
+        /**
+         * Serializes the template to xContent, using the legacy format where the mappings are
+         * nested under the type name.
+         *
+         * This method is used for serializing templates before storing them in the cluster metadata,
+         * and also in the REST layer when returning a deprecated typed response.
+         */
+        public static void toXContentWithTypes(IndexTemplateMetaData indexTemplateMetaData,
+                                               XContentBuilder builder,
+                                               ToXContent.Params params) throws IOException {
+            builder.startObject(indexTemplateMetaData.name());
+            toInnerXContent(indexTemplateMetaData, builder, params, true);
+            builder.endObject();
+        }
 
-        if (includeTemplateName) {
-            builder.startObject(this.name());
+        /**
+         * Removes the nested type in the xContent representation of {@link IndexTemplateMetaData}.
+         *
+         * This method is useful to help bridge the gap between an the internal representation which still uses (the legacy format) a
+         * nested type in the mapping, and the external representation which does not use a nested type in the mapping.
+         */
+        public static void removeType(IndexTemplateMetaData indexTemplateMetaData, XContentBuilder builder) throws IOException {
+            builder.startObject();
+            toInnerXContent(indexTemplateMetaData, builder,
+                new ToXContent.MapParams(Collections.singletonMap("reduce_mappings", "true")), false);
+            builder.endObject();
         }
 
-        builder.field("order", this.order());
-        if (this.version() != null) {
-            builder.field("version", this.version());
+        /**
+         * Serializes the template to xContent, making sure not to nest mappings under the
+         * type name.
+         *
+         * Note that this method should currently only be used for creating REST responses,
+         * and not when directly updating stored templates. Index templates are still stored
+         * in the old, typed format, and have yet to be migrated to be typeless.
+         */
+        public static void toXContent(IndexTemplateMetaData indexTemplateMetaData,
+                                      XContentBuilder builder,
+                                      ToXContent.Params params) throws IOException {
+            builder.startObject(indexTemplateMetaData.name());
+            toInnerXContent(indexTemplateMetaData, builder, params, false);
+            builder.endObject();
         }
-        builder.field("index_patterns", this.patterns());
 
-        builder.startObject("settings");
-        this.settings().toXContent(builder, params);
-        builder.endObject();
 
-        CompressedXContent m = this.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.startObject("mappings").endObject();
+        static void toInnerXContentWithTypes(IndexTemplateMetaData indexTemplateMetaData,
+                                             XContentBuilder builder,
+                                             ToXContent.Params params) throws IOException {
+            toInnerXContent(indexTemplateMetaData, builder, params, true);
         }
 
-        builder.startObject("aliases");
-        for (ObjectCursor<AliasMetaData> cursor : this.aliases().values()) {
-            AliasMetaData.Builder.toXContent(cursor.value, builder, params);
-        }
-        builder.endObject();
+        private static void toInnerXContent(IndexTemplateMetaData indexTemplateMetaData,
+                                            XContentBuilder builder,
+                                            ToXContent.Params params,
+                                            boolean includeTypeName) throws IOException {
 
-        if (includeTemplateName) {
-            builder.endObject();
-        }
+            builder.field("order", indexTemplateMetaData.order());
+            if (indexTemplateMetaData.version() != null) {
+                builder.field("version", indexTemplateMetaData.version());
+            }
+            builder.field("index_patterns", indexTemplateMetaData.patterns());
 
-        return builder;
-    }
+            builder.startObject("settings");
+            indexTemplateMetaData.settings().toXContent(builder, params);
+            builder.endObject();
 
-    @SuppressWarnings("unchecked")
-    private static Map<String, Object> reduceMapping(Map<String, Object> mapping) {
-        assert mapping.keySet().size() == 1;
-        return (Map<String, Object>) mapping.values().iterator().next();
-    }
+            includeTypeName &= (params.paramAsBoolean("reduce_mappings", false) == false);
 
-    private static final ObjectParser<Builder, String> PARSER = ObjectParser.fromBuilder("index_template", Builder::new);
+            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.startObject("mappings").endObject();
+            }
 
-    static {
-        PARSER.declareObject(Builder::settings,
-            (p, c) -> Settings.builder().put(Settings.fromXContent(p)).normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX).build(),
-            new ParseField("settings"));
-        PARSER.declareObject((builder, map) -> {
-            if (map.isEmpty() == false) {
-                String type = map.keySet().iterator().next();
-                builder.putMapping(type, map.get(type));
+            builder.startObject("aliases");
+            for (ObjectCursor<AliasMetaData> cursor : indexTemplateMetaData.aliases().values()) {
+                AliasMetaData.Builder.toXContent(cursor.value, builder, params);
             }
-        }, (p, c) -> parseMappings(p), new ParseField("mappings"));
-        PARSER.declareNamedObjects(Builder::putAliases, (p, c, n) -> AliasMetaData.Builder.fromXContent(p), new ParseField("aliases"));
-        PARSER.declareStringArray(Builder::patterns, new ParseField("index_patterns"));
-        PARSER.declareInt(Builder::order, new ParseField("order"));
-        PARSER.declareInt(Builder::version, new ParseField("version"));
-    }
+            builder.endObject();
+        }
 
-    // TODO it would be really nice if we could just copy bytes here, there's no need to parse and then
-    // re-stream the mappings
-    private static Map<String, CompressedXContent> parseMappings(XContentParser parser) throws IOException {
-        String mappingType = null;
-        String mappings = null;
-        while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
-            if (parser.currentToken() == XContentParser.Token.FIELD_NAME) {
-                mappingType = parser.currentName();
-            } else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
-                if (mappingType == null) {
-                    throw new XContentParseException(parser.getTokenLocation(), "Expected a mapping type");
+        @SuppressWarnings("unchecked")
+        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 {
+            Builder builder = new Builder(templateName);
+
+            String currentFieldName = skipTemplateName(parser);
+            XContentParser.Token token;
+            while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
+                if (token == XContentParser.Token.FIELD_NAME) {
+                    currentFieldName = parser.currentName();
+                } else if (token == XContentParser.Token.START_OBJECT) {
+                    if ("settings".equals(currentFieldName)) {
+                        Settings.Builder templateSettingsBuilder = Settings.builder();
+                        templateSettingsBuilder.put(Settings.fromXContent(parser));
+                        templateSettingsBuilder.normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX);
+                        builder.settings(templateSettingsBuilder.build());
+                    } else if ("mappings".equals(currentFieldName)) {
+                        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
+                            if (token == XContentParser.Token.FIELD_NAME) {
+                                currentFieldName = parser.currentName();
+                            } else if (token == XContentParser.Token.START_OBJECT) {
+                                String mappingType = currentFieldName;
+                                Map<String, Object> mappingSource =
+                                    MapBuilder.<String, Object>newMapBuilder().put(mappingType, parser.mapOrdered()).map();
+                                builder.putMapping(mappingType, Strings.toString(XContentFactory.jsonBuilder().map(mappingSource)));
+                            }
+                        }
+                    } else if ("aliases".equals(currentFieldName)) {
+                        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
+                            builder.putAlias(AliasMetaData.Builder.fromXContent(parser));
+                        }
+                    } else {
+                        throw new ElasticsearchParseException("unknown key [{}] for index template", currentFieldName);
+                    }
+                } else if (token == XContentParser.Token.START_ARRAY) {
+                    if ("mappings".equals(currentFieldName)) {
+                        while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
+                            Map<String, Object> mapping = parser.mapOrdered();
+                            if (mapping.size() == 1) {
+                                String mappingType = mapping.keySet().iterator().next();
+                                String mappingSource = Strings.toString(XContentFactory.jsonBuilder().map(mapping));
+
+                                if (mappingSource == null) {
+                                    // crap, no mapping source, warn?
+                                } else {
+                                    builder.putMapping(mappingType, mappingSource);
+                                }
+                            }
+                        }
+                    } else if ("index_patterns".equals(currentFieldName)) {
+                        List<String> index_patterns = new ArrayList<>();
+                        while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
+                            index_patterns.add(parser.text());
+                        }
+                        builder.patterns(index_patterns);
+                    }
+                } else if (token.isValue()) {
+                    if ("order".equals(currentFieldName)) {
+                        builder.order(parser.intValue());
+                    } else if ("version".equals(currentFieldName)) {
+                        builder.version(parser.intValue());
+                    }
                 }
-                mappings = Strings.toString(XContentFactory.jsonBuilder().map(Map.of(mappingType, parser.mapOrdered())));
             }
+            return builder.build();
         }
-        if (mappings == null) {
-            return Collections.emptyMap();
-        }
-        return Map.of(mappingType, new CompressedXContent(mappings));
-    }
 
-    public static IndexTemplateMetaData fromXContent(XContentParser parser, String templateName) throws IOException {
-        return PARSER.parse(parser, templateName).build();
+        private static String skipTemplateName(XContentParser parser) throws IOException {
+            XContentParser.Token token = parser.nextToken();
+            if (token == XContentParser.Token.START_OBJECT) {
+                token = parser.nextToken();
+                if (token == XContentParser.Token.FIELD_NAME) {
+                    String currentFieldName = parser.currentName();
+                    if (VALID_FIELDS.contains(currentFieldName)) {
+                        return currentFieldName;
+                    } else {
+                        // we just hit the template name, which should be ignored and we move on
+                        parser.nextToken();
+                    }
+                }
+            }
+
+            return null;
+        }
     }
 
 }

+ 2 - 4
server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java

@@ -1404,11 +1404,9 @@ public class MetaData implements Iterable<IndexMetaData>, Diffable<MetaData>, To
                 builder.endObject();
             }
 
-            ToXContent.Params typedParams
-                = new ToXContent.DelegatingMapParams(Map.of(IndexTemplateMetaData.INCLUDE_TYPE_NAME, "true"), params);
             builder.startObject("templates");
             for (ObjectCursor<IndexTemplateMetaData> cursor : metaData.templates().values()) {
-                cursor.value.toXContent(builder, typedParams);
+                IndexTemplateMetaData.Builder.toXContentWithTypes(cursor.value, builder, params);
             }
             builder.endObject();
 
@@ -1473,7 +1471,7 @@ public class MetaData implements Iterable<IndexMetaData>, Diffable<MetaData>, To
                         builder.hashesOfConsistentSettings(parser.mapStrings());
                     } else if ("templates".equals(currentFieldName)) {
                         while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
-                            builder.put(IndexTemplateMetaData.fromXContent(parser, parser.currentName()));
+                            builder.put(IndexTemplateMetaData.Builder.fromXContent(parser, parser.currentName()));
                         }
                     } else {
                         try {

+ 7 - 3
server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java

@@ -57,6 +57,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.UnaryOperator;
 
+import static java.util.Collections.singletonMap;
+
 /**
  * Upgrades Templates on behalf of installed {@link Plugin}s when a node joins the cluster
  */
@@ -246,12 +248,14 @@ public class TemplateUpgradeService implements ClusterStateListener {
         return Optional.empty();
     }
 
-    private static final ToXContent.Params PARAMS
-        = new ToXContent.MapParams(Map.of(IndexTemplateMetaData.INCLUDE_TEMPLATE_NAME, "false"));
+    private static final ToXContent.Params PARAMS = new ToXContent.MapParams(singletonMap("reduce_mappings", "true"));
 
     private BytesReference toBytesReference(IndexTemplateMetaData templateMetaData) {
         try {
-            return XContentHelper.toXContent(templateMetaData, XContentType.JSON, PARAMS, false);
+            return XContentHelper.toXContent((builder, params) -> {
+                IndexTemplateMetaData.Builder.toInnerXContentWithTypes(templateMetaData, builder, params);
+                return builder;
+            }, XContentType.JSON, PARAMS, false);
         } catch (IOException ex) {
             throw new IllegalStateException("Cannot serialize template [" + templateMetaData.getName() + "]", ex);
         }

+ 8 - 13
server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java

@@ -34,7 +34,6 @@ import org.elasticsearch.test.ESTestCase;
 
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.Matchers.contains;
@@ -55,15 +54,13 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
         final IndexTemplateMetaData indexTemplateMetaData;
         try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY,
             DeprecationHandler.THROW_UNSUPPORTED_OPERATION, templateBytes, XContentType.JSON)) {
-            indexTemplateMetaData = IndexTemplateMetaData.fromXContent(parser, "test");
+            indexTemplateMetaData = IndexTemplateMetaData.Builder.fromXContent(parser, "test");
         }
 
         final BytesReference templateBytesRoundTrip;
-        final ToXContent.Params params = new ToXContent.MapParams(
-            Map.of(IndexTemplateMetaData.INCLUDE_TYPE_NAME, "true", IndexTemplateMetaData.INCLUDE_TEMPLATE_NAME, "false"));
         try (XContentBuilder builder = XContentBuilder.builder(JsonXContent.jsonXContent)) {
             builder.startObject();
-            indexTemplateMetaData.toXContent(builder, params);
+            IndexTemplateMetaData.Builder.toXContentWithTypes(indexTemplateMetaData, builder, ToXContent.EMPTY_PARAMS);
             builder.endObject();
             templateBytesRoundTrip = BytesReference.bytes(builder);
         }
@@ -71,7 +68,7 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
         final IndexTemplateMetaData indexTemplateMetaDataRoundTrip;
         try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY,
             DeprecationHandler.THROW_UNSUPPORTED_OPERATION, templateBytesRoundTrip, XContentType.JSON)) {
-            indexTemplateMetaDataRoundTrip = IndexTemplateMetaData.fromXContent(parser, "test");
+            indexTemplateMetaDataRoundTrip = IndexTemplateMetaData.Builder.fromXContent(parser, "test");
         }
         assertThat(indexTemplateMetaData, equalTo(indexTemplateMetaDataRoundTrip));
     }
@@ -100,7 +97,7 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
                  XContentHelper.createParser(NamedXContentRegistry.EMPTY,
                      DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(templateWithEmptyPattern), XContentType.JSON)) {
             final IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
-                () -> IndexTemplateMetaData.fromXContent(parser, randomAlphaOfLengthBetween(1, 100)));
+                () -> IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100)));
             assertThat(ex.getMessage(), equalTo("Index patterns must not be null or empty; got []"));
         }
 
@@ -115,7 +112,7 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
                  XContentHelper.createParser(NamedXContentRegistry.EMPTY,
                      DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(templateWithoutPattern), XContentType.JSON)) {
             final IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
-                () -> IndexTemplateMetaData.fromXContent(parser, randomAlphaOfLengthBetween(1, 100)));
+                () -> IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100)));
             assertThat(ex.getMessage(), equalTo("Index patterns must not be null or empty; got null"));
         }
     }
@@ -125,7 +122,7 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
         try (XContentParser parser =
                  XContentHelper.createParser(NamedXContentRegistry.EMPTY,
                      DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(templateInJSON), XContentType.JSON)) {
-            IndexTemplateMetaData template = IndexTemplateMetaData.fromXContent(parser, randomAlphaOfLengthBetween(1, 100));
+            IndexTemplateMetaData template = IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100));
             assertThat(template.aliases().containsKey("log"), equalTo(true));
             assertThat(template.patterns(), contains("pattern-1"));
         }
@@ -160,14 +157,12 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
             templateBuilder.putMapping("doc", "{\"doc\":{\"properties\":{\"type\":\"text\"}}}");
         }
         IndexTemplateMetaData template = templateBuilder.build();
-        final ToXContent.Params params = new ToXContent.MapParams(
-            Map.of(IndexTemplateMetaData.INCLUDE_TYPE_NAME, "true", IndexTemplateMetaData.INCLUDE_TEMPLATE_NAME, "false"));
         XContentBuilder builder = XContentBuilder.builder(randomFrom(XContentType.JSON.xContent()));
         builder.startObject();
-        template.toXContent(builder, params);
+        IndexTemplateMetaData.Builder.toXContentWithTypes(template, builder, ToXContent.EMPTY_PARAMS);
         builder.endObject();
         try (XContentParser parser = createParser(shuffleXContent(builder))) {
-            IndexTemplateMetaData parsed = IndexTemplateMetaData.fromXContent(parser, templateName);
+            IndexTemplateMetaData parsed = IndexTemplateMetaData.Builder.fromXContent(parser, templateName);
             assertThat(parsed, equalTo(template));
         }
     }

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

@@ -47,7 +47,7 @@ public class TemplateUtils {
         final String template = loadTemplate(resource, version, versionProperty);
         try (XContentParser parser = XContentFactory.xContent(XContentType.JSON)
                 .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, template)) {
-            map.put(templateName, IndexTemplateMetaData.fromXContent(parser, templateName));
+            map.put(templateName, IndexTemplateMetaData.Builder.fromXContent(parser, templateName));
         } catch (IOException e) {
             // TODO: should we handle this with a thrown exception?
             logger.error("Error loading template [{}] as part of metadata upgrading", templateName);

+ 1 - 5
x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/TemplateHttpResource.java

@@ -18,7 +18,6 @@ import org.elasticsearch.common.bytes.BytesReference;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
 import org.elasticsearch.common.xcontent.NamedXContentRegistry;
-import org.elasticsearch.common.xcontent.ToXContent;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
 import org.elasticsearch.common.xcontent.XContentParser;
@@ -108,13 +107,10 @@ public class TemplateHttpResource extends PublishableHttpResource {
      HttpEntity templateToHttpEntity() {
         // the internal representation of a template has type nested under mappings.
         // this uses xContent to help remove the type before sending to the remote cluster
-        ToXContent.Params params = new ToXContent.MapParams(Map.of(IndexTemplateMetaData.INCLUDE_TEMPLATE_NAME, "false"));
         try (XContentParser parser = XContentFactory.xContent(XContentType.JSON)
             .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, template.get())) {
             XContentBuilder builder = JsonXContent.contentBuilder();
-            builder.startObject();
-            IndexTemplateMetaData.fromXContent(parser, templateName).toXContent(builder, params);
-            builder.endObject();
+            IndexTemplateMetaData.Builder.removeType(IndexTemplateMetaData.Builder.fromXContent(parser, templateName), builder);
             return new StringEntity(BytesReference.bytes(builder).utf8ToString(), ContentType.APPLICATION_JSON);
         } catch (IOException ex) {
             throw new IllegalStateException("Cannot serialize template [" + templateName + "] for monitoring export", ex);

+ 1 - 5
x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java

@@ -26,7 +26,6 @@ import org.elasticsearch.common.time.DateFormatter;
 import org.elasticsearch.common.util.concurrent.ThreadContext;
 import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
 import org.elasticsearch.common.xcontent.NamedXContentRegistry;
-import org.elasticsearch.common.xcontent.ToXContent;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
 import org.elasticsearch.common.xcontent.XContentHelper;
@@ -972,10 +971,7 @@ public class HttpExporterIT extends MonitoringIntegTestCase {
         try (XContentParser parser = XContentFactory.xContent(XContentType.JSON)
             .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, internalRepresentation)) {
             XContentBuilder builder = JsonXContent.contentBuilder();
-            ToXContent.Params params = new ToXContent.MapParams(Map.of(IndexTemplateMetaData.INCLUDE_TEMPLATE_NAME, "false"));
-            builder.startObject();
-            IndexTemplateMetaData.fromXContent(parser, "").toXContent(builder, params);
-            builder.endObject();
+            IndexTemplateMetaData.Builder.removeType(IndexTemplateMetaData.Builder.fromXContent(parser, ""), builder);
             return BytesReference.bytes(builder).utf8ToString();
         }
     }