From 2b0a26552f71048c5b6948c92e7e8912e02107dd Mon Sep 17 00:00:00 2001 From: Ky-Anh Huynh Date: Sat, 22 Aug 2020 11:36:30 +0200 Subject: [PATCH] Fix #2: -v -u can be used together --- README.md | 12 +++++++----- sub.go | 23 +++++++++++++++++++---- tests/test.sh | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 38202c0..a6ef7c1 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,11 @@ whose names match a predefined prefix/regexp. ### Supported options -* `-v` : Scan and output ocurrences of variables in the input +* `-v`: Scan and output all occurrences of variables in the input. * `-u`: Raise error when environment variable is not set. - This option doesn't work when `-v` is used. + When being used with `-v`, the program scans through the whole + input; otherwise, the program stops immediately when there is + any undefined (environment) variable. * `-p regexp`: Limit substitution to variables that match this prefix. You can use some regular expression as prefix. Default to `[^}]+`. Can be used as an alternative @@ -67,7 +69,7 @@ To limit substitution to variables that match some prefix, use `-p` option: The second command raises an error because the variable `TEST_VAR` matches the expected prefix `TEST_` and its value is not set. -You can also specify exactly a few variables to be substituted +You can also specify exactly a few variables to be substituted (which is exactly an alternative to the `shell-format` option in the original GNU tool `envsubst`): @@ -82,7 +84,7 @@ input argument `-p PREFIX`, the program will build the final regexp 1. Hence you can't use for example `-p '^FOO'`. 2. You can also easily trick the program with some fun `PREFIX` ;) - However, as seen in + However, as seen in https://github.com/icy/genvsub/blob/33e68048c6fe4b6ca0befadbc9fa5c19055ede8b/sub.go#L42 the program enforces input data to follow the form `${VARIABLE_NAME}`. I'm still thinking if we can allow more tricks here. @@ -144,7 +146,7 @@ This tool may be an answer. By accepting not-so-many side-effects, we can easily $ kustomize build \ | genvsub -u -p "(ENV_[_A-Z0-9]+)|STG_NAMESPACE|IMAGE_TAG|RESOURCE_PREFIX_" \ > output.yaml -$ if [[ $? -eq 0 ]]; then +$ if [[ $? -eq 0 ]]; then kubectl apply -f- < output.yaml fi ``` diff --git a/sub.go b/sub.go index 3f47188..140f713 100644 --- a/sub.go +++ b/sub.go @@ -21,6 +21,7 @@ import "flag" var regVarname = regexp.MustCompile(`.+`) var allVarSet = true var lastProcessedVar = "" +var errors = 0 /* users' controllers */ var setMinusU bool @@ -52,14 +53,19 @@ func repl_func(in []byte) []byte { } var_name := in_st[2 : len(in_st)-1] + var_set, var_val := lookUpEnv(var_name) + allVarSet = allVarSet && var_set + lastProcessedVar = var_name + return []byte(var_val) +} + +func lookUpEnv(var_name string) (bool, string) { var_val, var_set := os.LookupEnv(var_name) if !var_set { var_val = fmt.Sprintf("<%s::error::variable_unset>", var_name) fmt.Fprintf(os.Stderr, "%s\n", var_val) } - allVarSet = allVarSet && var_set - lastProcessedVar = var_name - return []byte(var_val) + return var_set, var_val } // https://github.com/jprichardson/readline-go/blob/master/readline.go @@ -92,7 +98,12 @@ func doLine(line string) { if scanOnly { if found := scanLine(line); found != nil { for _, v := range found { - fmt.Printf("%s\n", v[2:len(v)-1]) + var_name := string(v[2 : len(v)-1]) + var_set, _ := lookUpEnv(var_name) + fmt.Printf("%s\n", var_name) + if !var_set { + errors += 1 + } } } } else { @@ -113,4 +124,8 @@ func main() { regVarname = regexp.MustCompile(fmt.Sprintf(`\${(%s)}`, varPrefix)) fmt.Fprintf(os.Stderr, ":: genvsub is reading from STDIN and looking for variables with regexp '%s'\n", regVarname) eachLine(os.Stdin, doLine) + + if setMinusU && errors > 0 { + os.Exit(1) + } } diff --git a/tests/test.sh b/tests/test.sh index 3120984..534b4f7 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -124,7 +124,7 @@ test_prefix_test_complexv() { G_ERRORS="$?" _grep "^JIRA_USER_NAME" _grep "^JIRA_USER_PASSWORD" - [[ "$G_ERRORS" -eq 0 ]] + [[ "$G_ERRORS" -ge 1 ]] } test_change_prefix() {