From 978af4a40748da8a52d5205996cf27ff148447cc Mon Sep 17 00:00:00 2001 From: Jonas Kuske Date: Fri, 12 Sep 2025 10:59:41 +0200 Subject: [PATCH] fix(config): also error when env var in config is prefixed or suffixed Signed-off-by: Jonas Kuske --- README.md | 2 +- config/config.go | 11 ++++++++--- config_test.go | 5 ++++- testdata/snmp-auth-envvars.yml | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 088dfac5..310c817d 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ scrape_configs: ``` You could pass `username`, `password` & `priv_password` via environment variables of your choice in below format. -If the variables exist in the environment, they are resolved on the fly otherwise the string in the config file is passed as-is. +If the variables exist in the environment, they are resolved on the fly, otherwise `snmp_exporter` will error while loading the config. This requires the `--config.expand-environment-variables` flag be set. diff --git a/config/config.go b/config/config.go index ee25d417..be49c5b3 100644 --- a/config/config.go +++ b/config/config.go @@ -361,11 +361,16 @@ func (re *Regexp) UnmarshalYAML(unmarshal func(interface{}) error) error { } func substituteEnvVariables(value string) (string, error) { + var missingEnv = "" result := os.Expand(value, func(s string) string { - return os.Getenv(s) + v := os.Getenv(s) + if v == "" && missingEnv == "" { + missingEnv = s + } + return v }) - if result == "" { - return "", errors.New(value + " environment variable not found") + if missingEnv != "" { + return "", errors.New(missingEnv + " environment variable not found") } return result, nil } diff --git a/config_test.go b/config_test.go index eed7f4c9..bc678b88 100644 --- a/config_test.go +++ b/config_test.go @@ -73,7 +73,7 @@ func TestLoadMultipleConfigs(t *testing.T) { // When all environment variables are present func TestEnvSecrets(t *testing.T) { - t.Setenv("ENV_USERNAME", "snmp_username") + t.Setenv("ENV_USERNAME", "username") // snmp_ prefix is set in config file t.Setenv("ENV_PASSWORD", "snmp_password") t.Setenv("ENV_PRIV_PASSWORD", "snmp_priv_password") @@ -110,6 +110,9 @@ func TestEnvSecretsMissing(t *testing.T) { sc := &SafeConfig{} err := sc.ReloadConfig(nopLogger, []string{"testdata/snmp-auth-envvars.yml"}, true) + if err == nil { + t.Fatal("no error despite missing env var") + } if err != nil { // we check the error message pattern to determine the error if strings.Contains(err.Error(), "environment variable not found") { diff --git a/testdata/snmp-auth-envvars.yml b/testdata/snmp-auth-envvars.yml index cd742110..9182a4df 100644 --- a/testdata/snmp-auth-envvars.yml +++ b/testdata/snmp-auth-envvars.yml @@ -2,7 +2,7 @@ auths: with_secret: community: mysecret security_level: SomethingReadOnly - username: ${ENV_USERNAME} + username: snmp_${ENV_USERNAME} password: ${ENV_PASSWORD} auth_protocol: SHA256 priv_protocol: AES