From 5ef161d39462fb04864af739f6ef02677e0c4d34 Mon Sep 17 00:00:00 2001 From: Rene Cordier Date: Fri, 30 Jan 2026 16:48:04 +0700 Subject: [PATCH] WIP JAMES-4167 Triage rustf --- .../blob/objectstorage/aws/S3MinioDocker.java | 55 +++++++------------ .../objectstorage/aws/S3MinioExtension.java | 5 -- .../blob/objectstorage/aws/S3MinioTest.java | 47 ++-------------- 3 files changed, 24 insertions(+), 83 deletions(-) diff --git a/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioDocker.java b/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioDocker.java index d53482a39f2..adaa09878d0 100644 --- a/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioDocker.java +++ b/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioDocker.java @@ -19,6 +19,8 @@ package org.apache.james.blob.objectstorage.aws; +import static java.util.Collections.singletonMap; + import java.time.Duration; import java.util.UUID; @@ -34,13 +36,12 @@ public class S3MinioDocker { - public static final DockerImageName DOCKER_IMAGE_NAME = DockerImageName.parse("minio/minio") - .withTag("RELEASE.2025-06-13T11-33-47Z"); + public static final DockerImageName DOCKER_IMAGE_NAME = DockerImageName.parse("rustfs/rustfs") + .withTag("1.0.0-alpha.81"); - public static final int MINIO_PORT = 9000; - public static final int MINIO_WEB_ADMIN_PORT = 9090; - public static final String MINIO_ROOT_USER = "minio"; - public static final String MINIO_ROOT_PASSWORD = "minio123"; + public static final int S3_PORT = 9000; + public static final String S3_ACCESS_KEY = "testaccesskey"; + public static final String S3_SECRET_KEY = "testsecretkey"; private final GenericContainer container; @@ -55,25 +56,21 @@ public S3MinioDocker(Network network) { private GenericContainer getContainer() { return new GenericContainer<>(DOCKER_IMAGE_NAME) - .withExposedPorts(MINIO_PORT, MINIO_WEB_ADMIN_PORT) - .withEnv("MINIO_ROOT_USER", MINIO_ROOT_USER) - .withEnv("MINIO_ROOT_PASSWORD", MINIO_ROOT_PASSWORD) - .withCommand("server", "--certs-dir", "/opt/minio/certs", "/data", "--console-address", ":" + MINIO_WEB_ADMIN_PORT) - .withClasspathResourceMapping("/minio/private.key", - "/opt/minio/certs/private.key", - BindMode.READ_ONLY) - .withClasspathResourceMapping("/minio/public.crt", - "/opt/minio/certs/public.crt", - BindMode.READ_ONLY) - .waitingFor(Wait.forLogMessage(".*MinIO Object Storage Server.*", 1) + .withExposedPorts(S3_PORT) + .withEnv("RUSTFS_ACCESS_KEY", S3_ACCESS_KEY) + .withEnv("RUSTFS_SECRET_KEY", S3_SECRET_KEY) + .withEnv("RUSTFS_VOLUMES", "/data/rustfs{0..3}") + .withTmpFs(singletonMap("/data", "rw,mode=1777")) + //.waitingFor(Wait.forLogMessage(".*started successfully.*", 1) + .waitingFor(Wait.forLogMessage(".*Console WebUI.*", 2) .withStartupTimeout(Duration.ofMinutes(2))) - .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-minio-s3-test-" + UUID.randomUUID())); +// .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-rustfs-s3-test-" + UUID.randomUUID())); + .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-rustfs-s3-test")); } public void start() { if (!container.isRunning()) { container.start(); - setupMC(); } } @@ -85,25 +82,13 @@ public AwsS3AuthConfiguration getAwsS3AuthConfiguration() { Preconditions.checkArgument(container.isRunning(), "Container is not running"); return AwsS3AuthConfiguration.builder() .endpoint(Throwing.supplier(() -> new URIBuilder() - .setScheme("https") + .setScheme("http") .setHost(container.getHost()) - .setPort(container.getMappedPort(MINIO_PORT)) + .setPort(container.getMappedPort(S3_PORT)) .build()).get()) - .accessKeyId(MINIO_ROOT_USER) - .secretKey(MINIO_ROOT_PASSWORD) + .accessKeyId(S3_ACCESS_KEY) + .secretKey(S3_SECRET_KEY) .trustAll(true) .build(); } - - private void setupMC() { - Preconditions.checkArgument(container.isRunning(), "Container is not running"); - Throwing.runnable(() -> container.execInContainer("mc", "alias", "set", "--insecure", "james", "https://localhost:9000", MINIO_ROOT_USER, MINIO_ROOT_PASSWORD)).run(); - } - - public void flushAll() { - // Remove all objects - Throwing.runnable(() -> container.execInContainer("mc", "--insecure", "rm", "--recursive", "--force", "--dangerous", "james/")).run(); - // Remove all buckets - Throwing.runnable(() -> container.execInContainer("mc", "--insecure", "rb", "--force", "--dangerous", "james/")).run(); - } } diff --git a/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioExtension.java b/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioExtension.java index 12d95b3170b..833d1889871 100644 --- a/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioExtension.java +++ b/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioExtension.java @@ -38,11 +38,6 @@ public void afterAll(ExtensionContext extensionContext) { s3MinioDocker.stop(); } - @Override - public void afterEach(ExtensionContext extensionContext) { - s3MinioDocker.flushAll(); - } - @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return parameterContext.getParameter().getType() == S3MinioDocker.class; diff --git a/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioTest.java b/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioTest.java index dc4a4e3ba3b..c2631241c36 100644 --- a/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioTest.java +++ b/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/S3MinioTest.java @@ -24,28 +24,23 @@ import static org.apache.james.blob.api.BlobStoreDAOFixture.TEST_BUCKET_NAME; import static org.apache.james.blob.objectstorage.aws.S3BlobStoreConfiguration.UPLOAD_RETRY_EXCEPTION_PREDICATE; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.Optional; -import java.util.concurrent.ExecutionException; -import org.apache.james.blob.api.BlobId; import org.apache.james.blob.api.BlobStoreDAO; import org.apache.james.blob.api.BlobStoreDAOContract; import org.apache.james.blob.api.TestBlobId; import org.apache.james.metrics.api.NoopGaugeRegistry; import org.apache.james.metrics.tests.RecordingMetricFactory; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.retry.Retry; -import software.amazon.awssdk.services.s3.model.S3Exception; public class S3MinioTest implements BlobStoreDAOContract { @@ -75,24 +70,9 @@ static void tearDownClass() { s3ClientFactory.close(); } - @BeforeEach - void beforeEach() throws Exception { - // Why? https://github.com/apache/james-project/pull/1981#issuecomment-2380396460 - createBucket(TEST_BUCKET_NAME.asString()); - } - - private void createBucket(String bucketName) throws Exception { - s3ClientFactory.get().createBucket(builder -> builder.bucket(bucketName)) - .get(); - } - - private void deleteBucket(String bucketName) { - try { - s3ClientFactory.get().deleteBucket(builder -> builder.bucket(bucketName)) - .get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException("Error while deleting bucket", e); - } + @AfterEach + void tearDown() { + testee.deleteAllBuckets().block(); } @Override @@ -100,31 +80,12 @@ public BlobStoreDAO testee() { return testee; } - @Test - void saveWillThrowWhenBlobIdHasSlashCharacters() { - BlobId invalidBlobId = new TestBlobId("test-blob//id"); - assertThatThrownBy(() -> Mono.from(testee.save(TEST_BUCKET_NAME, invalidBlobId, SHORT_BYTEARRAY)).block()) - .isInstanceOf(S3Exception.class) - .hasMessageContaining("Object name contains unsupported characters"); - } - @Test void saveShouldWorkWhenValidBlobId() { Mono.from(testee.save(TEST_BUCKET_NAME, TEST_BLOB_ID, SHORT_BYTEARRAY)).block(); assertThat(Mono.from(testee.readBytes(TEST_BUCKET_NAME, TEST_BLOB_ID)).block()).isEqualTo(SHORT_BYTEARRAY); } - @Test - @Override - public void listBucketsShouldReturnEmptyWhenNone() { - deleteBucket(TEST_BUCKET_NAME.asString()); - - BlobStoreDAO store = testee(); - - assertThat(Flux.from(store.listBuckets()).collectList().block()) - .isEmpty(); - } - @Test @Override @Disabled("S3minio return `Connection: close` in header response, https://github.com/apache/james-project/pull/1981#issuecomment-2380396460")