Skip to content

Commit d76cb4f

Browse files
committed
Support jmespath for references with jmes: prefix
Signed-off-by: Tamal Saha <tamal@appscode.com>
1 parent ff3c5de commit d76cb4f

File tree

1 file changed

+63
-37
lines changed

1 file changed

+63
-37
lines changed

pkg/graph/lib.go

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"sort"
2727
"strings"
2828

29+
"github.com/jmespath/go-jmespath"
2930
"gomodules.xyz/jsonpath"
3031
core "k8s.io/api/core/v1"
3132
kerr "k8s.io/apimachinery/pkg/api/errors"
@@ -304,25 +305,19 @@ func (finder ObjectFinder) ResourcesFor(src *unstructured.Unstructured, e *Edge)
304305
// TODO: check that namespacePath must be empty
305306

306307
var out []*unstructured.Unstructured
307-
308308
for _, reference := range e.Connection.References {
309-
j := jsonpath.New("jsonpath")
310-
j.AllowMissingKeys(true)
311-
err := j.Parse(reference)
312-
if err != nil {
313-
return nil, fmt.Errorf("fails to parse reference %q between %s -> %s. err:%v", e.Connection.References, e.Src, e.Dst, err)
314-
}
315-
buf := new(bytes.Buffer)
316-
err = j.Execute(buf, src.Object)
317-
if err != nil {
318-
return nil, fmt.Errorf("fails to execute reference %q between %s -> %s. err:%v", e.Connection.References, e.Src, e.Dst, err)
319-
}
320-
r := csv.NewReader(buf)
321-
// Mapper.Comma = ';'
322-
r.Comment = '#'
323-
records, err := r.ReadAll()
324-
if err != nil {
325-
return nil, err
309+
var records [][]string
310+
var err error
311+
if strings.HasPrefix(reference, "jmes:") {
312+
records, err = execJmesPath(src.Object, reference[5:], e.Src, e.Dst)
313+
if err != nil {
314+
return nil, err
315+
}
316+
} else {
317+
records, err = execJsonPath(src.Object, reference, e.Src, e.Dst)
318+
if err != nil {
319+
return nil, err
320+
}
326321
}
327322
refs, err := ParseResourceRefs(records)
328323
if err != nil {
@@ -509,25 +504,18 @@ func (finder ObjectFinder) ResourcesFor(src *unstructured.Unstructured, e *Edge)
509504
rs := result.Items[i]
510505

511506
for _, reference := range e.Connection.References {
512-
513-
j := jsonpath.New("jsonpath")
514-
j.AllowMissingKeys(true)
515-
err := j.Parse(reference)
516-
if err != nil {
517-
return nil, fmt.Errorf("fails to parse reference %q between %s -> %s. err:%v", e.Connection.References, e.Src, e.Dst, err)
518-
}
519-
520-
buf := new(bytes.Buffer)
521-
err = j.Execute(buf, rs.Object)
522-
if err != nil {
523-
return nil, fmt.Errorf("fails to execute reference %q between %s -> %s. err:%v", e.Connection.References, e.Src, e.Dst, err)
524-
}
525-
r := csv.NewReader(buf)
526-
// Mapper.Comma = ';'
527-
r.Comment = '#'
528-
records, err := r.ReadAll()
529-
if err != nil {
530-
return nil, err
507+
var records [][]string
508+
var err error
509+
if strings.HasPrefix(reference, "jmes:") {
510+
records, err = execJmesPath(rs.Object, reference[5:], e.Src, e.Dst)
511+
if err != nil {
512+
return nil, err
513+
}
514+
} else {
515+
records, err = execJsonPath(rs.Object, reference, e.Src, e.Dst)
516+
if err != nil {
517+
return nil, err
518+
}
531519
}
532520
refs, err := ParseResourceRefs(records)
533521
if err != nil {
@@ -581,6 +569,44 @@ func (finder ObjectFinder) ResourcesFor(src *unstructured.Unstructured, e *Edge)
581569
return nil, nil
582570
}
583571

572+
func execJmesPath(data any, reference string, src, dst schema.GroupVersionKind) ([][]string, error) {
573+
result, err := jmespath.Search(reference, data)
574+
if err != nil {
575+
return nil, fmt.Errorf("fails to execute jmes reference %q between %s -> %s. err:%w", reference, src, dst, err)
576+
}
577+
switch v := result.(type) {
578+
case string:
579+
return [][]string{{v}}, nil
580+
case []string:
581+
out := make([][]string, len(v))
582+
for i, s := range v {
583+
out[i] = []string{s}
584+
}
585+
return out, nil
586+
case [][]string:
587+
return v, nil
588+
}
589+
return nil, fmt.Errorf("invalid result type %T for jmes reference %q between %s -> %s", result, reference, src, dst)
590+
}
591+
592+
func execJsonPath(data any, reference string, src, dst schema.GroupVersionKind) ([][]string, error) {
593+
j := jsonpath.New("jsonpath")
594+
j.AllowMissingKeys(true)
595+
err := j.Parse(reference)
596+
if err != nil {
597+
return nil, fmt.Errorf("fails to parse reference %q between %s -> %s. err:%v", reference, src, dst, err)
598+
}
599+
buf := new(bytes.Buffer)
600+
err = j.Execute(buf, data)
601+
if err != nil {
602+
return nil, fmt.Errorf("fails to execute reference %q between %s -> %s. err:%v", reference, src, dst, err)
603+
}
604+
r := csv.NewReader(buf)
605+
// Mapper.Comma = ';'
606+
r.Comment = '#'
607+
return r.ReadAll()
608+
}
609+
584610
func isConnected(conn rsapi.OwnershipLevel, obj *unstructured.Unstructured, owner *unstructured.Unstructured) bool {
585611
switch conn {
586612
case rsapi.Controller:

0 commit comments

Comments
 (0)