diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java index a726f4e108d7c..c1fa7d7ffafc2 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java @@ -22,7 +22,6 @@ 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; @@ -31,8 +30,6 @@ import java.util.List; import java.util.Objects; -import static java.util.Collections.singletonMap; - public class GetIndexTemplatesResponse extends ActionResponse implements ToXContentObject { private final List indexTemplates; @@ -77,11 +74,9 @@ public int hashCode() { @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.Builder.toXContent(indexTemplateMetaData, builder, params); + indexTemplateMetaData.toXContent(builder, params); } builder.endObject(); return builder; diff --git a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java index f7ea8a68283bb..f831207e2f0dd 100644 --- a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java +++ b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java @@ -53,6 +53,7 @@ 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; @@ -426,10 +427,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws coordinationMetaData().toXContent(builder, params); builder.endObject(); + ToXContent.Params templateParams = new DelegatingMapParams(Map.of(IndexTemplateMetaData.INCLUDE_TYPE_NAME, "true"), params); builder.startObject("templates"); for (ObjectCursor cursor : metaData().templates().values()) { - IndexTemplateMetaData templateMetaData = cursor.value; - IndexTemplateMetaData.Builder.toXContentWithTypes(templateMetaData, builder, params); + cursor.value.toXContent(builder, templateParams); } builder.endObject(); diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java index 4d2db27a4a840..aca857021ee8f 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java @@ -20,36 +20,38 @@ 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.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -public class IndexTemplateMetaData extends AbstractDiffable { +public class IndexTemplateMetaData extends AbstractDiffable implements ToXContentFragment { private final String name; @@ -228,9 +230,7 @@ public void writeTo(StreamOutput out) throws IOException { public String toString() { try { XContentBuilder builder = JsonXContent.contentBuilder(); - builder.startObject(); - IndexTemplateMetaData.Builder.toXContentWithTypes(this, builder, ToXContent.EMPTY_PARAMS); - builder.endObject(); + this.toXContent(builder, ToXContent.EMPTY_PARAMS); return Strings.toString(builder); } catch (IOException e) { throw new UncheckedIOException(e); @@ -319,185 +319,132 @@ public Builder putAlias(AliasMetaData.Builder aliasMetaData) { return this; } + public void putAliases(List aliases) { + for (AliasMetaData alias : aliases) { + putAlias(alias); + } + } + public IndexTemplateMetaData build() { return new IndexTemplateMetaData(name, order, version, indexPatterns, settings, mappings.build(), aliases.build()); } - /** - * 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(); - } + } - /** - * 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(); - } + public static final String INCLUDE_TYPE_NAME = "include_type_name"; + public static final String INCLUDE_TEMPLATE_NAME = "include_template_name"; - /** - * 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(); - } + @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); + + if (includeTemplateName) { + builder.startObject(this.name()); + } - static void toInnerXContentWithTypes(IndexTemplateMetaData indexTemplateMetaData, - XContentBuilder builder, - ToXContent.Params params) throws IOException { - toInnerXContent(indexTemplateMetaData, builder, params, true); + builder.field("order", this.order()); + if (this.version() != null) { + builder.field("version", this.version()); } + builder.field("index_patterns", this.patterns()); - private static void toInnerXContent(IndexTemplateMetaData indexTemplateMetaData, - XContentBuilder builder, - ToXContent.Params params, - boolean includeTypeName) throws IOException { + builder.startObject("settings"); + this.settings().toXContent(builder, params); + builder.endObject(); - builder.field("order", indexTemplateMetaData.order()); - if (indexTemplateMetaData.version() != null) { - builder.field("version", indexTemplateMetaData.version()); + CompressedXContent m = this.mappings(); + if (m != null) { + Map documentMapping = XContentHelper.convertToMap(new BytesArray(m.uncompressed()), true).v2(); + if (includeTypeName == false) { + documentMapping = reduceMapping(documentMapping); } - builder.field("index_patterns", indexTemplateMetaData.patterns()); + builder.field("mappings"); + builder.map(documentMapping); + } else { + builder.startObject("mappings").endObject(); + } + + builder.startObject("aliases"); + for (ObjectCursor cursor : this.aliases().values()) { + AliasMetaData.Builder.toXContent(cursor.value, builder, params); + } + builder.endObject(); - builder.startObject("settings"); - indexTemplateMetaData.settings().toXContent(builder, params); + if (includeTemplateName) { builder.endObject(); + } - includeTypeName &= (params.paramAsBoolean("reduce_mappings", false) == false); + return builder; + } + + @SuppressWarnings("unchecked") + private static Map reduceMapping(Map mapping) { + assert mapping.keySet().size() == 1; + return (Map) mapping.values().iterator().next(); + } - CompressedXContent m = indexTemplateMetaData.mappings(); - if (m != null) { - Map documentMapping = XContentHelper.convertToMap(new BytesArray(m.uncompressed()), true).v2(); - if (includeTypeName == false) { - documentMapping = reduceMapping(documentMapping); + private static final ObjectParser PARSER = ObjectParser.fromBuilder("index_template", Builder::new); + + static { + PARSER.declareObject(Builder::settings, + (p, c) -> Settings.builder().put(Settings.fromXContent(p)).normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX).build(), + new ParseField("settings")); + PARSER.declareField((builder, map) -> { + if (map.isEmpty() == false) { + for (String type : map.keySet()) { + builder.putMapping(type, map.get(type)); } - builder.field("mappings"); - builder.map(documentMapping); - } else { - builder.startObject("mappings").endObject(); } + }, (p, c) -> parsePossibleMappingArray(p), new ParseField("mappings"), ObjectParser.ValueType.OBJECT_ARRAY); + 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.startObject("aliases"); - for (ObjectCursor cursor : indexTemplateMetaData.aliases().values()) { - AliasMetaData.Builder.toXContent(cursor.value, builder, params); + /** + * Before the removal of mapping types (eg in {@link org.elasticsearch.Version#V_7_0_0}) + * multiple mappings could be emitted in an array. This will no longer apply when BWC with + * 7x nodes is not required. + */ + private static Map parsePossibleMappingArray(XContentParser parser) throws IOException { + if (parser.currentToken() == XContentParser.Token.START_ARRAY) { + Map mappings = new HashMap<>(); + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + mappings.putAll(parseMappings(parser)); } - builder.endObject(); + return mappings; } - - @SuppressWarnings("unchecked") - private static Map reduceMapping(Map mapping) { - assert mapping.keySet().size() == 1; - return (Map) mapping.values().iterator().next(); + else { + return parseMappings(parser); } + } - 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 mappingSource = - MapBuilder.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 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 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()); - } + // 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 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"); } + mappings = Strings.toString(XContentFactory.jsonBuilder().map(Map.of(mappingType, parser.mapOrdered()))); } - return builder.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; + 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(); } } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java index 8471364b07dea..06c6eb86784de 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java @@ -1372,9 +1372,11 @@ public static void toXContent(MetaData metaData, XContentBuilder builder, ToXCon builder.endObject(); } + ToXContent.Params typedParams + = new ToXContent.DelegatingMapParams(Map.of(IndexTemplateMetaData.INCLUDE_TYPE_NAME, "true"), params); builder.startObject("templates"); for (ObjectCursor cursor : metaData.templates().values()) { - IndexTemplateMetaData.Builder.toXContentWithTypes(cursor.value, builder, params); + cursor.value.toXContent(builder, typedParams); } builder.endObject(); @@ -1439,7 +1441,7 @@ public static MetaData fromXContent(XContentParser parser, boolean preserveUnkno builder.hashesOfConsistentSettings(parser.mapStrings()); } else if ("templates".equals(currentFieldName)) { while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - builder.put(IndexTemplateMetaData.Builder.fromXContent(parser, parser.currentName())); + builder.put(IndexTemplateMetaData.fromXContent(parser, parser.currentName())); } } else { try { diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java index deb04067acb9a..4b595ad14fc2f 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java @@ -57,8 +57,6 @@ 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 */ @@ -248,14 +246,12 @@ Optional, Set>> calculateTemplateChang return Optional.empty(); } - private static final ToXContent.Params PARAMS = new ToXContent.MapParams(singletonMap("reduce_mappings", "true")); + private static final ToXContent.Params PARAMS + = new ToXContent.MapParams(Map.of(IndexTemplateMetaData.INCLUDE_TEMPLATE_NAME, "false")); private BytesReference toBytesReference(IndexTemplateMetaData templateMetaData) { try { - return XContentHelper.toXContent((builder, params) -> { - IndexTemplateMetaData.Builder.toInnerXContentWithTypes(templateMetaData, builder, params); - return builder; - }, XContentType.JSON, PARAMS, false); + return XContentHelper.toXContent(templateMetaData, XContentType.JSON, PARAMS, false); } catch (IOException ex) { throw new IllegalStateException("Cannot serialize template [" + templateMetaData.getName() + "]", ex); } diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java index 49e886c1d4745..8249877290639 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java @@ -34,6 +34,7 @@ import java.util.Arrays; import java.util.Collections; +import java.util.Map; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.contains; @@ -54,13 +55,15 @@ public void testIndexTemplateMetaDataXContentRoundTrip() throws Exception { final IndexTemplateMetaData indexTemplateMetaData; try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, templateBytes, XContentType.JSON)) { - indexTemplateMetaData = IndexTemplateMetaData.Builder.fromXContent(parser, "test"); + indexTemplateMetaData = IndexTemplateMetaData.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.Builder.toXContentWithTypes(indexTemplateMetaData, builder, ToXContent.EMPTY_PARAMS); + indexTemplateMetaData.toXContent(builder, params); builder.endObject(); templateBytesRoundTrip = BytesReference.bytes(builder); } @@ -68,7 +71,7 @@ public void testIndexTemplateMetaDataXContentRoundTrip() throws Exception { final IndexTemplateMetaData indexTemplateMetaDataRoundTrip; try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, templateBytesRoundTrip, XContentType.JSON)) { - indexTemplateMetaDataRoundTrip = IndexTemplateMetaData.Builder.fromXContent(parser, "test"); + indexTemplateMetaDataRoundTrip = IndexTemplateMetaData.fromXContent(parser, "test"); } assertThat(indexTemplateMetaData, equalTo(indexTemplateMetaDataRoundTrip)); } @@ -97,7 +100,7 @@ public void testValidateInvalidIndexPatterns() throws Exception { XContentHelper.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(templateWithEmptyPattern), XContentType.JSON)) { final IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, - () -> IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100))); + () -> IndexTemplateMetaData.fromXContent(parser, randomAlphaOfLengthBetween(1, 100))); assertThat(ex.getMessage(), equalTo("Index patterns must not be null or empty; got []")); } @@ -112,7 +115,7 @@ DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(templateWithEmpty XContentHelper.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(templateWithoutPattern), XContentType.JSON)) { final IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, - () -> IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100))); + () -> IndexTemplateMetaData.fromXContent(parser, randomAlphaOfLengthBetween(1, 100))); assertThat(ex.getMessage(), equalTo("Index patterns must not be null or empty; got null")); } } @@ -122,12 +125,21 @@ public void testParseTemplateWithAliases() throws Exception { try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(templateInJSON), XContentType.JSON)) { - IndexTemplateMetaData template = IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100)); + IndexTemplateMetaData template = IndexTemplateMetaData.fromXContent(parser, randomAlphaOfLengthBetween(1, 100)); assertThat(template.aliases().containsKey("log"), equalTo(true)); assertThat(template.patterns(), contains("pattern-1")); } } + public void testXContentFromV7Nodes() throws Exception { + String json = "{\"mappings\":[{\"_doc\":{}}], \"index_patterns\": [\"pattern-1\"]}"; + try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY, + DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(json), XContentType.JSON)) { + IndexTemplateMetaData template = IndexTemplateMetaData.fromXContent(parser, ""); + assertNotNull(template.mappings()); + } + } + public void testFromToXContent() throws Exception { String templateName = randomUnicodeOfCodepointLengthBetween(1, 10); IndexTemplateMetaData.Builder templateBuilder = IndexTemplateMetaData.builder(templateName); @@ -157,12 +169,14 @@ public void testFromToXContent() throws Exception { 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(); - IndexTemplateMetaData.Builder.toXContentWithTypes(template, builder, ToXContent.EMPTY_PARAMS); + template.toXContent(builder, params); builder.endObject(); try (XContentParser parser = createParser(shuffleXContent(builder))) { - IndexTemplateMetaData parsed = IndexTemplateMetaData.Builder.fromXContent(parser, templateName); + IndexTemplateMetaData parsed = IndexTemplateMetaData.fromXContent(parser, templateName); assertThat(parsed, equalTo(template)); } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/template/TemplateUtils.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/template/TemplateUtils.java index 19140d9c011c4..cccad052c16b3 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/template/TemplateUtils.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/template/TemplateUtils.java @@ -47,7 +47,7 @@ public static void loadTemplateIntoMap(String resource, Map 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(); - IndexTemplateMetaData.Builder.removeType(IndexTemplateMetaData.Builder.fromXContent(parser, templateName), builder); + builder.startObject(); + IndexTemplateMetaData.fromXContent(parser, templateName).toXContent(builder, params); + builder.endObject(); return new StringEntity(BytesReference.bytes(builder).utf8ToString(), ContentType.APPLICATION_JSON); } catch (IOException ex) { throw new IllegalStateException("Cannot serialize template [" + templateName + "] for monitoring export", ex); diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java index f1a3501487c06..d21dc2ac62995 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java @@ -26,6 +26,7 @@ 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; @@ -971,7 +972,10 @@ private String getExternalTemplateRepresentation(String internalRepresentation) try (XContentParser parser = XContentFactory.xContent(XContentType.JSON) .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, internalRepresentation)) { XContentBuilder builder = JsonXContent.contentBuilder(); - IndexTemplateMetaData.Builder.removeType(IndexTemplateMetaData.Builder.fromXContent(parser, ""), builder); + ToXContent.Params params = new ToXContent.MapParams(Map.of(IndexTemplateMetaData.INCLUDE_TEMPLATE_NAME, "false")); + builder.startObject(); + IndexTemplateMetaData.fromXContent(parser, "").toXContent(builder, params); + builder.endObject(); return BytesReference.bytes(builder).utf8ToString(); } }