From 22783361494473deb9e59f8d62fe77cf63290b81 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 26 Aug 2025 18:37:47 -0600 Subject: [PATCH 01/14] Add mode filter to _resolve/index --- .../org/elasticsearch/TransportVersions.java | 1 + .../indices/resolve/ResolveIndexAction.java | 83 +++++++++++++++++-- .../admin/indices/RestResolveIndexAction.java | 12 ++- 3 files changed, 86 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/TransportVersions.java b/server/src/main/java/org/elasticsearch/TransportVersions.java index 81e4cca69769c..59110cb00e678 100644 --- a/server/src/main/java/org/elasticsearch/TransportVersions.java +++ b/server/src/main/java/org/elasticsearch/TransportVersions.java @@ -369,6 +369,7 @@ static TransportVersion def(int id) { public static final TransportVersion SCRIPT_RESCORER = def(9_143_0_00); public static final TransportVersion ESQL_LOOKUP_OPERATOR_EMITTED_ROWS = def(9_144_0_00); public static final TransportVersion ALLOCATION_DECISION_NOT_PREFERRED = def(9_145_0_00); + public static final TransportVersion RESOLVE_INDEX_MODE_FILTER = def(9_146_0_00); /* * STOP! READ THIS FIRST! No, really, diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java index a105a570864f4..2fdadbea81afe 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java @@ -56,6 +56,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -83,6 +84,7 @@ public static class Request extends LegacyActionRequest implements IndicesReques private String[] names; private IndicesOptions indicesOptions = DEFAULT_INDICES_OPTIONS; + private EnumSet indexModes = EnumSet.noneOf(IndexMode.class); public Request(String[] names) { this.names = names; @@ -93,6 +95,14 @@ public Request(String[] names, IndicesOptions indicesOptions) { this.indicesOptions = indicesOptions; } + public Request(String[] names, IndicesOptions indicesOptions, @Nullable EnumSet indexModes) { + this.names = names; + this.indicesOptions = indicesOptions; + if (indexModes != null) { + this.indexModes = indexModes; + } + } + @Override public ActionRequestValidationException validate() { return null; @@ -102,6 +112,11 @@ public Request(StreamInput in) throws IOException { super(in); this.names = in.readStringArray(); this.indicesOptions = IndicesOptions.readIndicesOptions(in); + if (in.getTransportVersion().onOrAfter(TransportVersions.RESOLVE_INDEX_MODE_FILTER)) { + this.indexModes = in.readEnumSet(IndexMode.class); + } else { + this.indexModes = EnumSet.noneOf(IndexMode.class); + } } @Override @@ -109,6 +124,9 @@ public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); out.writeStringArray(names); indicesOptions.writeIndicesOptions(out); + if (out.getTransportVersion().onOrAfter(TransportVersions.RESOLVE_INDEX_MODE_FILTER)) { + out.writeEnumSet(indexModes); + } } @Override @@ -503,7 +521,7 @@ protected void doExecute(Task task, Request request, final ActionListener indices = new ArrayList<>(); List aliases = new ArrayList<>(); List dataStreams = new ArrayList<>(); - resolveIndices(localIndices, projectState, indexNameExpressionResolver, indices, aliases, dataStreams); + resolveIndices(localIndices, projectState, indexNameExpressionResolver, indices, aliases, dataStreams, request.indexModes); if (remoteClusterIndices.size() > 0) { final int remoteRequests = remoteClusterIndices.size(); @@ -511,7 +529,7 @@ protected void doExecute(Task task, Request request, final ActionListener remoteResponses = Collections.synchronizedSortedMap(new TreeMap<>()); final Runnable terminalHandler = () -> { if (completionCounter.countDown()) { - mergeResults(remoteResponses, indices, aliases, dataStreams); + mergeResults(remoteResponses, indices, aliases, dataStreams, request.indexModes); listener.onResponse(new Response(indices, aliases, dataStreams)); } }; @@ -552,12 +570,35 @@ static void resolveIndices( IndexNameExpressionResolver resolver, List indices, List aliases, - List dataStreams + List dataStreams, + Set indexModes ) { if (localIndices == null) { return; } - resolveIndices(localIndices.indices(), localIndices.indicesOptions(), projectState, resolver, indices, aliases, dataStreams); + resolveIndices( + localIndices.indices(), + localIndices.indicesOptions(), + projectState, + resolver, + indices, + aliases, + dataStreams, + indexModes + ); + } + + // Shortcut for tests that don't need index mode filtering + static void resolveIndices( + String[] names, + IndicesOptions indicesOptions, + ProjectState projectState, + IndexNameExpressionResolver resolver, + List indices, + List aliases, + List dataStreams + ) { + resolveIndices(names, indicesOptions, projectState, resolver, indices, aliases, dataStreams, Collections.emptySet()); } /** @@ -578,7 +619,8 @@ static void resolveIndices( IndexNameExpressionResolver resolver, List indices, List aliases, - List dataStreams + List dataStreams, + Set indexModes ) { // redundant check to ensure that we don't resolve the list of empty names to "all" in this context if (names.length == 0) { @@ -601,7 +643,7 @@ static void resolveIndices( names ); for (ResolvedExpression s : resolvedIndexAbstractions) { - enrichIndexAbstraction(projectState, s, indices, aliases, dataStreams); + enrichIndexAbstraction(projectState, s, indices, aliases, dataStreams, indexModes); } indices.sort(Comparator.comparing(ResolvedIndexAbstraction::getName)); aliases.sort(Comparator.comparing(ResolvedIndexAbstraction::getName)); @@ -612,14 +654,22 @@ private static void mergeResults( Map remoteResponses, List indices, List aliases, - List dataStreams + List dataStreams, + Set indexModes ) { for (Map.Entry responseEntry : remoteResponses.entrySet()) { String clusterAlias = responseEntry.getKey(); Response response = responseEntry.getValue(); for (ResolvedIndex index : response.indices) { + // We want to filter here because the remote cluster might be too old to be able to filter + if (indexModes.isEmpty() == false && indexModes.contains(index.getMode()) == false) { + continue; + } indices.add(index.copy(RemoteClusterAware.buildRemoteIndexName(clusterAlias, index.getName()))); } + if (indexModes.isEmpty() == false && indexModes.contains(IndexMode.STANDARD) == false) { + continue; + } for (ResolvedAlias alias : response.aliases) { aliases.add(alias.copy(RemoteClusterAware.buildRemoteIndexName(clusterAlias, alias.getName()))); } @@ -634,7 +684,8 @@ private static void enrichIndexAbstraction( ResolvedExpression resolvedExpression, List indices, List aliases, - List dataStreams + List dataStreams, + Set indexModes ) { SortedMap indicesLookup = projectState.metadata().getIndicesLookup(); IndexAbstraction ia = indicesLookup.get(resolvedExpression.resource()); @@ -642,6 +693,12 @@ private static void enrichIndexAbstraction( switch (ia.getType()) { case CONCRETE_INDEX -> { IndexMetadata writeIndex = projectState.metadata().index(ia.getWriteIndex()); + IndexMode mode = writeIndex.getIndexMode() == null ? IndexMode.STANDARD : writeIndex.getIndexMode(); + if (indexModes.isEmpty() == false) { + if (indexModes.contains(mode) == false) { + return; + } + } String[] aliasNames = writeIndex.getAliases().keySet().stream().sorted().toArray(String[]::new); List attributes = new ArrayList<>(); attributes.add(writeIndex.getState() == IndexMetadata.State.OPEN ? Attribute.OPEN : Attribute.CLOSED); @@ -662,17 +719,25 @@ private static void enrichIndexAbstraction( aliasNames, attributes.stream().map(Enum::name).map(e -> e.toLowerCase(Locale.ROOT)).toArray(String[]::new), ia.getParentDataStream() == null ? null : ia.getParentDataStream().getName(), - writeIndex.getIndexMode() == null ? IndexMode.STANDARD : writeIndex.getIndexMode() + mode ) ); } case ALIAS -> { + if (indexModes.isEmpty() == false && indexModes.contains(IndexMode.STANDARD) == false) { + // If we didn't ask for standard indices, skip aliases too + return; + } String[] indexNames = getAliasIndexStream(resolvedExpression, ia, projectState.metadata()).map(Index::getName) .toArray(String[]::new); Arrays.sort(indexNames); aliases.add(new ResolvedAlias(ia.getName(), indexNames)); } case DATA_STREAM -> { + if (indexModes.isEmpty() == false && indexModes.contains(IndexMode.STANDARD) == false) { + // If we didn't ask for standard indices, skip datastreams too + return; + } DataStream dataStream = (DataStream) ia; Stream dataStreamIndices = resolvedExpression.selector() == null ? dataStream.getIndices().stream() diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java index a37f4f54cfa5a..5943b219c34ba 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java @@ -13,6 +13,7 @@ import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.client.internal.node.NodeClient; import org.elasticsearch.common.Strings; +import org.elasticsearch.index.IndexMode; import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.Scope; @@ -20,7 +21,10 @@ import org.elasticsearch.rest.action.RestToXContentListener; import java.io.IOException; +import java.util.Arrays; +import java.util.EnumSet; import java.util.List; +import java.util.Set; import static org.elasticsearch.rest.RestRequest.Method.GET; @@ -40,9 +44,15 @@ public List routes() { @Override protected BaseRestHandler.RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { String[] indices = Strings.splitStringByCommaToArray(request.param("name")); + String modeParam = request.param("mode"); ResolveIndexAction.Request resolveRequest = new ResolveIndexAction.Request( indices, - IndicesOptions.fromRequest(request, ResolveIndexAction.Request.DEFAULT_INDICES_OPTIONS) + IndicesOptions.fromRequest(request, ResolveIndexAction.Request.DEFAULT_INDICES_OPTIONS), + modeParam == null + ? null + : Arrays.stream(modeParam.split(",")) + .map(IndexMode::fromString) + .collect(() -> EnumSet.noneOf(IndexMode.class), EnumSet::add, EnumSet::addAll) ); return channel -> client.admin().indices().resolveIndex(resolveRequest, new RestToXContentListener<>(channel)); } From 9a13bac42053787f99e9e263d8dffbce8b55030d Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Wed, 27 Aug 2025 00:46:45 +0000 Subject: [PATCH 02/14] [CI] Auto commit changes from spotless --- .../rest/action/admin/indices/RestResolveIndexAction.java | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java index 5943b219c34ba..a0f9b4804d613 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java @@ -24,7 +24,6 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.List; -import java.util.Set; import static org.elasticsearch.rest.RestRequest.Method.GET; From bcac7ee7284ad96ca04e99c7dabb50a1b3d0ef2b Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 27 Aug 2025 09:09:08 -0600 Subject: [PATCH 03/14] Filter all sets --- .../indices/resolve/ResolveIndexAction.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java index 2fdadbea81afe..ff41beffd1a9b 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java @@ -64,6 +64,7 @@ import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; +import java.util.function.Predicate; import java.util.stream.Stream; import static org.elasticsearch.action.search.TransportSearchHelper.checkCCSVersionCompatibility; @@ -679,6 +680,17 @@ private static void mergeResults( } } + private static Predicate indexModeFilter(ProjectState projectState, Set indexModes) { + if (indexModes.isEmpty()) { + return index -> true; + } + return index -> { + IndexMetadata indexMetadata = projectState.metadata().index(index); + IndexMode mode = indexMetadata.getIndexMode() == null ? IndexMode.STANDARD : indexMetadata.getIndexMode(); + return indexModes.contains(mode); + }; + } + private static void enrichIndexAbstraction( ProjectState projectState, ResolvedExpression resolvedExpression, @@ -689,16 +701,15 @@ private static void enrichIndexAbstraction( ) { SortedMap indicesLookup = projectState.metadata().getIndicesLookup(); IndexAbstraction ia = indicesLookup.get(resolvedExpression.resource()); + var filterPredicate = indexModeFilter(projectState, indexModes); if (ia != null) { switch (ia.getType()) { case CONCRETE_INDEX -> { + if (filterPredicate.test(ia.getWriteIndex()) == false) { + return; + } IndexMetadata writeIndex = projectState.metadata().index(ia.getWriteIndex()); IndexMode mode = writeIndex.getIndexMode() == null ? IndexMode.STANDARD : writeIndex.getIndexMode(); - if (indexModes.isEmpty() == false) { - if (indexModes.contains(mode) == false) { - return; - } - } String[] aliasNames = writeIndex.getAliases().keySet().stream().sorted().toArray(String[]::new); List attributes = new ArrayList<>(); attributes.add(writeIndex.getState() == IndexMetadata.State.OPEN ? Attribute.OPEN : Attribute.CLOSED); @@ -728,7 +739,8 @@ private static void enrichIndexAbstraction( // If we didn't ask for standard indices, skip aliases too return; } - String[] indexNames = getAliasIndexStream(resolvedExpression, ia, projectState.metadata()).map(Index::getName) + String[] indexNames = getAliasIndexStream(resolvedExpression, ia, projectState.metadata()).filter(filterPredicate) + .map(Index::getName) .toArray(String[]::new); Arrays.sort(indexNames); aliases.add(new ResolvedAlias(ia.getName(), indexNames)); @@ -745,7 +757,7 @@ private static void enrichIndexAbstraction( case DATA -> dataStream.getDataComponent().getIndices().stream(); case FAILURES -> dataStream.getFailureIndices().stream(); }; - String[] backingIndices = dataStreamIndices.map(Index::getName).toArray(String[]::new); + String[] backingIndices = dataStreamIndices.filter(filterPredicate).map(Index::getName).toArray(String[]::new); dataStreams.add(new ResolvedDataStream(dataStream.getName(), backingIndices, DataStream.TIMESTAMP_FIELD_NAME)); } default -> throw new IllegalStateException("unknown index abstraction type: " + ia.getType()); From 201ca9c141bae560b2d7bd2fcaa988f2de76f2f4 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 27 Aug 2025 13:36:43 -0600 Subject: [PATCH 04/14] Add tests --- .../api/indices.resolve_index.json | 67 ++++++----- .../30_resolve_index_mode_filter.yml | 108 ++++++++++++++++++ .../indices/resolve/ResolveIndexAction.java | 14 +-- .../admin/indices/RestResolveIndexAction.java | 7 ++ 4 files changed, 158 insertions(+), 38 deletions(-) create mode 100644 rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.resolve_index/30_resolve_index_mode_filter.yml diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.resolve_index.json b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.resolve_index.json index e27e3a0450bff..bedf7fc5e49e8 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.resolve_index.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.resolve_index.json @@ -1,53 +1,60 @@ { - "indices.resolve_index":{ - "documentation":{ - "url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-resolve-index-api.html", - "description":"Returns information about any matching indices, aliases, and data streams" + "indices.resolve_index": { + "documentation": { + "url": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-resolve-index-api.html", + "description": "Returns information about any matching indices, aliases, and data streams" }, - "stability":"stable", - "visibility":"public", - "headers":{ - "accept": [ "application/json"] + "stability": "stable", + "visibility": "public", + "headers": { + "accept": [ + "application/json" + ] }, - "url":{ - "paths":[ + "url": { + "paths": [ { - "path":"/_resolve/index/{name}", - "methods":[ + "path": "/_resolve/index/{name}", + "methods": [ "GET" ], - "parts":{ - "name":{ - "type":"list", - "description":"A comma-separated list of names or wildcard expressions" + "parts": { + "name": { + "type": "list", + "description": "A comma-separated list of names or wildcard expressions" } } } ] }, - "params":{ - "expand_wildcards":{ - "type":"enum", - "options":[ + "params": { + "expand_wildcards": { + "type": "enum", + "options": [ "open", "closed", "hidden", "none", "all" ], - "default":"open", - "description":"Whether wildcard expressions should get expanded to open or closed indices (default: open)" + "default": "open", + "description": "Whether wildcard expressions should get expanded to open or closed indices (default: open)" + }, + "ignore_unavailable": { + "type": "boolean", + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "default": false }, - "ignore_unavailable":{ - "type":"boolean", - "description":"Whether specified concrete indices should be ignored when unavailable (missing or closed)", - "default":false + "allow_no_indices": { + "type": "boolean", + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "default": true }, - "allow_no_indices":{ - "type":"boolean", - "description":"Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", - "default":true + "mode": { + "type": "string", + "description": "Filter indices by index mode" } } } } + diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.resolve_index/30_resolve_index_mode_filter.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.resolve_index/30_resolve_index_mode_filter.yml new file mode 100644 index 0000000000000..64ef050365981 --- /dev/null +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.resolve_index/30_resolve_index_mode_filter.yml @@ -0,0 +1,108 @@ +--- +setup: + - do: + indices.create: + index: my-std-index + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + aliases: + my-std-alias: { } + + # 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 + aliases: + my-ts-alias: { } + # Create a lookup index + - do: + indices.create: + index: my-lookup-index + body: + settings: + index.mode: lookup + aliases: + my-lookup-alias: { } + +--- +"resolve index filters by mode": + - requires: + test_runner_features: [ capabilities ] + capabilities: + - method: GET + path: /_resolve/index/* + capabilities: [ mode_filter ] + reason: "Need support for mode filtering in indices.resolve_index" + + - do: + indices.resolve_index: + name: 'my-*' + mode: lookup + - length: { indices: 1 } + - match: { indices.0.name: "my-lookup-index" } + - match: { indices.0.mode: "lookup" } + - match: { indices.0.aliases: [ "my-lookup-alias" ] } + - length: { aliases: 1 } + - match: { aliases.0.name: "my-lookup-alias" } + - match: { aliases.0.indices: [ "my-lookup-index" ] } + +--- +"resolve index filters by mode, multiple modes": + - requires: + test_runner_features: [ capabilities ] + capabilities: + - method: GET + path: /_resolve/index/* + capabilities: [ mode_filter ] + reason: "Need support for mode filtering in indices.resolve_index" + + - do: + indices.resolve_index: + name: 'my-*' + mode: time_series,standard + - length: { indices: 2 } + - match: { indices.0.name: "my-std-index" } + - match: { indices.0.mode: "standard" } + - match: { indices.0.aliases: [ "my-std-alias" ] } + - match: { indices.1.name: "my-ts-index" } + - match: { indices.1.mode: "time_series" } + - match: { indices.1.aliases: [ "my-ts-alias" ] } + - length: { aliases: 2 } + - match: { aliases.0.name: "my-std-alias" } + - match: { aliases.0.indices: [ "my-std-index" ] } + - match: { aliases.1.name: "my-ts-alias" } + - match: { aliases.1.indices: [ "my-ts-index" ] } + +--- +teardown: + - do: + indices.delete: + index: my-std-index + ignore_unavailable: true + - do: + indices.delete: + index: my-ts-index + ignore_unavailable: true + - do: + indices.delete: + index: my-lookup-index + ignore_unavailable: true diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java index ff41beffd1a9b..4d4c9c703f2da 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java @@ -735,21 +735,16 @@ private static void enrichIndexAbstraction( ); } case ALIAS -> { - if (indexModes.isEmpty() == false && indexModes.contains(IndexMode.STANDARD) == false) { - // If we didn't ask for standard indices, skip aliases too - return; - } String[] indexNames = getAliasIndexStream(resolvedExpression, ia, projectState.metadata()).filter(filterPredicate) .map(Index::getName) .toArray(String[]::new); + if (indexModes.isEmpty() == false && indexNames.length == 0) { + return; + } Arrays.sort(indexNames); aliases.add(new ResolvedAlias(ia.getName(), indexNames)); } case DATA_STREAM -> { - if (indexModes.isEmpty() == false && indexModes.contains(IndexMode.STANDARD) == false) { - // If we didn't ask for standard indices, skip datastreams too - return; - } DataStream dataStream = (DataStream) ia; Stream dataStreamIndices = resolvedExpression.selector() == null ? dataStream.getIndices().stream() @@ -758,6 +753,9 @@ private static void enrichIndexAbstraction( case FAILURES -> dataStream.getFailureIndices().stream(); }; String[] backingIndices = dataStreamIndices.filter(filterPredicate).map(Index::getName).toArray(String[]::new); + if (indexModes.isEmpty() == false && backingIndices.length == 0) { + return; + } dataStreams.add(new ResolvedDataStream(dataStream.getName(), backingIndices, DataStream.TIMESTAMP_FIELD_NAME)); } default -> throw new IllegalStateException("unknown index abstraction type: " + ia.getType()); diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java index a0f9b4804d613..4e1b956e10b59 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java @@ -24,11 +24,13 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.List; +import java.util.Set; import static org.elasticsearch.rest.RestRequest.Method.GET; @ServerlessScope(Scope.PUBLIC) public class RestResolveIndexAction extends BaseRestHandler { + private static final Set CAPABILITIES = Set.of("mode_filter"); @Override public String getName() { @@ -40,6 +42,11 @@ public List routes() { return List.of(new Route(GET, "/_resolve/index/{name}")); } + @Override + public Set supportedCapabilities() { + return CAPABILITIES; + } + @Override protected BaseRestHandler.RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { String[] indices = Strings.splitStringByCommaToArray(request.param("name")); From 2957ec833de5ec0b46b1ab94e5d6dc9d63a075ad Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 27 Aug 2025 13:42:18 -0600 Subject: [PATCH 05/14] Update docs/changelog/133616.yaml --- docs/changelog/133616.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/changelog/133616.yaml diff --git a/docs/changelog/133616.yaml b/docs/changelog/133616.yaml new file mode 100644 index 0000000000000..6ed7783c5a559 --- /dev/null +++ b/docs/changelog/133616.yaml @@ -0,0 +1,5 @@ +pr: 133616 +summary: Add mode filter to _resolve/index +area: CCS +type: enhancement +issues: [] From 917210c171d736d5f791b4b379263d4e9e6bc645 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 27 Aug 2025 13:45:02 -0600 Subject: [PATCH 06/14] Update 133616.yaml --- docs/changelog/133616.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog/133616.yaml b/docs/changelog/133616.yaml index 6ed7783c5a559..0eddbc4f7e168 100644 --- a/docs/changelog/133616.yaml +++ b/docs/changelog/133616.yaml @@ -1,5 +1,5 @@ pr: 133616 summary: Add mode filter to _resolve/index -area: CCS +area: Indices APIs type: enhancement issues: [] From dbb3906517704ce444c74df0607acb46a890b0cb Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 27 Aug 2025 13:46:07 -0600 Subject: [PATCH 07/14] Avoid too many changes to spec JSON --- .../api/indices.resolve_index.json | 63 +++++++++---------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.resolve_index.json b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.resolve_index.json index bedf7fc5e49e8..a37e613492c59 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.resolve_index.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.resolve_index.json @@ -1,54 +1,52 @@ { - "indices.resolve_index": { - "documentation": { - "url": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-resolve-index-api.html", - "description": "Returns information about any matching indices, aliases, and data streams" + "indices.resolve_index":{ + "documentation":{ + "url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-resolve-index-api.html", + "description":"Returns information about any matching indices, aliases, and data streams" }, - "stability": "stable", - "visibility": "public", - "headers": { - "accept": [ - "application/json" - ] + "stability":"stable", + "visibility":"public", + "headers":{ + "accept": [ "application/json"] }, - "url": { - "paths": [ + "url":{ + "paths":[ { - "path": "/_resolve/index/{name}", - "methods": [ + "path":"/_resolve/index/{name}", + "methods":[ "GET" ], - "parts": { - "name": { - "type": "list", - "description": "A comma-separated list of names or wildcard expressions" + "parts":{ + "name":{ + "type":"list", + "description":"A comma-separated list of names or wildcard expressions" } } } ] }, - "params": { - "expand_wildcards": { - "type": "enum", - "options": [ + "params":{ + "expand_wildcards":{ + "type":"enum", + "options":[ "open", "closed", "hidden", "none", "all" ], - "default": "open", - "description": "Whether wildcard expressions should get expanded to open or closed indices (default: open)" + "default":"open", + "description":"Whether wildcard expressions should get expanded to open or closed indices (default: open)" }, - "ignore_unavailable": { - "type": "boolean", - "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", - "default": false + "ignore_unavailable":{ + "type":"boolean", + "description":"Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "default":false }, - "allow_no_indices": { - "type": "boolean", - "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", - "default": true + "allow_no_indices":{ + "type":"boolean", + "description":"Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "default":true }, "mode": { "type": "string", @@ -57,4 +55,3 @@ } } } - From 2a65b5c6c0e58a54e0a5a701f030f58e35b1bf67 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 27 Aug 2025 15:59:34 -0600 Subject: [PATCH 08/14] alias/stream filtering --- .../indices/resolve/ResolveIndexAction.java | 40 +++++++++++++++---- .../resolve/ResolveIndexRequestTests.java | 11 ++++- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java index 4d4c9c703f2da..afaa11fba20b4 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java @@ -65,6 +65,7 @@ import java.util.SortedMap; import java.util.TreeMap; import java.util.function.Predicate; +import java.util.stream.Collectors; import java.util.stream.Stream; import static org.elasticsearch.action.search.TransportSearchHelper.checkCCSVersionCompatibility; @@ -135,12 +136,12 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Request request = (Request) o; - return Arrays.equals(names, request.names); + return Arrays.equals(names, request.names) && indexModes.equals(request.indexModes); } @Override public int hashCode() { - return Arrays.hashCode(names); + return Objects.hash(Arrays.hashCode(names), indexModes); } @Override @@ -668,14 +669,39 @@ private static void mergeResults( } indices.add(index.copy(RemoteClusterAware.buildRemoteIndexName(clusterAlias, index.getName()))); } - if (indexModes.isEmpty() == false && indexModes.contains(IndexMode.STANDARD) == false) { - continue; - } + Set indexNames = indices.stream().map(ResolvedIndexAbstraction::getName).collect(Collectors.toSet()); for (ResolvedAlias alias : response.aliases) { - aliases.add(alias.copy(RemoteClusterAware.buildRemoteIndexName(clusterAlias, alias.getName()))); + if (indexModes.isEmpty() == false) { + // We need to filter out aliases that point to no indices after index mode filtering + String[] filteredIndices = Arrays.stream(alias.getIndices()) + .filter(idxName -> indexNames.contains(RemoteClusterAware.buildRemoteIndexName(clusterAlias, idxName))) + .toArray(String[]::new); + if (filteredIndices.length == 0) { + continue; + } + alias = new ResolvedAlias(RemoteClusterAware.buildRemoteIndexName(clusterAlias, alias.getName()), filteredIndices); + } else { + alias = alias.copy(RemoteClusterAware.buildRemoteIndexName(clusterAlias, alias.getName())); + } + aliases.add(alias); } for (ResolvedDataStream dataStream : response.dataStreams) { - dataStreams.add(dataStream.copy(RemoteClusterAware.buildRemoteIndexName(clusterAlias, dataStream.getName()))); + if (indexModes.isEmpty() == false) { + String[] filteredBackingIndices = Arrays.stream(dataStream.getBackingIndices()) + .filter(idxName -> indexNames.contains(RemoteClusterAware.buildRemoteIndexName(clusterAlias, idxName))) + .toArray(String[]::new); + if (filteredBackingIndices.length == 0) { + continue; + } + dataStream = new ResolvedDataStream( + RemoteClusterAware.buildRemoteIndexName(clusterAlias, dataStream.getName()), + filteredBackingIndices, + dataStream.getTimestampField() + ); + } else { + dataStream = dataStream.copy(RemoteClusterAware.buildRemoteIndexName(clusterAlias, dataStream.getName())); + } + dataStreams.add(dataStream); } } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexRequestTests.java index c2d00a6751c58..0bd9b1174ec4d 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexRequestTests.java @@ -12,8 +12,12 @@ import org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction.Request; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.index.IndexMode; import org.elasticsearch.test.AbstractWireSerializingTestCase; +import java.util.Arrays; +import java.util.EnumSet; + public class ResolveIndexRequestTests extends AbstractWireSerializingTestCase { @Override @@ -35,7 +39,12 @@ protected Request createTestInstance() { randomBoolean(), randomBoolean() ); - return new Request(names, indicesOptions); + if (randomBoolean()) { + return new Request(names, indicesOptions); + } else { + EnumSet randomModes = EnumSet.copyOf(randomNonEmptySubsetOf(Arrays.asList(IndexMode.values()))); + return new Request(names, indicesOptions, randomBoolean() ? null : randomModes); + } } @Override From 92df4ab484ad0748585f43270e8593e32b95c4a5 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 27 Aug 2025 17:30:16 -0600 Subject: [PATCH 09/14] moar tests --- .../indices/resolve/ResolveIndexAction.java | 29 +++++++ .../indices/resolve/ResolveIndexTests.java | 79 +++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java index afaa11fba20b4..7397105e43a81 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java @@ -294,6 +294,19 @@ public int hashCode() { result = 31 * result + Arrays.hashCode(attributes); return result; } + + @Override + public String toString() { + return String.format( + Locale.ROOT, + "ResolvedIndex{name=%s, aliases=%s, attributes=%s, dataStream=%s, mode=%s}", + getName(), + Arrays.toString(aliases), + Arrays.toString(attributes), + dataStream, + mode + ); + } } public static class ResolvedAlias extends ResolvedIndexAbstraction implements Writeable, ToXContentObject { @@ -351,6 +364,11 @@ public int hashCode() { result = 31 * result + Arrays.hashCode(indices); return result; } + + @Override + public String toString() { + return String.format(Locale.ROOT, "ResolvedAlias{name=%s, indices=%s}", getName(), Arrays.toString(indices)); + } } public static class ResolvedDataStream extends ResolvedIndexAbstraction implements Writeable, ToXContentObject { @@ -418,6 +436,17 @@ public int hashCode() { result = 31 * result + Arrays.hashCode(backingIndices); return result; } + + @Override + public String toString() { + return String.format( + Locale.ROOT, + "ResolvedDataStream{name=%s, backingIndices=%s, timestampField=%s}", + getName(), + Arrays.toString(backingIndices), + timestampField + ); + } } public static class Response extends ActionResponse implements ToXContentObject { diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java index 8dbc50aae0eb7..c1abc120d4cb1 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexTests.java @@ -46,6 +46,7 @@ import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -170,6 +171,84 @@ public void testResolveStarWithAllOptions() { validateDataStreams(dataStreams, "logs-mysql-prod", "logs-mysql-test"); } + public void testResolveModesFilter() { + String[] names = randomFrom(new String[] { "*" }, new String[] { "_all" }); + List indices = new ArrayList<>(); + List aliases = new ArrayList<>(); + List dataStreams = new ArrayList<>(); + + // One type + TransportAction.resolveIndices( + names, + IndicesOptions.STRICT_EXPAND_OPEN_CLOSED_HIDDEN, + projectState, + resolver, + indices, + aliases, + dataStreams, + EnumSet.of(IndexMode.TIME_SERIES) + ); + validateIndices(indices, "logs-pgsql-prod-20200102"); + assertThat(aliases.size(), equalTo(2)); + var alias1 = aliases.get(0); + assertThat(alias1.getName(), equalTo("logs-pgsql-prod")); + assertThat(alias1.getIndices(), arrayContaining("logs-pgsql-prod-20200102")); + var alias2 = aliases.get(1); + assertThat(alias2.getName(), equalTo("one-off-alias")); + assertThat(alias2.getIndices(), arrayContaining("logs-pgsql-prod-20200102")); + assertThat(dataStreams.size(), equalTo(0)); + + indices = new ArrayList<>(); + aliases = new ArrayList<>(); + dataStreams = new ArrayList<>(); + // Everything + TransportAction.resolveIndices( + names, + IndicesOptions.STRICT_EXPAND_OPEN_CLOSED_HIDDEN, + projectState, + resolver, + indices, + aliases, + dataStreams, + EnumSet.of(IndexMode.TIME_SERIES, IndexMode.STANDARD) + ); + validateIndices( + indices, + ".ds-logs-mysql-prod-" + dateString + "-000001", + ".ds-logs-mysql-prod-" + dateString + "-000002", + ".ds-logs-mysql-prod-" + dateString + "-000003", + ".ds-logs-mysql-prod-" + dateString + "-000004", + ".ds-logs-mysql-test-" + dateString + "-000001", + ".ds-logs-mysql-test-" + dateString + "-000002", + ".test-system-index", + "logs-pgsql-prod-20200101", + "logs-pgsql-prod-20200102", + "logs-pgsql-prod-20200103", + "logs-pgsql-test-20200101", + "logs-pgsql-test-20200102", + "logs-pgsql-test-20200103" + ); + validateAliases(aliases, "logs-pgsql-prod", "logs-pgsql-test", "one-off-alias"); + validateDataStreams(dataStreams, "logs-mysql-prod", "logs-mysql-test"); + // Not matched + indices = new ArrayList<>(); + aliases = new ArrayList<>(); + dataStreams = new ArrayList<>(); + TransportAction.resolveIndices( + names, + IndicesOptions.STRICT_EXPAND_OPEN_CLOSED_HIDDEN, + projectState, + resolver, + indices, + aliases, + dataStreams, + EnumSet.of(IndexMode.LOOKUP) + ); + assertThat(indices.size(), equalTo(0)); + assertThat(aliases.size(), equalTo(0)); + assertThat(dataStreams.size(), equalTo(0)); + } + public void testResolveWithPattern() { String[] names = new String[] { "logs-pgsql*" }; IndicesOptions indicesOptions = Request.DEFAULT_INDICES_OPTIONS; From 7cdf9d99aa9d12eee34413f515edfd4b5dc0d361 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 2 Sep 2025 10:59:58 -0600 Subject: [PATCH 10/14] new terms --- .../action/admin/indices/resolve/ResolveIndexAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java index 7397105e43a81..47749ff8cd419 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java @@ -692,7 +692,7 @@ private static void mergeResults( String clusterAlias = responseEntry.getKey(); Response response = responseEntry.getValue(); for (ResolvedIndex index : response.indices) { - // We want to filter here because the remote cluster might be too old to be able to filter + // We want to filter here because the linked cluster might be too old to be able to filter if (indexModes.isEmpty() == false && indexModes.contains(index.getMode()) == false) { continue; } From 9741bae6a53e3967748cef115b7d465b1550164c Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 2 Sep 2025 12:38:32 -0600 Subject: [PATCH 11/14] More comments --- .../admin/indices/resolve/ResolveIndexAction.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java index bde3899fa36a0..c0c6196df3f0a 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java @@ -683,6 +683,10 @@ static void resolveIndices( dataStreams.sort(Comparator.comparing(ResolvedIndexAbstraction::getName)); } + /** + * Merge the results from remote clusters into the local results lists. + * This will also do index mode filtering (if requested), as the remote cluster might be too old to do it itself. + */ private static void mergeResults( Map remoteResponses, List indices, @@ -694,7 +698,7 @@ private static void mergeResults( String clusterAlias = responseEntry.getKey(); Response response = responseEntry.getValue(); for (ResolvedIndex index : response.indices) { - // We want to filter here because the linked cluster might be too old to be able to filter + // We want to filter by mode here because the linked cluster might be too old to be able to filter if (indexModes.isEmpty() == false && indexModes.contains(index.getMode()) == false) { continue; } @@ -703,11 +707,12 @@ private static void mergeResults( Set indexNames = indices.stream().map(ResolvedIndexAbstraction::getName).collect(Collectors.toSet()); for (ResolvedAlias alias : response.aliases) { if (indexModes.isEmpty() == false) { - // We need to filter out aliases that point to no indices after index mode filtering + // We filter out indices that are not included in the main index list after index mode filtering String[] filteredIndices = Arrays.stream(alias.getIndices()) .filter(idxName -> indexNames.contains(RemoteClusterAware.buildRemoteIndexName(clusterAlias, idxName))) .toArray(String[]::new); if (filteredIndices.length == 0) { + // If this alias points to no indices after filtering, we skip it continue; } alias = new ResolvedAlias(RemoteClusterAware.buildRemoteIndexName(clusterAlias, alias.getName()), filteredIndices); @@ -718,10 +723,12 @@ private static void mergeResults( } for (ResolvedDataStream dataStream : response.dataStreams) { if (indexModes.isEmpty() == false) { + // We filter out indices that are not included in the main index list after index mode filtering String[] filteredBackingIndices = Arrays.stream(dataStream.getBackingIndices()) .filter(idxName -> indexNames.contains(RemoteClusterAware.buildRemoteIndexName(clusterAlias, idxName))) .toArray(String[]::new); if (filteredBackingIndices.length == 0) { + // If this data stream points to no backing indices after filtering, we skip it continue; } dataStream = new ResolvedDataStream( From d5fa63853ddce9f67cc06518ed6cb601b2f9e45a Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 2 Sep 2025 12:40:52 -0600 Subject: [PATCH 12/14] Fix transport verrsions --- .../org/elasticsearch/TransportVersions.java | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/TransportVersions.java b/server/src/main/java/org/elasticsearch/TransportVersions.java index c4ed99c31aea8..5af12ca1169d5 100644 --- a/server/src/main/java/org/elasticsearch/TransportVersions.java +++ b/server/src/main/java/org/elasticsearch/TransportVersions.java @@ -353,24 +353,6 @@ static TransportVersion def(int id) { public static final TransportVersion ML_INFERENCE_LLAMA_ADDED = def(9_125_0_00); public static final TransportVersion SHARD_WRITE_LOAD_IN_CLUSTER_INFO = def(9_126_0_00); public static final TransportVersion ESQL_SAMPLE_OPERATOR_STATUS = def(9_127_0_00); - public static final TransportVersion ESQL_TOPN_TIMINGS = def(9_128_0_00); - public static final TransportVersion NODE_WEIGHTS_ADDED_TO_NODE_BALANCE_STATS = def(9_129_0_00); - public static final TransportVersion RERANK_SNIPPETS = def(9_130_0_00); - public static final TransportVersion PIPELINE_TRACKING_INFO = def(9_131_0_00); - public static final TransportVersion COMPONENT_TEMPLATE_TRACKING_INFO = def(9_132_0_00); - public static final TransportVersion TO_CHILD_BLOCK_JOIN_QUERY = def(9_133_0_00); - public static final TransportVersion ML_INFERENCE_AI21_COMPLETION_ADDED = def(9_134_0_00); - public static final TransportVersion TRANSPORT_NODE_USAGE_STATS_FOR_THREAD_POOLS_ACTION = def(9_135_0_00); - public static final TransportVersion INDEX_TEMPLATE_TRACKING_INFO = def(9_136_0_00); - public static final TransportVersion EXTENDED_SNAPSHOT_STATS_IN_NODE_INFO = def(9_137_0_00); - 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); - public static final TransportVersion DATA_STREAM_WRITE_INDEX_ONLY_SETTINGS = def(9_142_0_00); - public static final TransportVersion SCRIPT_RESCORER = def(9_143_0_00); - public static final TransportVersion ESQL_LOOKUP_OPERATOR_EMITTED_ROWS = def(9_144_0_00); - public static final TransportVersion ALLOCATION_DECISION_NOT_PREFERRED = def(9_145_0_00); public static final TransportVersion RESOLVE_INDEX_MODE_FILTER = def(9_146_0_00); public static final TransportVersion PROJECT_RESERVED_STATE_MOVE_TO_REGISTRY = def(9_147_0_00); public static final TransportVersion STREAMS_ENDPOINT_PARAM_RESTRICTIONS = def(9_148_0_00); From bf68218a80c7c3055b23f42ee5d94857f543be48 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 2 Sep 2025 13:04:30 -0600 Subject: [PATCH 13/14] fix imports --- .../action/admin/indices/resolve/ResolveIndexAction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java index c0c6196df3f0a..ec86ffd975940 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/resolve/ResolveIndexAction.java @@ -10,6 +10,7 @@ package org.elasticsearch.action.admin.indices.resolve; import org.elasticsearch.TransportVersion; +import org.elasticsearch.TransportVersions; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.ActionResponse; From 0cbfcd7ee992dbd003b29b5cab85e5f981fe6806 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 2 Sep 2025 16:00:15 -0600 Subject: [PATCH 14/14] Move RESOLVE_INDEX_MODE_FILTER to the end --- server/src/main/java/org/elasticsearch/TransportVersions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/TransportVersions.java b/server/src/main/java/org/elasticsearch/TransportVersions.java index 5af12ca1169d5..7c5ae10bbedbc 100644 --- a/server/src/main/java/org/elasticsearch/TransportVersions.java +++ b/server/src/main/java/org/elasticsearch/TransportVersions.java @@ -353,9 +353,9 @@ static TransportVersion def(int id) { public static final TransportVersion ML_INFERENCE_LLAMA_ADDED = def(9_125_0_00); public static final TransportVersion SHARD_WRITE_LOAD_IN_CLUSTER_INFO = def(9_126_0_00); public static final TransportVersion ESQL_SAMPLE_OPERATOR_STATUS = def(9_127_0_00); - public static final TransportVersion RESOLVE_INDEX_MODE_FILTER = def(9_146_0_00); public static final TransportVersion PROJECT_RESERVED_STATE_MOVE_TO_REGISTRY = def(9_147_0_00); public static final TransportVersion STREAMS_ENDPOINT_PARAM_RESTRICTIONS = def(9_148_0_00); + public static final TransportVersion RESOLVE_INDEX_MODE_FILTER = def(9_149_0_00); /* * STOP! READ THIS FIRST! No, really,