From a0cbc0cb65ae601270bdbe3f5313e2dfd49c80e4 Mon Sep 17 00:00:00 2001 From: Marin Bezhanov Date: Wed, 19 Jun 2024 18:55:47 +0300 Subject: [PATCH 1/2] feat: support environment variable substitution in config files (#3195) Signed-off-by: Marin Bezhanov --- internal/config/config.go | 24 +++++++++++++++++++++++- internal/config/config_test.go | 14 ++++++++++++++ internal/config/testdata/envsubst.yml | 4 ++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 internal/config/testdata/envsubst.yml diff --git a/internal/config/config.go b/internal/config/config.go index 1e67dde43e..bdd916220f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -10,6 +10,7 @@ import ( "os" "path/filepath" "reflect" + "regexp" "slices" "strings" "time" @@ -27,10 +28,12 @@ const ( ) var ( - _ validator = (*Config)(nil) + _ validator = (*Config)(nil) + envsubst = regexp.MustCompile(`^\${([a-zA-Z_]+[a-zA-Z0-9_]*)}$`) ) var DecodeHooks = []mapstructure.DecodeHookFunc{ + stringToEnvsubstHookFunc(), mapstructure.StringToTimeDurationHookFunc(), stringToSliceHookFunc(), stringToEnumHookFunc(stringToCacheBackend), @@ -475,6 +478,25 @@ func experimentalFieldSkipHookFunc(types ...reflect.Type) mapstructure.DecodeHoo } } +// stringToEnvsubstHookFunc returns a DecodeHookFunc that substitutes +// `${VARIABLE}` strings with their matching environment variables. +func stringToEnvsubstHookFunc() mapstructure.DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || f != reflect.TypeOf("") { + return data, nil + } + str := data.(string) + if !envsubst.MatchString(str) { + return data, nil + } + key := envsubst.ReplaceAllString(str, `$1`) + return os.Getenv(key), nil + } +} + // stringToSliceHookFunc returns a DecodeHookFunc that converts // string to []string by splitting using strings.Fields(). func stringToSliceHookFunc() mapstructure.DecodeHookFunc { diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 271a8690d7..8541d8803e 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -243,6 +243,20 @@ func TestLoad(t *testing.T) { return cfg }, }, + { + name: "environment variable substitution", + path: "./testdata/envsubst.yml", + envOverrides: map[string]string{ + "HTTP_PORT": "18080", + "LOG_FORMAT": "json", + }, + expected: func() *Config { + cfg := Default() + cfg.Log.Encoding = "json" + cfg.Server.HTTPPort = 18080 + return cfg + }, + }, { name: "deprecated tracing jaeger", path: "./testdata/deprecated/tracing_jaeger.yml", diff --git a/internal/config/testdata/envsubst.yml b/internal/config/testdata/envsubst.yml new file mode 100644 index 0000000000..d8f80984fd --- /dev/null +++ b/internal/config/testdata/envsubst.yml @@ -0,0 +1,4 @@ +server: + http_port: ${HTTP_PORT} +log: + encoding: ${LOG_FORMAT} From 1804b130916779a241eaef105c952a3380707c95 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:39:17 -0400 Subject: [PATCH 2/2] docs: add mbezhanov as a contributor for code (#3197) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 +++ 2 files changed, 12 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 7440bdad5e..0ea4338739 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -448,6 +448,15 @@ "contributions": [ "code" ] + }, + { + "login": "mbezhanov", + "name": "Marin Bezhanov", + "avatar_url": "https://avatars.githubusercontent.com/u/785542?v=4", + "profile": "https://www.linkedin.com/in/mbezhanov", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 2a7fb61d21..f700c24930 100644 --- a/README.md +++ b/README.md @@ -397,6 +397,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Kyryl Perepelytsia
Kyryl Perepelytsia

💻 Aditya Patil
Aditya Patil

💻 + + Marin Bezhanov
Marin Bezhanov

💻 +