47
47
import java .util .Map ;
48
48
import java .util .Optional ;
49
49
import java .util .Set ;
50
+ import java .util .concurrent .atomic .AtomicBoolean ;
50
51
import java .util .concurrent .atomic .AtomicReference ;
51
52
import java .util .stream .Collectors ;
52
53
import java .util .stream .Stream ;
@@ -75,6 +76,11 @@ public class RcsCcsCommonYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
75
76
// the remote cluster is the one we write index operations etc... to
76
77
private static final String REMOTE_CLUSTER_NAME = "remote_cluster" ;
77
78
private static final AtomicReference <Map <String , Object >> API_KEY_MAP_REF = new AtomicReference <>();
79
+ private static final AtomicBoolean isRemoteConfigured = new AtomicBoolean (false );
80
+ private static final AtomicBoolean isCombinedComputed = new AtomicBoolean (false );
81
+ private static final AtomicReference <TestFeatureService > combinedTestFeatureServiceRef = new AtomicReference <>();
82
+ private static final AtomicReference <Set <String >> combinedOsSetRef = new AtomicReference <>();
83
+ private static final AtomicReference <Set <String >> combinedNodeVersionsRef = new AtomicReference <>();
78
84
79
85
private static LocalClusterConfigProvider commonClusterConfig = cluster -> cluster .module ("x-pack-async-search" )
80
86
.module ("aggregations" )
@@ -217,7 +223,7 @@ public void initSearchClient() throws IOException {
217
223
basicAuthHeaderValue ("remote_search_user" , new SecureString ("x-pack-test-password" .toCharArray ()))
218
224
)
219
225
.build (),
220
- clusterHosts .toArray (new HttpHost [clusterHosts . size () ])
226
+ clusterHosts .toArray (new HttpHost [0 ])
221
227
);
222
228
adminSearchClient = buildClient (
223
229
Settings .builder ()
@@ -226,13 +232,18 @@ public void initSearchClient() throws IOException {
226
232
basicAuthHeaderValue ("test_admin" , new SecureString ("x-pack-test-password" .toCharArray ()))
227
233
)
228
234
.build (),
229
- clusterHosts .toArray (new HttpHost [clusterHosts . size () ])
235
+ clusterHosts .toArray (new HttpHost [0 ])
230
236
);
231
237
232
238
searchYamlTestClient = new TestCandidateAwareClient (getRestSpec (), searchClient , hosts , this ::getClientBuilderWithSniffedHosts );
239
+ }
240
+
241
+ assert searchClient != null ;
242
+ assert adminSearchClient != null ;
243
+ assert clusterHosts != null ;
233
244
245
+ if (isRemoteConfigured .compareAndSet (false , true )) {
234
246
configureRemoteCluster ();
235
- // check that we have an established CCS connection
236
247
Request request = new Request ("GET" , "_remote/info" );
237
248
Response response = adminSearchClient .performRequest (request );
238
249
assertOK (response );
@@ -241,11 +252,6 @@ public void initSearchClient() throws IOException {
241
252
assertEquals ("::es_redacted::" , responseObject .evaluate (REMOTE_CLUSTER_NAME + ".cluster_credentials" ));
242
253
logger .info ("Established connection to remote cluster [" + REMOTE_CLUSTER_NAME + "]" );
243
254
}
244
-
245
- assert searchClient != null ;
246
- assert adminSearchClient != null ;
247
- assert clusterHosts != null ;
248
-
249
255
searchYamlTestClient .setTestCandidate (getTestCandidate ());
250
256
}
251
257
@@ -288,42 +294,47 @@ protected ClientYamlTestExecutionContext createRestTestExecutionContext(
288
294
// Ensure the test specific initialization is run by calling it explicitly (@Before annotations on base-derived class may
289
295
// be called in a different order)
290
296
initSearchClient ();
291
- // Reconcile and provide unified features, os, version(s), based on both clientYamlTestClient and searchYamlTestClient
292
- var searchOs = readOsFromNodesInfo (adminSearchClient );
293
- var searchNodeVersions = readVersionsFromNodesInfo (adminSearchClient );
294
- var semanticNodeVersions = searchNodeVersions .stream ()
295
- .map (ESRestTestCase ::parseLegacyVersion )
296
- .flatMap (Optional ::stream )
297
- .collect (Collectors .toSet ());
298
- final TestFeatureService searchTestFeatureService = createTestFeatureService (
299
- getClusterStateFeatures (adminSearchClient ),
300
- semanticNodeVersions
301
- );
302
- final TestFeatureService combinedTestFeatureService = (featureId , any ) -> {
303
- boolean adminFeature = testFeatureService .clusterHasFeature (featureId , any );
304
- boolean searchFeature = searchTestFeatureService .clusterHasFeature (featureId , any );
305
- return any ? adminFeature || searchFeature : adminFeature && searchFeature ;
306
- };
307
297
308
- final Set <String > combinedOsSet = Stream .concat (osSet .stream (), Stream .of (searchOs )).collect (Collectors .toSet ());
309
- final Set <String > combinedNodeVersions = Stream .concat (nodesVersions .stream (), searchNodeVersions .stream ())
310
- .collect (Collectors .toSet ());
298
+ // Compute & cache combined features/OS/versions
299
+ if (isCombinedComputed .compareAndSet (false , true )) {
300
+ var searchOs = readOsFromNodesInfo (adminSearchClient );
301
+ var searchNodeVersions = readVersionsFromNodesInfo (adminSearchClient );
302
+
303
+ var semanticNodeVersions = searchNodeVersions .stream ()
304
+ .map (ESRestTestCase ::parseLegacyVersion )
305
+ .flatMap (Optional ::stream )
306
+ .collect (Collectors .toSet ());
307
+
308
+ final TestFeatureService searchTestFeatureService = createTestFeatureService (
309
+ getClusterStateFeatures (adminSearchClient ),
310
+ semanticNodeVersions
311
+ );
312
+
313
+ final TestFeatureService combinedTestFeatureService = (featureId , any ) -> {
314
+ boolean adminFeature = testFeatureService .clusterHasFeature (featureId , any );
315
+ boolean searchFeature = searchTestFeatureService .clusterHasFeature (featureId , any );
316
+ return any ? (adminFeature || searchFeature ) : (adminFeature && searchFeature );
317
+ };
318
+ final Set <String > combinedOsSet = Stream .concat (osSet .stream (), Stream .of (searchOs )).collect (Collectors .toSet ());
319
+ final Set <String > combinedNodeVersions = Stream .concat (nodesVersions .stream (), searchNodeVersions .stream ())
320
+ .collect (Collectors .toSet ());
321
+
322
+ combinedTestFeatureServiceRef .set (combinedTestFeatureService );
323
+ combinedOsSetRef .set (combinedOsSet );
324
+ combinedNodeVersionsRef .set (combinedNodeVersions );
325
+ }
311
326
312
327
return new ClientYamlTestExecutionContext (
313
328
clientYamlTestCandidate ,
314
329
clientYamlTestClient ,
315
330
randomizeContentType (),
316
- combinedNodeVersions ,
317
- combinedTestFeatureService ,
318
- combinedOsSet
331
+ combinedNodeVersionsRef . get () ,
332
+ combinedTestFeatureServiceRef . get () ,
333
+ combinedOsSetRef . get ()
319
334
) {
320
335
// depending on the API called, we either return the client running against the "write" or the "search" cluster here
321
336
protected ClientYamlTestClient clientYamlTestClient (String apiName ) {
322
- if (CCS_APIS .contains (apiName )) {
323
- return searchYamlTestClient ;
324
- } else {
325
- return super .clientYamlTestClient (apiName );
326
- }
337
+ return CCS_APIS .contains (apiName ) ? searchYamlTestClient : super .clientYamlTestClient (apiName );
327
338
}
328
339
};
329
340
} catch (IOException e ) {
0 commit comments