1
2
3
4 package yaml
5
6 import (
7 "encoding/json"
8 "fmt"
9 "log"
10 "os"
11 "regexp"
12 "strconv"
13 "strings"
14
15 "sigs.k8s.io/kustomize/kyaml/errors"
16 "sigs.k8s.io/kustomize/kyaml/sliceutil"
17 "sigs.k8s.io/kustomize/kyaml/utils"
18 "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/labels"
19 yaml "sigs.k8s.io/yaml/goyaml.v3"
20 )
21
22
23 func MakeNullNode() *RNode {
24 return NewRNode(&Node{Tag: NodeTagNull})
25 }
26
27
28
29 func MakePersistentNullNode(value string) *RNode {
30 n := NewRNode(
31 &Node{
32 Tag: NodeTagNull,
33 Value: value,
34 Kind: yaml.ScalarNode,
35 },
36 )
37 n.ShouldKeep = true
38 return n
39 }
40
41
42
43 func IsMissingOrNull(node *RNode) bool {
44 return node.IsNil() || node.YNode().Tag == NodeTagNull
45 }
46
47
48
49 func IsEmptyMap(node *RNode) bool {
50 return IsMissingOrNull(node) || IsYNodeEmptyMap(node.YNode())
51 }
52
53
54 func GetValue(node *RNode) string {
55 if IsMissingOrNull(node) {
56 return ""
57 }
58 return node.YNode().Value
59 }
60
61
62
63 func Parse(value string) (*RNode, error) {
64 return Parser{Value: value}.Filter(nil)
65 }
66
67
68
69 func ReadFile(path string) (*RNode, error) {
70 b, err := os.ReadFile(path)
71 if err != nil {
72 return nil, err
73 }
74 return Parse(string(b))
75 }
76
77
78 func WriteFile(node *RNode, path string) error {
79 out, err := node.String()
80 if err != nil {
81 return err
82 }
83 return errors.WrapPrefixf(os.WriteFile(path, []byte(out), 0600), "writing RNode to file")
84 }
85
86
87
88 func UpdateFile(filter Filter, path string) error {
89
90 y, err := ReadFile(path)
91 if err != nil {
92 return err
93 }
94
95
96 if err := y.PipeE(filter); err != nil {
97 return err
98 }
99
100
101 return WriteFile(y, path)
102 }
103
104
105 func MustParse(value string) *RNode {
106 v, err := Parser{Value: value}.Filter(nil)
107 if err != nil {
108 panic(err)
109 }
110 return v
111 }
112
113
114 func NewScalarRNode(value string) *RNode {
115 return &RNode{
116 value: &yaml.Node{
117 Kind: yaml.ScalarNode,
118 Value: value,
119 }}
120 }
121
122
123
124
125 func NewStringRNode(value string) *RNode {
126 n := yaml.Node{Kind: yaml.ScalarNode}
127 n.SetString(value)
128 return NewRNode(&n)
129 }
130
131
132 func NewListRNode(values ...string) *RNode {
133 seq := &RNode{value: &yaml.Node{Kind: yaml.SequenceNode}}
134 for _, v := range values {
135 seq.value.Content = append(seq.value.Content, &yaml.Node{
136 Kind: yaml.ScalarNode,
137 Value: v,
138 })
139 }
140 return seq
141 }
142
143
144 func NewMapRNode(values *map[string]string) *RNode {
145 m := &RNode{value: &yaml.Node{
146 Kind: yaml.MappingNode,
147 }}
148 if values == nil {
149 return m
150 }
151
152 for k, v := range *values {
153 m.value.Content = append(m.value.Content, &yaml.Node{
154 Kind: yaml.ScalarNode,
155 Value: k,
156 }, &yaml.Node{
157 Kind: yaml.ScalarNode,
158 Value: v,
159 })
160 }
161
162 return m
163 }
164
165
166
167 func SyncMapNodesOrder(from, to *RNode) {
168 to.Copy()
169 res := &RNode{value: &yaml.Node{
170 Kind: to.YNode().Kind,
171 Style: to.YNode().Style,
172 Tag: to.YNode().Tag,
173 Anchor: to.YNode().Anchor,
174 Alias: to.YNode().Alias,
175 HeadComment: to.YNode().HeadComment,
176 LineComment: to.YNode().LineComment,
177 FootComment: to.YNode().FootComment,
178 Line: to.YNode().Line,
179 Column: to.YNode().Column,
180 }}
181
182 fromFieldNames, err := from.Fields()
183 if err != nil {
184 return
185 }
186
187 toFieldNames, err := to.Fields()
188 if err != nil {
189 return
190 }
191
192 for _, fieldName := range fromFieldNames {
193 if !sliceutil.Contains(toFieldNames, fieldName) {
194 continue
195 }
196
197 res.value.Content = append(res.value.Content, to.Field(fieldName).Key.YNode(), to.Field(fieldName).Value.YNode())
198 toFieldNames = sliceutil.Remove(toFieldNames, fieldName)
199 }
200
201 for _, fieldName := range toFieldNames {
202
203 res.value.Content = append(res.value.Content, to.Field(fieldName).Key.YNode(), to.Field(fieldName).Value.YNode())
204 }
205
206 to.SetYNode(res.YNode())
207 }
208
209
210 func NewRNode(value *yaml.Node) *RNode {
211 return &RNode{value: value}
212 }
213
214
215
216 type RNode struct {
217
218
219
220
221
222 fieldPath []string
223
224
225
226
227
228
229 value *yaml.Node
230
231
232 ShouldKeep bool
233
234 Match []string
235 }
236
237
238 func (rn *RNode) Copy() *RNode {
239 if rn == nil {
240 return nil
241 }
242 result := *rn
243 result.value = CopyYNode(rn.value)
244 return &result
245 }
246
247 var ErrMissingMetadata = fmt.Errorf("missing Resource metadata")
248
249
250 func (rn *RNode) IsNil() bool {
251 return rn == nil || rn.YNode() == nil
252 }
253
254
255 func (rn *RNode) IsTaggedNull() bool {
256 return !rn.IsNil() && IsYNodeTaggedNull(rn.YNode())
257 }
258
259
260
261 func (rn *RNode) IsNilOrEmpty() bool {
262 return rn.IsNil() || IsYNodeNilOrEmpty(rn.YNode())
263 }
264
265
266 func (rn *RNode) IsStringValue() bool {
267 return !rn.IsNil() && IsYNodeString(rn.YNode())
268 }
269
270
271 func (rn *RNode) GetMeta() (ResourceMeta, error) {
272 if IsMissingOrNull(rn) {
273 return ResourceMeta{}, nil
274 }
275 missingMeta := true
276 n := rn
277 if n.YNode().Kind == DocumentNode {
278
279 n = NewRNode(n.Content()[0])
280 }
281
282
283
284 m := ResourceMeta{}
285
286
287 if f := n.Field(APIVersionField); !f.IsNilOrEmpty() {
288 m.APIVersion = GetValue(f.Value)
289 missingMeta = false
290 }
291 if f := n.Field(KindField); !f.IsNilOrEmpty() {
292 m.Kind = GetValue(f.Value)
293 missingMeta = false
294 }
295
296 mf := n.Field(MetadataField)
297 if mf.IsNilOrEmpty() {
298 if missingMeta {
299 return m, ErrMissingMetadata
300 }
301 return m, nil
302 }
303 meta := mf.Value
304
305 if f := meta.Field(NameField); !f.IsNilOrEmpty() {
306 m.Name = f.Value.YNode().Value
307 missingMeta = false
308 }
309 if f := meta.Field(NamespaceField); !f.IsNilOrEmpty() {
310 m.Namespace = GetValue(f.Value)
311 missingMeta = false
312 }
313
314 if f := meta.Field(LabelsField); !f.IsNilOrEmpty() {
315 m.Labels = map[string]string{}
316 _ = f.Value.VisitFields(func(node *MapNode) error {
317 m.Labels[GetValue(node.Key)] = GetValue(node.Value)
318 return nil
319 })
320 missingMeta = false
321 }
322 if f := meta.Field(AnnotationsField); !f.IsNilOrEmpty() {
323 m.Annotations = map[string]string{}
324 _ = f.Value.VisitFields(func(node *MapNode) error {
325 m.Annotations[GetValue(node.Key)] = GetValue(node.Value)
326 return nil
327 })
328 missingMeta = false
329 }
330
331 if missingMeta {
332 return m, ErrMissingMetadata
333 }
334 return m, nil
335 }
336
337
338
339
340
341
342
343
344
345
346 func (rn *RNode) Pipe(functions ...Filter) (*RNode, error) {
347
348 if rn == nil {
349 return nil, nil
350 }
351
352 var v *RNode
353 var err error
354 if rn.value != nil && rn.value.Kind == yaml.DocumentNode {
355
356 v = &RNode{value: rn.value.Content[0]}
357 } else {
358 v = rn
359 }
360
361
362 for _, c := range functions {
363 v, err = c.Filter(v)
364 if err != nil || v == nil {
365 return v, errors.Wrap(err)
366 }
367 }
368 return v, err
369 }
370
371
372
373 func (rn *RNode) PipeE(functions ...Filter) error {
374 _, err := rn.Pipe(functions...)
375 return errors.Wrap(err)
376 }
377
378
379 func (rn *RNode) Document() *yaml.Node {
380 return rn.value
381 }
382
383
384
385 func (rn *RNode) YNode() *yaml.Node {
386 if rn == nil || rn.value == nil {
387 return nil
388 }
389 if rn.value.Kind == yaml.DocumentNode {
390 return rn.value.Content[0]
391 }
392 return rn.value
393 }
394
395
396 func (rn *RNode) SetYNode(node *yaml.Node) {
397 if rn.value == nil || node == nil {
398 rn.value = node
399 return
400 }
401 *rn.value = *node
402 }
403
404
405 func (rn *RNode) GetKind() string {
406 if node := rn.getMapFieldValue(KindField); node != nil {
407 return node.Value
408 }
409 return ""
410 }
411
412
413 func (rn *RNode) SetKind(k string) {
414 rn.SetMapField(NewScalarRNode(k), KindField)
415 }
416
417
418 func (rn *RNode) GetApiVersion() string {
419 if node := rn.getMapFieldValue(APIVersionField); node != nil {
420 return node.Value
421 }
422 return ""
423 }
424
425
426 func (rn *RNode) SetApiVersion(av string) {
427 rn.SetMapField(NewScalarRNode(av), APIVersionField)
428 }
429
430
431
432
433
434
435 func (rn *RNode) getMapFieldValue(field string) *yaml.Node {
436 var result *yaml.Node
437 visitMappingNodeFields(rn.Content(), func(key, value *yaml.Node) {
438 result = value
439 }, field)
440 return result
441 }
442
443
444
445 func (rn *RNode) GetName() string {
446 return rn.getMetaStringField(NameField)
447 }
448
449
450 func (rn *RNode) getMetaStringField(fName string) string {
451 md := rn.getMetaData()
452 if md == nil {
453 return ""
454 }
455 var result string
456 visitMappingNodeFields(md.Content, func(key, value *yaml.Node) {
457 if !IsYNodeNilOrEmpty(value) {
458 result = value.Value
459 }
460 }, fName)
461 return result
462 }
463
464
465
466 func (rn *RNode) getMetaData() *yaml.Node {
467 if IsMissingOrNull(rn) {
468 return nil
469 }
470 content := rn.Content()
471 if rn.YNode().Kind == DocumentNode {
472
473 content = content[0].Content
474 }
475 var mf *yaml.Node
476 visitMappingNodeFields(content, func(key, value *yaml.Node) {
477 if !IsYNodeNilOrEmpty(value) {
478 mf = value
479 }
480 }, MetadataField)
481 return mf
482 }
483
484
485 func (rn *RNode) SetName(name string) error {
486 return rn.SetMapField(NewScalarRNode(name), MetadataField, NameField)
487 }
488
489
490
491 func (rn *RNode) GetNamespace() string {
492 return rn.getMetaStringField(NamespaceField)
493 }
494
495
496
497 func (rn *RNode) SetNamespace(ns string) error {
498 meta, err := rn.Pipe(Lookup(MetadataField))
499 if err != nil {
500 return err
501 }
502 if ns == "" {
503 if rn == nil {
504 return nil
505 }
506 return meta.PipeE(Clear(NamespaceField))
507 }
508 return rn.SetMapField(
509 NewScalarRNode(ns), MetadataField, NamespaceField)
510 }
511
512
513
514
515
516
517
518
519 func (rn *RNode) GetAnnotations(annotations ...string) map[string]string {
520 return rn.getMapFromMeta(AnnotationsField, annotations...)
521 }
522
523
524 func (rn *RNode) SetAnnotations(m map[string]string) error {
525 return rn.setMapInMetadata(m, AnnotationsField)
526 }
527
528
529
530
531
532
533
534
535 func (rn *RNode) GetLabels(labels ...string) map[string]string {
536 return rn.getMapFromMeta(LabelsField, labels...)
537 }
538
539
540
541
542
543
544
545 func (rn *RNode) getMapFromMeta(fName string, fields ...string) map[string]string {
546 meta := rn.getMetaData()
547 if meta == nil {
548 return make(map[string]string)
549 }
550
551 var result map[string]string
552
553 visitMappingNodeFields(meta.Content, func(_, fNameValue *yaml.Node) {
554
555 expectedSize := len(fields)
556 if expectedSize == 0 {
557 expectedSize = len(fNameValue.Content) / 2
558 }
559 result = make(map[string]string, expectedSize)
560
561 visitMappingNodeFields(fNameValue.Content, func(key, value *yaml.Node) {
562 result[key.Value] = value.Value
563 }, fields...)
564 }, fName)
565
566 if result == nil {
567 return make(map[string]string)
568 }
569 return result
570 }
571
572
573 func (rn *RNode) SetLabels(m map[string]string) error {
574 return rn.setMapInMetadata(m, LabelsField)
575 }
576
577
578 func (rn *RNode) setMapInMetadata(m map[string]string, field string) error {
579 meta, err := rn.Pipe(LookupCreate(MappingNode, MetadataField))
580 if err != nil {
581 return err
582 }
583 if err = meta.PipeE(Clear(field)); err != nil {
584 return err
585 }
586 if len(m) == 0 {
587 return nil
588 }
589 mapNode, err := meta.Pipe(LookupCreate(MappingNode, field))
590 if err != nil {
591 return err
592 }
593 for _, k := range SortedMapKeys(m) {
594 if _, err := mapNode.Pipe(
595 SetField(k, NewStringRNode(m[k]))); err != nil {
596 return err
597 }
598 }
599 return nil
600 }
601
602 func (rn *RNode) SetMapField(value *RNode, path ...string) error {
603 return rn.PipeE(
604 LookupCreate(yaml.MappingNode, path[0:len(path)-1]...),
605 SetField(path[len(path)-1], value),
606 )
607 }
608
609 func (rn *RNode) GetDataMap() map[string]string {
610 n, err := rn.Pipe(Lookup(DataField))
611 if err != nil {
612 return nil
613 }
614 result := map[string]string{}
615 _ = n.VisitFields(func(node *MapNode) error {
616 result[GetValue(node.Key)] = GetValue(node.Value)
617 return nil
618 })
619 return result
620 }
621
622 func (rn *RNode) GetBinaryDataMap() map[string]string {
623 n, err := rn.Pipe(Lookup(BinaryDataField))
624 if err != nil {
625 return nil
626 }
627 result := map[string]string{}
628 _ = n.VisitFields(func(node *MapNode) error {
629 result[GetValue(node.Key)] = GetValue(node.Value)
630 return nil
631 })
632 return result
633 }
634
635
636
637 func (rn *RNode) GetValidatedDataMap(expectedKeys []string) (map[string]string, error) {
638 dataMap := rn.GetDataMap()
639 err := rn.validateDataMap(dataMap, expectedKeys)
640 return dataMap, err
641 }
642
643 func (rn *RNode) validateDataMap(dataMap map[string]string, expectedKeys []string) error {
644 if dataMap == nil {
645 return fmt.Errorf("The datamap is unassigned")
646 }
647 for key := range dataMap {
648 found := false
649 for _, expected := range expectedKeys {
650 if expected == key {
651 found = true
652 }
653 }
654 if !found {
655 return fmt.Errorf("an unexpected key (%v) was found", key)
656 }
657 }
658 return nil
659 }
660
661 func (rn *RNode) SetDataMap(m map[string]string) {
662 if rn == nil {
663 log.Fatal("cannot set data map on nil Rnode")
664 }
665 if err := rn.PipeE(Clear(DataField)); err != nil {
666 log.Fatal(err)
667 }
668 if len(m) == 0 {
669 return
670 }
671 if err := rn.LoadMapIntoConfigMapData(m); err != nil {
672 log.Fatal(err)
673 }
674 }
675
676 func (rn *RNode) SetBinaryDataMap(m map[string]string) {
677 if rn == nil {
678 log.Fatal("cannot set binaryData map on nil Rnode")
679 }
680 if err := rn.PipeE(Clear(BinaryDataField)); err != nil {
681 log.Fatal(err)
682 }
683 if len(m) == 0 {
684 return
685 }
686 if err := rn.LoadMapIntoConfigMapBinaryData(m); err != nil {
687 log.Fatal(err)
688 }
689 }
690
691
692 func (rn *RNode) AppendToFieldPath(parts ...string) {
693 rn.fieldPath = append(rn.fieldPath, parts...)
694 }
695
696
697
698 func (rn *RNode) FieldPath() []string {
699 return rn.fieldPath
700 }
701
702
703 func (rn *RNode) String() (string, error) {
704 if rn == nil {
705 return "", nil
706 }
707 return String(rn.value)
708 }
709
710
711 func (rn *RNode) MustString() string {
712 s, err := rn.String()
713 if err != nil {
714 panic(err)
715 }
716 return s
717 }
718
719
720 func (rn *RNode) Content() []*yaml.Node {
721 if rn == nil {
722 return nil
723 }
724 return rn.YNode().Content
725 }
726
727
728
729 func (rn *RNode) Fields() ([]string, error) {
730 if err := ErrorIfInvalid(rn, yaml.MappingNode); err != nil {
731 return nil, errors.Wrap(err)
732 }
733 var fields []string
734 visitMappingNodeFields(rn.Content(), func(key, value *yaml.Node) {
735 fields = append(fields, key.Value)
736 })
737 return fields, nil
738 }
739
740
741
742 func (rn *RNode) FieldRNodes() ([]*RNode, error) {
743 if err := ErrorIfInvalid(rn, yaml.MappingNode); err != nil {
744 return nil, errors.Wrap(err)
745 }
746 var fields []*RNode
747 visitMappingNodeFields(rn.Content(), func(key, value *yaml.Node) {
748
749 rNode := &RNode{}
750 rNode.SetYNode(key)
751 fields = append(fields, rNode)
752 })
753 return fields, nil
754 }
755
756
757
758 func (rn *RNode) Field(field string) *MapNode {
759 if rn.YNode().Kind != yaml.MappingNode {
760 return nil
761 }
762 var result *MapNode
763 visitMappingNodeFields(rn.Content(), func(key, value *yaml.Node) {
764 result = &MapNode{Key: NewRNode(key), Value: NewRNode(value)}
765 }, field)
766 return result
767 }
768
769
770
771 func (rn *RNode) VisitFields(fn func(node *MapNode) error) error {
772
773 srcFieldNames, err := rn.Fields()
774 if err != nil {
775 return errors.Wrap(err)
776 }
777
778
779 for _, fieldName := range srcFieldNames {
780 if err := fn(rn.Field(fieldName)); err != nil {
781 return errors.Wrap(err)
782 }
783 }
784 return nil
785 }
786
787
788
789
790
791 func visitMappingNodeFields(content []*yaml.Node, fn func(key, value *yaml.Node), fieldNames ...string) {
792 switch len(fieldNames) {
793 case 0:
794 visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool {
795 fn(key, value)
796 return true
797 })
798 case 1:
799 visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool {
800 if key == nil {
801 return true
802 }
803 if fieldNames[0] == key.Value {
804 fn(key, value)
805 return false
806 }
807 return true
808 })
809 default:
810 fieldsStillToVisit := make(map[string]bool, len(fieldNames))
811 for _, fieldName := range fieldNames {
812 fieldsStillToVisit[fieldName] = true
813 }
814 visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool {
815 if key == nil {
816 return true
817 }
818 if fieldsStillToVisit[key.Value] {
819 fn(key, value)
820 delete(fieldsStillToVisit, key.Value)
821 }
822 return len(fieldsStillToVisit) > 0
823 })
824 }
825 }
826
827
828
829
830
831 func visitFieldsWhileTrue(content []*yaml.Node, fn func(key, value *yaml.Node, keyIndex int) bool) {
832 for i := 0; i < len(content); i += 2 {
833 continueVisiting := fn(content[i], content[i+1], i)
834 if !continueVisiting {
835 return
836 }
837 }
838 }
839
840
841
842 func (rn *RNode) Elements() ([]*RNode, error) {
843 if err := ErrorIfInvalid(rn, yaml.SequenceNode); err != nil {
844 return nil, errors.Wrap(err)
845 }
846 var elements []*RNode
847 for i := 0; i < len(rn.Content()); i++ {
848 elements = append(elements, NewRNode(rn.Content()[i]))
849 }
850 return elements, nil
851 }
852
853
854
855
856 func (rn *RNode) ElementValues(key string) ([]string, error) {
857 if err := ErrorIfInvalid(rn, yaml.SequenceNode); err != nil {
858 return nil, errors.Wrap(err)
859 }
860 var elements []string
861 for i := 0; i < len(rn.Content()); i++ {
862 field := NewRNode(rn.Content()[i]).Field(key)
863 if !field.IsNilOrEmpty() {
864 elements = append(elements, field.Value.YNode().Value)
865 }
866 }
867 return elements, nil
868 }
869
870
871
872
873 func (rn *RNode) ElementValuesList(keys []string) ([][]string, error) {
874 if err := ErrorIfInvalid(rn, yaml.SequenceNode); err != nil {
875 return nil, errors.Wrap(err)
876 }
877 elements := make([][]string, len(rn.Content()))
878
879 for i := 0; i < len(rn.Content()); i++ {
880 for _, key := range keys {
881 field := NewRNode(rn.Content()[i]).Field(key)
882 if field.IsNilOrEmpty() {
883 elements[i] = append(elements[i], "")
884 } else {
885 elements[i] = append(elements[i], field.Value.YNode().Value)
886 }
887 }
888 }
889 return elements, nil
890 }
891
892
893
894 func (rn *RNode) Element(key, value string) *RNode {
895 if rn.YNode().Kind != yaml.SequenceNode {
896 return nil
897 }
898 elem, err := rn.Pipe(MatchElement(key, value))
899 if err != nil {
900 return nil
901 }
902 return elem
903 }
904
905
906
907
908 func (rn *RNode) ElementList(keys []string, values []string) *RNode {
909 if rn.YNode().Kind != yaml.SequenceNode {
910 return nil
911 }
912 elem, err := rn.Pipe(MatchElementList(keys, values))
913 if err != nil {
914 return nil
915 }
916 return elem
917 }
918
919
920
921 func (rn *RNode) VisitElements(fn func(node *RNode) error) error {
922 elements, err := rn.Elements()
923 if err != nil {
924 return errors.Wrap(err)
925 }
926
927 for i := range elements {
928 if err := fn(elements[i]); err != nil {
929 return errors.Wrap(err)
930 }
931 }
932 return nil
933 }
934
935
936
937
938
939
940 var AssociativeSequenceKeys = []string{"name"}
941
942
943 func (rn *RNode) IsAssociative() bool {
944 return rn.GetAssociativeKey() != ""
945 }
946
947
948
949 func (rn *RNode) GetAssociativeKey() string {
950
951 for _, key := range AssociativeSequenceKeys {
952 if checkKey(key, rn.Content()) {
953 return key
954 }
955 }
956
957
958 return ""
959 }
960
961
962 func (rn *RNode) MarshalJSON() ([]byte, error) {
963 s, err := rn.String()
964 if err != nil {
965 return nil, err
966 }
967
968 if rn.YNode().Kind == SequenceNode {
969 var a []interface{}
970 if err := Unmarshal([]byte(s), &a); err != nil {
971 return nil, err
972 }
973 return json.Marshal(a)
974 }
975
976 m := map[string]interface{}{}
977 if err := Unmarshal([]byte(s), &m); err != nil {
978 return nil, err
979 }
980 return json.Marshal(m)
981 }
982
983
984 func (rn *RNode) UnmarshalJSON(b []byte) error {
985 m := map[string]interface{}{}
986 if err := json.Unmarshal(b, &m); err != nil {
987 return err
988 }
989 r, err := FromMap(m)
990 if err != nil {
991 return err
992 }
993 rn.value = r.value
994 return nil
995 }
996
997
998
999 func (rn *RNode) DeAnchor() (err error) {
1000 rn.value, err = deAnchor(rn.value)
1001 return
1002 }
1003
1004
1005
1006
1007 func deAnchor(yn *yaml.Node) (res *yaml.Node, err error) {
1008 if yn == nil {
1009 return nil, nil
1010 }
1011 if yn.Anchor != "" {
1012
1013
1014 if yn.Kind == yaml.AliasNode {
1015
1016 return nil, fmt.Errorf(
1017 "anchor %q defined using alias %v", yn.Anchor, yn.Alias)
1018 }
1019 yn.Anchor = ""
1020 }
1021 switch yn.Kind {
1022 case yaml.ScalarNode:
1023 return yn, nil
1024 case yaml.AliasNode:
1025 result, err := deAnchor(yn.Alias)
1026 if err != nil {
1027 return nil, err
1028 }
1029 return CopyYNode(result), nil
1030 case yaml.MappingNode:
1031 toMerge, err := removeMergeTags(yn)
1032 if err != nil {
1033 return nil, err
1034 }
1035 err = mergeAll(yn, toMerge)
1036 if err != nil {
1037 return nil, err
1038 }
1039 fallthrough
1040 case yaml.DocumentNode, yaml.SequenceNode:
1041 for i := range yn.Content {
1042 yn.Content[i], err = deAnchor(yn.Content[i])
1043 if err != nil {
1044 return nil, err
1045 }
1046 }
1047 return yn, nil
1048 default:
1049 return nil, fmt.Errorf("cannot deAnchor kind %q", yn.Kind)
1050 }
1051 }
1052
1053
1054 func isMerge(yn *yaml.Node) bool {
1055 return yn.Tag == MergeTag
1056 }
1057
1058
1059
1060 func findMergeValues(yn *yaml.Node) ([]*yaml.Node, error) {
1061 if yn == nil {
1062 return []*yaml.Node{}, nil
1063 }
1064 switch yn.Kind {
1065 case MappingNode:
1066 return []*yaml.Node{yn}, nil
1067 case AliasNode:
1068 if yn.Alias != nil && yn.Alias.Kind != MappingNode {
1069 return nil, errors.Errorf("invalid map merge: received alias for a non-map value")
1070 }
1071 return []*yaml.Node{yn.Alias}, nil
1072 case SequenceNode:
1073 mergeValues := []*yaml.Node{}
1074 for i := 0; i < len(yn.Content); i++ {
1075 if yn.Content[i].Kind == SequenceNode {
1076 return nil, errors.Errorf("invalid map merge: received a nested sequence")
1077 }
1078 newMergeValues, err := findMergeValues(yn.Content[i])
1079 if err != nil {
1080 return nil, err
1081 }
1082 mergeValues = append(newMergeValues, mergeValues...)
1083 }
1084 return mergeValues, nil
1085 default:
1086 return nil, errors.Errorf("map merge requires map or sequence of maps as the value")
1087 }
1088 }
1089
1090
1091
1092
1093 func getMergeTagValue(yn *yaml.Node) (*yaml.Node, error) {
1094 var result *yaml.Node
1095 var err error
1096 visitFieldsWhileTrue(yn.Content, func(key, value *yaml.Node, _ int) bool {
1097 if isMerge(key) {
1098 if result != nil {
1099 err = fmt.Errorf("duplicate merge key")
1100 result = nil
1101 return false
1102 }
1103 result = value
1104 }
1105 return true
1106 })
1107 return result, err
1108 }
1109
1110
1111
1112 func removeMergeTags(yn *yaml.Node) ([]*yaml.Node, error) {
1113 if yn == nil || yn.Content == nil {
1114 return nil, nil
1115 }
1116 if yn.Kind != yaml.MappingNode {
1117 return nil, nil
1118 }
1119 value, err := getMergeTagValue(yn)
1120 if err != nil {
1121 return nil, err
1122 }
1123 toMerge, err := findMergeValues(value)
1124 if err != nil {
1125 return nil, err
1126 }
1127 err = NewRNode(yn).PipeE(Clear("<<"))
1128 if err != nil {
1129 return nil, err
1130 }
1131 return toMerge, nil
1132 }
1133
1134 func mergeAll(yn *yaml.Node, toMerge []*yaml.Node) error {
1135
1136
1137 rn := NewRNode(yn).Copy()
1138 toMerge = append(toMerge, yn)
1139 for i := range toMerge {
1140 rnToMerge := NewRNode(toMerge[i]).Copy()
1141 err := rnToMerge.VisitFields(func(node *MapNode) error {
1142 return rn.PipeE(MapEntrySetter{Key: node.Key, Value: node.Value})
1143 })
1144 if err != nil {
1145 return err
1146 }
1147 }
1148 *yn = *rn.value
1149 return nil
1150 }
1151
1152
1153 func (rn *RNode) GetValidatedMetadata() (ResourceMeta, error) {
1154 m, err := rn.GetMeta()
1155 if err != nil {
1156 return m, err
1157 }
1158 if m.Kind == "" {
1159 return m, fmt.Errorf("missing kind in object %v", m)
1160 }
1161 if strings.HasSuffix(m.Kind, "List") {
1162
1163 return m, nil
1164 }
1165 if m.NameMeta.Name == "" {
1166 return m, fmt.Errorf("missing metadata.name in object %v", m)
1167 }
1168 return m, nil
1169 }
1170
1171
1172 func (rn *RNode) MatchesAnnotationSelector(selector string) (bool, error) {
1173 s, err := labels.Parse(selector)
1174 if err != nil {
1175 return false, err
1176 }
1177 return s.Matches(labels.Set(rn.GetAnnotations())), nil
1178 }
1179
1180
1181 func (rn *RNode) MatchesLabelSelector(selector string) (bool, error) {
1182 s, err := labels.Parse(selector)
1183 if err != nil {
1184 return false, err
1185 }
1186 return s.Matches(labels.Set(rn.GetLabels())), nil
1187 }
1188
1189
1190
1191
1192
1193 func (rn *RNode) HasNilEntryInList() (bool, string) {
1194 return hasNilEntryInList(rn.value)
1195 }
1196
1197 func hasNilEntryInList(in interface{}) (bool, string) {
1198 switch v := in.(type) {
1199 case map[string]interface{}:
1200 for key, s := range v {
1201 if result, path := hasNilEntryInList(s); result {
1202 return result, key + "/" + path
1203 }
1204 }
1205 case []interface{}:
1206 for index, s := range v {
1207 if s == nil {
1208 return true, ""
1209 }
1210 if result, path := hasNilEntryInList(s); result {
1211 return result, "[" + strconv.Itoa(index) + "]/" + path
1212 }
1213 }
1214 }
1215 return false, ""
1216 }
1217
1218 func FromMap(m map[string]interface{}) (*RNode, error) {
1219 c, err := Marshal(m)
1220 if err != nil {
1221 return nil, err
1222 }
1223 return Parse(string(c))
1224 }
1225
1226 func (rn *RNode) Map() (map[string]interface{}, error) {
1227 if rn == nil || rn.value == nil {
1228 return make(map[string]interface{}), nil
1229 }
1230 var result map[string]interface{}
1231 if err := rn.value.Decode(&result); err != nil {
1232
1233
1234 str, _ := rn.String()
1235 return nil, fmt.Errorf("received error %w for the following resource:\n%s", err, str)
1236 }
1237 return result, nil
1238 }
1239
1240
1241 func ConvertJSONToYamlNode(jsonStr string) (*RNode, error) {
1242 var body map[string]interface{}
1243 err := json.Unmarshal([]byte(jsonStr), &body)
1244 if err != nil {
1245 return nil, err
1246 }
1247 yml, err := yaml.Marshal(body)
1248 if err != nil {
1249 return nil, err
1250 }
1251 node, err := Parse(string(yml))
1252 if err != nil {
1253 return nil, err
1254 }
1255 return node, nil
1256 }
1257
1258
1259 func checkKey(key string, elems []*Node) bool {
1260 count := 0
1261 for i := range elems {
1262 elem := NewRNode(elems[i])
1263 if elem.Field(key) != nil {
1264 count++
1265 }
1266 }
1267 return count == len(elems)
1268 }
1269
1270
1271 func (rn *RNode) GetSlice(path string) ([]interface{}, error) {
1272 value, err := rn.GetFieldValue(path)
1273 if err != nil {
1274 return nil, err
1275 }
1276 if sliceValue, ok := value.([]interface{}); ok {
1277 return sliceValue, nil
1278 }
1279 return nil, fmt.Errorf("node %s is not a slice", path)
1280 }
1281
1282
1283 func (rn *RNode) GetString(path string) (string, error) {
1284 value, err := rn.GetFieldValue(path)
1285 if err != nil {
1286 return "", err
1287 }
1288 if v, ok := value.(string); ok {
1289 return v, nil
1290 }
1291 return "", fmt.Errorf("node %s is not a string: %v", path, value)
1292 }
1293
1294
1295
1296
1297
1298
1299
1300
1301 func (rn *RNode) GetFieldValue(path string) (interface{}, error) {
1302 fields := convertSliceIndex(utils.SmarterPathSplitter(path, "."))
1303 rn, err := rn.Pipe(Lookup(fields...))
1304 if err != nil {
1305 return nil, err
1306 }
1307 if rn == nil {
1308 return nil, NoFieldError{path}
1309 }
1310 yn := rn.YNode()
1311
1312
1313 if yn.Kind == yaml.AliasNode {
1314 yn = yn.Alias
1315 }
1316
1317
1318 if yn.Kind == yaml.DocumentNode || yn.Kind == yaml.MappingNode {
1319 var result map[string]interface{}
1320 if err := yn.Decode(&result); err != nil {
1321 return nil, err
1322 }
1323 return result, err
1324 }
1325
1326
1327 if yn.Kind == yaml.SequenceNode {
1328 var result []interface{}
1329 if err := yn.Decode(&result); err != nil {
1330 return nil, err
1331 }
1332 return result, nil
1333 }
1334 if yn.Kind != yaml.ScalarNode {
1335 return nil, fmt.Errorf("expected ScalarNode, got Kind=%d", yn.Kind)
1336 }
1337
1338 switch yn.Tag {
1339 case NodeTagString:
1340 return yn.Value, nil
1341 case NodeTagInt:
1342 return strconv.Atoi(yn.Value)
1343 case NodeTagFloat:
1344 return strconv.ParseFloat(yn.Value, 64)
1345 case NodeTagBool:
1346 return strconv.ParseBool(yn.Value)
1347 default:
1348
1349 return yn.Value, nil
1350 }
1351 }
1352
1353
1354
1355
1356
1357 func convertSliceIndex(fields []string) []string {
1358 var res []string
1359 for _, s := range fields {
1360 if !strings.HasSuffix(s, "]") {
1361 res = append(res, s)
1362 continue
1363 }
1364 re := regexp.MustCompile(`^(.*)\[(\d+)\]$`)
1365 groups := re.FindStringSubmatch(s)
1366 if len(groups) == 0 {
1367
1368 res = append(res, s)
1369 continue
1370 }
1371 if groups[1] != "" {
1372 res = append(res, groups[1])
1373 }
1374 res = append(res, groups[2])
1375 }
1376 return res
1377 }
1378
1379 type NoFieldError struct {
1380 Field string
1381 }
1382
1383 func (e NoFieldError) Error() string {
1384 return fmt.Sprintf("no field named '%s'", e.Field)
1385 }
1386
View as plain text