Skip to content

Commit d5b7cbf

Browse files
committed
more test fixes
1 parent 6c2a0bc commit d5b7cbf

File tree

1 file changed

+165
-7
lines changed

1 file changed

+165
-7
lines changed

x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/CrossClusterEsqlRCS1MissingIndicesIT.java

Lines changed: 165 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.io.IOException;
2222
import java.util.ArrayList;
23+
import java.util.Collection;
2324
import java.util.List;
2425
import java.util.Map;
2526
import java.util.concurrent.atomic.AtomicBoolean;
@@ -72,13 +73,19 @@ public class CrossClusterEsqlRCS1MissingIndicesIT extends AbstractRemoteClusterS
7273
private static final String INDEX1 = "points"; // on local cluster only
7374
private static final String INDEX2 = "squares"; // on local and remote clusters
7475

75-
record ExpectedCluster(String clusterAlias, String indexExpression, String status, Integer totalShards) {}
76+
record ExpectedFailure(String type, Collection<String> messages) {}
77+
78+
record ExpectedCluster(String clusterAlias, String indexExpression, String status, Integer totalShards, ExpectedFailure failure) {
79+
ExpectedCluster(String clusterAlias, String indexExpression, String status, Integer totalShards) {
80+
this(clusterAlias, indexExpression, status, totalShards, null);
81+
}
82+
}
7683

7784
@SuppressWarnings("unchecked")
7885
void assertExpectedClustersForMissingIndicesTests(Map<String, Object> responseMap, List<ExpectedCluster> expected) {
86+
boolean hasPartial = false;
7987
Map<String, ?> clusters = (Map<String, ?>) responseMap.get("_clusters");
8088
assertThat((int) responseMap.get("took"), greaterThan(0));
81-
assertThat((boolean) responseMap.get("is_partial"), is(false));
8289

8390
Map<String, ?> detailsMap = (Map<String, ?>) clusters.get("details");
8491
assertThat(detailsMap.size(), is(expected.size()));
@@ -112,24 +119,28 @@ void assertExpectedClustersForMissingIndicesTests(Map<String, Object> responseMa
112119
assertThat(failures.size(), is(1));
113120
Map<String, ?> failure1 = (Map<String, ?>) failures.get(0);
114121
Map<String, ?> innerReason = (Map<String, ?>) failure1.get("reason");
115-
String expectedMsg = "Unknown index [" + expectedCluster.indexExpression() + "]";
116-
assertThat(innerReason.get("reason").toString(), containsString(expectedMsg));
117-
assertThat(innerReason.get("type").toString(), containsString("verification_exception"));
118-
122+
if (expectedCluster.failure() != null) {
123+
for (var f : expectedCluster.failure().messages()) {
124+
assertThat(innerReason.get("reason").toString(), containsString(f));
125+
}
126+
assertThat(innerReason.get("type").toString(), containsString(expectedCluster.failure().type()));
127+
}
128+
hasPartial = true;
119129
} else {
120130
fail(msg + "; Unexpected status: " + expectedCluster.status());
121131
}
122132
// currently failed shards is always zero - change this once we start allowing partial data for individual shard failures
123133
assertThat((int) shards.get("failed"), is(0));
124134
}
135+
assertThat((boolean) responseMap.get("is_partial"), is(hasPartial));
125136
}
126137

127138
@SuppressWarnings("unchecked")
128139
public void testSearchesAgainstNonMatchingIndices() throws Exception {
129140
setupRolesAndPrivileges();
130141
setupIndex();
131142

132-
configureRemoteCluster(REMOTE_CLUSTER_ALIAS, fulfillingCluster, true, randomBoolean(), randomBoolean());
143+
configureRemoteCluster(REMOTE_CLUSTER_ALIAS, fulfillingCluster, true, randomBoolean(), false);
133144

134145
// missing concrete local index is an error
135146
{
@@ -242,6 +253,153 @@ public void testSearchesAgainstNonMatchingIndices() throws Exception {
242253
}
243254
}
244255

256+
public void testSearchesAgainstNonMatchingIndicesSkipUnavailableTrue() throws Exception {
257+
setupRolesAndPrivileges();
258+
setupIndex();
259+
260+
configureRemoteCluster(REMOTE_CLUSTER_ALIAS, fulfillingCluster, true, randomBoolean(), true);
261+
262+
// missing concrete local index is an error
263+
// TODO: this may change soon
264+
{
265+
String q = Strings.format("FROM nomatch,%s:%s | STATS count(*)", REMOTE_CLUSTER_ALIAS, INDEX2);
266+
267+
String limit1 = q + " | LIMIT 1";
268+
ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest(esqlRequest(limit1)));
269+
assertThat(e.getMessage(), containsString("Unknown index [nomatch]"));
270+
271+
String limit0 = q + " | LIMIT 0";
272+
e = expectThrows(ResponseException.class, () -> client().performRequest(esqlRequest(limit0)));
273+
assertThat(e.getMessage(), containsString("Unknown index [nomatch]"));
274+
}
275+
276+
// missing concrete index on remote cluster is a failure if it's alone
277+
{
278+
String q = Strings.format("FROM %s:nomatch", REMOTE_CLUSTER_ALIAS);
279+
280+
String limit1 = q + " | LIMIT 1";
281+
ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest(esqlRequest(limit1)));
282+
assertThat(e.getMessage(), containsString(Strings.format("Unknown index [%s:nomatch]", REMOTE_CLUSTER_ALIAS)));
283+
284+
String limit0 = q + " | LIMIT 0";
285+
e = expectThrows(ResponseException.class, () -> client().performRequest(esqlRequest(limit0)));
286+
assertThat(e.getMessage(), containsString(Strings.format("Unknown index [%s:nomatch]", REMOTE_CLUSTER_ALIAS)));
287+
}
288+
289+
// since there is at least one matching index in the query, the missing wildcarded local index is not an error
290+
{
291+
String q = Strings.format("FROM nomatch*,%s:%s", REMOTE_CLUSTER_ALIAS, INDEX2);
292+
293+
String limit1 = q + " | LIMIT 1";
294+
Response response = client().performRequest(esqlRequest(limit1));
295+
assertOK(response);
296+
297+
Map<String, Object> map = responseAsMap(response);
298+
assertThat(((ArrayList<?>) map.get("columns")).size(), greaterThanOrEqualTo(1));
299+
assertThat(((ArrayList<?>) map.get("values")).size(), greaterThanOrEqualTo(1));
300+
301+
assertExpectedClustersForMissingIndicesTests(
302+
map,
303+
List.of(
304+
// local cluster is never marked as SKIPPED even when no matching indices - just marked as 0 shards searched
305+
new ExpectedCluster("(local)", "nomatch*", "successful", 0),
306+
new ExpectedCluster(REMOTE_CLUSTER_ALIAS, INDEX2, "successful", null)
307+
)
308+
);
309+
310+
String limit0 = q + " | LIMIT 0";
311+
response = client().performRequest(esqlRequest(limit0));
312+
assertOK(response);
313+
314+
map = responseAsMap(response);
315+
assertThat(((ArrayList<?>) map.get("columns")).size(), greaterThanOrEqualTo(1));
316+
assertThat(((ArrayList<?>) map.get("values")).size(), is(0));
317+
318+
assertExpectedClustersForMissingIndicesTests(
319+
map,
320+
List.of(
321+
// local cluster is never marked as SKIPPED even when no matching indices - just marked as 0 shards searched
322+
new ExpectedCluster("(local)", "nomatch*", "successful", 0),
323+
new ExpectedCluster(REMOTE_CLUSTER_ALIAS, INDEX2, "successful", 0)
324+
)
325+
);
326+
}
327+
328+
// an error is thrown if there are no matching indices at all
329+
{
330+
String q = Strings.format("FROM %s:nomatch*", REMOTE_CLUSTER_ALIAS);
331+
332+
String limit1 = q + " | LIMIT 1";
333+
ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest(esqlRequest(limit1)));
334+
assertThat(e.getMessage(), containsString(Strings.format("Unknown index [%s:nomatch*]", REMOTE_CLUSTER_ALIAS)));
335+
336+
String limit0 = q + " | LIMIT 0";
337+
e = expectThrows(ResponseException.class, () -> client().performRequest(esqlRequest(limit0)));
338+
assertThat(e.getMessage(), containsString(Strings.format("Unknown index [%s:nomatch*]", REMOTE_CLUSTER_ALIAS)));
339+
}
340+
341+
// an error is thrown if there are no matching indices at all (2 clusters)
342+
{
343+
String localExpr = "nomatch*";
344+
String remoteExpr = "nomatch*";
345+
String q = Strings.format("FROM %s,%s:%s", localExpr, REMOTE_CLUSTER_ALIAS, remoteExpr);
346+
347+
String limit1 = q + " | LIMIT 1";
348+
ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest(esqlRequest(limit1)));
349+
assertThat(e.getMessage(), containsString("Unknown index"));
350+
assertThat(e.getMessage(), containsString(Strings.format("%s:%s", REMOTE_CLUSTER_ALIAS, remoteExpr)));
351+
352+
String limit0 = q + " | LIMIT 0";
353+
e = expectThrows(ResponseException.class, () -> client().performRequest(esqlRequest(limit0)));
354+
assertThat(e.getMessage(), containsString("Unknown index"));
355+
assertThat(e.getMessage(), containsString(Strings.format("%s:%s", REMOTE_CLUSTER_ALIAS, remoteExpr)));
356+
}
357+
358+
// the remote cluster specified a concrete index that is not found - skip
359+
{
360+
String q = Strings.format("FROM %s,%s:nomatch,%s:%s*", INDEX1, REMOTE_CLUSTER_ALIAS, REMOTE_CLUSTER_ALIAS, INDEX2);
361+
362+
String limit1 = q + " | LIMIT 1";
363+
Response response = client().performRequest(esqlRequest(limit1));
364+
assertOK(response);
365+
366+
Map<String, Object> map = responseAsMap(response);
367+
assertThat(((ArrayList<?>) map.get("columns")).size(), greaterThanOrEqualTo(1));
368+
assertThat(((ArrayList<?>) map.get("values")).size(), greaterThanOrEqualTo(1));
369+
370+
assertExpectedClustersForMissingIndicesTests(
371+
map,
372+
List.of(
373+
new ExpectedCluster("(local)", INDEX1, "successful", null),
374+
// TODO: this will eventually be SUCCESS
375+
new ExpectedCluster(
376+
REMOTE_CLUSTER_ALIAS,
377+
"nomatch," + INDEX2,
378+
"skipped",
379+
0,
380+
new ExpectedFailure("index_not_found_exception", List.of("no such index", "nomatch"))
381+
)
382+
)
383+
);
384+
385+
String limit0 = q + " | LIMIT 0";
386+
response = client().performRequest(esqlRequest(limit0));
387+
assertOK(response);
388+
389+
map = responseAsMap(response);
390+
assertThat(((ArrayList<?>) map.get("columns")).size(), greaterThanOrEqualTo(1));
391+
assertThat(((ArrayList<?>) map.get("values")).size(), greaterThanOrEqualTo(0));
392+
393+
assertExpectedClustersForMissingIndicesTests(
394+
map,
395+
List.of(
396+
new ExpectedCluster("(local)", INDEX1, "successful", 0),
397+
new ExpectedCluster(REMOTE_CLUSTER_ALIAS, "nomatch," + INDEX2, "successful", 0)
398+
)
399+
);
400+
}
401+
}
402+
245403
private void setupRolesAndPrivileges() throws IOException {
246404
var putUserRequest = new Request("PUT", "/_security/user/" + REMOTE_SEARCH_USER);
247405
putUserRequest.setJsonEntity("""

0 commit comments

Comments
 (0)