diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 8d363cb978f..027a7adc170 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -41,6 +41,7 @@ body: - MySQL - Neo4j - NGINX + - OpenFGA - Oracle Free - Oracle XE - OrientDB diff --git a/.github/ISSUE_TEMPLATE/enhancement.yaml b/.github/ISSUE_TEMPLATE/enhancement.yaml index 6ee160c982b..c2f6d7504e8 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yaml +++ b/.github/ISSUE_TEMPLATE/enhancement.yaml @@ -41,6 +41,7 @@ body: - MySQL - Neo4j - NGINX + - OpenFGA - Oracle Free - Oracle XE - OrientDB diff --git a/.github/ISSUE_TEMPLATE/feature.yaml b/.github/ISSUE_TEMPLATE/feature.yaml index 3f8920b4059..3a03aa09bdd 100644 --- a/.github/ISSUE_TEMPLATE/feature.yaml +++ b/.github/ISSUE_TEMPLATE/feature.yaml @@ -41,6 +41,7 @@ body: - MySQL - Neo4j - NGINX + - OpenFGA - Oracle Free - Oracle XE - OrientDB diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bf9b145f2b3..163bf2db040 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -211,6 +211,10 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 10 + - package-ecosystem: "gradle" + directory: "/modules/openfga" + schedule: + interval: "weekly" - package-ecosystem: "gradle" directory: "/modules/oracle-free" schedule: diff --git a/.github/labeler.yml b/.github/labeler.yml index 0fd1ec90d29..c7eec3b4a6a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -131,6 +131,10 @@ - changed-files: - any-glob-to-any-file: - modules/nginx/**/* +"modules/openfga": + - changed-files: + - any-glob-to-any-file: + - modules/openfga/**/* "modules/oracle": - changed-files: - any-glob-to-any-file: diff --git a/.github/settings.yml b/.github/settings.yml index a4589aab643..c7458f63fc3 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -190,6 +190,9 @@ labels: - name: modules/nginx color: '#006b75' + - name: modules/openfga + color: '#006b75' + - name: modules/oracle color: '#006b75' diff --git a/docs/modules/openfga.md b/docs/modules/openfga.md new file mode 100644 index 00000000000..e11cae3560a --- /dev/null +++ b/docs/modules/openfga.md @@ -0,0 +1,30 @@ +# OpenFGA + +Testcontainers module for [OpenFGA](https://hub.docker.com/r/"openfga/openfga). + +## OpenFGAContainer's usage examples + +You can start an OpenFGA container instance from any Java application by using: + + +[OpenFGA container](../../modules/openfga/src/test/java/org/testcontainers/openfga/OpenFGAContainerTest.java) inside_block:container + + +## Adding this module to your project dependencies + +Add the following dependency to your `pom.xml`/`build.gradle` file: + +=== "Gradle" + ```groovy + testImplementation "org.testcontainers:openfga:{{latest_version}}" + ``` + +=== "Maven" + ```xml + + org.testcontainers + openfga + {{latest_version}} + test + + ``` diff --git a/mkdocs.yml b/mkdocs.yml index 784159e8e57..d51576a0bf6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,6 +88,7 @@ nav: - modules/minio.md - modules/mockserver.md - modules/nginx.md + - modules/openfga.md - modules/pulsar.md - modules/qdrant.md - modules/rabbitmq.md diff --git a/modules/openfga/build.gradle b/modules/openfga/build.gradle new file mode 100644 index 00000000000..9824603d5bd --- /dev/null +++ b/modules/openfga/build.gradle @@ -0,0 +1,21 @@ +description = "Testcontainers :: OpenFGA" + +dependencies { + api project(':testcontainers') + + testImplementation 'org.assertj:assertj-core:3.25.1' + testImplementation 'dev.openfga:openfga-sdk:0.3.2' +} + +test { + javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(11) + } +} + +compileTestJava { + javaCompiler = javaToolchains.compilerFor { + languageVersion = JavaLanguageVersion.of(11) + } + options.release.set(11) +} diff --git a/modules/openfga/src/main/java/org/testcontainers/openfga/OpenFGAContainer.java b/modules/openfga/src/main/java/org/testcontainers/openfga/OpenFGAContainer.java new file mode 100644 index 00000000000..986e385c0d3 --- /dev/null +++ b/modules/openfga/src/main/java/org/testcontainers/openfga/OpenFGAContainer.java @@ -0,0 +1,45 @@ +package org.testcontainers.openfga; + +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +/** + * Testcontainers implementation for OpenFGA. + *

+ * Supported image: {@code openfga/openfga} + *

+ * Exposed ports: + *

+ */ +public class OpenFGAContainer extends GenericContainer { + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("openfga/openfga"); + + public OpenFGAContainer(String image) { + this(DockerImageName.parse(image)); + } + + public OpenFGAContainer(DockerImageName dockerImageName) { + super(dockerImageName); + dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + + withExposedPorts(3000, 8080, 8081); + withCommand("run"); + waitingFor( + Wait.forHttp("/healthz").forPort(8080).forResponsePredicate(response -> response.contains("SERVING")) + ); + } + + public String getHttpEndpoint() { + return "http://" + getHost() + ":" + getMappedPort(8080); + } + + public String getGrpcEndpoint() { + return "http://" + getHost() + ":" + getMappedPort(8081); + } +} diff --git a/modules/openfga/src/test/java/org/testcontainers/openfga/OpenFGAContainerTest.java b/modules/openfga/src/test/java/org/testcontainers/openfga/OpenFGAContainerTest.java new file mode 100644 index 00000000000..688d4d31f10 --- /dev/null +++ b/modules/openfga/src/test/java/org/testcontainers/openfga/OpenFGAContainerTest.java @@ -0,0 +1,33 @@ +package org.testcontainers.openfga; + +import dev.openfga.sdk.api.client.OpenFgaClient; +import dev.openfga.sdk.api.client.model.ClientCreateStoreResponse; +import dev.openfga.sdk.api.configuration.ClientConfiguration; +import dev.openfga.sdk.api.model.CreateStoreRequest; +import dev.openfga.sdk.errors.FgaInvalidParameterException; +import org.junit.Test; + +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class OpenFGAContainerTest { + + @Test + public void withDefaultConfig() throws FgaInvalidParameterException, ExecutionException, InterruptedException { + try ( // container + OpenFGAContainer openfga = new OpenFGAContainer("openfga/openfga:v1.4.3") + // } + ) { + openfga.start(); + + ClientConfiguration config = new ClientConfiguration().apiUrl(openfga.getHttpEndpoint()); + OpenFgaClient client = new OpenFgaClient(config); + + assertThat(client.listStores().get().getStores()).isEmpty(); + ClientCreateStoreResponse store = client.createStore(new CreateStoreRequest().name("test")).get(); + assertThat(store.getId()).isNotNull(); + assertThat(client.listStores().get().getStores()).hasSize(1); + } + } +} diff --git a/modules/openfga/src/test/resources/logback-test.xml b/modules/openfga/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..83ef7a1a3ef --- /dev/null +++ b/modules/openfga/src/test/resources/logback-test.xml @@ -0,0 +1,16 @@ + + + + + + %d{HH:mm:ss.SSS} %-5level %logger - %msg%n + + + + + + + + +