From 67e7a3bf2247c36f262021d58532af2b2b144c38 Mon Sep 17 00:00:00 2001 From: Maks Osowski Date: Wed, 12 Mar 2025 17:47:51 +0100 Subject: [PATCH 1/3] chore(flagd): add disable metadata option Signed-off-by: Maks Osowski --- .../openfeature/contrib/provider/flagd/config.py | 9 +++++++++ .../contrib/provider/flagd/provider.py | 2 ++ .../resolvers/process/connector/grpc_watcher.py | 16 ++++++++++++---- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py index 59b86e2a..ebb10564 100644 --- a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py +++ b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py @@ -100,6 +100,7 @@ def __init__( # noqa: PLR0913 cert_path: typing.Optional[str] = None, default_authority: typing.Optional[str] = None, channel_credentials: typing.Optional[grpc.ChannelCredentials] = None, + sync_metadata_disabled: typing.Optional[bool] = None, ): self.host = env_or_default(ENV_VAR_HOST, DEFAULT_HOST) if host is None else host @@ -248,3 +249,11 @@ def __init__( # noqa: PLR0913 ) self.channel_credentials = channel_credentials + + # TODO: remove the metadata call entirely after https://github.com/open-feature/flagd/issues/1584 + # This is a temporary stop-gap solutions to support servers that don't implement sync.GetMetadata + # (see: https://buf.build/open-feature/flagd/docs/main:flagd.sync.v1#flagd.sync.v1.FlagSyncService.GetMetadata). + # Using this option sisables call to sync.GetMetadata + # Disabling will prevent static context from flagd being used in evaluations. + # GetMetadata and this option will be removed. + self.sync_metadata_disabled = sync_metadata_disabled diff --git a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/provider.py b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/provider.py index 59bad1c3..3fb23744 100644 --- a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/provider.py +++ b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/provider.py @@ -64,6 +64,7 @@ def __init__( # noqa: PLR0913 cert_path: typing.Optional[str] = None, default_authority: typing.Optional[str] = None, channel_credentials: typing.Optional[grpc.ChannelCredentials] = None, + sync_metadata_disabled: typing.Optional[bool] = None, ): """ Create an instance of the FlagdProvider @@ -106,6 +107,7 @@ def __init__( # noqa: PLR0913 cert_path=cert_path, default_authority=default_authority, channel_credentials=channel_credentials, + sync_metadata_disabled=sync_metadata_disabled, ) self.enriched_context: dict = {} diff --git a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py index 7b611dd4..e4867b10 100644 --- a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py +++ b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py @@ -6,6 +6,7 @@ import grpc from google.protobuf.json_format import MessageToDict +from google.protobuf.struct_pb2 import Struct from openfeature.evaluation_context import EvaluationContext from openfeature.event import ProviderEventDetails @@ -176,10 +177,17 @@ def listen(self) -> None: while self.active: try: - context_values_request = sync_pb2.GetMetadataRequest() - context_values_response: sync_pb2.GetMetadataResponse = ( - self.stub.GetMetadata(context_values_request, wait_for_ready=True) - ) + context_values_response: sync_pb2.GetMetadataResponse + if self.config.sync_metadata_disabled: + context_values_response = sync_pb2.GetMetadataResponse( + metadata=Struct() + ) + else: + context_values_request = sync_pb2.GetMetadataRequest() + context_values_response = self.stub.GetMetadata( + context_values_request, wait_for_ready=True + ) + context_values = MessageToDict(context_values_response) request = sync_pb2.SyncFlagsRequest(**request_args) From 39ea40b218569a908b9c1a77314f3c0d8acf4a49 Mon Sep 17 00:00:00 2001 From: Maks Osowski Date: Wed, 12 Mar 2025 17:54:42 +0100 Subject: [PATCH 2/3] chore(flagd): Minimally refactor GrpcWatcher.listen() to pass ruff complexity pre-commit Signed-off-by: Maks Osowski --- .../resolvers/process/connector/grpc_watcher.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py index e4867b10..66429666 100644 --- a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py +++ b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py @@ -163,17 +163,22 @@ def shutdown(self) -> None: self.active = False self.channel.close() + def _create_request_args(self) -> dict: + request_args = {} + if self.selector is not None: + request_args["selector"] = self.selector + if self.provider_id is not None: + request_args["provider_id"] = self.provider_id + + return request_args + def listen(self) -> None: call_args = ( {"timeout": self.streamline_deadline_seconds} if self.streamline_deadline_seconds > 0 else {} ) - request_args = {} - if self.selector is not None: - request_args["selector"] = self.selector - if self.provider_id is not None: - request_args["provider_id"] = self.provider_id + request_args = self._create_request_args() while self.active: try: From b742d8d3dd7f0bc92e4384ce15904c09f882508c Mon Sep 17 00:00:00 2001 From: cupofcat Date: Wed, 12 Mar 2025 18:33:49 +0100 Subject: [PATCH 3/3] Update providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Anton GrĂ¼bel Signed-off-by: cupofcat --- .../src/openfeature/contrib/provider/flagd/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py index ebb10564..e4f69dd7 100644 --- a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py +++ b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py @@ -253,7 +253,7 @@ def __init__( # noqa: PLR0913 # TODO: remove the metadata call entirely after https://github.com/open-feature/flagd/issues/1584 # This is a temporary stop-gap solutions to support servers that don't implement sync.GetMetadata # (see: https://buf.build/open-feature/flagd/docs/main:flagd.sync.v1#flagd.sync.v1.FlagSyncService.GetMetadata). - # Using this option sisables call to sync.GetMetadata + # Using this option disables call to sync.GetMetadata # Disabling will prevent static context from flagd being used in evaluations. # GetMetadata and this option will be removed. self.sync_metadata_disabled = sync_metadata_disabled