Skip to content

Commit

Permalink
Enable flagd targeting by forwarding context
Browse files Browse the repository at this point in the history
  • Loading branch information
alxckn committed Apr 8, 2024
1 parent cede6c8 commit f276b12
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 16 deletions.
51 changes: 51 additions & 0 deletions providers/openfeature-flagd-provider/docker/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
]
]
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -15,20 +17,20 @@ module Provider
#
# * <tt>metadata</tt> - Returns the associated provider metadata with the name
#
# * <tt>resolve_boolean_value(flag_key:, default_value:, context: nil)</tt>
# manner; <tt>client.resolve_boolean(flag_key: 'boolean-flag', default_value: false)</tt>
# * <tt>fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)</tt>
# manner; <tt>client.fetch_boolean(flag_key: 'boolean-flag', default_value: false)</tt>
#
# * <tt>resolve_integer_value(flag_key:, default_value:, context: nil)</tt>
# manner; <tt>client.resolve_integer_value(flag_key: 'integer-flag', default_value: 2)</tt>
# * <tt>fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)</tt>
# manner; <tt>client.fetch_integer_value(flag_key: 'integer-flag', default_value: 2)</tt>
#
# * <tt>resolve_float_value(flag_key:, default_value:, context: nil)</tt>
# manner; <tt>client.resolve_float_value(flag_key: 'float-flag', default_value: 2.0)</tt>
# * <tt>fetch_float_value(flag_key:, default_value:, evaluation_context: nil)</tt>
# manner; <tt>client.fetch_float_value(flag_key: 'float-flag', default_value: 2.0)</tt>
#
# * <tt>resolve_string_value(flag_key:, default_value:, context: nil)</tt>
# manner; <tt>client.resolve_string_value(flag_key: 'string-flag', default_value: 'some-default-value')</tt>
# * <tt>fetch_string_value(flag_key:, default_value:, evaluation_context: nil)</tt>
# manner; <tt>client.fetch_string_value(flag_key: 'string-flag', default_value: 'some-default-value')</tt>
#
# * <tt>resolve_object_value(flag_key:, default_value:, context: nil)</tt>
# manner; <tt>client.resolve_object_value(flag_key: 'flag', default_value: { default_value: 'value'})</tt>
# * <tt>fetch_object_value(flag_key:, default_value:, evaluation_context: nil)</tt>
# manner; <tt>client.fetch_object_value(flag_key: 'flag', default_value: { default_value: 'value'})</tt>
class Client
PROVIDER_NAME = "flagd Provider"

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit f276b12

Please sign in to comment.