Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding MinIO module #7440

Merged
merged 8 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ body:
- Kafka
- LocalStack
- MariaDB
- MinIO
- MockServer
- MongoDB
- MSSQLServer
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/enhancement.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ body:
- Kafka
- LocalStack
- MariaDB
- MinIO
- MockServer
- MongoDB
- MSSQLServer
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ body:
- Kafka
- LocalStack
- MariaDB
- MinIO
- MockServer
- MongoDB
- MSSQLServer
Expand Down
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ updates:
ignore:
- dependency-name: "org.mariadb:r2dbc-mariadb"
update-types: [ "version-update:semver-minor" ]
- package-ecosystem: "gradle"
directory: "/modules/minio"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/mockserver"
schedule:
Expand Down
2 changes: 2 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
- modules/localstack/**/*
"modules/mariadb":
- modules/mariadb/**/*
"modules/minio":
- modules/minio/**/*
"modules/mockserver":
- modules/mockserver/**/*
"modules/mongodb":
Expand Down
39 changes: 39 additions & 0 deletions docs/modules/minio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# MinIO Containers

Test containers can be used to automatically instantiate and manage [MinIO](https://min.io) containers.
eddumelendez marked this conversation as resolved.
Show resolved Hide resolved

## Usage example

Create a `MinIOContainer` to use it in your tests:
<!--codeinclude-->
[Starting a MinIO container](../../modules/minio/src/test/java/org/testcontainers/containers/MinIOContainerTest.java) inside_block:minioContainer
<!--/codeinclude-->

The [MinIO Java client](https://min.io/docs/minio/linux/developers/java/API.html) can be configured with the container as such:
<!--codeinclude-->
[Configuring a MinIO client](../../modules/minio/src/test/java/org/testcontainers/containers/MinIOContainerTest.java) inside_block:configuringClient
<!--/codeinclude-->

If needed the username and password can be overridden as such:
<!--codeinclude-->
[Overriding a MinIO container](../../modules/minio/src/test/java/org/testcontainers/containers/MinIOContainerTest.java) inside_block:minioOverrides
<!--/codeinclude-->

## Adding this module to your project dependencies

Add the following dependency to your `pom.xml`/`build.gradle` file:

=== "Gradle"
```groovy
testImplementation "org.testcontainers:minio:{{latest_version}}"
```

=== "Maven"
```xml
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>minio</artifactId>
<version>{{latest_version}}</version>
<scope>test</scope>
</dependency>
```
eddumelendez marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ nav:
- modules/k3s.md
- modules/kafka.md
- modules/localstack.md
- modules/minio.md
- modules/mockserver.md
- modules/nginx.md
- modules/pulsar.md
Expand Down
8 changes: 8 additions & 0 deletions modules/minio/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
description = "Testcontainers :: MinIO"

dependencies {
api project(':testcontainers')

testImplementation("io.minio:minio:8.5.5")
testImplementation 'org.assertj:assertj-core:3.24.2'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package org.testcontainers.containers;

import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;
import java.time.temporal.ChronoUnit;

/**
* Testcontainers implementation for MinIO.
* <p>
* Supported image: {@code MinIO}
* <p>
* Exposed ports: 9000,9001
*/
public class MinIOContainer extends GenericContainer<MinIOContainer> {

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("minio/minio");

private static final int MINIO_S3_PORT = 9000;

private static final int MINIO_UI_PORT = 9001;

private static final String DEFAULT_USER = "miniouser";

private static final String DEFAULT_PASSWORD = "miniopassword";

private String userName = DEFAULT_USER;

private String password = DEFAULT_PASSWORD;

/**
* Constructs a MinIO container from the dockerImageName
* @param dockerImageName the full image name to use
*/
public MinIOContainer(final String dockerImageName) {
this(DockerImageName.parse(dockerImageName));
}

/**
* Constructs a MinIO container from the dockerImageName
* @param dockerImageName the full image name to use
*/
public MinIOContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
}

/**
* Overrides the DEFAULT_USER
* @param userName the Root user to override
* @return this
*/
public MinIOContainer withUserName(String userName) {
this.userName = userName;
return this;
}

/**
* Overrides the DEFAULT_PASSWORD
* @param password the Root user's password to override
* @return this
*/
public MinIOContainer withPassword(String password) {
this.password = password;
return this;
}

/**
* Configures the MinIO container
*/
@Override
public void configure() {
withExposedPorts(MinIOContainer.MINIO_S3_PORT, MinIOContainer.MINIO_UI_PORT);

addEnv("MINIO_ROOT_USER", this.userName);
addEnv("MINIO_ROOT_PASSWORD", this.password);

withCommand("server", "--console-address", ":" + MINIO_UI_PORT, "/data");

waitingFor(
Wait
.forLogMessage(".*Status: 1 Online, 0 Offline..*", 1)
.withStartupTimeout(Duration.of(60, ChronoUnit.SECONDS))
);
}

/**
* @return the URL to upload/download objects from
*/
public String getS3URL() {
return String.format("http://%s:%s", this.getHost(), getMappedPort(MINIO_S3_PORT));
}

/**
* @return the Username for the Root user
*/
public String getUserName() {
return this.userName;
}

/**
* @return the password for the Root user
*/
public String getPassword() {
return this.password;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package org.testcontainers.containers;

import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.StatObjectArgs;
import io.minio.StatObjectResponse;
import io.minio.UploadObjectArgs;
import org.junit.Test;

import java.net.URL;

import static org.assertj.core.api.Assertions.assertThat;

public class MinIOContainerTest {

@Test
public void testBasicUsage() throws Exception {
// minioContainer {
MinIOContainer container = new MinIOContainer("minio/minio:RELEASE.2023-09-04T19-57-37Z");
// }
container.start();

// configuringClient {
MinioClient minioClient = MinioClient
.builder()
.endpoint(container.getS3URL())
.credentials(container.getUserName(), container.getPassword())
.build();

// }
minioClient.makeBucket(MakeBucketArgs.builder().bucket("test-bucket").region("us-west-2").build());

BucketExistsArgs existsArgs = BucketExistsArgs.builder().bucket("test-bucket").build();

assertThat(minioClient.bucketExists(existsArgs)).isTrue();

URL file = this.getClass().getResource("/object_to_upload.txt");
assertThat(file).isNotNull();
minioClient.uploadObject(
UploadObjectArgs.builder().bucket("test-bucket").object("my-objectname").filename(file.getPath()).build()
);

StatObjectResponse objectStat = minioClient.statObject(
StatObjectArgs.builder().bucket("test-bucket").object("my-objectname").build()
);

assertThat(objectStat.object()).isEqualTo("my-objectname");
}

@Test
public void testOverwriteUserPassword() throws Exception {
// minioOverrides {
MinIOContainer container = new MinIOContainer("minio/minio:RELEASE.2023-09-04T19-57-37Z")
.withUserName("testuser")
.withPassword("testpassword");
// }

assertThat(container.getUserName()).isEqualTo("testuser");
assertThat(container.getPassword()).isEqualTo("testpassword");
}
}
1 change: 1 addition & 0 deletions modules/minio/src/test/resources/object_to_upload.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is a file