|
8 | 8 | package org.elasticsearch.xpack.esql.session;
|
9 | 9 |
|
10 | 10 | import org.elasticsearch.ElasticsearchSecurityException;
|
| 11 | +import org.elasticsearch.ElasticsearchStatusException; |
11 | 12 | import org.elasticsearch.ExceptionsHelper;
|
12 | 13 | import org.elasticsearch.action.ActionListener;
|
13 |
| -import org.elasticsearch.action.OriginalIndices; |
14 | 14 | import org.elasticsearch.action.fieldcaps.FieldCapabilitiesFailure;
|
15 | 15 | import org.elasticsearch.action.search.ShardSearchFailure;
|
16 | 16 | import org.elasticsearch.action.support.IndicesOptions;
|
@@ -313,48 +313,53 @@ static void updateExecutionInfoAtEndOfPlanning(EsqlExecutionInfo execInfo) {
|
313 | 313 | }
|
314 | 314 |
|
315 | 315 | /**
|
316 |
| - * Checks the index expression for the presence of remote clusters. If found, it will ensure that the caller |
317 |
| - * has a valid Enterprise (or Trial) license on the querying cluster. |
318 |
| - * @param indices index expression requested by user |
319 |
| - * @param indicesGrouper grouper of index expressions by cluster alias |
320 |
| - * @param licenseState license state on the querying cluster |
| 316 | + * Checks the index expression for the presence of remote clusters. |
| 317 | + * If found, it will ensure that the caller has a valid Enterprise (or Trial) license on the querying cluster |
| 318 | + * as well as initialize corresponding cluster state in execution info. |
321 | 319 | * @throws org.elasticsearch.ElasticsearchStatusException if the license is not valid (or present) for ES|QL CCS search.
|
322 | 320 | */
|
323 |
| - public static void checkForCcsLicense( |
324 |
| - EsqlExecutionInfo executionInfo, |
325 |
| - List<IndexPattern> indices, |
| 321 | + public static void initCrossClusterState( |
326 | 322 | IndicesExpressionGrouper indicesGrouper,
|
327 |
| - Set<String> configuredClusters, |
328 |
| - XPackLicenseState licenseState |
329 |
| - ) { |
330 |
| - for (IndexPattern index : indices) { |
331 |
| - Map<String, OriginalIndices> groupedIndices; |
332 |
| - try { |
333 |
| - groupedIndices = indicesGrouper.groupIndices(configuredClusters, IndicesOptions.DEFAULT, index.indexPattern()); |
334 |
| - } catch (NoSuchRemoteClusterException e) { |
335 |
| - if (EsqlLicenseChecker.isCcsAllowed(licenseState)) { |
336 |
| - throw e; |
337 |
| - } else { |
338 |
| - throw EsqlLicenseChecker.invalidLicenseForCcsException(licenseState); |
339 |
| - } |
| 323 | + XPackLicenseState licenseState, |
| 324 | + List<IndexPattern> patterns, |
| 325 | + EsqlExecutionInfo executionInfo |
| 326 | + ) throws ElasticsearchStatusException { |
| 327 | + if (patterns.isEmpty()) { |
| 328 | + return; |
| 329 | + } |
| 330 | + assert patterns.size() == 1 : "Only single index pattern is supported"; |
| 331 | + try { |
| 332 | + var groupedIndices = indicesGrouper.groupIndices( |
| 333 | + // indicesGrouper.getConfiguredClusters() might return mutable set that changes as clusters connect or disconnect. |
| 334 | + // it is copied here so that we have the same resolution when request contains multiple remote cluster patterns with * |
| 335 | + Set.copyOf(indicesGrouper.getConfiguredClusters()), |
| 336 | + IndicesOptions.DEFAULT, |
| 337 | + patterns.getFirst().indexPattern() |
| 338 | + ); |
| 339 | + |
| 340 | + // initialize the cluster entries in EsqlExecutionInfo before throwing the invalid license error |
| 341 | + // so that the CCS telemetry handler can recognize that this error is CCS-related |
| 342 | + for (var entry : groupedIndices.entrySet()) { |
| 343 | + final String clusterAlias = entry.getKey(); |
| 344 | + final String indexExpr = Strings.arrayToCommaDelimitedString(entry.getValue().indices()); |
| 345 | + executionInfo.swapCluster(clusterAlias, (k, v) -> { |
| 346 | + assert v == null : "No cluster for " + clusterAlias + " should have been added to ExecutionInfo yet"; |
| 347 | + return new EsqlExecutionInfo.Cluster(clusterAlias, indexExpr, executionInfo.isSkipUnavailable(clusterAlias)); |
| 348 | + }); |
340 | 349 | }
|
| 350 | + |
341 | 351 | // check if it is a cross-cluster query
|
342 | 352 | if (groupedIndices.size() > 1 || groupedIndices.containsKey(RemoteClusterService.LOCAL_CLUSTER_GROUP_KEY) == false) {
|
343 | 353 | if (EsqlLicenseChecker.isCcsAllowed(licenseState) == false) {
|
344 |
| - // initialize the cluster entries in EsqlExecutionInfo before throwing the invalid license error |
345 |
| - // so that the CCS telemetry handler can recognize that this error is CCS-related |
346 |
| - for (Map.Entry<String, OriginalIndices> entry : groupedIndices.entrySet()) { |
347 |
| - executionInfo.swapCluster( |
348 |
| - entry.getKey(), |
349 |
| - (k, v) -> new EsqlExecutionInfo.Cluster( |
350 |
| - entry.getKey(), |
351 |
| - Strings.arrayToCommaDelimitedString(entry.getValue().indices()) |
352 |
| - ) |
353 |
| - ); |
354 |
| - } |
355 | 354 | throw EsqlLicenseChecker.invalidLicenseForCcsException(licenseState);
|
356 | 355 | }
|
357 | 356 | }
|
| 357 | + } catch (NoSuchRemoteClusterException e) { |
| 358 | + if (EsqlLicenseChecker.isCcsAllowed(licenseState)) { |
| 359 | + throw e; |
| 360 | + } else { |
| 361 | + throw EsqlLicenseChecker.invalidLicenseForCcsException(licenseState); |
| 362 | + } |
358 | 363 | }
|
359 | 364 | }
|
360 | 365 |
|
|
0 commit comments