From f59697e796f0b5dc967fda640ffe75fede1ad007 Mon Sep 17 00:00:00 2001 From: SBushmelev Date: Wed, 17 Dec 2025 20:50:29 +0400 Subject: [PATCH 1/2] Add method withBuckets in org.testcontainers.containers.MinIOContainer that create buckets after container started --- .../containers/MinIOContainer.java | 51 +++++++++++++++- .../containers/MinIOContainerTest.java | 58 ++++++++++++++++++- 2 files changed, 105 insertions(+), 4 deletions(-) diff --git a/modules/minio/src/main/java/org/testcontainers/containers/MinIOContainer.java b/modules/minio/src/main/java/org/testcontainers/containers/MinIOContainer.java index dfd499194ef..b3ad7940f6e 100644 --- a/modules/minio/src/main/java/org/testcontainers/containers/MinIOContainer.java +++ b/modules/minio/src/main/java/org/testcontainers/containers/MinIOContainer.java @@ -1,10 +1,18 @@ package org.testcontainers.containers; +import com.github.dockerjava.api.command.InspectContainerResponse; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.DockerImageName; +import java.io.IOException; import java.time.Duration; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static java.lang.String.format; /** * Testcontainers implementation for MinIO. @@ -29,12 +37,15 @@ public class MinIOContainer extends GenericContainer { private static final String DEFAULT_PASSWORD = "minioadmin"; + private final List buckets = new ArrayList<>(); + private String userName; private String password; /** * Constructs a MinIO container from the dockerImageName + * * @param dockerImageName the full image name to use */ public MinIOContainer(final String dockerImageName) { @@ -43,6 +54,7 @@ public MinIOContainer(final String dockerImageName) { /** * Constructs a MinIO container from the dockerImageName + * * @param dockerImageName the full image name to use */ public MinIOContainer(final DockerImageName dockerImageName) { @@ -60,6 +72,7 @@ public MinIOContainer(final DockerImageName dockerImageName) { /** * Overrides the DEFAULT_USER + * * @param userName the Root user to override * @return this */ @@ -70,6 +83,7 @@ public MinIOContainer withUserName(String userName) { /** * Overrides the DEFAULT_PASSWORD + * * @param password the Root user's password to override * @return this */ @@ -78,6 +92,17 @@ public MinIOContainer withPassword(String password) { return this; } + /** + * Create buckets after container started + * + * @param buckets bucket list + * @return this + */ + public MinIOContainer withBuckets(String... buckets) { + this.buckets.addAll(Arrays.stream(buckets).collect(Collectors.toList())); + return this; + } + /** * Configures the MinIO container */ @@ -99,7 +124,7 @@ public void configure() { * @return the URL to upload/download objects from */ public String getS3URL() { - return String.format("http://%s:%s", this.getHost(), getMappedPort(MINIO_S3_PORT)); + return format("http://%s:%s", this.getHost(), getMappedPort(MINIO_S3_PORT)); } /** @@ -115,4 +140,28 @@ public String getUserName() { public String getPassword() { return this.password; } + + @Override + protected void containerIsStarted(InspectContainerResponse containerInfo) { + if (!buckets.isEmpty()) { + try { + ExecResult setAliasExecResult = execInContainer("mc", "alias", "set", "local", format("http://localhost:%s", MINIO_S3_PORT), userName, password); + if (setAliasExecResult.getExitCode() == 0) { + for (String bucket : buckets) { + ExecResult createBucketExecResult = execInContainer("mc", "mb", format("local/%s", bucket)); + if (createBucketExecResult.getExitCode() == 0) { + logger().info("Create bucket {}", bucket); + } else { + logger().error("Cannot create bucket {}: {}", bucket, createBucketExecResult.getStderr()); + } + } + } else { + logger().error("Cannot set local alias {}", setAliasExecResult.getStderr()); + } + } catch (IOException | InterruptedException e) { + logger().error("Cannot create buckets {}", buckets, e); + } + } + } + } diff --git a/modules/minio/src/test/java/org/testcontainers/containers/MinIOContainerTest.java b/modules/minio/src/test/java/org/testcontainers/containers/MinIOContainerTest.java index 0998243de8e..743136799f4 100644 --- a/modules/minio/src/test/java/org/testcontainers/containers/MinIOContainerTest.java +++ b/modules/minio/src/test/java/org/testcontainers/containers/MinIOContainerTest.java @@ -6,19 +6,23 @@ import io.minio.StatObjectArgs; import io.minio.StatObjectResponse; import io.minio.UploadObjectArgs; +import io.minio.messages.Bucket; import org.junit.jupiter.api.Test; import java.net.URL; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; class MinIOContainerTest { + static final String MINIO_DOCKER_IMAGE_NAME = "minio/minio:RELEASE.2023-09-04T19-57-37Z"; + @Test void testBasicUsage() throws Exception { try ( // minioContainer { - MinIOContainer container = new MinIOContainer("minio/minio:RELEASE.2023-09-04T19-57-37Z"); + MinIOContainer container = new MinIOContainer(MINIO_DOCKER_IMAGE_NAME); // } ) { container.start(); @@ -58,7 +62,7 @@ void testBasicUsage() throws Exception { @Test void testDefaultUserPassword() { - try (MinIOContainer container = new MinIOContainer("minio/minio:RELEASE.2023-09-04T19-57-37Z")) { + try (MinIOContainer container = new MinIOContainer(MINIO_DOCKER_IMAGE_NAME)) { container.start(); assertThat(container.getUserName()).isEqualTo("minioadmin"); assertThat(container.getPassword()).isEqualTo("minioadmin"); @@ -69,7 +73,7 @@ void testDefaultUserPassword() { void testOverwriteUserPassword() { try ( // minioOverrides { - MinIOContainer container = new MinIOContainer("minio/minio:RELEASE.2023-09-04T19-57-37Z") + MinIOContainer container = new MinIOContainer(MINIO_DOCKER_IMAGE_NAME) .withUserName("testuser") .withPassword("testpassword"); // } @@ -79,4 +83,52 @@ void testOverwriteUserPassword() { assertThat(container.getPassword()).isEqualTo("testpassword"); } } + + @Test + void testWithBuckets() throws Exception { + try (MinIOContainer container = new MinIOContainer(MINIO_DOCKER_IMAGE_NAME) + .withUserName("testuser") + .withPassword("testpassword") + .withBuckets("first", "second")) { + container.start(); + + MinioClient minioClient = MinioClient + .builder() + .endpoint(container.getS3URL()) + .credentials(container.getUserName(), container.getPassword()) + .build(); + + BucketExistsArgs firstBucketArgs = BucketExistsArgs.builder().bucket("first").build(); + BucketExistsArgs secondBucketArgs = BucketExistsArgs.builder().bucket("second").build(); + + List bucketList = minioClient.listBuckets(); + + assertThat(bucketList).hasSize(2); + assertThat(minioClient.bucketExists(firstBucketArgs)).isTrue(); + assertThat(minioClient.bucketExists(secondBucketArgs)).isTrue(); + + minioClient.close(); + } + } + + @Test + void testWithBucketsEmpty() throws Exception { + try (MinIOContainer container = new MinIOContainer(MINIO_DOCKER_IMAGE_NAME) + .withUserName("testuser") + .withPassword("testpassword") + .withBuckets()) { + container.start(); + + MinioClient minioClient = MinioClient + .builder() + .endpoint(container.getS3URL()) + .credentials(container.getUserName(), container.getPassword()) + .build(); + + assertThat(minioClient.listBuckets()).isEmpty(); + + minioClient.close(); + } + } + } From 28b69876b8da3e844cb448a71a2ccabeb927d06e Mon Sep 17 00:00:00 2001 From: SBushmelev Date: Thu, 18 Dec 2025 19:33:07 +0400 Subject: [PATCH 2/2] Fix checkStyle --- .../org/testcontainers/containers/MinIOContainer.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/minio/src/main/java/org/testcontainers/containers/MinIOContainer.java b/modules/minio/src/main/java/org/testcontainers/containers/MinIOContainer.java index b3ad7940f6e..993944c878d 100644 --- a/modules/minio/src/main/java/org/testcontainers/containers/MinIOContainer.java +++ b/modules/minio/src/main/java/org/testcontainers/containers/MinIOContainer.java @@ -12,8 +12,6 @@ import java.util.List; import java.util.stream.Collectors; -import static java.lang.String.format; - /** * Testcontainers implementation for MinIO. *

@@ -124,7 +122,7 @@ public void configure() { * @return the URL to upload/download objects from */ public String getS3URL() { - return format("http://%s:%s", this.getHost(), getMappedPort(MINIO_S3_PORT)); + return String.format("http://%s:%s", this.getHost(), getMappedPort(MINIO_S3_PORT)); } /** @@ -145,10 +143,10 @@ public String getPassword() { protected void containerIsStarted(InspectContainerResponse containerInfo) { if (!buckets.isEmpty()) { try { - ExecResult setAliasExecResult = execInContainer("mc", "alias", "set", "local", format("http://localhost:%s", MINIO_S3_PORT), userName, password); + ExecResult setAliasExecResult = execInContainer("mc", "alias", "set", "local", String.format("http://localhost:%s", MINIO_S3_PORT), userName, password); if (setAliasExecResult.getExitCode() == 0) { for (String bucket : buckets) { - ExecResult createBucketExecResult = execInContainer("mc", "mb", format("local/%s", bucket)); + ExecResult createBucketExecResult = execInContainer("mc", "mb", String.format("local/%s", bucket)); if (createBucketExecResult.getExitCode() == 0) { logger().info("Create bucket {}", bucket); } else {