Browse Source

Add index mode to resolve index response. (#132858)

* Add index mode to resolve index response.

* Add yaml rest test

* Update docs/changelog/132858.yaml

---------

Co-authored-by: elasticsearchmachine <infra-root+elasticsearchmachine@elastic.co>
Sean Zatz 2 months ago
parent
commit
008cdd5b64

+ 5 - 0
docs/changelog/132858.yaml

@@ -0,0 +1,5 @@
+pr: 132858
+summary: Add index mode to resolve index response
+area: Indices APIs
+type: feature
+issues: []

+ 74 - 0
rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.resolve_index/25_resolve_index_with_mode.yml

@@ -0,0 +1,74 @@
+---
+setup:
+  - do:
+      indices.delete:
+        index: my-std-index
+        ignore_unavailable: true
+  - do:
+      indices.delete:
+        index: my-ts-index
+        ignore_unavailable: true
+
+# Only run this test if the cluster supports time series indexing.
+# If your project uses a different feature flag name, adjust it here.
+---
+"resolve index returns mode for standard and time_series indices":
+  - requires:
+      cluster_features: ["gte_v8.5.0", "resolve_index_returns_mode"]
+      reason: "Requires time series indexing support introduced in v8.5.0 & Node must support returning 'mode' in indices.resolve_index response"
+
+  # Create a standard index
+  - do:
+      indices.create:
+        index: my-std-index
+        body:
+          settings:
+            number_of_shards: 1
+            number_of_replicas: 0
+
+  # Create a time-series index
+  - do:
+      indices.create:
+        index: my-ts-index
+        body:
+          settings:
+            index.mode: time_series
+            number_of_shards: 1
+            number_of_replicas: 0
+            index.routing_path: ["host"]
+          mappings:
+            properties:
+              "@timestamp":
+                type: date
+              host:
+                type: keyword
+                time_series_dimension: true
+              metric:
+                type: keyword
+              value:
+                type: double
+
+  # Resolve standard index and verify mode
+  - do:
+      indices.resolve_index:
+        name: my-std-index
+  - match: { indices.0.name: "my-std-index" }
+  - match: { indices.0.mode: "standard" }
+
+  # Resolve time-series index and verify mode
+  - do:
+      indices.resolve_index:
+        name: my-ts-index
+  - match: { indices.0.name: "my-ts-index" }
+  - match: { indices.0.mode: "time_series" }
+
+---
+teardown:
+  - do:
+      indices.delete:
+        index: my-std-index
+        ignore_unavailable: true
+  - do:
+      indices.delete:
+        index: my-ts-index
+        ignore_unavailable: true

+ 2 - 1
server/src/main/java/module-info.java

@@ -434,7 +434,8 @@ module org.elasticsearch.server {
             org.elasticsearch.script.ScriptFeatures,
             org.elasticsearch.search.retriever.RetrieversFeatures,
             org.elasticsearch.action.admin.cluster.stats.ClusterStatsFeatures,
-            org.elasticsearch.ingest.IngestFeatures;
+            org.elasticsearch.ingest.IngestFeatures,
+            org.elasticsearch.action.admin.indices.resolve.ResolveIndexFeatures;
 
     uses org.elasticsearch.plugins.internal.SettingsExtension;
     uses RestExtension;

+ 1 - 0
server/src/main/java/org/elasticsearch/TransportVersions.java

@@ -365,6 +365,7 @@ public class TransportVersions {
     public static final TransportVersion SIMULATE_INGEST_MAPPING_MERGE_TYPE = def(9_138_0_00);
     public static final TransportVersion ESQL_LOOKUP_JOIN_ON_MANY_FIELDS = def(9_139_0_00);
     public static final TransportVersion SIMULATE_INGEST_EFFECTIVE_MAPPING = def(9_140_0_00);
+    public static final TransportVersion RESOLVE_INDEX_MODE_ADDED = def(9_141_0_00);
 
     /*
      * STOP! READ THIS FIRST! No, really,

+ 27 - 4
server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java

@@ -9,6 +9,7 @@
 
 package org.elasticsearch.action.admin.indices.resolve;
 
+import org.elasticsearch.TransportVersions;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.ActionRequestValidationException;
 import org.elasticsearch.action.ActionResponse;
@@ -39,6 +40,7 @@ import org.elasticsearch.common.util.concurrent.CountDown;
 import org.elasticsearch.common.util.concurrent.EsExecutors;
 import org.elasticsearch.core.Nullable;
 import org.elasticsearch.index.Index;
+import org.elasticsearch.index.IndexMode;
 import org.elasticsearch.injection.guice.Inject;
 import org.elasticsearch.search.SearchService;
 import org.elasticsearch.tasks.Task;
@@ -176,27 +178,35 @@ public class ResolveIndexAction extends ActionType<ResolveIndexAction.Response>
         static final ParseField ALIASES_FIELD = new ParseField("aliases");
         static final ParseField ATTRIBUTES_FIELD = new ParseField("attributes");
         static final ParseField DATA_STREAM_FIELD = new ParseField("data_stream");
+        static final ParseField MODE_FIELD = new ParseField("mode");
 
         private final String[] aliases;
         private final String[] attributes;
         private final String dataStream;
+        private final IndexMode mode;
 
         ResolvedIndex(StreamInput in) throws IOException {
             setName(in.readString());
             this.aliases = in.readStringArray();
             this.attributes = in.readStringArray();
             this.dataStream = in.readOptionalString();
+            if (in.getTransportVersion().onOrAfter(TransportVersions.RESOLVE_INDEX_MODE_ADDED)) {
+                this.mode = IndexMode.readFrom(in);
+            } else {
+                this.mode = null;
+            }
         }
 
-        ResolvedIndex(String name, String[] aliases, String[] attributes, @Nullable String dataStream) {
+        ResolvedIndex(String name, String[] aliases, String[] attributes, @Nullable String dataStream, IndexMode mode) {
             super(name);
             this.aliases = aliases;
             this.attributes = attributes;
             this.dataStream = dataStream;
+            this.mode = mode;
         }
 
         public ResolvedIndex copy(String newName) {
-            return new ResolvedIndex(newName, aliases, attributes, dataStream);
+            return new ResolvedIndex(newName, aliases, attributes, dataStream, mode);
         }
 
         public String[] getAliases() {
@@ -211,12 +221,19 @@ public class ResolveIndexAction extends ActionType<ResolveIndexAction.Response>
             return dataStream;
         }
 
+        public IndexMode getMode() {
+            return mode;
+        }
+
         @Override
         public void writeTo(StreamOutput out) throws IOException {
             out.writeString(getName());
             out.writeStringArray(aliases);
             out.writeStringArray(attributes);
             out.writeOptionalString(dataStream);
+            if (out.getTransportVersion().onOrAfter(TransportVersions.RESOLVE_INDEX_MODE_ADDED)) {
+                IndexMode.writeTo(mode, out);
+            }
         }
 
         @Override
@@ -230,6 +247,9 @@ public class ResolveIndexAction extends ActionType<ResolveIndexAction.Response>
             if (Strings.isNullOrEmpty(dataStream) == false) {
                 builder.field(DATA_STREAM_FIELD.getPreferredName(), dataStream);
             }
+            if (mode != null) {
+                builder.field(MODE_FIELD.getPreferredName(), mode.toString());
+            }
             builder.endObject();
             return builder;
         }
@@ -242,12 +262,14 @@ public class ResolveIndexAction extends ActionType<ResolveIndexAction.Response>
             return getName().equals(index.getName())
                 && Objects.equals(dataStream, index.dataStream)
                 && Arrays.equals(aliases, index.aliases)
-                && Arrays.equals(attributes, index.attributes);
+                && Arrays.equals(attributes, index.attributes)
+                && Objects.equals(mode, index.mode);
         }
 
         @Override
         public int hashCode() {
             int result = Objects.hash(getName(), dataStream);
+            result = 31 * result + Objects.hashCode(mode);
             result = 31 * result + Arrays.hashCode(aliases);
             result = 31 * result + Arrays.hashCode(attributes);
             return result;
@@ -639,7 +661,8 @@ public class ResolveIndexAction extends ActionType<ResolveIndexAction.Response>
                                 ia.getName(),
                                 aliasNames,
                                 attributes.stream().map(Enum::name).map(e -> e.toLowerCase(Locale.ROOT)).toArray(String[]::new),
-                                ia.getParentDataStream() == null ? null : ia.getParentDataStream().getName()
+                                ia.getParentDataStream() == null ? null : ia.getParentDataStream().getName(),
+                                writeIndex.getIndexMode() == null ? IndexMode.STANDARD : writeIndex.getIndexMode()
                             )
                         );
                     }

+ 32 - 0
server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexFeatures.java

@@ -0,0 +1,32 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+package org.elasticsearch.action.admin.indices.resolve;
+
+import org.elasticsearch.features.FeatureSpecification;
+import org.elasticsearch.features.NodeFeature;
+
+import java.util.Set;
+
+public class ResolveIndexFeatures implements FeatureSpecification {
+
+    // Feature published by nodes that return "mode" in indices.resolve_index responses.
+    public static final NodeFeature RESOLVE_INDEX_RETURNS_MODE = new NodeFeature("resolve_index_returns_mode");
+
+    @Override
+    public Set<NodeFeature> getFeatures() {
+        return Set.of(RESOLVE_INDEX_RETURNS_MODE);
+    }
+
+    @Override
+    public Set<NodeFeature> getTestFeatures() {
+        return Set.of(RESOLVE_INDEX_RETURNS_MODE);
+    }
+
+}

+ 1 - 0
server/src/main/resources/META-INF/services/org.elasticsearch.features.FeatureSpecification

@@ -20,3 +20,4 @@ org.elasticsearch.script.ScriptFeatures
 org.elasticsearch.cluster.routing.RoutingFeatures
 org.elasticsearch.action.admin.cluster.stats.ClusterStatsFeatures
 org.elasticsearch.ingest.IngestFeatures
+org.elasticsearch.action.admin.indices.resolve.ResolveIndexFeatures

+ 7 - 2
server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexResponseTests.java

@@ -15,6 +15,7 @@ import org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.Resolve
 import org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.Response;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.io.stream.Writeable;
+import org.elasticsearch.index.IndexMode;
 import org.elasticsearch.test.AbstractXContentSerializingTestCase;
 import org.elasticsearch.xcontent.ConstructingObjectParser;
 import org.elasticsearch.xcontent.XContentParser;
@@ -28,6 +29,7 @@ import static org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.
 import static org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.ResolvedIndex.ALIASES_FIELD;
 import static org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.ResolvedIndex.ATTRIBUTES_FIELD;
 import static org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.ResolvedIndex.DATA_STREAM_FIELD;
+import static org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.ResolvedIndex.MODE_FIELD;
 import static org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.ResolvedIndexAbstraction.NAME_FIELD;
 import static org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.Response.DATA_STREAMS_FIELD;
 import static org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.Response.INDICES_FIELD;
@@ -76,8 +78,9 @@ public class ResolveIndexResponseTests extends AbstractXContentSerializingTestCa
         String[] aliases = randomStringArray(0, 5);
         String[] attributes = randomSubsetOf(List.of("open", "hidden", "frozen")).toArray(Strings.EMPTY_ARRAY);
         String dataStream = randomBoolean() ? randomAlphaOfLength(6) : null;
+        IndexMode mode = randomFrom(IndexMode.values());
 
-        return new ResolvedIndex(name, aliases, attributes, dataStream);
+        return new ResolvedIndex(name, aliases, attributes, dataStream, mode);
     }
 
     private static ResolvedAlias createTestResolvedAliasInstance() {
@@ -109,7 +112,8 @@ public class ResolveIndexResponseTests extends AbstractXContentSerializingTestCa
             (String) args[0],
             args[1] != null ? ((List<String>) args[1]).toArray(Strings.EMPTY_ARRAY) : new String[0],
             ((List<String>) args[2]).toArray(Strings.EMPTY_ARRAY),
-            (String) args[3]
+            (String) args[3],
+            IndexMode.fromString((String) args[4])
         )
     );
     @SuppressWarnings("unchecked")
@@ -133,6 +137,7 @@ public class ResolveIndexResponseTests extends AbstractXContentSerializingTestCa
         INDEX_PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), ALIASES_FIELD);
         INDEX_PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), ATTRIBUTES_FIELD);
         INDEX_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), DATA_STREAM_FIELD);
+        INDEX_PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), MODE_FIELD);
         ALIAS_PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME_FIELD);
         ALIAS_PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), INDICES_FIELD);
         RESPONSE_PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), (p, c) -> indexFromXContent(p), INDICES_FIELD);

+ 29 - 15
server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java

@@ -32,6 +32,7 @@ import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.time.DateFormatter;
 import org.elasticsearch.common.util.concurrent.ThreadContext;
+import org.elasticsearch.index.IndexMode;
 import org.elasticsearch.index.IndexNotFoundException;
 import org.elasticsearch.index.IndexVersion;
 import org.elasticsearch.indices.SystemIndexDescriptor;
@@ -68,14 +69,22 @@ import static org.hamcrest.core.IsNull.notNullValue;
 public class ResolveIndexTests extends ESTestCase {
 
     private final Object[][] indices = new Object[][] {
-        // name, isClosed, isHidden, isSystem, isFrozen, dataStream, aliases
-        { "logs-pgsql-prod-20200101", false, false, false, true, null, new String[] { "logs-pgsql-prod" } },
-        { "logs-pgsql-prod-20200102", false, false, false, true, null, new String[] { "logs-pgsql-prod", "one-off-alias" } },
-        { "logs-pgsql-prod-20200103", false, false, false, false, null, new String[] { "logs-pgsql-prod" } },
-        { "logs-pgsql-test-20200101", true, false, false, false, null, new String[] { "logs-pgsql-test" } },
-        { "logs-pgsql-test-20200102", false, false, false, false, null, new String[] { "logs-pgsql-test" } },
-        { "logs-pgsql-test-20200103", false, false, false, false, null, new String[] { "logs-pgsql-test" } },
-        { ".test-system-index", false, false, true, false, null, new String[] {} } };
+        // name, isClosed, isHidden, isSystem, isFrozen, dataStream, aliases, mode
+        { "logs-pgsql-prod-20200101", false, false, false, true, null, new String[] { "logs-pgsql-prod" }, IndexMode.STANDARD },
+        {
+            "logs-pgsql-prod-20200102",
+            false,
+            false,
+            false,
+            true,
+            null,
+            new String[] { "logs-pgsql-prod", "one-off-alias" },
+            IndexMode.TIME_SERIES },
+        { "logs-pgsql-prod-20200103", false, false, false, false, null, new String[] { "logs-pgsql-prod" }, IndexMode.STANDARD },
+        { "logs-pgsql-test-20200101", true, false, false, false, null, new String[] { "logs-pgsql-test" }, IndexMode.STANDARD },
+        { "logs-pgsql-test-20200102", false, false, false, false, null, new String[] { "logs-pgsql-test" }, IndexMode.STANDARD },
+        { "logs-pgsql-test-20200103", false, false, false, false, null, new String[] { "logs-pgsql-test" }, IndexMode.STANDARD },
+        { ".test-system-index", false, false, true, false, null, new String[] {}, IndexMode.STANDARD } };
 
     private final Object[][] dataStreams = new Object[][] {
         // name, numBackingIndices
@@ -234,8 +243,8 @@ public class ResolveIndexTests extends ESTestCase {
         String tomorrowSuffix = dateFormatter.format(now.plus(Duration.ofDays(1L)));
         Object[][] indices = new Object[][] {
             // name, isClosed, isHidden, isFrozen, dataStream, aliases
-            { "logs-pgsql-prod-" + todaySuffix, false, true, false, false, null, Strings.EMPTY_ARRAY },
-            { "logs-pgsql-prod-" + tomorrowSuffix, false, true, false, false, null, Strings.EMPTY_ARRAY } };
+            { "logs-pgsql-prod-" + todaySuffix, false, true, false, false, null, Strings.EMPTY_ARRAY, IndexMode.STANDARD },
+            { "logs-pgsql-prod-" + tomorrowSuffix, false, true, false, false, null, Strings.EMPTY_ARRAY, IndexMode.STANDARD } };
         final ProjectMetadata project = buildProjectMetadata(randomProjectIdOrDefault(), new Object[][] {}, indices).build();
         String[] requestedIndex = new String[] { "<logs-pgsql-prod-{now/d}>" };
         Set<ResolvedExpression> resolvedIndices = resolver.resolveExpressions(
@@ -356,6 +365,7 @@ public class ResolveIndexTests extends ESTestCase {
             assertThat(resolvedIndex.getAliases(), is(((String[]) indexInfo[6])));
             assertThat(resolvedIndex.getAttributes(), is(flagsToAttributes(indexInfo)));
             assertThat(resolvedIndex.getDataStream(), equalTo((String) indexInfo[5]));
+            assertThat(resolvedIndex.getMode().toString(), equalTo(((IndexMode) indexInfo[7]).toString()));
         }
     }
 
@@ -444,7 +454,8 @@ public class ResolveIndexTests extends ESTestCase {
             boolean hidden = (boolean) indexInfo[2];
             boolean system = (boolean) indexInfo[3];
             boolean frozen = (boolean) indexInfo[4];
-            allIndices.add(createIndexMetadata(indexName, aliases, closed, hidden, system, frozen));
+            IndexMode mode = (IndexMode) indexInfo[7];
+            allIndices.add(createIndexMetadata(indexName, aliases, closed, hidden, system, frozen, mode));
         }
 
         for (IndexMetadata index : allIndices) {
@@ -460,12 +471,14 @@ public class ResolveIndexTests extends ESTestCase {
         boolean closed,
         boolean hidden,
         boolean system,
-        boolean frozen
+        boolean frozen,
+        IndexMode mode
     ) {
         Settings.Builder settingsBuilder = Settings.builder()
             .put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current())
             .put("index.hidden", hidden)
-            .put("index.frozen", frozen);
+            .put("index.frozen", frozen)
+            .put("index.mode", mode.toString());
 
         IndexMetadata.Builder indexBuilder = IndexMetadata.builder(name)
             .settings(settingsBuilder)
@@ -482,7 +495,7 @@ public class ResolveIndexTests extends ESTestCase {
     }
 
     private static IndexMetadata createIndexMetadata(String name, boolean hidden) {
-        return createIndexMetadata(name, Strings.EMPTY_ARRAY, false, true, false, false);
+        return createIndexMetadata(name, Strings.EMPTY_ARRAY, false, true, false, false, IndexMode.STANDARD);
     }
 
     private static Object[] findInfo(Object[][] indexSource, String indexName) {
@@ -507,7 +520,8 @@ public class ResolveIndexTests extends ESTestCase {
                         false,
                         false,
                         dataStreamName,
-                        Strings.EMPTY_ARRAY };
+                        Strings.EMPTY_ARRAY,
+                        IndexMode.STANDARD };
                 }
             }
         }

+ 66 - 0
server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolvedIndexSerializingTests.java

@@ -0,0 +1,66 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+package org.elasticsearch.action.admin.indices.resolve;
+
+import org.elasticsearch.common.io.stream.Writeable;
+import org.elasticsearch.index.IndexMode;
+import org.elasticsearch.test.AbstractWireSerializingTestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ResolvedIndexSerializingTests extends AbstractWireSerializingTestCase<ResolveIndexAction.ResolvedIndex> {
+
+    @Override
+    protected Writeable.Reader<ResolveIndexAction.ResolvedIndex> instanceReader() {
+        return ResolveIndexAction.ResolvedIndex::new;
+    }
+
+    @Override
+    protected ResolveIndexAction.ResolvedIndex mutateInstance(ResolveIndexAction.ResolvedIndex instance) {
+        String name = instance.getName();
+        String[] aliases = instance.getAliases();
+        String[] attributes = instance.getAttributes();
+        String dataStream = instance.getDataStream();
+        IndexMode mode = instance.getMode();
+        mode = randomValueOtherThan(mode, () -> randomFrom(IndexMode.values()));
+        return new ResolveIndexAction.ResolvedIndex(name, aliases, attributes, dataStream, mode);
+    }
+
+    @Override
+    protected ResolveIndexAction.ResolvedIndex createTestInstance() {
+        return createTestItem();
+    }
+
+    private static ResolveIndexAction.ResolvedIndex createTestItem() {
+        // Random index name
+        final String name = randomAlphaOfLengthBetween(5, 20);
+
+        // Random aliases (possibly empty)
+        final String[] aliases = randomBoolean()
+            ? new String[0]
+            : randomArray(0, 4, String[]::new, () -> randomAlphaOfLengthBetween(3, 15));
+
+        // Attributes: always one of "open"/"closed", plus optional flags
+        final List<String> attrs = new ArrayList<>();
+        attrs.add(randomBoolean() ? "open" : "closed");
+        if (randomBoolean()) attrs.add("hidden");
+        if (randomBoolean()) attrs.add("system");
+        if (randomBoolean()) attrs.add("frozen");
+        final String[] attributes = attrs.toArray(new String[0]);
+
+        final String dataStream = randomBoolean() ? randomAlphaOfLengthBetween(3, 15) : null;
+
+        final IndexMode mode = randomFrom(IndexMode.values());
+
+        return new ResolveIndexAction.ResolvedIndex(name, aliases, attributes, dataStream, mode);
+
+    }
+}

+ 8 - 8
server/src/test/java/org/elasticsearch/action/admin/indices/resolve/TransportResolveClusterActionTests.java

@@ -104,30 +104,30 @@ public class TransportResolveClusterActionTests extends ESTestCase {
 
         // as long as there is one non-closed index it should return true
         indices = new ArrayList<>();
-        indices.add(new ResolveIndexAction.ResolvedIndex("foo", null, new String[] { "open" }, ".ds-foo"));
+        indices.add(new ResolveIndexAction.ResolvedIndex("foo", null, new String[] { "open" }, ".ds-foo", null));
         assertThat(TransportResolveClusterAction.hasNonClosedMatchingIndex(indices), equalTo(true));
 
-        indices.add(new ResolveIndexAction.ResolvedIndex("bar", null, new String[] { "system" }, ".ds-bar"));
+        indices.add(new ResolveIndexAction.ResolvedIndex("bar", null, new String[] { "system" }, ".ds-bar", null));
         assertThat(TransportResolveClusterAction.hasNonClosedMatchingIndex(indices), equalTo(true));
 
-        indices.add(new ResolveIndexAction.ResolvedIndex("baz", null, new String[] { "system", "open", "hidden" }, null));
+        indices.add(new ResolveIndexAction.ResolvedIndex("baz", null, new String[] { "system", "open", "hidden" }, null, null));
         assertThat(TransportResolveClusterAction.hasNonClosedMatchingIndex(indices), equalTo(true));
 
-        indices.add(new ResolveIndexAction.ResolvedIndex("quux", null, new String[0], null));
+        indices.add(new ResolveIndexAction.ResolvedIndex("quux", null, new String[0], null, null));
         assertThat(TransportResolveClusterAction.hasNonClosedMatchingIndex(indices), equalTo(true));
 
-        indices.add(new ResolveIndexAction.ResolvedIndex("wibble", null, new String[] { "system", "closed" }, null));
+        indices.add(new ResolveIndexAction.ResolvedIndex("wibble", null, new String[] { "system", "closed" }, null, null));
         assertThat(TransportResolveClusterAction.hasNonClosedMatchingIndex(indices), equalTo(true));
 
         // if only closed indexes are present, should return false
         indices.clear();
-        indices.add(new ResolveIndexAction.ResolvedIndex("wibble", null, new String[] { "system", "closed" }, null));
+        indices.add(new ResolveIndexAction.ResolvedIndex("wibble", null, new String[] { "system", "closed" }, null, null));
         assertThat(TransportResolveClusterAction.hasNonClosedMatchingIndex(indices), equalTo(false));
-        indices.add(new ResolveIndexAction.ResolvedIndex("wobble", null, new String[] { "closed" }, null));
+        indices.add(new ResolveIndexAction.ResolvedIndex("wobble", null, new String[] { "closed" }, null, null));
         assertThat(TransportResolveClusterAction.hasNonClosedMatchingIndex(indices), equalTo(false));
 
         // now add a non-closed index and should return true
-        indices.add(new ResolveIndexAction.ResolvedIndex("aaa", null, new String[] { "hidden" }, null));
+        indices.add(new ResolveIndexAction.ResolvedIndex("aaa", null, new String[] { "hidden" }, null, null));
         assertThat(TransportResolveClusterAction.hasNonClosedMatchingIndex(indices), equalTo(true));
     }
 }