From 7706aaeeee680cb492207becb1b1fd5321067218 Mon Sep 17 00:00:00 2001 From: olcbean <26058559+olcbean@users.noreply.github.com> Date: Wed, 30 May 2018 12:31:24 +0200 Subject: [PATCH] Fix AliasMetaData parsing (#30866) AliasMetaData should be parsed more leniently so that the high-level REST client can support forward compatibility on it. This commit addresses this issue that was found as part of #28799 and adds dedicated XContent tests as well. --- .../cluster/metadata/AliasMetaData.java | 19 ++++++- .../cluster/metadata/AliasMetaDataTests.java | 54 +++++++++++++++++-- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java index 3293be21859bd..b73a9d6032801 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java @@ -30,10 +30,12 @@ import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.util.set.Sets; 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.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; import java.io.IOException; import java.util.Collections; @@ -42,7 +44,7 @@ import static java.util.Collections.emptySet; -public class AliasMetaData extends AbstractDiffable { +public class AliasMetaData extends AbstractDiffable implements ToXContentFragment { private final String alias; @@ -199,6 +201,17 @@ public static Diff readDiffFrom(StreamInput in) throws IOExceptio return readDiffFrom(AliasMetaData::new, in); } + @Override + public String toString() { + return Strings.toString(this, true, true); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + AliasMetaData.Builder.toXContent(this, builder, params); + return builder; + } + public static class Builder { private final String alias; @@ -314,6 +327,8 @@ public static AliasMetaData fromXContent(XContentParser parser) throws IOExcepti if ("filter".equals(currentFieldName)) { Map filter = parser.mapOrdered(); builder.filter(filter); + } else { + parser.skipChildren(); } } else if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) { if ("filter".equals(currentFieldName)) { @@ -327,6 +342,8 @@ public static AliasMetaData fromXContent(XContentParser parser) throws IOExcepti } else if ("search_routing".equals(currentFieldName) || "searchRouting".equals(currentFieldName)) { builder.searchRouting(parser.text()); } + } else if (token == XContentParser.Token.START_ARRAY) { + parser.skipChildren(); } } return builder.build(); diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/AliasMetaDataTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/AliasMetaDataTests.java index d5ae07f43418a..00865cc9a6579 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/AliasMetaDataTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/AliasMetaDataTests.java @@ -19,18 +19,19 @@ package org.elasticsearch.cluster.metadata; +import org.elasticsearch.cluster.metadata.AliasMetaData.Builder; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.util.set.Sets; -import org.elasticsearch.common.xcontent.XContent; -import org.elasticsearch.common.xcontent.XContentHelper; -import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; import java.io.IOException; +import java.util.function.Predicate; import static org.hamcrest.Matchers.equalTo; -public class AliasMetaDataTests extends ESTestCase { +public class AliasMetaDataTests extends AbstractXContentTestCase { public void testSerialization() throws IOException { final AliasMetaData before = @@ -52,4 +53,49 @@ public void testSerialization() throws IOException { assertThat(after, equalTo(before)); } + + @Override + protected AliasMetaData createTestInstance() { + return createTestItem(); + } + + @Override + protected Predicate getRandomFieldsExcludeFilter() { + return p -> p.equals("") // do not add elements at the top-level as any element at this level is parsed as a new alias + || p.contains(".filter"); // do not insert random data into AliasMetaData#filter + } + + @Override + protected AliasMetaData doParseInstance(XContentParser parser) throws IOException { + if (parser.nextToken() == XContentParser.Token.START_OBJECT) { + parser.nextToken(); + } + assertEquals(XContentParser.Token.FIELD_NAME, parser.currentToken()); + AliasMetaData aliasMetaData = AliasMetaData.Builder.fromXContent(parser); + assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken()); + return aliasMetaData; + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } + + private static AliasMetaData createTestItem() { + Builder builder = AliasMetaData.builder(randomAlphaOfLengthBetween(3, 10)); + if (randomBoolean()) { + builder.routing(randomAlphaOfLengthBetween(3, 10)); + } + if (randomBoolean()) { + builder.searchRouting(randomAlphaOfLengthBetween(3, 10)); + } + if (randomBoolean()) { + builder.indexRouting(randomAlphaOfLengthBetween(3, 10)); + } + if (randomBoolean()) { + builder.filter("{\"term\":{\"year\":2016}}"); + } + return builder.build(); + } + }