diff --git a/go.mod b/go.mod index 878de320..a647e318 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,4 @@ require ( golang.org/x/text v0.3.7 ) -require github.com/go-logr/logr v1.2.3 // indirect +require github.com/go-logr/logr v1.2.3 diff --git a/pkg/openfeature/client.go b/pkg/openfeature/client.go index 99b79ea4..f7624731 100644 --- a/pkg/openfeature/client.go +++ b/pkg/openfeature/client.go @@ -461,8 +461,8 @@ func (c Client) evaluate( return evalDetails, nil } -func flattenContext(evalCtx EvaluationContext) map[string]interface{} { - flatCtx := map[string]interface{}{} +func flattenContext(evalCtx EvaluationContext) FlattenedContext { + flatCtx := FlattenedContext{} if evalCtx.Attributes != nil { flatCtx = evalCtx.Attributes } diff --git a/pkg/openfeature/client_test.go b/pkg/openfeature/client_test.go index 7bd49da0..c5d521e1 100644 --- a/pkg/openfeature/client_test.go +++ b/pkg/openfeature/client_test.go @@ -416,7 +416,7 @@ func TestRequirement_1_4_9(t *testing.T) { func TestFlattenContext(t *testing.T) { tests := map[string]struct { inCtx EvaluationContext - outCtx map[string]interface{} + outCtx FlattenedContext }{ "happy path": { inCtx: EvaluationContext{ @@ -427,7 +427,7 @@ func TestFlattenContext(t *testing.T) { }, TargetingKey: "user", }, - outCtx: map[string]interface{}{ + outCtx: FlattenedContext{ TargetingKey: "user", "1": "string", "2": 0.01, @@ -442,7 +442,7 @@ func TestFlattenContext(t *testing.T) { "3": false, }, }, - outCtx: map[string]interface{}{ + outCtx: FlattenedContext{ "1": "string", "2": 0.01, "3": false, @@ -458,7 +458,7 @@ func TestFlattenContext(t *testing.T) { "3": false, }, }, - outCtx: map[string]interface{}{ + outCtx: FlattenedContext{ TargetingKey: "user", "1": "string", "2": 0.01, @@ -469,7 +469,7 @@ func TestFlattenContext(t *testing.T) { inCtx: EvaluationContext{ TargetingKey: "user", }, - outCtx: map[string]interface{}{ + outCtx: FlattenedContext{ TargetingKey: "user", }, }, diff --git a/pkg/openfeature/noop_provider.go b/pkg/openfeature/noop_provider.go index 90500f40..5cd5561c 100644 --- a/pkg/openfeature/noop_provider.go +++ b/pkg/openfeature/noop_provider.go @@ -11,7 +11,7 @@ func (e NoopProvider) Metadata() Metadata { } // BooleanEvaluation returns a boolean flag. -func (e NoopProvider) BooleanEvaluation(ctx context.Context, flag string, defaultValue bool, evalCtx map[string]interface{}) BoolResolutionDetail { +func (e NoopProvider) BooleanEvaluation(ctx context.Context, flag string, defaultValue bool, evalCtx FlattenedContext) BoolResolutionDetail { return BoolResolutionDetail{ Value: defaultValue, ResolutionDetail: ResolutionDetail{ @@ -22,7 +22,7 @@ func (e NoopProvider) BooleanEvaluation(ctx context.Context, flag string, defaul } // StringEvaluation returns a string flag. -func (e NoopProvider) StringEvaluation(ctx context.Context, flag string, defaultValue string, evalCtx map[string]interface{}) StringResolutionDetail { +func (e NoopProvider) StringEvaluation(ctx context.Context, flag string, defaultValue string, evalCtx FlattenedContext) StringResolutionDetail { return StringResolutionDetail{ Value: defaultValue, ResolutionDetail: ResolutionDetail{ @@ -33,7 +33,7 @@ func (e NoopProvider) StringEvaluation(ctx context.Context, flag string, default } // FloatEvaluation returns a float flag. -func (e NoopProvider) FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx map[string]interface{}) FloatResolutionDetail { +func (e NoopProvider) FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx FlattenedContext) FloatResolutionDetail { return FloatResolutionDetail{ Value: defaultValue, ResolutionDetail: ResolutionDetail{ @@ -44,7 +44,7 @@ func (e NoopProvider) FloatEvaluation(ctx context.Context, flag string, defaultV } // IntEvaluation returns an int flag. -func (e NoopProvider) IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx map[string]interface{}) IntResolutionDetail { +func (e NoopProvider) IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx FlattenedContext) IntResolutionDetail { return IntResolutionDetail{ Value: defaultValue, ResolutionDetail: ResolutionDetail{ @@ -55,7 +55,7 @@ func (e NoopProvider) IntEvaluation(ctx context.Context, flag string, defaultVal } // ObjectEvaluation returns an object flag -func (e NoopProvider) ObjectEvaluation(ctx context.Context, flag string, defaultValue interface{}, evalCtx map[string]interface{}) InterfaceResolutionDetail { +func (e NoopProvider) ObjectEvaluation(ctx context.Context, flag string, defaultValue interface{}, evalCtx FlattenedContext) InterfaceResolutionDetail { return InterfaceResolutionDetail{ Value: defaultValue, ResolutionDetail: ResolutionDetail{ diff --git a/pkg/openfeature/provider.go b/pkg/openfeature/provider.go index a5ff81f9..de85a71c 100644 --- a/pkg/openfeature/provider.go +++ b/pkg/openfeature/provider.go @@ -16,15 +16,19 @@ const ( TargetingKey string = "targetingKey" // evaluation context map key. The targeting key uniquely identifies the subject (end-user, or client service) of a flag evaluation. ) +// FlattenedContext contains metadata for a given flag evaluation in a flattened structure. +// TargetingKey ("targetingKey") is stored as a string value if provided in the evaluation context. +type FlattenedContext map[string]interface{} + // FeatureProvider interface defines a set of functions that can be called in order to evaluate a flag. // vendors should implement type FeatureProvider interface { Metadata() Metadata - BooleanEvaluation(ctx context.Context, flag string, defaultValue bool, evalCtx map[string]interface{}) BoolResolutionDetail - StringEvaluation(ctx context.Context, flag string, defaultValue string, evalCtx map[string]interface{}) StringResolutionDetail - FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx map[string]interface{}) FloatResolutionDetail - IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx map[string]interface{}) IntResolutionDetail - ObjectEvaluation(ctx context.Context, flag string, defaultValue interface{}, evalCtx map[string]interface{}) InterfaceResolutionDetail + BooleanEvaluation(ctx context.Context, flag string, defaultValue bool, evalCtx FlattenedContext) BoolResolutionDetail + StringEvaluation(ctx context.Context, flag string, defaultValue string, evalCtx FlattenedContext) StringResolutionDetail + FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx FlattenedContext) FloatResolutionDetail + IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx FlattenedContext) IntResolutionDetail + ObjectEvaluation(ctx context.Context, flag string, defaultValue interface{}, evalCtx FlattenedContext) InterfaceResolutionDetail Hooks() []Hook } diff --git a/pkg/openfeature/provider_mock_test.go b/pkg/openfeature/provider_mock_test.go index bcdb2b16..b68fc1f7 100644 --- a/pkg/openfeature/provider_mock_test.go +++ b/pkg/openfeature/provider_mock_test.go @@ -35,7 +35,7 @@ func (m *MockFeatureProvider) EXPECT() *MockFeatureProviderMockRecorder { } // BooleanEvaluation mocks base method. -func (m *MockFeatureProvider) BooleanEvaluation(ctx context.Context, flag string, defaultValue bool, evalCtx map[string]interface{}) BoolResolutionDetail { +func (m *MockFeatureProvider) BooleanEvaluation(ctx context.Context, flag string, defaultValue bool, evalCtx FlattenedContext) BoolResolutionDetail { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BooleanEvaluation", ctx, flag, defaultValue, evalCtx) ret0, _ := ret[0].(BoolResolutionDetail) @@ -49,7 +49,7 @@ func (mr *MockFeatureProviderMockRecorder) BooleanEvaluation(ctx, flag, defaultV } // FloatEvaluation mocks base method. -func (m *MockFeatureProvider) FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx map[string]interface{}) FloatResolutionDetail { +func (m *MockFeatureProvider) FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx FlattenedContext) FloatResolutionDetail { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FloatEvaluation", ctx, flag, defaultValue, evalCtx) ret0, _ := ret[0].(FloatResolutionDetail) @@ -77,7 +77,7 @@ func (mr *MockFeatureProviderMockRecorder) Hooks() *gomock.Call { } // IntEvaluation mocks base method. -func (m *MockFeatureProvider) IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx map[string]interface{}) IntResolutionDetail { +func (m *MockFeatureProvider) IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx FlattenedContext) IntResolutionDetail { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IntEvaluation", ctx, flag, defaultValue, evalCtx) ret0, _ := ret[0].(IntResolutionDetail) @@ -105,7 +105,7 @@ func (mr *MockFeatureProviderMockRecorder) Metadata() *gomock.Call { } // ObjectEvaluation mocks base method. -func (m *MockFeatureProvider) ObjectEvaluation(ctx context.Context, flag string, defaultValue interface{}, evalCtx map[string]interface{}) InterfaceResolutionDetail { +func (m *MockFeatureProvider) ObjectEvaluation(ctx context.Context, flag string, defaultValue interface{}, evalCtx FlattenedContext) InterfaceResolutionDetail { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ObjectEvaluation", ctx, flag, defaultValue, evalCtx) ret0, _ := ret[0].(InterfaceResolutionDetail) @@ -119,7 +119,7 @@ func (mr *MockFeatureProviderMockRecorder) ObjectEvaluation(ctx, flag, defaultVa } // StringEvaluation mocks base method. -func (m *MockFeatureProvider) StringEvaluation(ctx context.Context, flag, defaultValue string, evalCtx map[string]interface{}) StringResolutionDetail { +func (m *MockFeatureProvider) StringEvaluation(ctx context.Context, flag, defaultValue string, evalCtx FlattenedContext) StringResolutionDetail { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StringEvaluation", ctx, flag, defaultValue, evalCtx) ret0, _ := ret[0].(StringResolutionDetail) diff --git a/pkg/openfeature/provider_test.go b/pkg/openfeature/provider_test.go index 5c1983e8..9662d5a6 100644 --- a/pkg/openfeature/provider_test.go +++ b/pkg/openfeature/provider_test.go @@ -42,11 +42,11 @@ func TestRequirement_2_2(t *testing.T) { mockProvider := NewMockFeatureProvider(ctrl) type requirements interface { - BooleanEvaluation(ctx context.Context, flag string, defaultValue bool, evalCtx map[string]interface{}) BoolResolutionDetail - StringEvaluation(ctx context.Context, flag string, defaultValue string, evalCtx map[string]interface{}) StringResolutionDetail - FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx map[string]interface{}) FloatResolutionDetail - IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx map[string]interface{}) IntResolutionDetail - ObjectEvaluation(ctx context.Context, flag string, defaultValue interface{}, evalCtx map[string]interface{}) InterfaceResolutionDetail + BooleanEvaluation(ctx context.Context, flag string, defaultValue bool, evalCtx FlattenedContext) BoolResolutionDetail + StringEvaluation(ctx context.Context, flag string, defaultValue string, evalCtx FlattenedContext) StringResolutionDetail + FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx FlattenedContext) FloatResolutionDetail + IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx FlattenedContext) IntResolutionDetail + ObjectEvaluation(ctx context.Context, flag string, defaultValue interface{}, evalCtx FlattenedContext) InterfaceResolutionDetail } var mockProviderI interface{} = mockProvider