From db8602e2d90853e95ddf151260df60987e8929a0 Mon Sep 17 00:00:00 2001 From: Michael Edgar Date: Mon, 19 Aug 2024 04:10:25 -0400 Subject: [PATCH] Transfer only contents of Kafka and ZooKeeper properties files (#76) Signed-off-by: Michael Edgar --- .../test/container/StrimziKafkaContainer.java | 16 +++++++-- .../container/StrimziZookeeperContainer.java | 3 +- .../java/io/strimzi/test/container/Utils.java | 34 ++++++++++++++++++- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/strimzi/test/container/StrimziKafkaContainer.java b/src/main/java/io/strimzi/test/container/StrimziKafkaContainer.java index 9545b1e..2b62bf2 100644 --- a/src/main/java/io/strimzi/test/container/StrimziKafkaContainer.java +++ b/src/main/java/io/strimzi/test/container/StrimziKafkaContainer.java @@ -75,6 +75,7 @@ public class StrimziKafkaContainer extends GenericContainer bootstrapServersProvider = c -> String.format("PLAINTEXT://%s:%s", getHost(), this.kafkaExposedPort); private String clusterId; + private MountableFile serverPropertiesFile; // proxy attributes private ToxiproxyContainer proxyContainer; @@ -282,6 +283,11 @@ protected void containerIsStarting(final InspectContainerResponse containerInfo, command += "bin/kafka-server-start.sh config/kraft/server.properties" + kafkaConfigurationOverride; } + Utils.asTransferableBytes(serverPropertiesFile).ifPresent(properties -> copyFileToContainer( + properties, + this.useKraft ? "/opt/kafka/config/kraft/server.properties" : "/opt/kafka/config/server.properties" + )); + LOGGER.info("Copying command to 'STARTER_SCRIPT' script."); copyFileToContainer( @@ -354,7 +360,7 @@ public String getBootstrapServers() { /** * Get the cluster id. This is only supported for KRaft containers. - * @return The cluster id. + * @return The cluster id. */ public String getClusterId() { return clusterId; @@ -442,8 +448,12 @@ public StrimziKafkaContainer withPort(final int fixedPort) { * @return StrimziKafkaContainer instance */ public StrimziKafkaContainer withServerProperties(final MountableFile serverPropertiesFile) { - withCopyFileToContainer(serverPropertiesFile, - this.useKraft ? "/opt/kafka/config/kraft/server.properties" : "/opt/kafka/config/server.properties"); + /* + * Save a reference to the file and delay copying to the container until the container + * is starting. This allows for `useKraft` to be set either before or after this method + * is called. + */ + this.serverPropertiesFile = serverPropertiesFile; return self(); } diff --git a/src/main/java/io/strimzi/test/container/StrimziZookeeperContainer.java b/src/main/java/io/strimzi/test/container/StrimziZookeeperContainer.java index 30cc03c..ce5a6e3 100644 --- a/src/main/java/io/strimzi/test/container/StrimziZookeeperContainer.java +++ b/src/main/java/io/strimzi/test/container/StrimziZookeeperContainer.java @@ -112,7 +112,8 @@ protected void containerIsStarting(InspectContainerResponse containerInfo, boole * @return StrimziZookeeperContainer instance */ public StrimziZookeeperContainer withZooKeeperPropertiesFile(final MountableFile zooKeeperPropertiesFile) { - withCopyFileToContainer(zooKeeperPropertiesFile, "/opt/kafka/config/zookeeper.properties"); + Utils.asTransferableBytes(zooKeeperPropertiesFile) + .ifPresent(properties -> withCopyToContainer(properties, "/opt/kafka/config/zookeeper.properties")); return this; } diff --git a/src/main/java/io/strimzi/test/container/Utils.java b/src/main/java/io/strimzi/test/container/Utils.java index 8b35808..c9072bf 100644 --- a/src/main/java/io/strimzi/test/container/Utils.java +++ b/src/main/java/io/strimzi/test/container/Utils.java @@ -7,11 +7,17 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.io.UncheckedIOException; import java.net.ServerSocket; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; import java.util.function.BooleanSupplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.images.builder.Transferable; +import org.testcontainers.utility.MountableFile; /** * Utils contains auxiliary static methods, which are used in whole project. @@ -81,6 +87,32 @@ static long waitFor(String description, long pollIntervalMs, long timeoutMs, Boo } } + /** + * Converts the contents of {@code file} to a new Transferable. If the file is + * null, an empty Optional is returned. This method reads the contents of the + * file to avoid preservation of the file's owner and group attributes when + * copying into the container. + * + * @param file the source file + * @return an Optional containing the Transferable contents of file, or an empty + * Optional when the file is null. + */ + static Optional asTransferableBytes(MountableFile file) { + if (file != null) { + final byte[] data; + + try { + data = Files.readAllBytes(Path.of(file.getFilesystemPath())); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + return Optional.of(Transferable.of(data)); + } + + return Optional.empty(); + } + /** * Finds a free server port which can be used by the web server * @@ -90,7 +122,7 @@ public static int getFreePort() { try (ServerSocket serverSocket = new ServerSocket(0)) { return serverSocket.getLocalPort(); } catch (IOException e) { - throw new RuntimeException("Failed to find free port", e); + throw new UncheckedIOException("Failed to find free port", e); } } }