Skip to content

Commit

Permalink
cfgparser: add optional splitting of ENV variable values on comma via…
Browse files Browse the repository at this point in the history
… env_split
  • Loading branch information
rjocoleman committed Mar 16, 2024
1 parent 798c411 commit 1d28bd2
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 6 deletions.
12 changes: 10 additions & 2 deletions docs/reference/config-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ directive0 {env:VAR}
Parse is forgiving and incomplete variable placeholder (e.g. '{env:VAR') will
be left as-is. Variables are expanded inside quotes too.

Environment values that are comma separated can optionally be split to space separated strings using {env_split:COMMA_SEPARATED_VARIABLE_NAME}

```
# SEP_VAR=foo,bar,baz
directive1 {env_split:SEP_VAR}
```

In this usage the value of `directive1` would be `foo bar baz` (and `{env:SEP_VAR}` would be `foo,bar,baz`)

## Snippets & imports

You can reuse blocks of configuration by defining them as "snippets". Snippet
Expand Down Expand Up @@ -196,5 +206,3 @@ No-op module. It doesn't need to be configured explicitly and can be referenced
using "dummy" name. It can act as a delivery target or auth.
provider. In the latter case, it will accept any credentials, allowing any
client to authenticate using any username and password (use with care!).


18 changes: 14 additions & 4 deletions framework/cfgparser/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,21 @@ func expandEnvironment(nodes []Node) []Node {
return newNodes
}

var unixEnvvarRe = regexp.MustCompile(`{env:([^\$]+)}`)
var unixEnvvarRe = regexp.MustCompile(`\{(env|env_split):([^\}]+)\}`)

func removeUnexpandedEnvvars(s string) string {
s = unixEnvvarRe.ReplaceAllString(s, "")
return s
return unixEnvvarRe.ReplaceAllStringFunc(s, func(match string) string {
matches := unixEnvvarRe.FindStringSubmatch(match)
if len(matches) != 3 {
return match // Not a valid pattern
}
key, mode := matches[2], matches[1]
value := os.Getenv(key)
if mode == "env_split" {
value = strings.ReplaceAll(value, ",", " ")
}
return value
})
}

func buildEnvReplacer() *strings.Replacer {
Expand All @@ -61,7 +71,7 @@ func buildEnvReplacer() *strings.Replacer {
key := parts[0]
value := parts[1]

pairs = append(pairs, "{env:"+key+"}", value)
pairs = append(pairs, "{env:"+key+"}", value, "{envSplit:"+key+"}", value)
}
return strings.NewReplacer(pairs...)
}
42 changes: 42 additions & 0 deletions framework/cfgparser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,47 @@ var cases = []struct {
},
false,
},
{
"environment variable split at comma expansion",
`a {env_split:TESTING_VARIABLE_SPLIT}`,
[]Node{
{
Name: "a",
Args: []string{"value1 value2 value3"},
Children: nil,
File: "test",
Line: 1,
},
},
false,
},
{
"environment variable mixed usage",
`mixed {env:TESTING_VARIABLE} {env_split:TESTING_VARIABLE_SPLIT}`,
[]Node{
{
Name: "mixed",
Args: []string{"ABCDEF", "value1 value2 value3"},
Children: nil,
File: "test",
Line: 1,
},
},
false,
},
{
"environment variable not split on comma",
`not_split {env:TESTING_VARIABLE_SPLIT}`,
[]Node{
{
Name: "not_split",
Args: []string{"value1,value2,value3"},
File: "test",
Line: 1,
},
},
false,
},
{
"snippet expansion",
`(foo) { a }
Expand Down Expand Up @@ -581,6 +622,7 @@ func printTree(t *testing.T, root Node, indent int) {
func TestRead(t *testing.T) {
os.Setenv("TESTING_VARIABLE", "ABCDEF")
os.Setenv("TESTING_VARIABLE2", "ABC2 DEF2")
os.Setenv("TESTING_VARIABLE_SPLIT", "value1,value2,value3")

for _, case_ := range cases {
case_ := case_
Expand Down

0 comments on commit 1d28bd2

Please sign in to comment.