add new thiongs

This commit is contained in:
grambbledook
2026-01-07 19:05:09 +01:00
parent e66240e087
commit 0616aae6f7
2 changed files with 76 additions and 21 deletions
+57 -5
View File
@@ -1,6 +1,8 @@
package setting
import (
"encoding/json"
"fmt"
"strconv"
"gopkg.in/ini.v1"
@@ -8,6 +10,20 @@ import (
"github.com/grafana/grafana/pkg/util"
)
type FeatureToggleType string
const Structure FeatureToggleType = "structure"
const Integer FeatureToggleType = "integer"
const Float FeatureToggleType = "float"
const Boolean FeatureToggleType = "boolean"
const String FeatureToggleType = "string"
type FeatureToggle struct {
Type FeatureToggleType `json:"type"`
Name string `json:"name"`
Value any `json:"value"`
}
// Deprecated: should use `featuremgmt.FeatureToggles`
func (cfg *Cfg) readFeatureToggles(iniFile *ini.File) error {
section := iniFile.Section("feature_toggles")
@@ -15,18 +31,31 @@ func (cfg *Cfg) readFeatureToggles(iniFile *ini.File) error {
if err != nil {
return err
}
// TODO IsFeatureToggleEnabled has been deprecated for 2 years now, we should remove this function completely
// nolint:staticcheck
cfg.IsFeatureToggleEnabled = func(key string) bool { return toggles[key] }
cfg.IsFeatureToggleEnabled = func(key string) bool {
toggle, ok := toggles[key]
if !ok {
return false
}
return toggle.Type == Boolean && toggle.Value == true
}
return nil
}
func ReadFeatureTogglesFromInitFile(featureTogglesSection *ini.Section) (map[string]bool, error) {
featureToggles := make(map[string]bool, 10)
func ReadFeatureTogglesFromInitFile(featureTogglesSection *ini.Section) (map[string]FeatureToggle, error) {
featureToggles := make(map[string]FeatureToggle, 10)
// parse the comma separated list in `enable`.
featuresTogglesStr := valueAsString(featureTogglesSection, "enable", "")
for _, feature := range util.SplitString(featuresTogglesStr) {
featureToggles[feature] = true
featureToggles[feature] = FeatureToggle{
Type: Boolean,
Name: feature,
Value: true,
}
}
// read all other settings under [feature_toggles]. If a toggle is
@@ -36,12 +65,35 @@ func ReadFeatureTogglesFromInitFile(featureTogglesSection *ini.Section) (map[str
continue
}
b, err := strconv.ParseBool(v.Value())
b, err := ParseFlag(v.Name(), v.Value())
if err != nil {
return featureToggles, err
}
flag, exists := featureToggles[v.Name()]
if exists && flag.Type != b.Type {
return nil, fmt.Errorf("type mismatch during flag declaration '%s': %s, %s", v.Name(), flag.Type, b.Type)
}
featureToggles[v.Name()] = b
}
return featureToggles, nil
}
func ParseFlag(name, value string) (FeatureToggle, error) {
var structure any
if boolean, err := strconv.ParseBool(value); err == nil {
return FeatureToggle{Type: Boolean, Name: name, Value: boolean}, nil
}
if integer, err := strconv.Atoi(value); err == nil {
return FeatureToggle{Type: Integer, Name: name, Value: integer}, nil
}
if float, err := strconv.ParseFloat(value, 64); err == nil {
return FeatureToggle{Type: Float, Name: name, Value: float}, nil
}
if err := json.Unmarshal([]byte(value), &structure); err == nil {
return FeatureToggle{Type: Structure, Name: name, Value: structure}, nil
}
return FeatureToggle{Type: String, Name: name, Value: value}, nil
}
+19 -16
View File
@@ -1,7 +1,7 @@
package setting
import (
"strconv"
"errors"
"testing"
"github.com/stretchr/testify/require"
@@ -13,16 +13,16 @@ func TestFeatureToggles(t *testing.T) {
name string
conf map[string]string
err error
expectedToggles map[string]bool
expectedToggles map[string]FeatureToggle
}{
{
name: "can parse feature toggles passed in the `enable` array",
conf: map[string]string{
"enable": "feature1,feature2",
},
expectedToggles: map[string]bool{
"feature1": true,
"feature2": true,
expectedToggles: map[string]FeatureToggle{
"feature1": {Name: "feature1", Type: Boolean, Value: true},
"feature2": {Name: "feature2", Type: Boolean, Value: true},
},
},
{
@@ -31,10 +31,10 @@ func TestFeatureToggles(t *testing.T) {
"enable": "feature1,feature2",
"feature3": "true",
},
expectedToggles: map[string]bool{
"feature1": true,
"feature2": true,
"feature3": true,
expectedToggles: map[string]FeatureToggle{
"feature1": {Name: "feature1", Type: Boolean, Value: true},
"feature2": {Name: "feature2", Type: Boolean, Value: true},
"feature3": {Name: "feature3", Type: Boolean, Value: true},
},
},
{
@@ -43,9 +43,9 @@ func TestFeatureToggles(t *testing.T) {
"enable": "feature1,feature2",
"feature2": "false",
},
expectedToggles: map[string]bool{
"feature1": true,
"feature2": false,
expectedToggles: map[string]FeatureToggle{
"feature1": {Name: "feature1", Type: Boolean, Value: true},
"feature2": {Name: "feature2", Type: Boolean, Value: false},
},
},
{
@@ -54,8 +54,8 @@ func TestFeatureToggles(t *testing.T) {
"enable": "feature1,feature2",
"feature2": "invalid",
},
expectedToggles: map[string]bool{},
err: strconv.ErrSyntax,
expectedToggles: map[string]FeatureToggle{},
err: errors.New("type mismatch during flag declaration 'feature2': boolean, string"),
},
}
@@ -69,11 +69,14 @@ func TestFeatureToggles(t *testing.T) {
}
featureToggles, err := ReadFeatureTogglesFromInitFile(toggles)
require.ErrorIs(t, err, tc.err)
if tc.err != nil {
require.EqualError(t, err, tc.err.Error())
}
if err == nil {
for k, v := range featureToggles {
require.Equal(t, tc.expectedToggles[k], v, tc.name)
toggle, _ := tc.expectedToggles[k]
require.Equal(t, toggle, v, tc.name)
}
}
}