Skip to content

Commit f4cb021

Browse files
authored
replace all ${VAR} references with env var values in watches yaml (#45)
* replace all ${VAR} references with env var values in watches yaml Signed-off-by: John Mazzitelli <[email protected]> * don't use regex, just use os.Expand * use t.Setenv * copy-paste error - remove nolint --------- Signed-off-by: John Mazzitelli <[email protected]>
1 parent 8dc66b5 commit f4cb021

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
- version: "${WATCH_VERSION}"
3+
group: "app.example.com"
4+
kind: "AnsibleSelectorTest"
5+
playbook: ${WATCH_PLAYBOOK}
6+
selector:
7+
matchLabels:
8+
${WATCH_MATCH_LABEL_VAR_NAME}: "${WATCH_MATCH_LABEL_VAR_VALUE}"
9+
undefined: "${WATCH_UNDEFINED_ENV_VAR}"
10+
matchExpressions:
11+
- {key: ${WATCH_MATCH_EXPRESSIONS_KEY}, operator: In, values: [a, b]}

internal/ansible/watches/watches.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,12 +313,15 @@ func New(gvk schema.GroupVersionKind, role, playbook string, vars map[string]int
313313
func Load(path string, maxReconciler, ansibleVerbosity int) ([]Watch, error) {
314314
maxConcurrentReconcilesDefault = maxReconciler
315315
ansibleVerbosityDefault = ansibleVerbosity
316-
b, err := os.ReadFile(path)
316+
fileb, err := os.ReadFile(path)
317317
if err != nil {
318318
log.Error(err, "Failed to get config file")
319319
return nil, err
320320
}
321321

322+
// Replace any environment variable references with their values
323+
b := replaceEnvVariables(fileb)
324+
322325
// First unmarshal into a slice of aliases.
323326
alias := []alias{}
324327
err = yaml.Unmarshal(b, &alias)
@@ -358,6 +361,22 @@ func Load(path string, maxReconciler, ansibleVerbosity int) ([]Watch, error) {
358361
return watches, nil
359362
}
360363

364+
// replaceEnvVariables will replace all ${VAR} references found in the byte array
365+
// with the actual values of the env variables. If an env variable is not defined
366+
// the ${VAR} reference remains as-is in the returned byte array.
367+
func replaceEnvVariables(input []byte) []byte {
368+
outputString := os.Expand(string(input), func(varName string) string {
369+
varValue, exists := os.LookupEnv(varName)
370+
if !exists {
371+
// If the environment variable doesn't exist, keep the original reference
372+
return "${" + varName + "}"
373+
}
374+
return varValue
375+
})
376+
377+
return []byte(outputString)
378+
}
379+
361380
// verify that a given GroupVersionKind has a Version and Kind
362381
// A GVK without a group is valid. Certain scenarios may cause a GVK
363382
// without a group to fail in other ways later in the initialization

internal/ansible/watches/watches_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,3 +892,44 @@ func TestGetPossibleRolePaths(t *testing.T) {
892892
})
893893
}
894894
}
895+
896+
func TestReplaceEnvVars(t *testing.T) {
897+
cwd, err := os.Getwd()
898+
if err != nil {
899+
t.Fatalf("Unable to get working directory: %v", err)
900+
}
901+
watchesFile := filepath.Join(cwd, "testdata", "env-vars.yaml")
902+
playbookFile := filepath.Join(cwd, "testdata", "playbook.yml")
903+
904+
t.Setenv("WATCH_PLAYBOOK", playbookFile)
905+
t.Setenv("WATCH_VERSION", "v123")
906+
t.Setenv("WATCH_MATCH_LABEL_VAR_NAME", "label123")
907+
t.Setenv("WATCH_MATCH_LABEL_VAR_VALUE", "value123")
908+
t.Setenv("WATCH_MATCH_EXPRESSIONS_KEY", "key123")
909+
910+
watchSlice, err := Load(watchesFile, 1, 1)
911+
if err != nil {
912+
// this would fail if the WATCH_PLAYBOOK env var wasn't replaced
913+
t.Fatalf("Failed to process watches yaml with env vars: %v", err)
914+
}
915+
if watchSlice[0].GroupVersionKind.Group != "app.example.com" {
916+
t.Fatalf("Failed to parse hardcoded group - the watches yaml did not load properly: %+v", watchSlice[0])
917+
}
918+
if watchSlice[0].GroupVersionKind.Version != "v123" {
919+
t.Fatalf("Failed to replace version with env var: %+v", watchSlice[0])
920+
}
921+
if labelValue, ok := watchSlice[0].Selector.MatchLabels["label123"]; !ok {
922+
t.Fatalf("Failed to replace first match label name with env var: %+v", watchSlice[0])
923+
} else if labelValue != "value123" {
924+
t.Fatalf("Failed to replace first match label value with env var: %+v", watchSlice[0])
925+
}
926+
if labelValue, ok := watchSlice[0].Selector.MatchLabels["undefined"]; !ok {
927+
t.Fatalf("Failed to find the second match label name: %+v", watchSlice[0])
928+
} else if labelValue != "${WATCH_UNDEFINED_ENV_VAR}" {
929+
t.Fatalf("Failed to keep env var reference as-is: %+v", watchSlice[0])
930+
}
931+
keyValue := watchSlice[0].Selector.MatchExpressions[0].Key
932+
if keyValue != "key123" {
933+
t.Fatalf("Failed to replace match expression key with env var: %+v", watchSlice[0])
934+
}
935+
}

0 commit comments

Comments
 (0)