From 05c37b0547b879ac0a982c27565975736463d47a Mon Sep 17 00:00:00 2001 From: Simon Schrottner Date: Wed, 3 Jul 2024 13:28:21 +0200 Subject: [PATCH] feat: testcontainers instead of docker compose Signed-off-by: Simon Schrottner --- .github/workflows/ci.yml | 21 ------ providers/flagd/docker-compose.yaml | 17 ----- providers/flagd/pom.xml | 21 +++++- providers/flagd/schemas | 2 +- .../providers/flagd/e2e/ContainerConfig.java | 71 +++++++++++++++++++ .../e2e/RunFlagdInProcessCucumberTest.java | 4 +- ...unFlagdInProcessReconnectCucumberTest.java | 6 +- .../flagd/e2e/RunFlagdRpcCucumberTest.java | 4 +- .../e2e/RunFlagdRpcReconnectCucumberTest.java | 6 +- .../e2e/process/FlagdInProcessSetup.java | 16 ++++- .../process/FlagdInProcessSetup.java | 14 +++- .../e2e/reconnect/rpc/FlagdRpcSetup.java | 15 +++- .../flagd/e2e/rpc/FlagdRpcSetup.java | 15 ++++ .../test/resources/flagdTestbed.properties | 3 + 14 files changed, 164 insertions(+), 51 deletions(-) delete mode 100644 providers/flagd/docker-compose.yaml create mode 100644 providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/ContainerConfig.java create mode 100644 providers/flagd/src/test/resources/flagdTestbed.properties diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d3388624..cbb4dde40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,27 +11,6 @@ on: jobs: main: runs-on: ubuntu-latest - services: - # flagd-testbed for flagd RPC provider e2e tests - flagd: - image: ghcr.io/open-feature/flagd-testbed:v0.5.5 - ports: - - 8013:8013 - # flagd-testbed for flagd RPC provider reconnect e2e tests - flagd-unstable: - image: ghcr.io/open-feature/flagd-testbed-unstable:v0.5.5 - ports: - - 8014:8013 - # sync-testbed for flagd in-process provider e2e tests - sync: - image: ghcr.io/open-feature/sync-testbed:v0.5.5 - ports: - - 9090:9090 - # sync-testbed for flagd in-process provider reconnect e2e tests - sync-unstable: - image: ghcr.io/open-feature/sync-testbed-unstable:v0.5.5 - ports: - - 9091:9090 steps: - name: Checkout Repository diff --git a/providers/flagd/docker-compose.yaml b/providers/flagd/docker-compose.yaml deleted file mode 100644 index d8630fc5f..000000000 --- a/providers/flagd/docker-compose.yaml +++ /dev/null @@ -1,17 +0,0 @@ -services: - flagd: - image: ghcr.io/open-feature/flagd-testbed:v0.5.5 - ports: - - 8013:8013 - flagd-unstable: - image: ghcr.io/open-feature/flagd-testbed-unstable:v0.5.5 - ports: - - 8014:8013 - flagd-sync: - image: ghcr.io/open-feature/sync-testbed:v0.5.5 - ports: - - 9090:9090 - flagd-sync-unstable: - image: ghcr.io/open-feature/sync-testbed-unstable:v0.5.5 - ports: - - 9091:9090 \ No newline at end of file diff --git a/providers/flagd/pom.xml b/providers/flagd/pom.xml index 087baadbf..42a46aa26 100644 --- a/providers/flagd/pom.xml +++ b/providers/flagd/pom.xml @@ -132,6 +132,25 @@ 1.17.0 + + org.junit.jupiter + junit-jupiter + 5.8.1 + test + + + org.testcontainers + testcontainers + 1.19.8 + test + + + org.testcontainers + junit-jupiter + 1.19.8 + test + + @@ -402,4 +421,4 @@ - \ No newline at end of file + diff --git a/providers/flagd/schemas b/providers/flagd/schemas index e72b08b71..8c72c14ee 160000 --- a/providers/flagd/schemas +++ b/providers/flagd/schemas @@ -1 +1 @@ -Subproject commit e72b08b71ad8654e8a31ec6f75a9c8b4d47db8ca +Subproject commit 8c72c14eebff2a5b20fe2afb90c7ad44c1184ae8 diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/ContainerConfig.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/ContainerConfig.java new file mode 100644 index 000000000..6b8ba78d6 --- /dev/null +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/ContainerConfig.java @@ -0,0 +1,71 @@ +package dev.openfeature.contrib.providers.flagd.e2e; + +import org.jetbrains.annotations.NotNull; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.utility.DockerImageName; + +import java.io.IOException; +import java.util.Properties; + +public class ContainerConfig { + private static final String version; + + static { + Properties properties = new Properties(); + try { + properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("flagdTestbed.properties")); + version = properties.getProperty("version"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * + * @return a {@link org.testcontainers.containers.GenericContainer} instance of a stable sync flagd server with the port 9090 exposed + */ + public static GenericContainer sync() { + return sync(false); + } + + /** + * + * @param unstable if an unstable version of the container, which terminates the connection regularly should be used. + * @return a {@link org.testcontainers.containers.GenericContainer} instance of a sync flagd server with the port 9090 exposed + */ + public static GenericContainer sync(boolean unstable) { + String container = generateContainerName("sync", unstable); + return new GenericContainer(DockerImageName.parse(container)) + .withExposedPorts(9090); + } + + /** + * + * @return a {@link org.testcontainers.containers.GenericContainer} instance of a stable flagd server with the port 8013 exposed + */ + public static GenericContainer flagd() { + return flagd(false); + } + + /** + * + * @param unstable if an unstable version of the container, which terminates the connection regularly should be used. + * @return a {@link org.testcontainers.containers.GenericContainer} instance of a flagd server with the port 8013 exposed + */ + public static GenericContainer flagd(boolean unstable) { + String container = generateContainerName("flagd", unstable); + return new GenericContainer(DockerImageName.parse(container)) + .withExposedPorts(8013); + } + + private static @NotNull String generateContainerName(String type, boolean unstable) { + String container = "ghcr.io/open-feature/"; + container += type; + container += "-testbed"; + if (unstable) { + container += "-unstable"; + } + container += ":" + version; + return container; + } +} diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdInProcessCucumberTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdInProcessCucumberTest.java index f250ced7d..048a1f328 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdInProcessCucumberTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdInProcessCucumberTest.java @@ -5,6 +5,7 @@ import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectClasspathResource; import org.junit.platform.suite.api.Suite; +import org.testcontainers.junit.jupiter.Testcontainers; import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; @@ -20,6 +21,7 @@ @SelectClasspathResource("features/flagd.feature") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.process,dev.openfeature.contrib.providers.flagd.e2e.steps") +@Testcontainers public class RunFlagdInProcessCucumberTest { - + } diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdInProcessReconnectCucumberTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdInProcessReconnectCucumberTest.java index bda21e110..97fe2d355 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdInProcessReconnectCucumberTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdInProcessReconnectCucumberTest.java @@ -5,12 +5,13 @@ import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectClasspathResource; import org.junit.platform.suite.api.Suite; +import org.testcontainers.junit.jupiter.Testcontainers; import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; /** - * Class for running the reconnection tests for the in-process provider + * Class for running the reconnection tests for the in-process provider */ @Order(value = Integer.MAX_VALUE) @Suite @@ -18,6 +19,7 @@ @SelectClasspathResource("features/flagd-reconnect.feature") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.reconnect.process,dev.openfeature.contrib.providers.flagd.e2e.reconnect.steps") +@Testcontainers public class RunFlagdInProcessReconnectCucumberTest { - + } diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdRpcCucumberTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdRpcCucumberTest.java index 05591d20b..11bdea0e7 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdRpcCucumberTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdRpcCucumberTest.java @@ -5,6 +5,7 @@ import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectClasspathResource; import org.junit.platform.suite.api.Suite; +import org.testcontainers.junit.jupiter.Testcontainers; import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; @@ -20,7 +21,8 @@ @SelectClasspathResource("features/flagd.feature") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.rpc,dev.openfeature.contrib.providers.flagd.e2e.steps") +@Testcontainers public class RunFlagdRpcCucumberTest { - + } diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdRpcReconnectCucumberTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdRpcReconnectCucumberTest.java index 0c41c06f7..fa226c1a6 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdRpcReconnectCucumberTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunFlagdRpcReconnectCucumberTest.java @@ -5,12 +5,13 @@ import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectClasspathResource; import org.junit.platform.suite.api.Suite; +import org.testcontainers.junit.jupiter.Testcontainers; import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; /** - * Class for running the reconnection tests for the RPC provider + * Class for running the reconnection tests for the RPC provider */ @Order(value = Integer.MAX_VALUE) @Suite @@ -18,7 +19,8 @@ @SelectClasspathResource("features/flagd-reconnect.feature") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.reconnect.rpc,dev.openfeature.contrib.providers.flagd.e2e.reconnect.steps") +@Testcontainers public class RunFlagdRpcReconnectCucumberTest { - + } diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/process/FlagdInProcessSetup.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/process/FlagdInProcessSetup.java index 2dbf171be..d23caf42a 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/process/FlagdInProcessSetup.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/process/FlagdInProcessSetup.java @@ -1,5 +1,7 @@ package dev.openfeature.contrib.providers.flagd.e2e.process; +import dev.openfeature.contrib.providers.flagd.e2e.ContainerConfig; +import io.cucumber.java.AfterAll; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.parallel.Isolated; @@ -9,20 +11,30 @@ import dev.openfeature.contrib.providers.flagd.e2e.steps.StepDefinitions; import dev.openfeature.sdk.FeatureProvider; import io.cucumber.java.BeforeAll; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.utility.DockerImageName; @Isolated() @Order(value = Integer.MAX_VALUE) public class FlagdInProcessSetup { private static FeatureProvider provider; - + + private static final GenericContainer flagdContainer = ContainerConfig.sync(); + @BeforeAll() public static void setup() throws InterruptedException { + flagdContainer.start(); FlagdInProcessSetup.provider = new FlagdProvider(FlagdOptions.builder() .resolverType(Config.Resolver.IN_PROCESS) .deadline(3000) - .port(9090) + .port(flagdContainer.getFirstMappedPort()) .build()); StepDefinitions.setProvider(provider); } + + @AfterAll + public static void tearDown() { + flagdContainer.stop(); + } } diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/reconnect/process/FlagdInProcessSetup.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/reconnect/process/FlagdInProcessSetup.java index 5dd736351..3ad3ac5f4 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/reconnect/process/FlagdInProcessSetup.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/reconnect/process/FlagdInProcessSetup.java @@ -1,5 +1,7 @@ package dev.openfeature.contrib.providers.flagd.e2e.reconnect.process; +import dev.openfeature.contrib.providers.flagd.e2e.ContainerConfig; +import io.cucumber.java.AfterAll; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.parallel.Isolated; @@ -9,17 +11,20 @@ import dev.openfeature.contrib.providers.flagd.e2e.reconnect.steps.StepDefinitions; import dev.openfeature.sdk.FeatureProvider; import io.cucumber.java.BeforeAll; +import org.testcontainers.containers.GenericContainer; @Isolated() @Order(value = Integer.MAX_VALUE) public class FlagdInProcessSetup { - + + private static final GenericContainer flagdContainer = ContainerConfig.sync(true); @BeforeAll() public static void setup() throws InterruptedException { + flagdContainer.start(); FeatureProvider workingProvider = new FlagdProvider(FlagdOptions.builder() .resolverType(Config.Resolver.IN_PROCESS) .deadline(3000) - .port(9091) + .port(flagdContainer.getFirstMappedPort()) .build()); StepDefinitions.setUnstableProvider(workingProvider); @@ -30,4 +35,9 @@ public static void setup() throws InterruptedException { .build()); StepDefinitions.setUnavailableProvider(unavailableProvider); } + + @AfterAll + public static void tearDown() { + flagdContainer.stop(); + } } diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/reconnect/rpc/FlagdRpcSetup.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/reconnect/rpc/FlagdRpcSetup.java index ae46a5b36..945baa3cc 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/reconnect/rpc/FlagdRpcSetup.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/reconnect/rpc/FlagdRpcSetup.java @@ -1,5 +1,7 @@ package dev.openfeature.contrib.providers.flagd.e2e.reconnect.rpc; +import dev.openfeature.contrib.providers.flagd.e2e.ContainerConfig; +import io.cucumber.java.AfterAll; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.parallel.Isolated; @@ -10,16 +12,22 @@ import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.CacheType; import dev.openfeature.sdk.FeatureProvider; import io.cucumber.java.BeforeAll; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.utility.DockerImageName; @Isolated() @Order(value = Integer.MAX_VALUE) public class FlagdRpcSetup { + private static final GenericContainer flagdContainer = ContainerConfig.flagd(true); @BeforeAll() public static void setup() throws InterruptedException { + flagdContainer.start(); + FeatureProvider workingProvider = new FlagdProvider(FlagdOptions.builder() .resolverType(Config.Resolver.RPC) - .port(8014) + .port(flagdContainer.getFirstMappedPort()) // set a generous deadline, to prevent timeouts in actions .deadline(3000) .cacheType(CacheType.DISABLED.getValue()) @@ -35,4 +43,9 @@ public static void setup() throws InterruptedException { .build()); StepDefinitions.setUnavailableProvider(unavailableProvider); } + + @AfterAll + public static void tearDown() { + flagdContainer.stop(); + } } diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/rpc/FlagdRpcSetup.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/rpc/FlagdRpcSetup.java index a137a5e34..27ab4ea6d 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/rpc/FlagdRpcSetup.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/rpc/FlagdRpcSetup.java @@ -1,6 +1,8 @@ package dev.openfeature.contrib.providers.flagd.e2e.rpc; +import dev.openfeature.contrib.providers.flagd.e2e.ContainerConfig; import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.CacheType; +import io.cucumber.java.AfterAll; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.parallel.Isolated; @@ -10,21 +12,34 @@ import dev.openfeature.contrib.providers.flagd.e2e.steps.StepDefinitions; import dev.openfeature.sdk.FeatureProvider; import io.cucumber.java.BeforeAll; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; @Isolated() @Order(value = Integer.MAX_VALUE) public class FlagdRpcSetup { private static FeatureProvider provider; + private static final GenericContainer flagdContainer = ContainerConfig.flagd(); @BeforeAll() public static void setup() { + flagdContainer.start(); FlagdRpcSetup.provider = new FlagdProvider(FlagdOptions.builder() .resolverType(Config.Resolver.RPC) + .port(flagdContainer.getFirstMappedPort()) // set a generous deadline, to prevent timeouts in actions .deadline(3000) .cacheType(CacheType.DISABLED.getValue()) .build()); StepDefinitions.setProvider(provider); } + + @AfterAll + public static void tearDown() { + flagdContainer.stop(); + } + } diff --git a/providers/flagd/src/test/resources/flagdTestbed.properties b/providers/flagd/src/test/resources/flagdTestbed.properties new file mode 100644 index 000000000..a5b5463d7 --- /dev/null +++ b/providers/flagd/src/test/resources/flagdTestbed.properties @@ -0,0 +1,3 @@ +# todo: properly configure renovate with a regex matcher to update this version +# renovate: datasource=docker packageName=docker versioning=docker +version=v0.5.5