mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
setting: configure toggles as true/false instead of array (#43326)
Signed-off-by: bergquist <carl.bergquist@gmail.com>
This commit is contained in:
@@ -1076,9 +1076,17 @@ grpc_port =
|
|||||||
license_path =
|
license_path =
|
||||||
|
|
||||||
[feature_toggles]
|
[feature_toggles]
|
||||||
# enable features, separated by spaces
|
# there are currently two ways to enable feature toggles in the `grafana.ini`.
|
||||||
|
# you can either pass an array of feature you want to enable to the `enable` field or
|
||||||
|
# configure each toggle by setting the name of the toggle to true/false. Toggles set to true/false
|
||||||
|
# will take presidence over toggles in the `enable` list.
|
||||||
|
|
||||||
|
# enable = feature1,feature2
|
||||||
enable =
|
enable =
|
||||||
|
|
||||||
|
# feature1 = true
|
||||||
|
# feature2 = false
|
||||||
|
|
||||||
[date_formats]
|
[date_formats]
|
||||||
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
|
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
|
||||||
|
|
||||||
|
|||||||
@@ -1055,8 +1055,15 @@
|
|||||||
;license_path =
|
;license_path =
|
||||||
|
|
||||||
[feature_toggles]
|
[feature_toggles]
|
||||||
# enable features, separated by spaces
|
# there are currently two ways to enable feature toggles in the `grafana.ini`.
|
||||||
;enable =
|
# you can either pass an array of feature you want to enable to the `enable` field or
|
||||||
|
# configure each toggle by setting the name of the toggle to true/false. Toggles set to true/false
|
||||||
|
# will take presidence over toggles in the `enable` list.
|
||||||
|
|
||||||
|
;enable = feature1,feature2
|
||||||
|
|
||||||
|
;feature1 = true
|
||||||
|
;feature2 = false
|
||||||
|
|
||||||
[date_formats]
|
[date_formats]
|
||||||
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
|
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
|
||||||
|
|||||||
@@ -1407,17 +1407,6 @@ func (cfg *Cfg) readRenderingSettings(iniFile *ini.File) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Cfg) readFeatureToggles(iniFile *ini.File) error {
|
|
||||||
// Read and populate feature toggles list
|
|
||||||
featureTogglesSection := iniFile.Section("feature_toggles")
|
|
||||||
cfg.FeatureToggles = make(map[string]bool)
|
|
||||||
featuresTogglesStr := valueAsString(featureTogglesSection, "enable", "")
|
|
||||||
for _, feature := range util.SplitString(featuresTogglesStr) {
|
|
||||||
cfg.FeatureToggles[feature] = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAlertingSettings(iniFile *ini.File) error {
|
func readAlertingSettings(iniFile *ini.File) error {
|
||||||
alerting := iniFile.Section("alerting")
|
alerting := iniFile.Section("alerting")
|
||||||
enabled, err := alerting.Key("enabled").Bool()
|
enabled, err := alerting.Key("enabled").Bool()
|
||||||
|
|||||||
74
pkg/setting/setting_feature_toggles.go
Normal file
74
pkg/setting/setting_feature_toggles.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package setting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/util"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
featureToggleInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||||
|
Name: "feature_toggles_info",
|
||||||
|
Help: "info metric that exposes what feature toggles are enabled or not",
|
||||||
|
Namespace: "grafana",
|
||||||
|
}, []string{"name"})
|
||||||
|
|
||||||
|
defaultFeatureToggles = map[string]bool{
|
||||||
|
"recordedQueries": false,
|
||||||
|
"accesscontrol": false,
|
||||||
|
"service-accounts": false,
|
||||||
|
"httpclientprovider_azure_auth": false,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (cfg *Cfg) readFeatureToggles(iniFile *ini.File) error {
|
||||||
|
toggles, err := overrideDefaultWithConfiguration(iniFile, defaultFeatureToggles)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.FeatureToggles = toggles
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func overrideDefaultWithConfiguration(iniFile *ini.File, featureToggles map[string]bool) (map[string]bool, error) {
|
||||||
|
// Read and populate feature toggles list
|
||||||
|
featureTogglesSection := iniFile.Section("feature_toggles")
|
||||||
|
|
||||||
|
// parse the comma separated list in `enable`.
|
||||||
|
featuresTogglesStr := valueAsString(featureTogglesSection, "enable", "")
|
||||||
|
for _, feature := range util.SplitString(featuresTogglesStr) {
|
||||||
|
featureToggles[feature] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// read all other settings under [feature_toggles]. If a toggle is
|
||||||
|
// present in both the value in `enable` is overridden.
|
||||||
|
for _, v := range featureTogglesSection.Keys() {
|
||||||
|
if v.Name() == "enable" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := strconv.ParseBool(v.Value())
|
||||||
|
if err != nil {
|
||||||
|
return featureToggles, err
|
||||||
|
}
|
||||||
|
|
||||||
|
featureToggles[v.Name()] = b
|
||||||
|
}
|
||||||
|
|
||||||
|
// track if feature toggles are enabled or not using an info metric
|
||||||
|
for k, v := range featureToggles {
|
||||||
|
if v {
|
||||||
|
featureToggleInfo.WithLabelValues(k).Set(1)
|
||||||
|
} else {
|
||||||
|
featureToggleInfo.WithLabelValues(k).Set(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return featureToggles, nil
|
||||||
|
}
|
||||||
98
pkg/setting/setting_feature_toggles_test.go
Normal file
98
pkg/setting/setting_feature_toggles_test.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package setting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFeatureToggles(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
conf map[string]string
|
||||||
|
err error
|
||||||
|
expectedToggles map[string]bool
|
||||||
|
defaultToggles map[string]bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "can parse feature toggles listed under [feature_toggles]",
|
||||||
|
conf: map[string]string{
|
||||||
|
"enable": "feature1,feature2",
|
||||||
|
"feature3": "true",
|
||||||
|
},
|
||||||
|
expectedToggles: map[string]bool{
|
||||||
|
"feature1": true,
|
||||||
|
"feature2": true,
|
||||||
|
"feature3": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "toggles under [feature_toggles] overrides those in the array",
|
||||||
|
conf: map[string]string{
|
||||||
|
"enable": "feature1,feature2",
|
||||||
|
"feature2": "false",
|
||||||
|
},
|
||||||
|
expectedToggles: map[string]bool{
|
||||||
|
"feature1": true,
|
||||||
|
"feature2": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid boolean value should return syntax error",
|
||||||
|
conf: map[string]string{
|
||||||
|
"enable": "feature1,feature2",
|
||||||
|
"feature2": "invalid",
|
||||||
|
},
|
||||||
|
expectedToggles: map[string]bool{},
|
||||||
|
err: strconv.ErrSyntax,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should override default feature toggles",
|
||||||
|
defaultToggles: map[string]bool{
|
||||||
|
"feature1": true,
|
||||||
|
},
|
||||||
|
conf: map[string]string{
|
||||||
|
"feature1": "false",
|
||||||
|
},
|
||||||
|
expectedToggles: map[string]bool{
|
||||||
|
"feature1": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
f := ini.Empty()
|
||||||
|
|
||||||
|
toggles, _ := f.NewSection("feature_toggles")
|
||||||
|
for k, v := range tc.conf {
|
||||||
|
_, err := toggles.NewKey(k, v)
|
||||||
|
require.ErrorIs(t, err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
dt := map[string]bool{}
|
||||||
|
if len(tc.defaultToggles) > 0 {
|
||||||
|
dt = tc.defaultToggles
|
||||||
|
}
|
||||||
|
|
||||||
|
featureToggles, err := overrideDefaultWithConfiguration(f, dt)
|
||||||
|
require.ErrorIs(t, err, tc.err)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
for k, v := range featureToggles {
|
||||||
|
require.Equal(t, tc.expectedToggles[k], v, tc.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user