From 3d1bf75b204365d6206d8dfb2bcc0a1dedd1d489 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Fri, 17 May 2024 11:15:46 -0700 Subject: [PATCH 1/3] support resolver type from env vars Signed-off-by: Kavindu Dodanduwa --- providers/flagd/README.md | 29 ++++++++++--------- providers/flagd/schemas | 2 +- .../contrib/providers/flagd/Config.java | 19 ++++++++++++ .../contrib/providers/flagd/FlagdOptions.java | 4 +-- .../providers/flagd/FlagdOptionsTest.java | 25 ++++++++++++++++ 5 files changed, 62 insertions(+), 17 deletions(-) diff --git a/providers/flagd/README.md b/providers/flagd/README.md index 7d28e4ef8..194da5ff6 100644 --- a/providers/flagd/README.md +++ b/providers/flagd/README.md @@ -77,20 +77,21 @@ variables. Given below are the supported configurations: -| Option name | Environment variable name | Type & Values | Default | Compatible resolver | -|-----------------------|--------------------------------|------------------------|-----------|---------------------| -| host | FLAGD_HOST | String | localhost | rpc & in-process | -| port | FLAGD_PORT | int | 8013 | rpc & in-process | -| tls | FLAGD_TLS | boolean | false | rpc & in-process | -| socketPath | FLAGD_SOCKET_PATH | String | null | rpc & in-process | -| certPath | FLAGD_SERVER_CERT_PATH | String | null | rpc & in-process | -| deadline | FLAGD_DEADLINE_MS | int | 500 | rpc & in-process | -| selector | FLAGD_SOURCE_SELECTOR | String | null | in-process | -| cache | FLAGD_CACHE | String - lru, disabled | lru | rpc | -| maxCacheSize | FLAGD_MAX_CACHE_SIZE | int | 1000 | rpc | -| maxEventStreamRetries | FLAGD_MAX_EVENT_STREAM_RETRIES | int | 5 | rpc | -| retryBackoffMs | FLAGD_RETRY_BACKOFF_MS | int | 1000 | rpc | -| offlineFlagSourcePath | FLAGD_OFFLINE_FLAG_SOURCE_PATH | String | null | in-process | +| Option name | Environment variable name | Type & Values | Default | Compatible resolver | +|-----------------------|--------------------------------|--------------------------|-----------|---------------------| +| resolver | FLAGD_RESOLVER | String - rpc, in-process | rpc | | +| host | FLAGD_HOST | String | localhost | rpc & in-process | +| port | FLAGD_PORT | int | 8013 | rpc & in-process | +| tls | FLAGD_TLS | boolean | false | rpc & in-process | +| socketPath | FLAGD_SOCKET_PATH | String | null | rpc & in-process | +| certPath | FLAGD_SERVER_CERT_PATH | String | null | rpc & in-process | +| deadline | FLAGD_DEADLINE_MS | int | 500 | rpc & in-process | +| selector | FLAGD_SOURCE_SELECTOR | String | null | in-process | +| cache | FLAGD_CACHE | String - lru, disabled | lru | rpc | +| maxCacheSize | FLAGD_MAX_CACHE_SIZE | int | 1000 | rpc | +| maxEventStreamRetries | FLAGD_MAX_EVENT_STREAM_RETRIES | int | 5 | rpc | +| retryBackoffMs | FLAGD_RETRY_BACKOFF_MS | int | 1000 | rpc | +| offlineFlagSourcePath | FLAGD_OFFLINE_FLAG_SOURCE_PATH | String | null | in-process | > [!NOTE] > Some configurations are only applicable for RPC resolver. diff --git a/providers/flagd/schemas b/providers/flagd/schemas index cc2f5a1b5..8c72c14ee 160000 --- a/providers/flagd/schemas +++ b/providers/flagd/schemas @@ -1 +1 @@ -Subproject commit cc2f5a1b506700eca1e56b462921573532f2b463 +Subproject commit 8c72c14eebff2a5b20fe2afb90c7ad44c1184ae8 diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java index 68564c51b..b882f3cf9 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java @@ -2,6 +2,8 @@ import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.CacheType; +import java.util.function.Function; + /** * Helper class to hold configuration default values. */ @@ -14,6 +16,7 @@ public final class Config { static final int DEFAULT_DEADLINE = 500; static final int DEFAULT_MAX_CACHE_SIZE = 1000; + static final String RESOLVER_ENV_VAR = "FLAGD_RESOLVER"; static final String HOST_ENV_VAR_NAME = "FLAGD_HOST"; static final String PORT_ENV_VAR_NAME = "FLAGD_PORT"; static final String TLS_ENV_VAR_NAME = "FLAGD_TLS"; @@ -55,6 +58,22 @@ static int fallBackToEnvOrDefault(String key, int defaultValue) { } } + static Evaluator fromValueProvider(Function provider) { + final String resolverVar = provider.apply(RESOLVER_ENV_VAR); + if (resolverVar == null) { + return DEFAULT_RESOLVER_TYPE; + } + + switch (resolverVar) { + case "in-process": + return Evaluator.IN_PROCESS; + case "rpc": + return Evaluator.RPC; + default: + return DEFAULT_RESOLVER_TYPE; + } + } + /** * flagd evaluator type. */ diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java index 32d2ae678..a51defe87 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java @@ -15,7 +15,6 @@ import static dev.openfeature.contrib.providers.flagd.Config.DEFAULT_MAX_CACHE_SIZE; import static dev.openfeature.contrib.providers.flagd.Config.DEFAULT_MAX_EVENT_STREAM_RETRIES; import static dev.openfeature.contrib.providers.flagd.Config.DEFAULT_PORT; -import static dev.openfeature.contrib.providers.flagd.Config.DEFAULT_RESOLVER_TYPE; import static dev.openfeature.contrib.providers.flagd.Config.DEFAULT_TLS; import static dev.openfeature.contrib.providers.flagd.Config.HOST_ENV_VAR_NAME; import static dev.openfeature.contrib.providers.flagd.Config.MAX_CACHE_SIZE_ENV_VAR_NAME; @@ -27,6 +26,7 @@ import static dev.openfeature.contrib.providers.flagd.Config.SOURCE_SELECTOR_ENV_VAR_NAME; import static dev.openfeature.contrib.providers.flagd.Config.TLS_ENV_VAR_NAME; import static dev.openfeature.contrib.providers.flagd.Config.fallBackToEnvOrDefault; +import static dev.openfeature.contrib.providers.flagd.Config.fromValueProvider; /** * FlagdOptions is a builder to build flagd provider options. @@ -40,7 +40,7 @@ public class FlagdOptions { * flagd resolving type. */ @Builder.Default - private Config.Evaluator resolverType = DEFAULT_RESOLVER_TYPE; + private Config.Evaluator resolverType = fromValueProvider(System::getenv); /** * flagd connection host. diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java index a95b9f36f..ae27a2fd7 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java @@ -4,6 +4,8 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import java.util.function.Function; + import static dev.openfeature.contrib.providers.flagd.Config.DEFAULT_CACHE; import static dev.openfeature.contrib.providers.flagd.Config.DEFAULT_HOST; import static dev.openfeature.contrib.providers.flagd.Config.DEFAULT_MAX_CACHE_SIZE; @@ -31,6 +33,7 @@ public void TestDefaults() { assertNull(builder.getSelector()); assertNull(builder.getOpenTelemetry()); assertNull(builder.getOfflineFlagSourcePath()); + assertEquals(Config.Evaluator.RPC, builder.getResolverType()); } @Test @@ -48,6 +51,7 @@ public void TestBuilderOptions() { .selector("app=weatherApp") .offlineFlagSourcePath("some-path") .openTelemetry(openTelemetry) + .resolverType(Config.Evaluator.IN_PROCESS) .build(); assertEquals("https://hosted-flagd", flagdOptions.getHost()); @@ -60,5 +64,26 @@ public void TestBuilderOptions() { assertEquals("app=weatherApp", flagdOptions.getSelector()); assertEquals("some-path", flagdOptions.getOfflineFlagSourcePath()); assertEquals(openTelemetry, flagdOptions.getOpenTelemetry()); + assertEquals(Config.Evaluator.IN_PROCESS, flagdOptions.getResolverType()); + } + + + @Test + public void testValueProviderForEdgeCase_valid() { + Function dummy = s -> "in-process"; + assertEquals(Config.Evaluator.IN_PROCESS, Config.fromValueProvider(dummy)); + + dummy = s -> "rpc"; + assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(dummy)); } + + @Test + public void testValueProviderForEdgeCase_invalid() { + Function dummy = s -> "some-other"; + assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(dummy)); + + dummy = s -> null; + assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(dummy)); + } + } From b86c8e41de02ac5ccf8f51297d387e9eba22ba97 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Fri, 17 May 2024 11:30:05 -0700 Subject: [PATCH 2/3] improve test validation Signed-off-by: Kavindu Dodanduwa --- .../openfeature/contrib/providers/flagd/FlagdOptionsTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java index ae27a2fd7..34bbac220 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java @@ -80,10 +80,10 @@ public void testValueProviderForEdgeCase_valid() { @Test public void testValueProviderForEdgeCase_invalid() { Function dummy = s -> "some-other"; - assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(dummy)); + assertEquals(Config.DEFAULT_RESOLVER_TYPE, Config.fromValueProvider(dummy)); dummy = s -> null; - assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(dummy)); + assertEquals(Config.DEFAULT_RESOLVER_TYPE, Config.fromValueProvider(dummy)); } } From 3d601c405f4dd3932fce8be5c3465b117a513a98 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Fri, 17 May 2024 12:05:50 -0700 Subject: [PATCH 3/3] case insensitive parsing of resolver Signed-off-by: Kavindu Dodanduwa --- .../contrib/providers/flagd/Config.java | 5 ++++- .../contrib/providers/flagd/FlagdOptionsTest.java | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java index b882f3cf9..5dfec4e13 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java @@ -1,12 +1,14 @@ package dev.openfeature.contrib.providers.flagd; import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.CacheType; +import lombok.extern.slf4j.Slf4j; import java.util.function.Function; /** * Helper class to hold configuration default values. */ +@Slf4j public final class Config { static final Evaluator DEFAULT_RESOLVER_TYPE = Evaluator.RPC; static final String DEFAULT_PORT = "8013"; @@ -64,12 +66,13 @@ static Evaluator fromValueProvider(Function provider) { return DEFAULT_RESOLVER_TYPE; } - switch (resolverVar) { + switch (resolverVar.toLowerCase()) { case "in-process": return Evaluator.IN_PROCESS; case "rpc": return Evaluator.RPC; default: + log.warn("Unsupported resolver variable: {}", resolverVar); return DEFAULT_RESOLVER_TYPE; } } diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java index 34bbac220..db70a21b5 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java @@ -70,11 +70,17 @@ public void TestBuilderOptions() { @Test public void testValueProviderForEdgeCase_valid() { - Function dummy = s -> "in-process"; - assertEquals(Config.Evaluator.IN_PROCESS, Config.fromValueProvider(dummy)); + Function valueProvider = s -> "in-process"; + assertEquals(Config.Evaluator.IN_PROCESS, Config.fromValueProvider(valueProvider)); - dummy = s -> "rpc"; - assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(dummy)); + valueProvider = s -> "IN-PROCESS"; + assertEquals(Config.Evaluator.IN_PROCESS, Config.fromValueProvider(valueProvider)); + + valueProvider = s -> "rpc"; + assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(valueProvider)); + + valueProvider = s -> "RPC"; + assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(valueProvider)); } @Test