浏览代码

[Test] Allow configuring configDir for the Java test cluster (#125094)

For creating and deleting projects in multi-project tests, we need
create and delete settings and secrets files on the fly. This PR adds
such feature to the Java test cluster with an option to specify the
config directory.
Yang Wang 7 月之前
父节点
当前提交
a1b0ed104b

+ 10 - 5
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalClusterFactory.java

@@ -54,6 +54,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.Properties;
 import java.util.Set;
 import java.util.Set;
 import java.util.UUID;
 import java.util.UUID;
@@ -146,7 +147,7 @@ public abstract class AbstractLocalClusterFactory<S extends LocalClusterSpec, H
             this.repoDir = baseWorkingDir.resolve("repo");
             this.repoDir = baseWorkingDir.resolve("repo");
             this.dataDir = workingDir.resolve("data");
             this.dataDir = workingDir.resolve("data");
             this.logsDir = workingDir.resolve("logs");
             this.logsDir = workingDir.resolve("logs");
-            this.configDir = workingDir.resolve("config");
+            this.configDir = Optional.ofNullable(spec.getConfigDir()).orElse(workingDir.resolve("config"));
             this.tempDir = workingDir.resolve("tmp"); // elasticsearch temporary directory
             this.tempDir = workingDir.resolve("tmp"); // elasticsearch temporary directory
             this.debugPort = DefaultLocalClusterHandle.NEXT_DEBUG_PORT.getAndIncrement();
             this.debugPort = DefaultLocalClusterHandle.NEXT_DEBUG_PORT.getAndIncrement();
         }
         }
@@ -294,6 +295,10 @@ public abstract class AbstractLocalClusterFactory<S extends LocalClusterSpec, H
             return workingDir;
             return workingDir;
         }
         }
 
 
+        Path getConfigDir() {
+            return configDir;
+        }
+
         public void waitUntilReady() {
         public void waitUntilReady() {
             try {
             try {
                 Retry.retryUntilTrue(NODE_UP_TIMEOUT, Duration.ofMillis(500), () -> {
                 Retry.retryUntilTrue(NODE_UP_TIMEOUT, Duration.ofMillis(500), () -> {
@@ -426,7 +431,7 @@ public abstract class AbstractLocalClusterFactory<S extends LocalClusterSpec, H
                 try (Stream<Path> configFiles = Files.walk(distributionDir.resolve("config"))) {
                 try (Stream<Path> configFiles = Files.walk(distributionDir.resolve("config"))) {
                     for (Path file : configFiles.toList()) {
                     for (Path file : configFiles.toList()) {
                         Path relativePath = distributionDir.resolve("config").relativize(file);
                         Path relativePath = distributionDir.resolve("config").relativize(file);
-                        Path dest = configDir.resolve(relativePath);
+                        Path dest = configDir.resolve(relativePath.toFile().getPath());
                         if (Files.exists(dest) == false) {
                         if (Files.exists(dest) == false) {
                             Files.createDirectories(dest.getParent());
                             Files.createDirectories(dest.getParent());
                             Files.copy(file, dest);
                             Files.copy(file, dest);
@@ -640,7 +645,7 @@ public abstract class AbstractLocalClusterFactory<S extends LocalClusterSpec, H
                 if (operators.isEmpty() == false) {
                 if (operators.isEmpty() == false) {
                     // TODO: Support service accounts here
                     // TODO: Support service accounts here
                     final String operatorUsersFileName = "operator_users.yml";
                     final String operatorUsersFileName = "operator_users.yml";
-                    final Path destination = workingDir.resolve("config").resolve(operatorUsersFileName);
+                    final Path destination = configDir.resolve(operatorUsersFileName);
                     if (Files.exists(destination)) {
                     if (Files.exists(destination)) {
                         throw new IllegalStateException(
                         throw new IllegalStateException(
                             "Operator users file ["
                             "Operator users file ["
@@ -667,7 +672,7 @@ public abstract class AbstractLocalClusterFactory<S extends LocalClusterSpec, H
         }
         }
 
 
         private void writeRolesFile() {
         private void writeRolesFile() {
-            Path destination = workingDir.resolve("config").resolve("roles.yml");
+            Path destination = configDir.resolve("roles.yml");
             spec.getRolesFiles().forEach(rolesFile -> {
             spec.getRolesFiles().forEach(rolesFile -> {
                 try (
                 try (
                     Writer writer = Files.newBufferedWriter(destination, StandardOpenOption.APPEND);
                     Writer writer = Files.newBufferedWriter(destination, StandardOpenOption.APPEND);
@@ -857,7 +862,7 @@ public abstract class AbstractLocalClusterFactory<S extends LocalClusterSpec, H
 
 
         private Map<String, String> getEnvironmentVariables() {
         private Map<String, String> getEnvironmentVariables() {
             Map<String, String> environment = new HashMap<>(spec.resolveEnvironment());
             Map<String, String> environment = new HashMap<>(spec.resolveEnvironment());
-            environment.put("ES_PATH_CONF", workingDir.resolve("config").toString());
+            environment.put("ES_PATH_CONF", configDir.toString());
             environment.put("ES_TMPDIR", workingDir.resolve("tmp").toString());
             environment.put("ES_TMPDIR", workingDir.resolve("tmp").toString());
             // Windows requires this as it defaults to `c:\windows` despite ES_TMPDIR
             // Windows requires this as it defaults to `c:\windows` despite ES_TMPDIR
             environment.put("TMP", workingDir.resolve("tmp").toString());
             environment.put("TMP", workingDir.resolve("tmp").toString());

+ 2 - 1
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/AbstractLocalClusterSpecBuilder.java

@@ -212,7 +212,8 @@ public abstract class AbstractLocalClusterSpecBuilder<T extends ElasticsearchClu
                 getExtraConfigFiles(),
                 getExtraConfigFiles(),
                 getSystemPropertyProviders(),
                 getSystemPropertyProviders(),
                 getSystemProperties(),
                 getSystemProperties(),
-                getJvmArgs()
+                getJvmArgs(),
+                Optional.ofNullable(getConfigDirSupplier()).map(Supplier::get).orElse(null)
             );
             );
         }
         }
     }
     }

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

@@ -17,6 +17,7 @@ import org.elasticsearch.test.cluster.local.distribution.DistributionType;
 import org.elasticsearch.test.cluster.util.Version;
 import org.elasticsearch.test.cluster.util.Version;
 import org.elasticsearch.test.cluster.util.resource.Resource;
 import org.elasticsearch.test.cluster.util.resource.Resource;
 
 
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashMap;
@@ -47,6 +48,7 @@ public abstract class AbstractLocalSpecBuilder<T extends LocalSpecBuilder<?>> im
     private DistributionType distributionType;
     private DistributionType distributionType;
     private Version version;
     private Version version;
     private String keystorePassword;
     private String keystorePassword;
+    private Supplier<Path> configDirSupplier;
 
 
     protected AbstractLocalSpecBuilder(AbstractLocalSpecBuilder<?> parent) {
     protected AbstractLocalSpecBuilder(AbstractLocalSpecBuilder<?> parent) {
         this.parent = parent;
         this.parent = parent;
@@ -270,6 +272,16 @@ public abstract class AbstractLocalSpecBuilder<T extends LocalSpecBuilder<?>> im
         return inherit(() -> parent.getKeystorePassword(), keystorePassword);
         return inherit(() -> parent.getKeystorePassword(), keystorePassword);
     }
     }
 
 
+    @Override
+    public T withConfigDir(Supplier<Path> configDirSupplier) {
+        this.configDirSupplier = configDirSupplier;
+        return cast(this);
+    }
+
+    public Supplier<Path> getConfigDirSupplier() {
+        return inherit(() -> parent.getConfigDirSupplier(), configDirSupplier);
+    }
+
     @Override
     @Override
     public T version(Version version) {
     public T version(Version version) {
         this.version = version;
         this.version = version;

+ 5 - 5
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultLocalClusterHandle.java

@@ -237,15 +237,15 @@ public class DefaultLocalClusterHandle implements LocalClusterHandle {
     private void configureWaitSecurity(WaitForHttpResource wait, Node node) {
     private void configureWaitSecurity(WaitForHttpResource wait, Node node) {
         String caFile = node.getSpec().getSetting("xpack.security.http.ssl.certificate_authorities", null);
         String caFile = node.getSpec().getSetting("xpack.security.http.ssl.certificate_authorities", null);
         if (caFile != null) {
         if (caFile != null) {
-            wait.setCertificateAuthorities(node.getWorkingDir().resolve("config").resolve(caFile).toFile());
+            wait.setCertificateAuthorities(node.getConfigDir().resolve(caFile).toFile());
         }
         }
         String sslCertFile = node.getSpec().getSetting("xpack.security.http.ssl.certificate", null);
         String sslCertFile = node.getSpec().getSetting("xpack.security.http.ssl.certificate", null);
         if (sslCertFile != null) {
         if (sslCertFile != null) {
-            wait.setCertificateAuthorities(node.getWorkingDir().resolve("config").resolve(sslCertFile).toFile());
+            wait.setCertificateAuthorities(node.getConfigDir().resolve(sslCertFile).toFile());
         }
         }
         String sslKeystoreFile = node.getSpec().getSetting("xpack.security.http.ssl.keystore.path", null);
         String sslKeystoreFile = node.getSpec().getSetting("xpack.security.http.ssl.keystore.path", null);
         if (sslKeystoreFile != null && caFile == null) { // Can not set both trust stores and CA
         if (sslKeystoreFile != null && caFile == null) { // Can not set both trust stores and CA
-            wait.setTrustStoreFile(node.getWorkingDir().resolve("config").resolve(sslKeystoreFile).toFile());
+            wait.setTrustStoreFile(node.getConfigDir().resolve(sslKeystoreFile).toFile());
         }
         }
         String keystorePassword = node.getSpec().getSetting("xpack.security.http.ssl.keystore.secure_password", null);
         String keystorePassword = node.getSpec().getSetting("xpack.security.http.ssl.keystore.secure_password", null);
         if (keystorePassword != null) {
         if (keystorePassword != null) {
@@ -254,7 +254,7 @@ public class DefaultLocalClusterHandle implements LocalClusterHandle {
     }
     }
 
 
     private boolean isSecurityAutoConfigured(Node node) {
     private boolean isSecurityAutoConfigured(Node node) {
-        Path configFile = node.getWorkingDir().resolve("config").resolve("elasticsearch.yml");
+        Path configFile = node.getConfigDir().resolve("elasticsearch.yml");
         try (Stream<String> lines = Files.lines(configFile)) {
         try (Stream<String> lines = Files.lines(configFile)) {
             return lines.anyMatch(l -> l.contains("BEGIN SECURITY AUTO CONFIGURATION"));
             return lines.anyMatch(l -> l.contains("BEGIN SECURITY AUTO CONFIGURATION"));
         } catch (IOException e) {
         } catch (IOException e) {
@@ -273,7 +273,7 @@ public class DefaultLocalClusterHandle implements LocalClusterHandle {
                     LOGGER.info("Skipping writing unicast hosts file for node {}", node.getName());
                     LOGGER.info("Skipping writing unicast hosts file for node {}", node.getName());
                     return;
                     return;
                 }
                 }
-                Path hostsFile = node.getWorkingDir().resolve("config").resolve("unicast_hosts.txt");
+                Path hostsFile = node.getConfigDir().resolve("unicast_hosts.txt");
                 LOGGER.info("Writing unicast hosts file {} for node {}", hostsFile, node.getName());
                 LOGGER.info("Writing unicast hosts file {} for node {}", hostsFile, node.getName());
                 Files.writeString(hostsFile, transportUris);
                 Files.writeString(hostsFile, transportUris);
             } catch (IOException e) {
             } catch (IOException e) {

+ 11 - 2
test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java

@@ -19,6 +19,7 @@ import org.elasticsearch.test.cluster.local.model.User;
 import org.elasticsearch.test.cluster.util.Version;
 import org.elasticsearch.test.cluster.util.Version;
 import org.elasticsearch.test.cluster.util.resource.Resource;
 import org.elasticsearch.test.cluster.util.resource.Resource;
 
 
+import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
@@ -103,6 +104,7 @@ public class LocalClusterSpec implements ClusterSpec {
         private final List<SystemPropertyProvider> systemPropertyProviders;
         private final List<SystemPropertyProvider> systemPropertyProviders;
         private final Map<String, String> systemProperties;
         private final Map<String, String> systemProperties;
         private final List<String> jvmArgs;
         private final List<String> jvmArgs;
+        private final Path configDir;
         private Version version;
         private Version version;
 
 
         public LocalNodeSpec(
         public LocalNodeSpec(
@@ -124,7 +126,8 @@ public class LocalClusterSpec implements ClusterSpec {
             Map<String, Resource> extraConfigFiles,
             Map<String, Resource> extraConfigFiles,
             List<SystemPropertyProvider> systemPropertyProviders,
             List<SystemPropertyProvider> systemPropertyProviders,
             Map<String, String> systemProperties,
             Map<String, String> systemProperties,
-            List<String> jvmArgs
+            List<String> jvmArgs,
+            Path configDir
         ) {
         ) {
             this.cluster = cluster;
             this.cluster = cluster;
             this.name = name;
             this.name = name;
@@ -145,6 +148,7 @@ public class LocalClusterSpec implements ClusterSpec {
             this.systemPropertyProviders = systemPropertyProviders;
             this.systemPropertyProviders = systemPropertyProviders;
             this.systemProperties = systemProperties;
             this.systemProperties = systemProperties;
             this.jvmArgs = jvmArgs;
             this.jvmArgs = jvmArgs;
+            this.configDir = configDir;
         }
         }
 
 
         void setVersion(Version version) {
         void setVersion(Version version) {
@@ -203,6 +207,10 @@ public class LocalClusterSpec implements ClusterSpec {
             return jvmArgs;
             return jvmArgs;
         }
         }
 
 
+        public Path getConfigDir() {
+            return configDir;
+        }
+
         public boolean isSecurityEnabled() {
         public boolean isSecurityEnabled() {
             return Boolean.parseBoolean(getSetting("xpack.security.enabled", getVersion().onOrAfter("8.0.0") ? "true" : "false"));
             return Boolean.parseBoolean(getSetting("xpack.security.enabled", getVersion().onOrAfter("8.0.0") ? "true" : "false"));
         }
         }
@@ -339,7 +347,8 @@ public class LocalClusterSpec implements ClusterSpec {
                         n.extraConfigFiles,
                         n.extraConfigFiles,
                         n.systemPropertyProviders,
                         n.systemPropertyProviders,
                         n.systemProperties,
                         n.systemProperties,
-                        n.jvmArgs
+                        n.jvmArgs,
+                        n.configDir
                     )
                     )
                 )
                 )
                 .toList();
                 .toList();

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

@@ -18,6 +18,7 @@ import org.elasticsearch.test.cluster.local.distribution.DistributionType;
 import org.elasticsearch.test.cluster.util.Version;
 import org.elasticsearch.test.cluster.util.Version;
 import org.elasticsearch.test.cluster.util.resource.Resource;
 import org.elasticsearch.test.cluster.util.resource.Resource;
 
 
+import java.nio.file.Path;
 import java.util.function.Consumer;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.function.Supplier;
@@ -155,4 +156,10 @@ interface LocalSpecBuilder<T extends LocalSpecBuilder<?>> {
      * Adds an additional command line argument to node JVM arguments.
      * Adds an additional command line argument to node JVM arguments.
      */
      */
     T jvmArg(String arg);
     T jvmArg(String arg);
+
+    /**
+     * Register a supplier to provide the config directory. The default config directory
+     * is used when the supplier is null or the return value of the supplier is null.
+     */
+    T withConfigDir(Supplier<Path> configDirSupplier);
 }
 }