浏览代码

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.
olcbean 7 年之前
父节点
当前提交
6341d101d2

+ 18 - 1
server/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java

@@ -30,10 +30,12 @@ import org.elasticsearch.common.io.stream.StreamInput;
 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 java.util.Set;
 
 import static java.util.Collections.emptySet;
 
-public class AliasMetaData extends AbstractDiffable<AliasMetaData> {
+public class AliasMetaData extends AbstractDiffable<AliasMetaData> implements ToXContentFragment {
 
     private final String alias;
 
@@ -199,6 +201,17 @@ public class AliasMetaData extends AbstractDiffable<AliasMetaData> {
         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 class AliasMetaData extends AbstractDiffable<AliasMetaData> {
                     if ("filter".equals(currentFieldName)) {
                         Map<String, Object> 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 class AliasMetaData extends AbstractDiffable<AliasMetaData> {
                     } 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();

+ 50 - 4
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<AliasMetaData> {
 
     public void testSerialization() throws IOException {
         final AliasMetaData before =
@@ -52,4 +53,49 @@ public class AliasMetaDataTests extends ESTestCase {
 
         assertThat(after, equalTo(before));
     }
+
+    @Override
+    protected AliasMetaData createTestInstance() {
+        return createTestItem();
+    }
+
+    @Override
+    protected Predicate<String> 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();
+    }
+
 }