5252import java .util .Map ;
5353import java .util .Optional ;
5454import java .util .Set ;
55+ import java .util .concurrent .atomic .AtomicBoolean ;
56+ import java .util .concurrent .atomic .AtomicReference ;
5557import java .util .function .BiPredicate ;
5658import java .util .stream .Collectors ;
5759import java .util .stream .Stream ;
@@ -78,6 +80,12 @@ public class CcsCommonYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
7880 // the remote cluster is the one we write index operations etc... to
7981 private static final String REMOTE_CLUSTER_NAME = "remote_cluster" ;
8082
83+ private static final AtomicBoolean isRemoteConfigured = new AtomicBoolean (false );
84+ private static final AtomicBoolean isCombinedComputed = new AtomicBoolean (false );
85+ private static final AtomicReference <TestFeatureService > combinedTestFeatureServiceRef = new AtomicReference <>();
86+ private static final AtomicReference <Set <String >> combinedOsSetRef = new AtomicReference <>();
87+ private static final AtomicReference <Set <String >> combinedNodeVersionsRef = new AtomicReference <>();
88+
8189 private static LocalClusterConfigProvider commonClusterConfig = cluster -> cluster .module ("x-pack-async-search" )
8290 .module ("aggregations" )
8391 .module ("analysis-common" )
@@ -165,25 +173,26 @@ public void initSearchClient() throws IOException {
165173 }
166174 clusterHosts = unmodifiableList (hosts );
167175 logger .info ("initializing REST search clients against {}" , clusterHosts );
168- searchClient = buildClient (restClientSettings (), clusterHosts .toArray (new HttpHost [clusterHosts . size () ]));
169- adminSearchClient = buildClient (restAdminSettings (), clusterHosts .toArray (new HttpHost [clusterHosts . size () ]));
176+ searchClient = buildClient (restClientSettings (), clusterHosts .toArray (new HttpHost [0 ]));
177+ adminSearchClient = buildClient (restAdminSettings (), clusterHosts .toArray (new HttpHost [0 ]));
170178
171179 searchYamlTestClient = new TestCandidateAwareClient (getRestSpec (), searchClient , hosts , this ::getClientBuilderWithSniffedHosts );
172180
173- // check that we have an established CCS connection
174- Request request = new Request ("GET" , "_remote/info" );
175- Response response = adminSearchClient .performRequest (request );
176- assertOK (response );
177- ObjectPath responseObject = ObjectPath .createFromResponse (response );
178- assertNotNull (responseObject .evaluate (REMOTE_CLUSTER_NAME ));
179- assertNull (responseObject .evaluate (REMOTE_CLUSTER_NAME + ".cluster_credentials" ));
180- logger .info ("Established connection to remote cluster [" + REMOTE_CLUSTER_NAME + "]" );
181+ assert searchClient != null ;
182+ assert adminSearchClient != null ;
183+ assert clusterHosts != null ;
184+
185+ if (isRemoteConfigured .compareAndSet (false , true )) {
186+ // check that we have an established CCS connection
187+ Request request = new Request ("GET" , "_remote/info" );
188+ Response response = adminSearchClient .performRequest (request );
189+ assertOK (response );
190+ ObjectPath responseObject = ObjectPath .createFromResponse (response );
191+ assertNotNull (responseObject .evaluate (REMOTE_CLUSTER_NAME ));
192+ assertNull (responseObject .evaluate (REMOTE_CLUSTER_NAME + ".cluster_credentials" ));
193+ logger .info ("Established connection to remote cluster [" + REMOTE_CLUSTER_NAME + "]" );
194+ }
181195 }
182-
183- assert searchClient != null ;
184- assert adminSearchClient != null ;
185- assert clusterHosts != null ;
186-
187196 searchYamlTestClient .setTestCandidate (getTestCandidate ());
188197 }
189198
@@ -301,44 +310,46 @@ protected ClientYamlTestExecutionContext createRestTestExecutionContext(
301310 final Set <String > osSet
302311 ) {
303312 try {
304- // Ensure the test specific initialization is run by calling it explicitly (@Before annotations on base-derived class may
305- // be called in a different order)
306- initSearchClient ();
307- // Reconcile and provide unified features, os, version(s), based on both clientYamlTestClient and searchYamlTestClient
308- var searchOs = readOsFromNodesInfo (adminSearchClient );
309- var searchNodeVersions = readVersionsFromNodesInfo (adminSearchClient );
310- var semanticNodeVersions = searchNodeVersions .stream ()
311- .map (ESRestTestCase ::parseLegacyVersion )
312- .flatMap (Optional ::stream )
313- .collect (Collectors .toSet ());
314- final TestFeatureService searchTestFeatureService = createTestFeatureService (
315- getClusterStateFeatures (adminSearchClient ),
316- semanticNodeVersions
317- );
318- final TestFeatureService combinedTestFeatureService = (featureId , any ) -> {
319- boolean adminFeature = testFeatureService .clusterHasFeature (featureId , any );
320- boolean searchFeature = searchTestFeatureService .clusterHasFeature (featureId , any );
321- return any ? adminFeature || searchFeature : adminFeature && searchFeature ;
322- };
323- final Set <String > combinedOsSet = Stream .concat (osSet .stream (), Stream .of (searchOs )).collect (Collectors .toSet ());
324- final Set <String > combinedNodeVersions = Stream .concat (nodesVersions .stream (), searchNodeVersions .stream ())
325- .collect (Collectors .toSet ());
313+ if (isCombinedComputed .compareAndSet (false , true )) {
314+ // Ensure the test specific initialization is run by calling it explicitly (@Before annotations on base-derived class may
315+ // be called in a different order)
316+ initSearchClient ();
317+ // Reconcile and provide unified features, os, version(s), based on both clientYamlTestClient and searchYamlTestClient
318+ var searchOs = readOsFromNodesInfo (adminSearchClient );
319+ var searchNodeVersions = readVersionsFromNodesInfo (adminSearchClient );
320+ var semanticNodeVersions = searchNodeVersions .stream ()
321+ .map (ESRestTestCase ::parseLegacyVersion )
322+ .flatMap (Optional ::stream )
323+ .collect (Collectors .toSet ());
324+ final TestFeatureService searchTestFeatureService = createTestFeatureService (
325+ getClusterStateFeatures (adminSearchClient ),
326+ semanticNodeVersions
327+ );
328+ final TestFeatureService combinedTestFeatureService = (featureId , any ) -> {
329+ boolean adminFeature = testFeatureService .clusterHasFeature (featureId , any );
330+ boolean searchFeature = searchTestFeatureService .clusterHasFeature (featureId , any );
331+ return any ? adminFeature || searchFeature : adminFeature && searchFeature ;
332+ };
333+ final Set <String > combinedOsSet = Stream .concat (osSet .stream (), Stream .of (searchOs )).collect (Collectors .toSet ());
334+ final Set <String > combinedNodeVersions = Stream .concat (nodesVersions .stream (), searchNodeVersions .stream ())
335+ .collect (Collectors .toSet ());
336+
337+ combinedTestFeatureServiceRef .set (combinedTestFeatureService );
338+ combinedOsSetRef .set (combinedOsSet );
339+ combinedNodeVersionsRef .set (combinedNodeVersions );
340+ }
326341
327342 return new ClientYamlTestExecutionContext (
328343 clientYamlTestCandidate ,
329344 clientYamlTestClient ,
330345 randomizeContentType (),
331- combinedNodeVersions ,
332- combinedTestFeatureService ,
333- combinedOsSet
346+ combinedNodeVersionsRef . get () ,
347+ combinedTestFeatureServiceRef . get () ,
348+ combinedOsSetRef . get ()
334349 ) {
335350 // depending on the API called, we either return the client running against the "write" or the "search" cluster here
336351 protected ClientYamlTestClient clientYamlTestClient (String apiName ) {
337- if (CCS_APIS .contains (apiName )) {
338- return searchYamlTestClient ;
339- } else {
340- return super .clientYamlTestClient (apiName );
341- }
352+ return CCS_APIS .contains (apiName ) ? searchYamlTestClient : super .clientYamlTestClient (apiName );
342353 }
343354 };
344355 } catch (IOException e ) {
0 commit comments