diff --git a/confmap/internal/e2e/expand_test.go b/confmap/internal/e2e/expand_test.go index 2c5c6cb20f5..61a08977aaa 100644 --- a/confmap/internal/e2e/expand_test.go +++ b/confmap/internal/e2e/expand_test.go @@ -20,6 +20,8 @@ import ( func Test_EscapedEnvVars_NoDefaultScheme(t *testing.T) { const expandedValue = "some expanded value" t.Setenv("ENV_VALUE", expandedValue) + t.Setenv("ENV_LIST", "['$$ESCAPE_ME','$$ESCAPE_ME']") + t.Setenv("ENV_MAP", "{'key': '$$ESCAPE_ME'}") expectedMap := map[string]any{ "test_map": map[string]any{ @@ -38,6 +40,8 @@ func Test_EscapedEnvVars_NoDefaultScheme(t *testing.T) { "key13": "env:MAP_VALUE_2}${ENV_VALUE}{", "key14": "$" + expandedValue, "key15": "$ENV_VALUE", + "key16": []any{"$ESCAPE_ME", "$ESCAPE_ME"}, + "key17": map[string]any{"key": "$ESCAPE_ME"}, }, } @@ -59,6 +63,8 @@ func Test_EscapedEnvVars_NoDefaultScheme(t *testing.T) { func Test_EscapedEnvVars_DefaultScheme(t *testing.T) { const expandedValue = "some expanded value" t.Setenv("ENV_VALUE", expandedValue) + t.Setenv("ENV_LIST", "['$$ESCAPE_ME','$$ESCAPE_ME']") + t.Setenv("ENV_MAP", "{'key': '$$ESCAPE_ME'}") expectedMap := map[string]any{ "test_map": map[string]any{ @@ -77,6 +83,8 @@ func Test_EscapedEnvVars_DefaultScheme(t *testing.T) { "key13": "env:MAP_VALUE_2}${ENV_VALUE}{", "key14": "$" + expandedValue, "key15": "$ENV_VALUE", + "key16": []any{"$ESCAPE_ME", "$ESCAPE_ME"}, + "key17": map[string]any{"key": "$ESCAPE_ME"}, }, } diff --git a/confmap/internal/e2e/testdata/expand-escaped-env.yaml b/confmap/internal/e2e/testdata/expand-escaped-env.yaml index ca3df782cb6..74a1d9fa2af 100644 --- a/confmap/internal/e2e/testdata/expand-escaped-env.yaml +++ b/confmap/internal/e2e/testdata/expand-escaped-env.yaml @@ -29,3 +29,7 @@ test_map: key14: "$$${env:ENV_VALUE}" # $ -> $ key15: "$ENV_VALUE" + # list is escaped + key16: "${env:ENV_LIST}" + # map is escaped + key17: "${env:ENV_MAP}" diff --git a/confmap/resolver.go b/confmap/resolver.go index 3237a258c74..92b22bfbf1d 100644 --- a/confmap/resolver.go +++ b/confmap/resolver.go @@ -181,11 +181,7 @@ func (mr *Resolver) Resolve(ctx context.Context) (*Conf, error) { if err != nil { return nil, err } - if v, ok := val.(string); ok { - cfgMap[k] = strings.ReplaceAll(v, "$$", "$") - } else { - cfgMap[k] = val - } + cfgMap[k] = escapeDollarSign(val) } retMap = NewFromStringMap(cfgMap) @@ -199,6 +195,31 @@ func (mr *Resolver) Resolve(ctx context.Context) (*Conf, error) { return retMap, nil } +func escapeDollarSign(val any) any { + switch v := val.(type) { + case string: + return strings.ReplaceAll(v, "$$", "$") + case expandedValue: + v.Original = strings.ReplaceAll(v.Original, "$$", "$") + v.Value = escapeDollarSign(v.Value) + return v + case []any: + nslice := make([]any, len(v), len(v)) + for i, x := range v { + nslice[i] = escapeDollarSign(x) + } + return nslice + case map[string]any: + nmap := make(map[string]any, len(v)) + for k, x := range v { + nmap[k] = escapeDollarSign(x) + } + return nmap + default: + return val + } +} + // Watch blocks until any configuration change was detected or an unrecoverable error // happened during monitoring the configuration changes. //