Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1cfd2ca
Always error out if CCS expression shows up when CCS is not supported
smalyshev Dec 3, 2025
0cc995c
Update docs/changelog/139009.yaml
smalyshev Dec 3, 2025
3c38e78
Better fix with context option
smalyshev Dec 3, 2025
c1944c2
bug ref
smalyshev Dec 3, 2025
5664342
Reduce ctor explosion
smalyshev Dec 3, 2025
ea87ec0
improve comment
smalyshev Dec 3, 2025
266048a
fix tests
smalyshev Dec 3, 2025
f1f63dc
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 4, 2025
e177894
Fix semantic query tests
smalyshev Dec 4, 2025
734f118
more tests
smalyshev Dec 4, 2025
9217de3
fix test
smalyshev Dec 4, 2025
711f73f
disable bwc
smalyshev Dec 4, 2025
9709893
temp fix for SQL
smalyshev Dec 4, 2025
0bbf320
More test fixes
smalyshev Dec 5, 2025
a1bfc7a
Fix test
smalyshev Dec 8, 2025
a7e0a17
fix test
smalyshev Dec 8, 2025
4ee6cbe
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 9, 2025
e83781e
Update comments
smalyshev Dec 8, 2025
2977d97
Update docs/changelog/139009.yaml
smalyshev Dec 9, 2025
aba5bea
add test
smalyshev Dec 9, 2025
d92f41b
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 10, 2025
65d858d
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 10, 2025
ce6a12b
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 11, 2025
61edbc6
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 11, 2025
7ca0397
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 11, 2025
225e8a9
Revert "Update docs/changelog/139009.yaml"
smalyshev Dec 10, 2025
9b7867e
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 16, 2025
30dea66
Update docs/changelog/139009.yaml
smalyshev Dec 17, 2025
fe336ed
Merge branch 'main' into ccs-not-supported-fix
smalyshev Dec 23, 2025
589d807
Maybe this is not needed
smalyshev Dec 23, 2025
b661188
Merge branch 'main' into ccs-not-supported-fix
smalyshev Jan 2, 2026
83d2c82
Update 139009.yaml
smalyshev Jan 2, 2026
e8a6a0e
Merge branch 'main' into ccs-not-supported-fix
smalyshev Jan 5, 2026
f9965a8
rename method to emphasize it ignores remote expressions
smalyshev Jan 5, 2026
92396d7
fix comments
smalyshev Jan 5, 2026
a577e26
ws
smalyshev Jan 5, 2026
2c9bc9b
Merge branch 'main' into ccs-not-supported-fix
smalyshev Jan 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog/139009.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 139009
summary: Always error out if CCS expression shows up when CCS is not supported
area: CCS
type: bug
issues: [ 138987 ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
setup:
- do:
indices.create:
index: test_1

---
"Remote index mapping, should fail":
- requires:
cluster_features: [ "search.indices_boost_remote_index_fix" ]
reason: "indices_boost remote index fix must be present"
- do:
catch: /Cross-cluster calls are not supported in this context but remote indices were requested:/
indices.get_mapping:
index: remote1:test_1

---
"Remote and local index mapping, should fail":
- requires:
cluster_features: [ "search.indices_boost_remote_index_fix" ]
reason: "indices_boost remote index fix must be present"
- do:
catch: /Cross-cluster calls are not supported in this context but remote indices were requested:/
indices.get_mapping:
index: test_1,remote1:test_1

---
"Remote index mapping, ignore_unavailable=true, should fail":
- requires:
cluster_features: [ "search.indices_boost_remote_index_fix" ]
reason: "indices_boost remote index fix must be present"
- do:
catch: /Cross-cluster calls are not supported in this context but remote indices were requested:/
indices.get_mapping:
ignore_unavailable: true
index: remote1:test_1

Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,17 @@ setup:
- match: { hits.total: 2}
- match: { hits.hits.0._index: test_2 }
- match: { hits.hits.1._index: test_1 }

---
"Remote expressions not supported in indices boost":
- requires:
cluster_features: ["search.indices_boost_remote_index_fix"]
reason: "indices_boost remote index fix must be present"
- do:
catch: /Cross-cluster calls are not supported in this context but remote indices were requested:/
search:
rest_total_hits_as_int: true
ignore_unavailable: true
index: _all
body:
indices_boost: [{nonexistent: 2.0}, {remote1:test_1: 1.0}, {test_2: 2.0}]
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ protected void masterOperation(
request.indices()
);
Map<String, AliasFilter> indicesAndFilters = new HashMap<>();
Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressions(project.metadata(), request.indices());
Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressionsIgnoringRemotes(
project.metadata(),
request.indices()
);
for (String index : concreteIndices) {
final AliasFilter aliasFilter = indicesService.buildAliasFilter(project, index, indicesAndAliases);
final String[] aliases = indexNameExpressionResolver.allIndexAliases(project.metadata(), index, indicesAndAliases);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ static void resolveIndices(
projectState.metadata(),
indicesOptions,
true,
false,
names
);
for (ResolvedExpression s : resolvedIndexAbstractions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ private ProjectState getProjectState() {
@Override
protected ShardValidateQueryRequest newShardRequest(int numShards, ShardRouting shard, ValidateQueryRequest request) {
final ProjectState projectState = getProjectState();
final Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressions(
final Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressionsIgnoringRemotes(
projectState.metadata(),
request.indices()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ protected boolean resolveIndex(ExplainRequest request) {

@Override
protected void resolveRequest(ProjectState state, InternalRequest request) {
final Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressions(
final Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressionsIgnoringRemotes(
state.metadata(),
request.request().index()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1722,7 +1722,7 @@ private void executeSearch(
} else {
final Index[] indices = resolvedIndices.getConcreteLocalIndices();
concreteLocalIndices = Arrays.stream(indices).map(Index::getName).toArray(String[]::new);
final Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressions(
final Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressionsIgnoringRemotes(
projectState.metadata(),
searchRequest.indices()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public void searchShards(Task task, SearchShardsRequest searchShardsRequest, Act
),
listener.delegateFailureAndWrap((delegate, searchRequest) -> {
Index[] concreteIndices = resolvedIndices.getConcreteLocalIndices();
final Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressions(
final Set<ResolvedExpression> indicesAndAliases = indexNameExpressionResolver.resolveExpressionsIgnoringRemotes(
project.metadata(),
searchRequest.indices()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,12 @@ public String[] concreteIndexNames(ProjectMetadata project, IndicesOptions optio
Context context = new Context(
project,
options,
System.currentTimeMillis(),
false,
false,
false,
false,
false,
getSystemIndexAccessLevel(),
getSystemIndexAccessPredicate(),
getNetNewSystemIndexPredicate()
Expand Down Expand Up @@ -299,10 +305,12 @@ public List<ResolvedExpression> dataStreams(ProjectMetadata project, IndicesOpti
Context context = new Context(
project,
options,
System.currentTimeMillis(),
false,
false,
true,
true,
false,
getSystemIndexAccessLevel(),
getSystemIndexAccessPredicate(),
getNetNewSystemIndexPredicate()
Expand Down Expand Up @@ -463,7 +471,7 @@ public static InvalidIndexNameException invalidExclusion() {
* Validates the requested expression by performing the following checks:
* - Ensure it's not empty
* - Ensure it doesn't start with `_`
* - Ensure it's not a remote expression unless the allow unavailable targets is enabled.
* - Ensure it's not a remote expression unless remotes are allowed by the context.
*/
private static void validateResourceExpression(Context context, boolean isExclusion, String current, String[] expressions) {
if (Strings.isEmpty(current)) {
Expand All @@ -476,17 +484,14 @@ private static void validateResourceExpression(Context context, boolean isExclus
if (current.charAt(0) == '_') {
throw new InvalidIndexNameException(current, "must not start with '_'.");
}
ensureRemoteExpressionRequireIgnoreUnavailable(context.getOptions(), current, expressions);
checkForRemoteIndexExpression(context, current, expressions);
}

/**
* Throws an exception if the expression is a remote expression and we do not allow unavailable targets
* Throws an exception if the expression is a remote expression and we do not allow it.
*/
private static void ensureRemoteExpressionRequireIgnoreUnavailable(IndicesOptions options, String current, String[] expressions) {
if (options.ignoreUnavailable()) {
return;
}
if (RemoteClusterAware.isRemoteIndexName(current)) {
private static void checkForRemoteIndexExpression(Context context, String current, String[] expressions) {
if (context.isAllowRemoteIndices() == false && RemoteClusterAware.isRemoteIndexName(current)) {
List<String> crossClusterIndices = RemoteClusterAware.getRemoteIndexExpressions(expressions);
throw new IllegalArgumentException(
"Cross-cluster calls are not supported in this context but remote indices were requested: " + crossClusterIndices
Expand Down Expand Up @@ -588,6 +593,7 @@ public Index[] concreteIndices(ProjectMetadata project, IndicesRequest request,
false,
request.includeDataStreams(),
false,
false,
getSystemIndexAccessLevel(),
getSystemIndexAccessPredicate(),
getNetNewSystemIndexPredicate()
Expand Down Expand Up @@ -1006,8 +1012,8 @@ public static void assertExpressionHasNullOrDataSelector(String expression) {
/**
* Resolve an array of expressions to the set of indices and aliases that these expressions match.
*/
public Set<ResolvedExpression> resolveExpressions(ProjectMetadata project, String... expressions) {
return resolveExpressions(project, IndicesOptions.lenientExpandOpen(), false, expressions);
public Set<ResolvedExpression> resolveExpressionsIgnoringRemotes(ProjectMetadata project, String... expressions) {
return resolveExpressions(project, IndicesOptions.lenientExpandOpen(), false, true, expressions);
}

/**
Expand All @@ -1019,15 +1025,18 @@ public Set<ResolvedExpression> resolveExpressions(
ProjectMetadata project,
IndicesOptions indicesOptions,
boolean preserveDataStreams,
boolean allowRemoteIndices,
String... expressions
) {
Context context = new Context(
project,
indicesOptions,
System.currentTimeMillis(),
true,
false,
true,
preserveDataStreams,
allowRemoteIndices,
getSystemIndexAccessLevel(),
getSystemIndexAccessPredicate(),
getNetNewSystemIndexPredicate()
Expand Down Expand Up @@ -1226,7 +1235,10 @@ public Map<String, Set<String>> resolveSearchRouting(ProjectMetadata project, @N
Context context = new Context(
project,
IndicesOptions.lenientExpandOpen(),
System.currentTimeMillis(),
false,
false,
true,
false,
true,
getSystemIndexAccessLevel(),
Expand Down Expand Up @@ -1534,52 +1546,24 @@ public static class Context {
private final boolean resolveToWriteIndex;
private final boolean includeDataStreams;
private final boolean preserveDataStreams;
private final boolean allowRemoteIndices;
private final SystemIndexAccessLevel systemIndexAccessLevel;
private final Predicate<String> systemIndexAccessPredicate;
private final Predicate<String> netNewSystemIndexPredicate;

Context(ProjectMetadata project, IndicesOptions options, SystemIndexAccessLevel systemIndexAccessLevel) {
this(project, options, systemIndexAccessLevel, Predicates.always(), Predicates.never());
}

Context(
ProjectMetadata project,
IndicesOptions options,
SystemIndexAccessLevel systemIndexAccessLevel,
Predicate<String> systemIndexAccessPredicate,
Predicate<String> netNewSystemIndexPredicate
) {
this(
project,
options,
System.currentTimeMillis(),
systemIndexAccessLevel,
systemIndexAccessPredicate,
netNewSystemIndexPredicate
);
}

Context(
ProjectMetadata project,
IndicesOptions options,
boolean preserveAliases,
boolean resolveToWriteIndex,
boolean includeDataStreams,
SystemIndexAccessLevel systemIndexAccessLevel,
Predicate<String> systemIndexAccessPredicate,
Predicate<String> netNewSystemIndexPredicate
) {
this(
project,
options,
System.currentTimeMillis(),
preserveAliases,
resolveToWriteIndex,
includeDataStreams,
false,
false,
false,
false,
false,
systemIndexAccessLevel,
systemIndexAccessPredicate,
netNewSystemIndexPredicate
Predicates.always(),
Predicates.never()
);
}

Expand All @@ -1589,7 +1573,6 @@ public static class Context {
boolean preserveAliases,
boolean resolveToWriteIndex,
boolean includeDataStreams,
boolean preserveDataStreams,
SystemIndexAccessLevel systemIndexAccessLevel,
Predicate<String> systemIndexAccessPredicate,
Predicate<String> netNewSystemIndexPredicate
Expand All @@ -1601,27 +1584,6 @@ public static class Context {
preserveAliases,
resolveToWriteIndex,
includeDataStreams,
preserveDataStreams,
systemIndexAccessLevel,
systemIndexAccessPredicate,
netNewSystemIndexPredicate
);
}

Context(
ProjectMetadata project,
IndicesOptions options,
long startTime,
SystemIndexAccessLevel systemIndexAccessLevel,
Predicate<String> systemIndexAccessPredicate,
Predicate<String> netNewSystemIndexPredicate
) {
this(
project,
options,
startTime,
false,
false,
false,
false,
systemIndexAccessLevel,
Expand All @@ -1638,6 +1600,7 @@ protected Context(
boolean resolveToWriteIndex,
boolean includeDataStreams,
boolean preserveDataStreams,
boolean allowRemoteIndices,
SystemIndexAccessLevel systemIndexAccessLevel,
Predicate<String> systemIndexAccessPredicate,
Predicate<String> netNewSystemIndexPredicate
Expand All @@ -1649,6 +1612,7 @@ protected Context(
this.resolveToWriteIndex = resolveToWriteIndex;
this.includeDataStreams = includeDataStreams;
this.preserveDataStreams = preserveDataStreams;
this.allowRemoteIndices = allowRemoteIndices;
this.systemIndexAccessLevel = systemIndexAccessLevel;
this.systemIndexAccessPredicate = systemIndexAccessPredicate;
this.netNewSystemIndexPredicate = netNewSystemIndexPredicate;
Expand Down Expand Up @@ -1691,6 +1655,10 @@ public boolean isPreserveDataStreams() {
return preserveDataStreams;
}

public boolean isAllowRemoteIndices() {
return allowRemoteIndices;
}

/**
* Used to determine system index access is allowed in this context (e.g. for this request).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public Set<NodeFeature> getFeatures() {
public static final NodeFeature SEARCH_WITH_NO_DIMENSIONS_BUGFIX = new NodeFeature("search.vectors.no_dimensions_bugfix");
public static final NodeFeature SEARCH_RESCORE_SCRIPT = new NodeFeature("search.rescore.script");
public static final NodeFeature NEGATIVE_FUNCTION_SCORE_BAD_REQUEST = new NodeFeature("search.negative.function.score.bad.request");
public static final NodeFeature INDICES_BOOST_REMOTE_INDEX_FIX = new NodeFeature("search.indices_boost_remote_index_fix");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(asking to learn) Why does this need to go into a NodeFeature?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you make it a node feature? I am wondering if an API capability is more appropriate.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to make it work as API capability - which API would this capability relate to? This happens across multiple APIs... I could link it to a random API, e.g. _mappings but is that more correct?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should link it to all the affected APIs, shouldn't we?

Copy link
Copy Markdown
Contributor Author

@smalyshev smalyshev Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the APIs that use index resolution? Or can use index boosts? That could be a lot of them, and I am not sure how to practically do that. I don't think just having a test justifies changing every API that uses a feature (I am not even sure there's a way to reliably find them?), there should be some better way, unless I miss something?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the APIs that use index resolution? Or can use index boosts?

I was referring to the APIs that use index resolution but their behaviour changes with this.

That could be a lot of them, and I am not sure how to practically do that.

Considering that this is only relevant for testing, so I would add it to the APIs you are testing, in this case the mapping, the index boosts and any other you choose to test.

Unless I am mistaken API capabilities were the recommended way to capture API (and behaviour) changes. Do you think that's not the case?


@Override
public Set<NodeFeature> getTestFeatures() {
Expand All @@ -47,7 +48,8 @@ public Set<NodeFeature> getTestFeatures() {
BBQ_HNSW_DEFAULT_INDEXING,
SEARCH_WITH_NO_DIMENSIONS_BUGFIX,
SEARCH_RESCORE_SCRIPT,
NEGATIVE_FUNCTION_SCORE_BAD_REQUEST
NEGATIVE_FUNCTION_SCORE_BAD_REQUEST,
INDICES_BOOST_REMOTE_INDEX_FIX
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ public void testResolveHiddenProperlyWithDateMath() {
project,
IndicesOptions.LENIENT_EXPAND_OPEN,
true,
false,
requestedIndex
);
assertThat(resolvedIndices.size(), is(1));
Expand Down
Loading