From 4eb6be5de944614b21f5a8a6072350692239944b Mon Sep 17 00:00:00 2001 From: Uwe Krueger Date: Sun, 17 Feb 2019 11:15:56 +0100 Subject: [PATCH] fix endless loop for nested lambda evaluation error --- dynaml/lambda.go | 5 ++-- flow/environment.go | 6 +++-- spiff++.go | 25 +++++++++++++++++-- yaml/equals.go | 61 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 yaml/equals.go diff --git a/dynaml/lambda.go b/dynaml/lambda.go index 0c7dcf1..b2aa0f8 100644 --- a/dynaml/lambda.go +++ b/dynaml/lambda.go @@ -123,9 +123,10 @@ func short(val interface{}, all bool) string { case map[string]yaml.Node: s := "{" sep := "" - for k, e := range v { + getSortedKeys(v) + for _, k := range getSortedKeys(v) { if all || k != "_" { - s = fmt.Sprintf("%s%s%s: %s", s, sep, k, short(e.Value(), all)) + s = fmt.Sprintf("%s%s%s: %s", s, sep, k, short(v[k].Value(), all)) sep = ", " } } diff --git a/flow/environment.go b/flow/environment.go index 633e88e..f29ff26 100644 --- a/flow/environment.go +++ b/flow/environment.go @@ -194,10 +194,12 @@ func (e DefaultEnvironment) Flow(source yaml.Node, shouldOverride bool) (yaml.No debug.Debug("@@} ---> %+v\n", next) next = Cleanup(next, updateBinding(next)) - if reflect.DeepEqual(result, next) { + b := reflect.DeepEqual(result, next) + //b,r:=yaml.Equals(result, next,[]string{}) + if b { break } - + //fmt.Printf("****** found diff: %s\n", r) result = next } debug.Debug("@@@ Done\n") diff --git a/spiff++.go b/spiff++.go index 178b35a..d48976a 100644 --- a/spiff++.go +++ b/spiff++.go @@ -52,6 +52,11 @@ func main() { Name: "path", Usage: "output is taken from given path", }, + cli.StringSliceFlag{ + Name: "select", + Usage: "filter dedicated output fields", + Value: &cli.StringSlice{}, + }, }, Action: func(c *cli.Context) { if len(c.Args()) < 1 { @@ -59,7 +64,10 @@ func main() { os.Exit(1) } debug.DebugFlag = c.Bool("debug") - merge(c.Args()[0], c.Bool("partial"), c.Bool("json"), c.Bool("split"), c.String("path"), c.Args()[1:]) + merge(c.Args()[0], c.Bool("partial"), + c.Bool("json"), c.Bool("split"), + c.String("path"), c.StringSlice("select"), + c.Args()[1:]) }, }, { @@ -108,7 +116,7 @@ func main() { app.Run(os.Args) } -func merge(templateFilePath string, partial bool, json, split bool, subpath string, stubFilePaths []string) { +func merge(templateFilePath string, partial bool, json, split bool, subpath string, selection []string, stubFilePaths []string) { var templateFile []byte var err error var stdin = false @@ -190,6 +198,19 @@ func merge(templateFilePath string, partial bool, json, split bool, subpath stri } flowed = node } + if len(selection) > 0 { + new := map[string]yaml.Node{} + for _, p := range selection { + comps := strings.Split(p, ".") + node, ok := yaml.FindR(true, flowed, comps...) + if !ok { + log.Fatalln(fmt.Sprintf("path %q not found%s", subpath, doc)) + } + new[comps[len(comps)-1]] = node + + } + flowed = yaml.NewNode(new, "") + } if split { if list, ok := flowed.Value().([]yaml.Node); ok { for _, d := range list { diff --git a/yaml/equals.go b/yaml/equals.go new file mode 100644 index 0000000..8d394b0 --- /dev/null +++ b/yaml/equals.go @@ -0,0 +1,61 @@ +package yaml + +import ( + "fmt" + "reflect" +) + +func Equals(a, b Node, path []string) (bool, string) { + + if reflect.TypeOf(a.Value()) != reflect.TypeOf(b.Value()) { + return false, fmt.Sprintf("non matching type %T!=%T at %+v", a.Value(), b.Value(), path) + + } + if a.Value() == nil && b.Value() == nil { + return true, "" + } + if a.Value() == nil || b.Value() == nil { + return false, fmt.Sprintf("found non-matching nil at %+v", path) + } + + if !reflect.DeepEqual(a.GetAnnotation(), b.GetAnnotation()) { + return false, fmt.Sprintf("annotation diff at %+v: %v", path, a.GetAnnotation()) + } + switch va := a.Value().(type) { + case []Node: + vb := b.Value().([]Node) + if len(va) != len(vb) { + return false, fmt.Sprintf("list length mismatch %d!=%s at %+v", len(va), len(vb), path) + } + for i, v := range va { + if b, r := Equals(v, vb[i], append(path, fmt.Sprintf("[%d]", i))); !b { + return b, r + } + } + case map[string]Node: + vb := b.Value().(map[string]Node) + + for k, v := range va { + _, ok := vb[k] + if !ok { + return false, fmt.Sprintf("key %q missing in b at %+v", k, path) + } + if b, r := Equals(v, vb[k], append(path, k)); !b { + return b, r + } + } + for k := range vb { + _, ok := va[k] + if !ok { + return false, fmt.Sprintf("additional key %q in b at %+v", k, path) + } + } + default: + e := reflect.DeepEqual(a.Value(), b.Value()) + if !e { + return false, fmt.Sprintf("diff at %+v: %v!=%v", path, a.Value(), b.Value()) + } + + } + return true, "" +}