Skip to content

Commit

Permalink
Add support for multiple yaml documents on eval (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
cezarsa authored Nov 29, 2022
1 parent 7ef61dc commit bfb4ada
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 78 deletions.
78 changes: 37 additions & 41 deletions cmd/vals/main.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package main

import (
"bytes"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"os"
Expand Down Expand Up @@ -41,20 +39,32 @@ func fatal(format string, args ...interface{}) {
os.Exit(1)
}

func readNodesOrFail(f *string) []yaml.Node {
nodes, err := vals.Inputs(*f)
if err != nil {
fatal("%v", err)
}
return nodes
}

func readOrFail(f *string) map[string]interface{} {
m, err := vals.Input(*f)
nodes := readNodesOrFail(f)
if len(nodes) == 0 {
fatal("no document found")
}
var nodeValue map[string]interface{}
err := nodes[0].Decode(&nodeValue)
if err != nil {
fatal("%v", err)
}
return m
return nodeValue
}

func writeOrFail(o *string, res interface{}) {
out, err := vals.Output(*o, res)
func writeOrFail(o *string, nodes []yaml.Node) {
err := vals.Output(os.Stdout, *o, nodes)
if err != nil {
fatal("%v", err)
}
fmt.Printf("%s", *out)
}

func main() {
Expand All @@ -79,11 +89,24 @@ func main() {
e := evalCmd.Bool("exclude-secret", false, "Leave secretref+<uri> as-is and only replace ref+<uri>")
evalCmd.Parse(os.Args[2:])

m := readOrFail(f)
nodes := readNodesOrFail(f)

res, err := vals.Eval(m, vals.Options{ExcludeSecret: *e})
if err != nil {
fatal("%v", err)
var res []yaml.Node
for _, node := range nodes {
var nodeValue map[string]interface{}
err := node.Decode(&nodeValue)
if err != nil {
fatal("%v", err)
}
evalResult, err := vals.Eval(nodeValue, vals.Options{ExcludeSecret: *e})
if err != nil {
fatal("%v", err)
}
err = node.Encode(evalResult)
if err != nil {
fatal("%v", err)
}
res = append(res, node)
}

writeOrFail(o, res)
Expand Down Expand Up @@ -122,10 +145,7 @@ func main() {
o := evalCmd.String("o", "yaml", "Output type which is either \"yaml\" or \"json\"")
evalCmd.Parse(os.Args[2:])

nodes, err := vals.Inputs(*f)
if err != nil {
fatal("%v", err)
}
nodes := readNodesOrFail(f)

var res []yaml.Node
for _, node := range nodes {
Expand All @@ -136,31 +156,7 @@ func main() {
res = append(res, *n)
}

for i, node := range res {
buf := &bytes.Buffer{}
encoder := yaml.NewEncoder(buf)
encoder.SetIndent(2)

if err := encoder.Encode(&node); err != nil {
fatal("%v", err)
}
if *o == "json" {
var v interface{}
if err := json.Unmarshal(buf.Bytes(), &v); err != nil {
fatal("%v", err)
}
bs, err := json.Marshal(v)
if err != nil {
fatal("%v", err)
}
print(string(bs))
} else {
print(buf.String())
}
if i != len(res)-1 {
fmt.Println("---")
}
}
writeOrFail(o, res)
case CmdVersion:
if len(version) == 0 {
fmt.Println("Version: dev")
Expand Down Expand Up @@ -203,7 +199,7 @@ func KsDecode(node yaml.Node) (*yaml.Node, error) {
}
}

if isSecret {
if isSecret && !kk.IsZero() {
kk.Value = "stringData"

v := vv
Expand Down
65 changes: 28 additions & 37 deletions io.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"bufio"
"encoding/json"
"fmt"
"gopkg.in/yaml.v3"
"io"
"io/ioutil"
"os"

"gopkg.in/yaml.v3"
)

func Inputs(f string) ([]yaml.Node, error) {
Expand All @@ -24,7 +24,10 @@ func Inputs(f string) ([]yaml.Node, error) {
} else {
return nil, fmt.Errorf("Nothing to eval: No file specified")
}
return nodesFromReader(reader)
}

func nodesFromReader(reader io.Reader) ([]yaml.Node, error) {
nodes := []yaml.Node{}
buf := bufio.NewReader(reader)
decoder := yaml.NewDecoder(buf)
Expand All @@ -41,41 +44,29 @@ func Inputs(f string) ([]yaml.Node, error) {
return nodes, nil
}

func Input(f string) (map[string]interface{}, error) {
m := map[string]interface{}{}
var input []byte
var err error
if f == "-" {
input, err = ioutil.ReadAll(os.Stdin)
} else if f != "" {
input, err = ioutil.ReadFile(f)
} else {
return nil, fmt.Errorf("Nothing to eval: No file specified")
}
if err != nil {
return nil, err
}
if err := yaml.Unmarshal(input, &m); err != nil {
return nil, err
}

return m, nil
}
func Output(output io.Writer, format string, nodes []yaml.Node) error {
for i, node := range nodes {
var v interface{}
if err := node.Decode(&v); err != nil {
return err
}
if format == "json" {
bs, err := json.Marshal(v)
if err != nil {
return err
}
fmt.Fprintln(output, string(bs))
} else {
encoder := yaml.NewEncoder(output)
encoder.SetIndent(2)

func Output(o string, res interface{}) (*string, error) {
var err error
var out []byte
switch o {
case "yaml":
out, err = yaml.Marshal(res)
case "json":
out, err = json.Marshal(res)
default:
return nil, fmt.Errorf("Unknown output type: %s", o)
}
if err != nil {
return nil, fmt.Errorf("Failed marshalling into %s: %v", o, err)
if err := encoder.Encode(v); err != nil {
return err
}
}
if i != len(nodes)-1 {
fmt.Fprintln(output, "---")
}
}
str := string(out)
return &str, nil
return nil
}
80 changes: 80 additions & 0 deletions io_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package vals

import (
"bytes"
"strings"
"testing"
)

func Test_InputOutput(t *testing.T) {
baseDocument := `foo:
bar:
- baz
`

tests := []struct {
name string
input string
format string
expected string
}{
{
name: "single document yaml",
input: baseDocument,
format: "yaml",
expected: "foo:\n bar:\n - baz\n",
},
{
name: "multi document yaml",
input: baseDocument + "---\nbar: baz\n",
format: "yaml",
expected: "foo:\n bar:\n - baz\n---\nbar: baz\n",
},
{
name: "single document json",
input: baseDocument,
format: "json",
expected: "{\"foo\":{\"bar\":[\"baz\"]}}\n",
},
{
name: "multi document json",
input: baseDocument + "---\nbar: baz\n",
format: "json",
expected: "{\"foo\":{\"bar\":[\"baz\"]}}\n---\n{\"bar\":\"baz\"}\n",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
nodes, err := nodesFromReader(strings.NewReader(tt.input))
if err != nil {
t.Fatal(err)
}
buf := &bytes.Buffer{}
err = Output(buf, tt.format, nodes)
if err != nil {
t.Fatal(err)
}

if buf.String() != tt.expected {
t.Errorf("Expected %q, got %q", tt.expected, buf.String())
}

nodesRoundTrip, err := nodesFromReader(buf)
if err != nil {
t.Fatal(err)
}

bufRoundTrip := &bytes.Buffer{}
err = Output(bufRoundTrip, "yaml", nodesRoundTrip)
if err != nil {
t.Fatal(err)
}

if bufRoundTrip.String() != tt.input {
t.Errorf("Expected %q, got %q", tt.input, bufRoundTrip.String())
}

})
}
}

0 comments on commit bfb4ada

Please sign in to comment.