diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/GetAutoFollowPatternResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/GetAutoFollowPatternResponse.java index f4afb2d650e..ce42c98e57c 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/GetAutoFollowPatternResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/GetAutoFollowPatternResponse.java @@ -19,41 +19,59 @@ package org.elasticsearch.client.ccr; +import org.elasticsearch.common.ParseField; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentParser.Token; -import java.io.IOException; +import java.util.AbstractMap; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.NavigableMap; import java.util.Objects; +import java.util.TreeMap; +import java.util.stream.Collectors; public final class GetAutoFollowPatternResponse { - public static GetAutoFollowPatternResponse fromXContent(final XContentParser parser) throws IOException { - final Map patterns = new HashMap<>(); - for (Token token = parser.nextToken(); token != Token.END_OBJECT; token = parser.nextToken()) { - if (token == Token.FIELD_NAME) { - final String name = parser.currentName(); - final Pattern pattern = Pattern.PARSER.parse(parser, null); - patterns.put(name, pattern); - } - } - return new GetAutoFollowPatternResponse(patterns); + static final ParseField PATTERNS_FIELD = new ParseField("patterns"); + static final ParseField NAME_FIELD = new ParseField("name"); + static final ParseField PATTERN_FIELD = new ParseField("pattern"); + + private static final ConstructingObjectParser, Void> ENTRY_PARSER = new ConstructingObjectParser<>( + "get_auto_follow_pattern_response", args -> new AbstractMap.SimpleEntry<>((String) args[0], (Pattern) args[1])); + + static { + ENTRY_PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME_FIELD); + ENTRY_PARSER.declareObject(ConstructingObjectParser.constructorArg(), Pattern.PARSER, PATTERN_FIELD); } - private final Map patterns; + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( + "get_auto_follow_pattern_response", args -> { + @SuppressWarnings("unchecked") + List> entries = (List>) args[0]; + return new GetAutoFollowPatternResponse(new TreeMap<>(entries.stream() + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)))); + }); - GetAutoFollowPatternResponse(Map patterns) { - this.patterns = Collections.unmodifiableMap(patterns); + static { + PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), ENTRY_PARSER, PATTERNS_FIELD); } - public Map getPatterns() { + public static GetAutoFollowPatternResponse fromXContent(final XContentParser parser) { + return PARSER.apply(parser, null); + } + + private final NavigableMap patterns; + + GetAutoFollowPatternResponse(NavigableMap patterns) { + this.patterns = Collections.unmodifiableNavigableMap(patterns); + } + + public NavigableMap getPatterns() { return patterns; } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/GetAutoFollowPatternResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/GetAutoFollowPatternResponseTests.java index 64eb9ba4f9f..b4a37286b4a 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/GetAutoFollowPatternResponseTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/GetAutoFollowPatternResponseTests.java @@ -27,8 +27,9 @@ import org.elasticsearch.test.ESTestCase; import java.io.IOException; import java.util.Collections; -import java.util.HashMap; import java.util.Map; +import java.util.NavigableMap; +import java.util.TreeMap; import static org.elasticsearch.client.ccr.PutAutoFollowPatternRequest.FOLLOW_PATTERN_FIELD; import static org.elasticsearch.client.ccr.PutAutoFollowPatternRequest.LEADER_PATTERNS_FIELD; @@ -48,7 +49,7 @@ public class GetAutoFollowPatternResponseTests extends ESTestCase { private GetAutoFollowPatternResponse createTestInstance() { int numPatterns = randomIntBetween(0, 16); - Map patterns = new HashMap<>(numPatterns); + NavigableMap patterns = new TreeMap<>(); for (int i = 0; i < numPatterns; i++) { GetAutoFollowPatternResponse.Pattern pattern = new GetAutoFollowPatternResponse.Pattern( randomAlphaOfLength(4), Collections.singletonList(randomAlphaOfLength(4)), randomAlphaOfLength(4)); @@ -90,17 +91,26 @@ public class GetAutoFollowPatternResponseTests extends ESTestCase { public static void toXContent(GetAutoFollowPatternResponse response, XContentBuilder builder) throws IOException { builder.startObject(); { + builder.startArray(GetAutoFollowPatternResponse.PATTERNS_FIELD.getPreferredName()); for (Map.Entry entry : response.getPatterns().entrySet()) { - builder.startObject(entry.getKey()); - GetAutoFollowPatternResponse.Pattern pattern = entry.getValue(); - builder.field(REMOTE_CLUSTER_FIELD.getPreferredName(), pattern.getRemoteCluster()); - builder.field(LEADER_PATTERNS_FIELD.getPreferredName(), pattern.getLeaderIndexPatterns()); - if (pattern.getFollowIndexNamePattern()!= null) { - builder.field(FOLLOW_PATTERN_FIELD.getPreferredName(), pattern.getFollowIndexNamePattern()); + builder.startObject(); + { + builder.field(GetAutoFollowPatternResponse.NAME_FIELD.getPreferredName(), entry.getKey()); + builder.startObject(GetAutoFollowPatternResponse.PATTERN_FIELD.getPreferredName()); + { + GetAutoFollowPatternResponse.Pattern pattern = entry.getValue(); + builder.field(REMOTE_CLUSTER_FIELD.getPreferredName(), pattern.getRemoteCluster()); + builder.field(LEADER_PATTERNS_FIELD.getPreferredName(), pattern.getLeaderIndexPatterns()); + if (pattern.getFollowIndexNamePattern()!= null) { + builder.field(FOLLOW_PATTERN_FIELD.getPreferredName(), pattern.getFollowIndexNamePattern()); + } + entry.getValue().toXContentFragment(builder, ToXContent.EMPTY_PARAMS); + } + builder.endObject(); } - entry.getValue().toXContentFragment(builder, ToXContent.EMPTY_PARAMS); builder.endObject(); } + builder.endArray(); } builder.endObject(); } diff --git a/docs/reference/ccr/apis/auto-follow/get-auto-follow-pattern.asciidoc b/docs/reference/ccr/apis/auto-follow/get-auto-follow-pattern.asciidoc index b154f6b907e..19eb2b928ae 100644 --- a/docs/reference/ccr/apis/auto-follow/get-auto-follow-pattern.asciidoc +++ b/docs/reference/ccr/apis/auto-follow/get-auto-follow-pattern.asciidoc @@ -87,15 +87,19 @@ The API returns the following result: [source,js] -------------------------------------------------- { - "my_auto_follow_pattern" : - { - "remote_cluster" : "remote_cluster", - "leader_index_patterns" : - [ - "leader_index*" - ], - "follow_index_pattern" : "{{leader_index}}-follower" - } + "patterns": [ + { + "name": "my_auto_follow_pattern", + "pattern": { + "remote_cluster" : "remote_cluster", + "leader_index_patterns" : + [ + "leader_index*" + ], + "follow_index_pattern" : "{{leader_index}}-follower" + } + } + ] } -------------------------------------------------- // TESTRESPONSE diff --git a/x-pack/plugin/ccr/qa/rest/src/test/resources/rest-api-spec/test/ccr/auto_follow.yml b/x-pack/plugin/ccr/qa/rest/src/test/resources/rest-api-spec/test/ccr/auto_follow.yml index 4d4026f46a4..ebf9176c30a 100644 --- a/x-pack/plugin/ccr/qa/rest/src/test/resources/rest-api-spec/test/ccr/auto_follow.yml +++ b/x-pack/plugin/ccr/qa/rest/src/test/resources/rest-api-spec/test/ccr/auto_follow.yml @@ -31,15 +31,17 @@ - do: ccr.get_auto_follow_pattern: name: my_pattern - - match: { my_pattern.remote_cluster: 'local' } - - match: { my_pattern.leader_index_patterns: ['logs-*'] } - - match: { my_pattern.max_outstanding_read_requests: 2 } + - match: { patterns.0.name: 'my_pattern' } + - match: { patterns.0.pattern.remote_cluster: 'local' } + - match: { patterns.0.pattern.leader_index_patterns: ['logs-*'] } + - match: { patterns.0.pattern.max_outstanding_read_requests: 2 } - do: ccr.get_auto_follow_pattern: {} - - match: { my_pattern.remote_cluster: 'local' } - - match: { my_pattern.leader_index_patterns: ['logs-*'] } - - match: { my_pattern.max_outstanding_read_requests: 2 } + - match: { patterns.0.name: 'my_pattern' } + - match: { patterns.0.pattern.remote_cluster: 'local' } + - match: { patterns.0.pattern.leader_index_patterns: ['logs-*'] } + - match: { patterns.0.pattern.max_outstanding_read_requests: 2 } - do: ccr.delete_auto_follow_pattern: diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/GetAutoFollowPatternAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/GetAutoFollowPatternAction.java index 58a909a62ad..098ba6dba69 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/GetAutoFollowPatternAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/GetAutoFollowPatternAction.java @@ -111,10 +111,21 @@ public class GetAutoFollowPatternAction extends Action entry : autoFollowPatterns.entrySet()) { - builder.startObject(entry.getKey()); - entry.getValue().toXContent(builder, params); - builder.endObject(); + { + builder.startArray("patterns"); + for (Map.Entry entry : autoFollowPatterns.entrySet()) { + builder.startObject(); + { + builder.field("name", entry.getKey()); + builder.startObject("pattern"); + { + entry.getValue().toXContent(builder, params); + } + builder.endObject(); + } + builder.endObject(); + } + builder.endArray(); } builder.endObject(); return builder;