diff --git a/pkg/services/featuremgmt/models.go b/pkg/services/featuremgmt/models.go index abcbf838933..cb378155956 100644 --- a/pkg/services/featuremgmt/models.go +++ b/pkg/services/featuremgmt/models.go @@ -130,10 +130,10 @@ type FeatureFlagType int const ( Boolean FeatureFlagType = iota + String Integer Float - Object - String + Structure ) func (t FeatureFlagType) String() string { @@ -144,7 +144,7 @@ func (t FeatureFlagType) String() string { return "number" case Float: return "float" - case Object: + case Structure: return "object" case String: return "string" @@ -176,7 +176,7 @@ func (t *FeatureFlagType) UnmarshalJSON(b []byte) error { case "float": *t = Float case "object": - *t = Object + *t = Structure case "string": *t = String } @@ -192,6 +192,8 @@ type FeatureFlag struct { // CEL-GO expression. Using the value "true" will mean this is on by default Expression string `json:"expression,omitempty"` + // Type of the feature flag (boolean, number, string, structure), + Type FeatureFlagType `json:"type,omitempty"` // Special behavior properties RequiresDevMode bool `json:"requiresDevMode,omitempty"` // can not be enabled in production @@ -200,8 +202,6 @@ type FeatureFlag struct { // The server must be initialized with the value RequiresRestart bool `json:"requiresRestart,omitempty"` - - Type FeatureFlagType `json:"type,omitempty"` } type FeatureToggleWebhookPayload struct { diff --git a/pkg/services/featuremgmt/static_provider.go b/pkg/services/featuremgmt/static_provider.go index 17d85efc406..9554c2a5ba4 100644 --- a/pkg/services/featuremgmt/static_provider.go +++ b/pkg/services/featuremgmt/static_provider.go @@ -1,6 +1,7 @@ package featuremgmt import ( + "encoding/json" "fmt" "github.com/open-feature/go-sdk/openfeature" "github.com/open-feature/go-sdk/openfeature/memprovider" @@ -87,8 +88,8 @@ func createFlag(flag FeatureFlag) (memprovider.InMemoryFlag, error) { value, err = strconv.Atoi(flag.Expression) case Float: value, err = strconv.ParseFloat(flag.Expression, 64) - case Object: - value = value + case Structure: + err = json.Unmarshal([]byte(flag.Expression), &value) default: return memprovider.InMemoryFlag{}, fmt.Errorf("unsupported flag type %s", flag.Type) } diff --git a/pkg/services/featuremgmt/static_provider_test.go b/pkg/services/featuremgmt/static_provider_test.go index 40127a08fbb..01ddcd8dc2e 100644 --- a/pkg/services/featuremgmt/static_provider_test.go +++ b/pkg/services/featuremgmt/static_provider_test.go @@ -111,7 +111,6 @@ func Test_StaticProvider_DifferentType(t *testing.T) { flags FeatureFlag defaultValue any expectedValue any - test int }{ { flags: FeatureFlag{ @@ -121,7 +120,6 @@ func Test_StaticProvider_DifferentType(t *testing.T) { }, defaultValue: false, expectedValue: true, - test: 0, }, { flags: FeatureFlag{ @@ -131,7 +129,6 @@ func Test_StaticProvider_DifferentType(t *testing.T) { }, defaultValue: 0.0, expectedValue: 1.0, - test: 1, }, { flags: FeatureFlag{ @@ -141,7 +138,6 @@ func Test_StaticProvider_DifferentType(t *testing.T) { }, defaultValue: "red", expectedValue: "blue", - test: 2, }, { flags: FeatureFlag{ @@ -151,7 +147,15 @@ func Test_StaticProvider_DifferentType(t *testing.T) { }, defaultValue: int64(0), expectedValue: int64(1), - test: 3, + }, + { + flags: FeatureFlag{ + Name: "Flag", + Expression: `{ "foo": "bar" }`, + Type: Structure, + }, + defaultValue: nil, + expectedValue: map[string]any{"foo": "bar"}, }, } @@ -160,17 +164,17 @@ func Test_StaticProvider_DifferentType(t *testing.T) { assert.NoError(t, err) var result any - switch tt.test { - case 0: + switch tt.flags.Type { + case Boolean: result = provider.BooleanEvaluation(t.Context(), tt.flags.Name, tt.defaultValue.(bool), openfeature.FlattenedContext{}).Value - case 1: + case Float: result = provider.FloatEvaluation(t.Context(), tt.flags.Name, tt.defaultValue.(float64), openfeature.FlattenedContext{}).Value - case 2: + case String: result = provider.StringEvaluation(t.Context(), tt.flags.Name, tt.defaultValue.(string), openfeature.FlattenedContext{}).Value - case 3: + case Integer: result = provider.IntEvaluation(t.Context(), tt.flags.Name, tt.defaultValue.(int64), openfeature.FlattenedContext{}).Value - case 4: - result = provider.ObjectEvaluation(t.Context(), tt.flags.Name, tt.defaultValue.(map[string]any), openfeature.FlattenedContext{}).Value + case Structure: + result = provider.ObjectEvaluation(t.Context(), tt.flags.Name, tt.defaultValue, openfeature.FlattenedContext{}).Value } assert.Equal(t, tt.expectedValue, result)