Skip to content

Commit 19c15a4

Browse files
Fix checkin
1 parent 05710b9 commit 19c15a4

File tree

2 files changed

+130
-1
lines changed

2 files changed

+130
-1
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.search.ccs;
11+
12+
import org.elasticsearch.action.search.SearchRequest;
13+
import org.elasticsearch.action.search.SearchResponse;
14+
import org.elasticsearch.action.search.TransportSearchAction;
15+
import org.elasticsearch.common.settings.Setting;
16+
import org.elasticsearch.common.settings.Settings;
17+
import org.elasticsearch.common.util.CollectionUtils;
18+
import org.elasticsearch.plugins.ClusterPlugin;
19+
import org.elasticsearch.plugins.Plugin;
20+
import org.elasticsearch.test.AbstractMultiClustersTestCase;
21+
import org.elasticsearch.transport.ConnectTransportException;
22+
import org.elasticsearch.transport.RemoteTransportException;
23+
import org.hamcrest.Matchers;
24+
25+
import java.util.Collection;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.concurrent.ExecutionException;
29+
30+
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
31+
32+
public class CpsDoesNotUseSkipUnavailableIT extends AbstractMultiClustersTestCase {
33+
private static final String LINKED_CLUSTER_1 = "cluster-a";
34+
35+
public static class CpsPlugin extends Plugin implements ClusterPlugin {
36+
@Override
37+
public List<Setting<?>> getSettings() {
38+
return List.of(ForceConnectTimeoutSetting);
39+
}
40+
}
41+
42+
private static final Setting<String> ForceConnectTimeoutSetting = Setting.simpleString(
43+
"serverless.cross_project.enabled",
44+
Setting.Property.NodeScope
45+
);
46+
47+
@Override
48+
protected List<String> remoteClusterAlias() {
49+
return List.of(LINKED_CLUSTER_1);
50+
}
51+
52+
@Override
53+
protected Collection<Class<? extends Plugin>> nodePlugins(String clusterAlias) {
54+
return CollectionUtils.appendToCopy(super.nodePlugins(clusterAlias), CpsPlugin.class);
55+
}
56+
57+
@Override
58+
protected Settings nodeSettings() {
59+
return Settings.builder().put(super.nodeSettings()).put("serverless.cross_project.enabled", "true").build();
60+
}
61+
62+
@Override
63+
protected Map<String, Boolean> skipUnavailableForRemoteClusters() {
64+
// Setting skip_unavailable=false results in a fatal error when the linked cluster is not available.
65+
return Map.of(LINKED_CLUSTER_1, false);
66+
}
67+
68+
public void testCpsShouldNotUseSkipUnavailable() {
69+
// Add some dummy data to prove we are communicating fine with the remote.
70+
assertAcked(client(LINKED_CLUSTER_1).admin().indices().prepareCreate("test-index"));
71+
client(LINKED_CLUSTER_1).prepareIndex("test-index").setSource("sample-field", "sample-value").get();
72+
client(LINKED_CLUSTER_1).admin().indices().prepareRefresh("test-index").get();
73+
74+
// Shut down the linked cluster we'd be targeting in the search.
75+
try {
76+
cluster(LINKED_CLUSTER_1).close();
77+
} catch (Exception e) {
78+
throw new AssertionError(e);
79+
}
80+
81+
/*
82+
* Under normal circumstances, we should get a fatal error for when skip_unavailable=false for a linked cluster
83+
* and that cluster is targeted in a search op. However, in CPS environment, setting allow_partial_search_results=true
84+
* should not result in a fatal error.
85+
*/
86+
{
87+
var searchRequest = getSearchRequest(true);
88+
searchRequest.setCcsMinimizeRoundtrips(randomBoolean());
89+
var result = safeGet(client().execute(TransportSearchAction.TYPE, searchRequest));
90+
91+
var originCluster = result.getClusters().getCluster(LOCAL_CLUSTER);
92+
assertThat(originCluster.getStatus(), Matchers.is(SearchResponse.Cluster.Status.SUCCESSFUL));
93+
94+
var linkedCluster = result.getClusters().getCluster(LINKED_CLUSTER_1);
95+
assertThat(linkedCluster.getStatus(), Matchers.is(SearchResponse.Cluster.Status.SKIPPED));
96+
97+
var linkedClusterFailures = result.getClusters().getCluster(LINKED_CLUSTER_1).getFailures();
98+
assertThat(linkedClusterFailures.size(), Matchers.is(1));
99+
// Failure is something along the lines of shard failure and is caused by a connection error.
100+
assertThat(
101+
linkedClusterFailures.getFirst().getCause(),
102+
Matchers.anyOf(Matchers.instanceOf(RemoteTransportException.class), Matchers.instanceOf(ConnectTransportException.class))
103+
);
104+
}
105+
106+
/*
107+
* Previously, we did not get a fatal error even when skip_unavailable=false for the linked cluster.
108+
* Now, we disable partial results and expect a fatal error. This proves that in CPS environment,
109+
* search uses allow_partial_search_results and not skip_unavailable.
110+
*/
111+
{
112+
var searchRequest = getSearchRequest(false);
113+
searchRequest.setCcsMinimizeRoundtrips(randomBoolean());
114+
var ae = expectThrows(AssertionError.class, () -> safeGet(client().execute(TransportSearchAction.TYPE, searchRequest)));
115+
assertThat(ae.getCause(), Matchers.instanceOf(ExecutionException.class));
116+
assertThat(
117+
ae.getCause().getCause(),
118+
Matchers.anyOf(Matchers.instanceOf(RemoteTransportException.class), Matchers.instanceOf(ConnectTransportException.class))
119+
);
120+
}
121+
}
122+
123+
private SearchRequest getSearchRequest(boolean allowPartialResults) {
124+
// Include both origin and linked cluster in the search op.
125+
var searchRequest = new SearchRequest("*", "*:*");
126+
searchRequest.allowPartialSearchResults(allowPartialResults);
127+
return searchRequest;
128+
}
129+
}

server/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
231231
builder.startObject();
232232
builder.field("cluster_uuid", clusterUUID);
233233
builder.field("mode", mode);
234-
// builder.field("skip_unavailable", skipUnavailable);
234+
builder.field("skip_unavailable", skipUnavailable);
235235
builder.field("transport.compress", transportCompress);
236236
builder.field("status", status);
237237
builder.field("version", versions);

0 commit comments

Comments
 (0)