配置 Minio 服务器以与测试容器一起使用

ott*_*ath 8 docker minio testcontainers

我的应用程序使用Minio进行 S3 兼容的对象存储,并且我想通过Testcontainers在集成测试中使用 Minio docker 映像。

对于一些非常基本的测试,我使用 docker 映像运行 GenericContainer ,除了和 之外minio/minio没有任何配置。然后我的测试使用 Minio 的Java Client SDK。这些工作正常并且表现得像预期的那样。MINIO_ACCESS_KEYMINIO_SECRET_KEY

但对于其他集成测试,我需要在 Mino 中设置单独的用户。据我所知,用户只能使用Admin API添加到 Minio ,没有 Java 客户端,只有minio/mcdocker 镜像( CLI 在用于服务器的 docker 镜像mc中不可用)。minio/minio

在命令行上,我可以像这样使用 Admin API:

$ docker run --interactive --tty --detach --entrypoint=/bin/sh --name minio_admin minio/mc
Run Code Online (Sandbox Code Playgroud)

保持容器运行有点--interactive --tty困难,这样我以后就可以运行如下命令:

$ docker exec --interactive --tty minio_admin mc admin user add ...
Run Code Online (Sandbox Code Playgroud)

使用 Testcontainers,我尝试这样做:

public void testAdminApi() throws Exception {
    GenericContainer mc = new GenericContainer("minio/mc")
            .withCommand("/bin/sh")
            .withCreateContainerCmdModifier(new Consumer<CreateContainerCmd>() {
                @Override
                public void accept(CreateContainerCmd cmd) {
                    cmd
                            .withAttachStdin(true)
                            .withStdinOpen(true)
                            .withTty(true);
                }
            });

    mc.start();
    log.info("mc is running: {}", mc.isRunning());

    String command = "mc";
    Container.ExecResult result = mc.execInContainer(command);
    log.info("Executing command '{}' returned exit code '{}' and stdout '{}'", command, result.getExitCode(), result.getStdout());

    assertEquals(0, result.getExitCode());
}
Run Code Online (Sandbox Code Playgroud)

日志显示容器正在启动,但对其执行命令会返回退出代码 126 并声明其处于停止状态:

[minio/mc:latest] - Starting container with ID: 4f96fc7583fe62290925472c4c6b329fbeb7a55b38a3c0ad41ee797db1431841
[minio/mc:latest] - Container minio/mc:latest is starting: 4f96fc7583fe62290925472c4c6b329fbeb7a55b38a3c0ad41ee797db1431841
[minio/mc:latest] - Container minio/mc:latest started
minio.MinioAdminTests - mc is running: true
org.testcontainers.containers.ExecInContainerPattern - /kind_volhard: Running "exec" command: mc
minio.MinioAdminTests - Executing command 'mc' returned exit code '126'
  and stdout 'cannot exec in a stopped state: unknown'

java.lang.AssertionError: Expected: 0, Actual: 126
Run Code Online (Sandbox Code Playgroud)

在摆弄这个问题几个小时之后,我已经没有想法了。有人可以帮忙吗?

ott*_*ath 7

感谢@glebsts 和@bsideup,我能够让我的集成测试正常工作。以下是如何添加用户的最小示例:

public class MinioIntegrationTest {

    private static final String ADMIN_ACCESS_KEY = "admin";
    private static final String ADMIN_SECRET_KEY = "12345678";
    private static final String USER_ACCESS_KEY = "bob";
    private static final String USER_SECRET_KEY = "87654321";

    private static GenericContainer minioServer;
    private static String minioServerUrl;

    @BeforeAll
    static void setUp() throws Exception {
        int port = 9000;
        minioServer = new GenericContainer("minio/minio")
                .withEnv("MINIO_ACCESS_KEY", ADMIN_ACCESS_KEY)
                .withEnv("MINIO_SECRET_KEY", ADMIN_SECRET_KEY)
                .withCommand("server /data")
                .withExposedPorts(port)
                .waitingFor(new HttpWaitStrategy()
                        .forPath("/minio/health/ready")
                        .forPort(port)
                        .withStartupTimeout(Duration.ofSeconds(10)));
        minioServer.start();

        Integer mappedPort = minioServer.getFirstMappedPort();
        Testcontainers.exposeHostPorts(mappedPort);
        minioServerUrl = String.format("http://%s:%s", minioServer.getContainerIpAddress(), mappedPort);

        // Minio Java SDK uses s3v4 protocol by default, need to specify explicitly for mc
        String cmdTpl = "mc config host add myminio http://host.testcontainers.internal:%s %s %s --api s3v4 && "
                + "mc admin user add myminio %s %s readwrite";
        String cmd = String.format(cmdTpl, mappedPort, ADMIN_ACCESS_KEY, ADMIN_SECRET_KEY, USER_ACCESS_KEY, USER_SECRET_KEY);

        GenericContainer mcContainer = new GenericContainer<>("minio/mc")
                .withStartupCheckStrategy(new OneShotStartupCheckStrategy())
                .withCreateContainerCmdModifier(containerCommand -> containerCommand
                        .withTty(true)
                        .withEntrypoint("/bin/sh", "-c", cmd));
        mcContainer.start();
    }

    @Test
    public void canCreateBucketWithAdminUser() throws Exception {
        MinioClient client = new MinioClient(minioServerUrl, ADMIN_ACCESS_KEY, ADMIN_SECRET_KEY);
        client.ignoreCertCheck();

        String bucketName = "foo";
        client.makeBucket(bucketName);
        assertTrue(client.bucketExists(bucketName));
    }

    @Test
    public void canCreateBucketWithNonAdminUser() throws Exception {
        MinioClient client = new MinioClient(minioServerUrl, USER_ACCESS_KEY, USER_SECRET_KEY);
        client.ignoreCertCheck();

        String bucketName = "bar";
        client.makeBucket(bucketName);
        assertTrue(client.bucketExists(bucketName));
    }

    @AfterAll
    static void shutDown() {
        if (minioServer.isRunning()) {
            minioServer.stop();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


bsi*_*eup 4

您可以使用和运行一次性容器(使用OneShotStartupCheckStrategy),连接到与您正在运行的 minio 服务器相同的网络(请参阅网络)。mcwithCommand("your command")