MM-30740 Add support for boolean feature flags. (#16311)
* Add support for boolean feature flags. * Tests * Use strconv.ParseBool to accept additional values as true. * Update config/feature_flags.go Co-authored-by: Christopher Poile <cpoile@gmail.com> Co-authored-by: Christopher Poile <cpoile@gmail.com> Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
faaac9cb74
Коммит
a87e8d1c20
@@ -6,6 +6,8 @@ package config
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/mlog"
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
@@ -73,7 +75,8 @@ func (f *FeatureFlagSynchronizer) Close() {
|
||||
// featureFlagsFromMap sets the feature flags from a map[string]string.
|
||||
// It starts with baseFeatureFlags and only sets values that are
|
||||
// given by the upstream management system.
|
||||
// Makes the assumption that all feature flags are strings for now.
|
||||
// Makes the assumption that all feature flags are strings or booleans.
|
||||
// Strings are converted to booleans by considering case insensitive "on" or any value considered by strconv.ParseBool as true and any other value as false.
|
||||
func featureFlagsFromMap(featuresMap map[string]string, baseFeatureFlags model.FeatureFlags) model.FeatureFlags {
|
||||
refStruct := reflect.ValueOf(&baseFeatureFlags).Elem()
|
||||
for fieldName, fieldValue := range featuresMap {
|
||||
@@ -83,13 +86,20 @@ func featureFlagsFromMap(featuresMap map[string]string, baseFeatureFlags model.F
|
||||
continue
|
||||
}
|
||||
|
||||
refField.Set(reflect.ValueOf(fieldValue))
|
||||
switch refField.Type().Kind() {
|
||||
case reflect.Bool:
|
||||
parsedBoolValue, _ := strconv.ParseBool(fieldValue)
|
||||
refField.Set(reflect.ValueOf(strings.ToLower(fieldValue) == "on" || parsedBoolValue))
|
||||
default:
|
||||
refField.Set(reflect.ValueOf(fieldValue))
|
||||
}
|
||||
|
||||
}
|
||||
return baseFeatureFlags
|
||||
}
|
||||
|
||||
// featureFlagsToMap returns the feature flags as a map[string]string
|
||||
// Currently assumes that all feature flags are strings for now.
|
||||
// Supports boolean and string feature flags.
|
||||
func featureFlagsToMap(featureFlags *model.FeatureFlags) map[string]string {
|
||||
refStructVal := reflect.ValueOf(*featureFlags)
|
||||
refStructType := reflect.TypeOf(*featureFlags)
|
||||
@@ -100,7 +110,12 @@ func featureFlagsToMap(featureFlags *model.FeatureFlags) map[string]string {
|
||||
if !refFieldVal.IsValid() {
|
||||
continue
|
||||
}
|
||||
ret[refFieldType.Name] = refFieldVal.String()
|
||||
switch refFieldType.Type.Kind() {
|
||||
case reflect.Bool:
|
||||
ret[refFieldType.Name] = strconv.FormatBool(refFieldVal.Bool())
|
||||
default:
|
||||
ret[refFieldType.Name] = refFieldVal.String()
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
@@ -67,6 +67,41 @@ func TestFeatureFlagsFromMap(t *testing.T) {
|
||||
Base: model.FeatureFlags{},
|
||||
ExpectedTestValue: "",
|
||||
},
|
||||
"bool on": {
|
||||
FeatureMap: map[string]string{"TestBoolFeature": "on"},
|
||||
Base: model.FeatureFlags{TestBoolFeature: true},
|
||||
ExpectedTestValue: "",
|
||||
},
|
||||
"bool true": {
|
||||
FeatureMap: map[string]string{"TestBoolFeature": "true"},
|
||||
Base: model.FeatureFlags{TestBoolFeature: true},
|
||||
ExpectedTestValue: "",
|
||||
},
|
||||
"bool True": {
|
||||
FeatureMap: map[string]string{"TestBoolFeature": "True"},
|
||||
Base: model.FeatureFlags{TestBoolFeature: true},
|
||||
ExpectedTestValue: "",
|
||||
},
|
||||
"bool 1": {
|
||||
FeatureMap: map[string]string{"TestBoolFeature": "1"},
|
||||
Base: model.FeatureFlags{TestBoolFeature: true},
|
||||
ExpectedTestValue: "",
|
||||
},
|
||||
"bool off": {
|
||||
FeatureMap: map[string]string{"TestBoolFeature": "off"},
|
||||
Base: model.FeatureFlags{},
|
||||
ExpectedTestValue: "",
|
||||
},
|
||||
"bool false": {
|
||||
FeatureMap: map[string]string{"TestBoolFeature": "false"},
|
||||
Base: model.FeatureFlags{},
|
||||
ExpectedTestValue: "",
|
||||
},
|
||||
"bool other value": {
|
||||
FeatureMap: map[string]string{"TestBoolFeature": "someotherbadvalue"},
|
||||
Base: model.FeatureFlags{},
|
||||
ExpectedTestValue: "",
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require.Equal(t, tc.ExpectedTestValue, featureFlagsFromMap(tc.FeatureMap, tc.Base).TestFeature)
|
||||
@@ -97,3 +132,23 @@ func TestFeatureFlagsToMap(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFeatureFlagsToMapBool(t *testing.T) {
|
||||
for name, tc := range map[string]struct {
|
||||
Flags model.FeatureFlags
|
||||
TestFeatureValue string
|
||||
}{
|
||||
"false": {
|
||||
TestFeatureValue: "false",
|
||||
Flags: model.FeatureFlags{},
|
||||
},
|
||||
"true": {
|
||||
TestFeatureValue: "true",
|
||||
Flags: model.FeatureFlags{TestBoolFeature: true},
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require.Equal(t, tc.TestFeatureValue, featureFlagsToMap(&tc.Flags)["TestBoolFeature"])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user