diff --git a/pom.xml b/pom.xml
index 96ac6dd..3e2d365 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,13 +15,14 @@
OpenFeature bundle for Dropwizard
-
- 8
+
+ 11
UTF-8
UTF-8
5.0.0
1.18.2
0.11.17
+ 1.0.1
0.8.14
3.14.1
3.2.8
@@ -31,6 +32,7 @@
3.5.4
3.5.4
5.20.0
+ 1.21.3
0.9.0
@@ -75,8 +77,15 @@
mockito-bom
${mockito.version}
pom
- test
+ import
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
@@ -112,6 +121,12 @@
flagd
${openfeature-contrib-providers-flagd.version}
+
+ dev.openfeature.contrib.providers
+ go-feature-flag
+ ${openfeature-contrib-providers-go-feature-flag.version}
+
+
io.dropwizard
dropwizard-testing
@@ -127,6 +142,21 @@
mockito-junit-jupiter
test
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ testcontainers
+ test
+
@@ -165,8 +195,7 @@
maven-compiler-plugin
${maven-compiler-plugin.version}
- ${java.version}
- ${java.version}
+ ${maven.compiler.release}
diff --git a/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/GoFeatureFlagConfiguration.java b/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/GoFeatureFlagConfiguration.java
new file mode 100644
index 0000000..864b8c2
--- /dev/null
+++ b/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/GoFeatureFlagConfiguration.java
@@ -0,0 +1,26 @@
+package io.github.sideshowcoder.dropwizard_openfeature;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProviderOptions;
+import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProviderOptions.GoFeatureFlagProviderOptionsBuilder;
+import dev.openfeature.contrib.providers.gofeatureflag.exception.InvalidOptions;
+import jakarta.validation.constraints.NotNull;
+
+public class GoFeatureFlagConfiguration {
+
+ @JsonProperty
+ @NotNull
+ private String endpoint;
+
+ public GoFeatureFlagProviderOptions getGoFeatureFlagProviderOptions() throws InvalidOptions {
+ GoFeatureFlagProviderOptionsBuilder builder = GoFeatureFlagProviderOptions.builder();
+
+ builder.endpoint(endpoint);
+
+ GoFeatureFlagProviderOptions options = builder.build();
+ options.validate();
+ return options;
+ }
+
+}
diff --git a/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureBundle.java b/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureBundle.java
index 6177a93..9aa31d9 100644
--- a/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureBundle.java
+++ b/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureBundle.java
@@ -1,6 +1,9 @@
package io.github.sideshowcoder.dropwizard_openfeature;
import dev.openfeature.contrib.providers.flagd.FlagdProvider;
+import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProvider;
+import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProviderOptions;
+import dev.openfeature.contrib.providers.gofeatureflag.exception.InvalidOptions;
import dev.openfeature.sdk.Client;
import dev.openfeature.sdk.FeatureProvider;
import dev.openfeature.sdk.OpenFeatureAPI;
@@ -44,6 +47,13 @@ private synchronized void initializeFeatureProvider(OpenFeatureConfiguration con
case FLAGD:
featureProvider = new FlagdProvider(config.getFlagd().getFlagdOptions());
break;
+ case GOFEATUREFLAG:
+ try {
+ featureProvider = new GoFeatureFlagProvider(config.getGoFeatureFlag().getGoFeatureFlagProviderOptions());
+ } catch(InvalidOptions e) {
+ new RuntimeException(e);
+ }
+ break;
}
}
}
diff --git a/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureConfiguration.java b/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureConfiguration.java
index 1ec8b69..6a4d48d 100644
--- a/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureConfiguration.java
+++ b/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureConfiguration.java
@@ -11,6 +11,10 @@ public class OpenFeatureConfiguration {
@JsonProperty
private FlagdConfiguration flagd = new FlagdConfiguration();
+ @Valid
+ @JsonProperty
+ private GoFeatureFlagConfiguration gofeatureflag = new GoFeatureFlagConfiguration();
+
@Valid
@JsonProperty
private OpenFeatureHealthCheckConfiguration healthcheck = new OpenFeatureHealthCheckConfiguration();
@@ -28,6 +32,14 @@ public void setFlagd(FlagdConfiguration flagd) {
this.flagd = flagd;
}
+ public GoFeatureFlagConfiguration getGoFeatureFlag() {
+ return gofeatureflag;
+ }
+
+ public void setGoFeatureFlag(GoFeatureFlagConfiguration gofeatureflag) {
+ this.gofeatureflag = gofeatureflag;
+ }
+
public OpenFeatureHealthCheckConfiguration getHealthcheck() {
return healthcheck;
}
diff --git a/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/ProviderType.java b/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/ProviderType.java
index 3e46a69..7f846df 100644
--- a/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/ProviderType.java
+++ b/src/main/java/io/github/sideshowcoder/dropwizard_openfeature/ProviderType.java
@@ -2,5 +2,6 @@
public enum ProviderType {
FLAGD,
+ GOFEATUREFLAG,
INMEMORY;
}
diff --git a/src/test/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureBundleGoFeatureFlagProviderTest.java b/src/test/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureBundleGoFeatureFlagProviderTest.java
new file mode 100644
index 0000000..8a5d281
--- /dev/null
+++ b/src/test/java/io/github/sideshowcoder/dropwizard_openfeature/OpenFeatureBundleGoFeatureFlagProviderTest.java
@@ -0,0 +1,65 @@
+package io.github.sideshowcoder.dropwizard_openfeature;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+import org.testcontainers.utility.MountableFile;
+
+import com.codahale.metrics.health.HealthCheck;
+
+import dev.openfeature.sdk.Client;
+import dev.openfeature.sdk.EvaluationContext;
+import dev.openfeature.sdk.ImmutableContext;
+import dev.openfeature.sdk.OpenFeatureAPI;
+import io.dropwizard.testing.ResourceHelpers;
+import io.dropwizard.testing.junit5.DropwizardAppExtension;
+import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
+import io.github.sideshowcoder.dropwizard_openfeature.helpers.App;
+import io.github.sideshowcoder.dropwizard_openfeature.helpers.Config;
+
+@Testcontainers
+@ExtendWith(DropwizardExtensionsSupport.class)
+public class OpenFeatureBundleGoFeatureFlagProviderTest {
+
+ @Container
+ private static GenericContainer> goFeatureFlagRelay = createGoFeatureFlagContainer();
+
+ private static GenericContainer> createGoFeatureFlagContainer() {
+ GenericContainer> container = new GenericContainer<>(DockerImageName.parse("gofeatureflag/go-feature-flag:latest"))
+ .withCopyFileToContainer(MountableFile.forClasspathResource("goff-proxy.yaml"), "/goff/goff-proxy.yaml")
+ .withCopyFileToContainer(MountableFile.forClasspathResource("go-feature-flags-flags.yaml"), "/goff/flags.yaml");
+
+ container.setPortBindings(List.of("1031:1031"));
+ container.waitingFor(Wait.forHttp("/health"));
+
+ return container;
+ }
+
+ private static final DropwizardAppExtension APP = new DropwizardAppExtension<>(
+ App.class,
+ ResourceHelpers.resourceFilePath("go-feature-flag-provider-config.yml")
+ );
+
+ @Test
+ public void initializesHealthCheck() throws Exception {
+ HealthCheck.Result healthcheckResult = APP.getEnvironment().healthChecks().runHealthCheck("openfeature-health-check");
+ assertTrue(healthcheckResult.isHealthy());
+ }
+
+ @Test
+ public void providesFeatureFlagsViaInMemoryProvider() throws Exception {
+ Client client = OpenFeatureAPI.getInstance().getClient("go-feature-flag-client");
+ // GoFeatureFlags requires a target key for all queries!
+ EvaluationContext ctx = new ImmutableContext("target");
+ assertEquals("red", client.getStringValue("staticstringflag", "not-expected-value", ctx));
+ }
+}
diff --git a/src/test/resources/basic-flagd-config.yml b/src/test/resources/basic-flagd-config.yml
index 04995ee..e4403d4 100644
--- a/src/test/resources/basic-flagd-config.yml
+++ b/src/test/resources/basic-flagd-config.yml
@@ -1,4 +1,4 @@
host: flagd
port: 8082
resolver: rpc
-cacheType: disabled
\ No newline at end of file
+cacheType: disabled
diff --git a/src/test/resources/go-feature-flag-provider-config.yml b/src/test/resources/go-feature-flag-provider-config.yml
new file mode 100644
index 0000000..b51c2ce
--- /dev/null
+++ b/src/test/resources/go-feature-flag-provider-config.yml
@@ -0,0 +1,4 @@
+openfeature:
+ provider: gofeatureflag
+ gofeatureflag:
+ endpoint: "http://localhost:1031/"
diff --git a/src/test/resources/go-feature-flags-flags.yaml b/src/test/resources/go-feature-flags-flags.yaml
new file mode 100644
index 0000000..538b374
--- /dev/null
+++ b/src/test/resources/go-feature-flags-flags.yaml
@@ -0,0 +1,7 @@
+staticstringflag:
+ variations:
+ red: "red"
+ green: "green"
+ blue: "blue"
+ defaultRule:
+ variation: red
diff --git a/src/test/resources/goff-proxy.yaml b/src/test/resources/goff-proxy.yaml
new file mode 100644
index 0000000..4a373a3
--- /dev/null
+++ b/src/test/resources/goff-proxy.yaml
@@ -0,0 +1,3 @@
+retrievers:
+ - kind: file
+ path: /goff/flags.yaml