From d11bd84086bd85bbbebb268c00f3298d0ff602bd Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Tue, 24 Sep 2024 10:04:10 +0200 Subject: [PATCH] feat: make vals able to eval dictionaries Signed-off-by: Thomas Becker --- vals.go | 45 +++++++++++++++++++++++++++++++++++++++++---- vals_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/vals.go b/vals.go index a76f158a..fdb23a73 100644 --- a/vals.go +++ b/vals.go @@ -467,6 +467,7 @@ func (r *Runtime) Get(code string) (string, error) { return ret, nil } + func cloneMap(m map[string]interface{}) map[string]interface{} { bs, err := yaml.Marshal(m) if err != nil { @@ -615,15 +616,28 @@ func EvalNodes(nodes []yaml.Node, c Options) ([]yaml.Node, error) { var res []yaml.Node for _, node := range nodes { node := node - var nodeValue map[string]interface{} + var nodeValue interface{} err := node.Decode(&nodeValue) if err != nil { return nil, err } - evalResult, err := Eval(nodeValue, c) - if err != nil { - return nil, err + + var evalResult interface{} + switch v := nodeValue.(type) { + case map[string]interface{}: + evalResult, err = Eval(v, c) + if err != nil { + return nil, err + } + case []interface{}: + evalResult, err = evalArray(v, c) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("unexpected type: %T", v) } + err = node.Encode(evalResult) if err != nil { return nil, err @@ -637,6 +651,29 @@ func EvalNodes(nodes []yaml.Node, c Options) ([]yaml.Node, error) { return res, nil } +func evalArray(arr []interface{}, c Options) ([]interface{}, error) { + var res []interface{} + for _, item := range arr { + switch v := item.(type) { + case map[string]interface{}: + evalResult, err := Eval(v, c) + if err != nil { + return nil, err + } + res = append(res, evalResult) + case []interface{}: + evalResult, err := evalArray(v, c) + if err != nil { + return nil, err + } + res = append(res, evalResult) + default: + res = append(res, v) + } + } + return res, nil +} + func Eval(template map[string]interface{}, o ...Options) (map[string]interface{}, error) { opts := Options{} if len(o) > 0 { diff --git a/vals_test.go b/vals_test.go index d811ccb5..c15d339a 100644 --- a/vals_test.go +++ b/vals_test.go @@ -116,3 +116,36 @@ kind: Secret require.Equal(t, expected, buf.String()) } + +func TestEvalNodesWithDictionaries(t *testing.T) { + var yamlDocs = `- entry: first + username: ref+echo://secrets.enc.yaml +- entry: second + username: ref+echo://secrets.enc.yaml +` + + var expected = `- entry: first + username: secrets.enc.yaml +- entry: second + username: secrets.enc.yaml +` + + tmpFile, err := os.CreateTemp("", "secrets.yaml") + defer os.Remove(tmpFile.Name()) + require.NoError(t, err) + + _, err = tmpFile.WriteString(yamlDocs) + require.NoError(t, err) + + input, err := Inputs(tmpFile.Name()) + require.NoError(t, err) + + nodes, err := EvalNodes(input, Options{}) + require.NoError(t, err) + buf := new(strings.Builder) + + err = Output(buf, "", nodes) + require.NoError(t, err) + + require.Equal(t, expected, buf.String()) +}