diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 336a27b7e28..fe98ec96d3b 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -655,6 +655,25 @@ func (cfg *Cfg) applyEnvVariableOverrides(file *ini.File) error { } } + // Override feature toggles from environment variables. + // This is done separately because feature toggles are not stored in the ini file. + // Overriding feature toggles from environment variables is useful when setting them to `false`. + // To set them to `true`, `GF_FEATURE_TOGGLES_ENABLED` can also be used. + const featureTogglesPrefix = "GF_FEATURE_TOGGLES_" + featuresSection := file.Section("feature_toggles") + for _, kv := range os.Environ() { + parts := strings.SplitN(kv, "=", 2) + if len(parts) != 2 { + continue + } + featureName := parts[0] + featureValue := parts[1] + if !strings.HasPrefix(featureName, featureTogglesPrefix) { + continue + } + featuresSection.Key(strings.TrimPrefix(featureName, featureTogglesPrefix)).SetValue(featureValue) + cfg.appliedEnvOverrides = append(cfg.appliedEnvOverrides, fmt.Sprintf("%s=%s", featureName, RedactedValue(featureName, featureValue))) + } return nil } diff --git a/pkg/setting/setting_test.go b/pkg/setting/setting_test.go index 57bce42da71..8b86aa50dfa 100644 --- a/pkg/setting/setting_test.go +++ b/pkg/setting/setting_test.go @@ -681,3 +681,30 @@ func TestDynamicSection(t *testing.T) { assert.Equal(t, value, ds.section.Key(key).String()) }) } + +func TestFeatureTogglesEnvVars(t *testing.T) { + t.Run("should read feature toggles from ini", func(t *testing.T) { + cfg := NewCfg() + const feature = "someFeature" + + err := cfg.Load(CommandLineArgs{HomePath: "../../", Config: "testdata/feature_toggles.ini"}) + require.NoError(t, err) + + require.True(t, cfg.IsFeatureToggleEnabled(feature)) + }) + + t.Run("should override feature toggles from env vars", func(t *testing.T) { + cfg := NewCfg() + const someFeature = "someFeature" + const otherFeature = "otherFeature" + + require.NoError(t, os.Setenv("GF_FEATURE_TOGGLES_"+someFeature, "false")) + require.NoError(t, os.Setenv("GF_FEATURE_TOGGLES_"+otherFeature, "true")) + + err := cfg.Load(CommandLineArgs{HomePath: "../../", Config: "testdata/feature_toggles.ini"}) + require.NoError(t, err) + + require.False(t, cfg.IsFeatureToggleEnabled(someFeature)) + require.True(t, cfg.IsFeatureToggleEnabled(otherFeature)) + }) +} diff --git a/pkg/setting/testdata/feature_toggles.ini b/pkg/setting/testdata/feature_toggles.ini new file mode 100644 index 00000000000..4ca26148bb2 --- /dev/null +++ b/pkg/setting/testdata/feature_toggles.ini @@ -0,0 +1,7 @@ +app_mode = production + +[server] +domain = test.com + +[feature_toggles] +someFeature = true