diff --git a/providers/openfeature-flagd-provider/docker/flags.json b/providers/openfeature-flagd-provider/docker/flags.json
index 5c46ccc..e5fd506 100644
--- a/providers/openfeature-flagd-provider/docker/flags.json
+++ b/providers/openfeature-flagd-provider/docker/flags.json
@@ -36,6 +36,57 @@
"real-object": { "real": "value" }
},
"defaultVariant": "real-object"
+ },
+ "boolean-flag-targeting": {
+ "state": "ENABLED",
+ "variants": {
+ "on": true,
+ "off": false
+ },
+ "defaultVariant": "off",
+ "targeting": {
+ "if": [
+ {
+ "==": [
+ {
+ "var": "be_true"
+ },
+ true
+ ]
+ },
+ "on"
+ ]
+ }
+ },
+ "color-palette-experiment": {
+ "state": "ENABLED",
+ "defaultVariant": "grey",
+ "variants": {
+ "red": "#b91c1c",
+ "blue": "#0284c7",
+ "green": "#16a34a",
+ "grey": "#4b5563"
+ },
+ "targeting": {
+ "fractional": [
+ [
+ "red",
+ 25
+ ],
+ [
+ "blue",
+ 25
+ ],
+ [
+ "green",
+ 25
+ ],
+ [
+ "grey",
+ 25
+ ]
+ ]
+ }
}
}
}
diff --git a/providers/openfeature-flagd-provider/lib/openfeature/flagd/provider/client.rb b/providers/openfeature-flagd-provider/lib/openfeature/flagd/provider/client.rb
index 90a67fc..31cfa46 100644
--- a/providers/openfeature-flagd-provider/lib/openfeature/flagd/provider/client.rb
+++ b/providers/openfeature-flagd-provider/lib/openfeature/flagd/provider/client.rb
@@ -1,9 +1,11 @@
# frozen_string_literal: true
require "grpc"
+require 'google/protobuf/well_known_types'
require_relative "schema/v1/schema_services_pb"
require_relative "configuration"
+
module OpenFeature
module FlagD
module Provider
@@ -15,20 +17,20 @@ module Provider
#
# * metadata - Returns the associated provider metadata with the name
#
- # * resolve_boolean_value(flag_key:, default_value:, context: nil)
- # manner; client.resolve_boolean(flag_key: 'boolean-flag', default_value: false)
+ # * fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
+ # manner; client.fetch_boolean(flag_key: 'boolean-flag', default_value: false)
#
- # * resolve_integer_value(flag_key:, default_value:, context: nil)
- # manner; client.resolve_integer_value(flag_key: 'integer-flag', default_value: 2)
+ # * fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
+ # manner; client.fetch_integer_value(flag_key: 'integer-flag', default_value: 2)
#
- # * resolve_float_value(flag_key:, default_value:, context: nil)
- # manner; client.resolve_float_value(flag_key: 'float-flag', default_value: 2.0)
+ # * fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
+ # manner; client.fetch_float_value(flag_key: 'float-flag', default_value: 2.0)
#
- # * resolve_string_value(flag_key:, default_value:, context: nil)
- # manner; client.resolve_string_value(flag_key: 'string-flag', default_value: 'some-default-value')
+ # * fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
+ # manner; client.fetch_string_value(flag_key: 'string-flag', default_value: 'some-default-value')
#
- # * resolve_object_value(flag_key:, default_value:, context: nil)
- # manner; client.resolve_object_value(flag_key: 'flag', default_value: { default_value: 'value'})
+ # * fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
+ # manner; client.fetch_object_value(flag_key: 'flag', default_value: { default_value: 'value'})
class Client
PROVIDER_NAME = "flagd Provider"
@@ -40,7 +42,7 @@ def initialize(configuration: nil)
end
def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
- request = Grpc::ResolveBooleanRequest.new(flag_key: flag_key)
+ request = Grpc::ResolveBooleanRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
process_request { @grpc_client.resolve_boolean(request) }
end
@@ -54,22 +56,22 @@ def fetch_number_value(flag_key:, default_value:, evaluation_context: nil)
end
def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
- request = Grpc::ResolveIntRequest.new(flag_key: flag_key)
+ request = Grpc::ResolveIntRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
process_request { @grpc_client.resolve_int(request) }
end
def fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
- request = Grpc::ResolveFloatRequest.new(flag_key: flag_key)
- process_request { @grpc_client.resolve_float(request) }
+ request = Grpc::ResolveFloatRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
+ process_request { @grpc_client.resolve_float(request) }
end
def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
- request = Grpc::ResolveStringRequest.new(flag_key: flag_key)
+ request = Grpc::ResolveStringRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
process_request { @grpc_client.resolve_string(request) }
end
def fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
- request = Grpc::ResolveObjectRequest.new(flag_key: flag_key)
+ request = Grpc::ResolveObjectRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
process_request { @grpc_client.resolve_object(request) }
end
@@ -93,6 +95,14 @@ def process_request(&block)
error_response("GENERAL", e.message)
end
+ def prepare_evaluation_context(evaluation_context)
+ return nil if !evaluation_context
+
+ fields = evaluation_context.fields
+ fields["targetingKey"] = fields.delete(:targeting_key)
+ Google::Protobuf::Struct.from_hash(fields)
+ end
+
def error_response(error_code, error_message)
ResolutionDetails.new(error_code, error_message, "ERROR", nil, nil)
end
diff --git a/providers/openfeature-flagd-provider/spec/openfeature/flagd/provider_spec.rb b/providers/openfeature-flagd-provider/spec/openfeature/flagd/provider_spec.rb
index d7b1f93..d40ed3f 100644
--- a/providers/openfeature-flagd-provider/spec/openfeature/flagd/provider_spec.rb
+++ b/providers/openfeature-flagd-provider/spec/openfeature/flagd/provider_spec.rb
@@ -110,6 +110,33 @@
end
end
+ context "get value with evaluated context" do
+ it do
+ expect(
+ client.fetch_boolean_value(
+ flag_key: 'boolean-flag-targeting',
+ default_value: false,
+ evaluation_context: OpenFeature::SDK::EvaluationContext.new(be_true: true)
+ )
+ ).to be_truthy
+ end
+
+ it do
+ fetch_value_with_targeting_key = ->(targeting_key) do
+ client.fetch_boolean_value(
+ flag_key: 'color-palette-experiment',
+ default_value: "#b91c1c",
+ evaluation_context: OpenFeature::SDK::EvaluationContext.new(targeting_key: targeting_key)
+ )
+ end
+
+ initial_value = fetch_value_with_targeting_key.("123")
+ (0..2).to_a.each do # try with 1000
+ expect(fetch_value_with_targeting_key.("123")).to eq(initial_value)
+ end
+ end
+ end
+
context "get details" do
it do
expect(client.fetch_boolean_details(flag_key: 'boolean-flag', default_value: false).resolution_details.to_h).to include(