فهرست منبع

Convert ccs-common-rest QA project to new test clusters framework (#92516)

Mark Vieira 2 سال پیش
والد
کامیت
13181ea2e6

+ 6 - 1
build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java

@@ -40,6 +40,8 @@ import org.gradle.api.tasks.ClasspathNormalizer;
 import org.gradle.api.tasks.PathSensitivity;
 import org.gradle.api.tasks.util.PatternFilterable;
 
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -199,6 +201,7 @@ public class RestTestBasePlugin implements Plugin<Project> {
             }
             c.withDependencies(dependencies -> {
                 // Add dependencies of any modules
+                Collection<Dependency> additionalDependencies = new HashSet<>();
                 for (Dependency dependency : dependencies) {
                     if (dependency instanceof ProjectDependency projectDependency) {
                         List<String> extendedPlugins = projectDependency.getDependencyProject()
@@ -208,11 +211,13 @@ public class RestTestBasePlugin implements Plugin<Project> {
 
                         for (String extendedPlugin : extendedPlugins) {
                             findModulePath(project, extendedPlugin).ifPresent(
-                                modulePath -> dependencies.add(project.getDependencies().project(Map.of("path", modulePath)))
+                                modulePath -> additionalDependencies.add(project.getDependencies().project(Map.of("path", modulePath)))
                             );
                         }
                     }
                 }
+
+                dependencies.addAll(additionalDependencies);
             });
         });
     }

+ 6 - 59
qa/ccs-common-rest/build.gradle

@@ -1,20 +1,4 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-
-import org.elasticsearch.gradle.Version
-import org.elasticsearch.gradle.internal.test.RestIntegTestTask
-import org.elasticsearch.gradle.testclusters.DefaultTestClustersTask
-
-
-apply plugin: 'elasticsearch.internal-testclusters'
-apply plugin: 'elasticsearch.standalone-rest-test'
-apply plugin: 'elasticsearch.rest-resources'
+apply plugin: 'elasticsearch.internal-yaml-rest-test'
 
 // This subproject copies a subset of the rest-api-spec rest tests and runs them in a slightly
 // modified way on two clusters connected via CCS. All operations except searches and a few other
@@ -35,42 +19,13 @@ restResources {
   }
 }
 
-def remoteCluster = testClusters.register("ccs-remote") {
-  numberOfNodes = 2
-  setting 'node.roles', '[data,ingest,master]'
-}
-
-def localCluster = testClusters.register("ccs-local") {
-  setting 'node.roles', '[data,ingest,master,remote_cluster_client]'
-  setting 'cluster.remote.connections_per_cluster', '1'
-  setting 'cluster.remote.remote_cluster.seeds',
-    { "\"${remoteCluster.get().getAllTransportPortURI().get(0)}\"" }
-}
-
-testClusters.configureEach {
-  setting 'xpack.security.enabled', 'false'
-  requiresFeature 'es.index_mode_feature_flag_registered', Version.fromString("8.0.0")
+dependencies {
+  clusterModules project(':x-pack:plugin:async-search')
+  clusterModules project(':modules:mapper-extras')
+  clusterModules project(':modules:aggregations')
 }
 
-// the following task is needed to make sure the remote cluster is running before the local cluster
-// gets configured with the remotes cluster seed
-tasks.register('startRemoteCluster', DefaultTestClustersTask) {
-  useCluster remoteCluster
-  doLast {
-    clusters.each { c ->
-      print "Remote cluster transport uri for ccs configuration is: "
-      println c.getAllTransportPortURI().get(0)
-    }
-  }
-}
-
-tasks.register("ccs-remote", RestIntegTestTask) {
-  mustRunAfter("precommit")
-  dependsOn startRemoteCluster
-
-  useCluster remoteCluster
-  useCluster localCluster
-
+tasks.named("yamlRestTest") {
   systemProperty 'tests.rest.blacklist',
     [
       'search/150_rewrite_on_coordinator/Ensure that we fetch the document only once', // terms lookup query with index
@@ -86,13 +41,5 @@ tasks.register("ccs-remote", RestIntegTestTask) {
       'search.aggregation/70_adjacency_matrix/Terms lookup', // terms lookup by "index" doesn't seem to work correctly
       'async_search/20-with-poin-in-time/Async search with point in time' // [indices] cannot be used with point in time
     ].join(',')
-
-
-  doFirst {
-    println "Remote cluster endpoints are: ${-> remoteCluster.get().allHttpSocketURI.join(",")}"
-    println "Local cluster endpoints are: ${-> localCluster.get().allHttpSocketURI.join(",")}"
-    nonInputProperties.systemProperty('tests.rest.cluster', remoteCluster.map(c -> c.allHttpSocketURI.join(",")))
-    nonInputProperties.systemProperty('tests.rest.search_cluster', localCluster.map(c -> c.allHttpSocketURI.join(",")))
-  }
 }
 

+ 38 - 4
qa/ccs-common-rest/src/test/java/org/elasticsearch/test/rest/yaml/CcsCommonYamlTestSuiteIT.java → qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/CcsCommonYamlTestSuiteIT.java

@@ -23,6 +23,9 @@ import org.elasticsearch.client.Response;
 import org.elasticsearch.client.RestClient;
 import org.elasticsearch.core.IOUtils;
 import org.elasticsearch.core.Tuple;
+import org.elasticsearch.test.cluster.ElasticsearchCluster;
+import org.elasticsearch.test.cluster.FeatureFlag;
+import org.elasticsearch.test.cluster.local.LocalClusterConfigProvider;
 import org.elasticsearch.test.rest.ObjectPath;
 import org.elasticsearch.test.rest.yaml.section.ClientYamlTestSection;
 import org.elasticsearch.test.rest.yaml.section.DoSection;
@@ -32,6 +35,9 @@ import org.elasticsearch.test.rest.yaml.section.IsTrueAssertion;
 import org.elasticsearch.test.rest.yaml.section.MatchAssertion;
 import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -58,9 +64,34 @@ public class CcsCommonYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
     private static RestClient adminSearchClient;
     private static List<HttpHost> clusterHosts;
     private static ClientYamlTestClient searchYamlTestClient;
-
     // the remote cluster is the one we write index operations etc... to
     private static final String REMOTE_CLUSTER_NAME = "remote_cluster";
+
+    private static LocalClusterConfigProvider commonClusterConfig = cluster -> cluster.module("x-pack-async-search")
+        .module("aggregations")
+        .module("mapper-extras")
+        .setting("xpack.security.enabled", "false")
+        .feature(FeatureFlag.TIME_SERIES_MODE);
+
+    private static ElasticsearchCluster remoteCluster = ElasticsearchCluster.local()
+        .name(REMOTE_CLUSTER_NAME)
+        .nodes(2)
+        .setting("node.roles", "[data,ingest,master]")
+        .apply(commonClusterConfig)
+        .build();
+
+    private static ElasticsearchCluster localCluster = ElasticsearchCluster.local()
+        .name("local_cluster")
+        .setting("node.roles", "[data,ingest,master,remote_cluster_client]")
+        .setting("cluster.remote.remote_cluster.seeds", () -> "\"" + remoteCluster.getTransportEndpoint(0) + "\"")
+        .setting("cluster.remote.connections_per_cluster", "1")
+        .apply(commonClusterConfig)
+        .build();
+
+    @ClassRule
+    // Use a RuleChain to ensure that remote cluster is started before local cluster
+    public static TestRule clusterRule = RuleChain.outerRule(remoteCluster).around(localCluster);
+
     // the CCS api calls that we run against the "search" cluster in this test setup
     private static final Set<String> CCS_APIS = Set.of(
         "search",
@@ -75,6 +106,11 @@ public class CcsCommonYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
         "async_search.delete"
     );
 
+    @Override
+    protected String getTestRestCluster() {
+        return remoteCluster.getHttpAddresses();
+    }
+
     /**
      * initialize the search client and an additional administration client and check for an established connection
      */
@@ -84,9 +120,7 @@ public class CcsCommonYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
             assert adminSearchClient == null;
             assert clusterHosts == null;
 
-            final String cluster = System.getProperty("tests.rest.search_cluster");
-            assertNotNull("[tests.rest.search_cluster] is not configured", cluster);
-            String[] stringUrls = cluster.split(",");
+            String[] stringUrls = localCluster.getHttpAddresses().split(",");
             List<HttpHost> hosts = new ArrayList<>(stringUrls.length);
             for (String stringUrl : stringUrls) {
                 int portSeparator = stringUrl.lastIndexOf(':');

+ 24 - 0
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/ClusterHandle.java

@@ -42,4 +42,28 @@ public interface ClusterHandle extends Closeable {
      * @return cluster node HTTP transport addresses
      */
     String getHttpAddresses();
+
+    /**
+     * Returns the HTTP transport endpoint for the node at the given index. If this method is called on an unstarted cluster, the cluster
+     * will be started. This method is thread-safe and subsequent calls will wait for cluster start and availability.
+     *
+     * @return cluster node HTTP transport addresses
+     */
+    String getHttpAddress(int index);
+
+    /**
+     * Returns a comma-separated list of TCP transport endpoints for cluster. If this method is called on an unstarted cluster, the cluster
+     * will be started. This method is thread-safe and subsequent calls will wait for cluster start and availability.
+     *
+     * @return cluster node TCP transport endpoints
+     */
+    String getTransportEndpoints();
+
+    /**
+     * Returns the TCP transport endpoint for the node at the given index. If this method is called on an unstarted cluster, the cluster
+     * will be started. This method is thread-safe and subsequent calls will wait for cluster start and availability.
+     *
+     * @return cluster node TCP transport endpoints
+     */
+    String getTransportEndpoint(int index);
 }

+ 6 - 0
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalSpecBuilder.java

@@ -52,6 +52,12 @@ public abstract class AbstractLocalSpecBuilder<T extends LocalSpecBuilder<?>> im
         return cast(this);
     }
 
+    @Override
+    public T setting(String setting, Supplier<String> value) {
+        this.settingsProviders.add(s -> Map.of(setting, value.get()));
+        return cast(this);
+    }
+
     Map<String, String> getSettings() {
         return inherit(() -> parent.getSettings(), settings);
     }

+ 16 - 0
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterHandle.java

@@ -103,6 +103,22 @@ public class LocalClusterHandle implements ClusterHandle {
         return execute(() -> nodes.parallelStream().map(Node::getHttpAddress).collect(Collectors.joining(",")));
     }
 
+    @Override
+    public String getHttpAddress(int index) {
+        return getHttpAddresses().split(",")[index];
+    }
+
+    @Override
+    public String getTransportEndpoints() {
+        start();
+        return execute(() -> nodes.parallelStream().map(Node::getTransportEndpoint).collect(Collectors.joining(",")));
+    }
+
+    @Override
+    public String getTransportEndpoint(int index) {
+        return getTransportEndpoints().split(",")[index];
+    }
+
     private void waitUntilReady() {
         writeUnicastHostsFile();
         try {

+ 18 - 0
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalElasticsearchCluster.java

@@ -73,6 +73,24 @@ public class LocalElasticsearchCluster implements ElasticsearchCluster {
         return handle.getHttpAddresses();
     }
 
+    @Override
+    public String getHttpAddress(int index) {
+        checkHandle();
+        return handle.getHttpAddress(index);
+    }
+
+    @Override
+    public String getTransportEndpoints() {
+        checkHandle();
+        return handle.getTransportEndpoints();
+    }
+
+    @Override
+    public String getTransportEndpoint(int index) {
+        checkHandle();
+        return handle.getTransportEndpoint(index);
+    }
+
     private void checkHandle() {
         if (handle == null) {
             throw new IllegalStateException("Cluster handle has not been initialized. Did you forget the @ClassRule annotation?");

+ 7 - 0
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalSpecBuilder.java

@@ -13,6 +13,8 @@ import org.elasticsearch.test.cluster.FeatureFlag;
 import org.elasticsearch.test.cluster.SettingsProvider;
 import org.elasticsearch.test.cluster.local.distribution.DistributionType;
 
+import java.util.function.Supplier;
+
 interface LocalSpecBuilder<T extends LocalSpecBuilder<?>> {
     /**
      * Register a {@link SettingsProvider}.
@@ -24,6 +26,11 @@ interface LocalSpecBuilder<T extends LocalSpecBuilder<?>> {
      */
     T setting(String setting, String value);
 
+    /**
+     * Add a new node setting computed by the given supplier.
+     */
+    T setting(String setting, Supplier<String> value);
+
     /**
      * Register a {@link EnvironmentProvider}.
      */