Settings: Env override support for dynamic settings (#21439)

* Settings: supports env overrrides for dynamic settings

* Settings: makes it possible to explicitly get env override support for dynamic settings

* Make linter happy
This commit is contained in:
Leonard Gram 2020-01-10 15:33:54 +01:00 committed by GitHub
parent c5f906f472
commit 673ccdc448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 5 deletions

View File

@ -0,0 +1,35 @@
package setting
import (
"os"
"testing"
"github.com/stretchr/testify/require"
)
func TestDynamicSettingsSupport_Override(t *testing.T) {
cfg := NewCfg()
envKey := "GF_FOO_BAR"
sectionName := "foo"
keyName := "bar"
expected := "dynamic value"
os.Setenv(envKey, expected)
defer func() { os.Unsetenv(envKey) }()
value := cfg.SectionWithEnvOverrides(sectionName).Key(keyName).MustString("default value")
require.Equal(t, expected, value)
}
func TestDynamicSettingsSupport_NoOverride(t *testing.T) {
cfg := NewCfg()
sectionName := "foo"
keyName := "bar"
expected := "default value"
_, err := cfg.Raw.Section(sectionName).NewKey(keyName, expected)
require.NoError(t, err)
value := cfg.SectionWithEnvOverrides(sectionName).Key(keyName).String()
require.Equal(t, expected, value)
}

View File

@ -32,6 +32,7 @@ const (
HTTP2 Scheme = "h2"
SOCKET Scheme = "socket"
DEFAULT_HTTP_ADDR string = "0.0.0.0"
REDACTED_PASSWORD string = "*********"
)
const (
@ -327,15 +328,13 @@ func applyEnvVariableOverrides(file *ini.File) error {
appliedEnvOverrides = make([]string, 0)
for _, section := range file.Sections() {
for _, key := range section.Keys() {
sectionName := strings.ToUpper(strings.Replace(section.Name(), ".", "_", -1))
keyName := strings.ToUpper(strings.Replace(key.Name(), ".", "_", -1))
envKey := fmt.Sprintf("GF_%s_%s", sectionName, keyName)
envKey := envKey(section.Name(), key.Name())
envValue := os.Getenv(envKey)
if len(envValue) > 0 {
key.SetValue(envValue)
if shouldRedactKey(envKey) {
envValue = "*********"
envValue = REDACTED_PASSWORD
}
if shouldRedactURLKey(envKey) {
u, err := url.Parse(envValue)
@ -359,6 +358,13 @@ func applyEnvVariableOverrides(file *ini.File) error {
return nil
}
func envKey(sectionName string, keyName string) string {
sN := strings.ToUpper(strings.Replace(sectionName, ".", "_", -1))
kN := strings.ToUpper(strings.Replace(keyName, ".", "_", -1))
envKey := fmt.Sprintf("GF_%s_%s", sN, kN)
return envKey
}
func applyCommandLineDefaultProperties(props map[string]string, file *ini.File) {
appliedCommandLineProperties = make([]string, 0)
for _, section := range file.Sections() {
@ -368,7 +374,7 @@ func applyCommandLineDefaultProperties(props map[string]string, file *ini.File)
if exists {
key.SetValue(value)
if shouldRedactKey(keyString) {
value = "*********"
value = REDACTED_PASSWORD
}
appliedCommandLineProperties = append(appliedCommandLineProperties, fmt.Sprintf("%s=%s", keyString, value))
}
@ -1114,6 +1120,37 @@ func (cfg *Cfg) LogConfigSources() {
cfg.Logger.Info("App mode " + Env)
}
type DynamicSection struct {
section *ini.Section
Logger log.Logger
}
// Key dynamically overrides keys with environment variables.
// As a side effect, the value of the setting key will be updated if an environment variable is present.
func (s *DynamicSection) Key(k string) *ini.Key {
envKey := envKey(s.section.Name(), k)
envValue := os.Getenv(envKey)
key := s.section.Key(k)
if len(envValue) == 0 {
return key
}
key.SetValue(envValue)
if shouldRedactKey(envKey) {
envValue = REDACTED_PASSWORD
}
s.Logger.Info("Config overridden from Environment variable", "var", fmt.Sprintf("%s=%s", envKey, envValue))
return key
}
// SectionWithEnvOverrides dynamically overrides keys with environment variables.
// As a side effect, the value of the setting key will be updated if an environment variable is present.
func (cfg *Cfg) SectionWithEnvOverrides(s string) *DynamicSection {
return &DynamicSection{cfg.Raw.Section(s), cfg.Logger}
}
func IsExpressionsEnabled() bool {
v, ok := FeatureToggles["expressions"]
if !ok {