...
1
2
3
4 package walk
5
6 import (
7 "fmt"
8 "os"
9 "strings"
10
11 "sigs.k8s.io/kustomize/kyaml/fieldmeta"
12 "sigs.k8s.io/kustomize/kyaml/openapi"
13 "sigs.k8s.io/kustomize/kyaml/yaml"
14 "sigs.k8s.io/kustomize/kyaml/yaml/schema"
15 )
16
17
18 type Walker struct {
19
20 Visitor
21
22 Schema *openapi.ResourceSchema
23
24
25
26 Sources Sources
27
28
29 Path []string
30
31
32
33
34 InferAssociativeLists bool
35
36
37
38 VisitKeysAsScalars bool
39
40
41 MergeOptions yaml.MergeOptions
42 }
43
44
45 func (l Walker) Kind() yaml.Kind {
46 for _, s := range l.Sources {
47 if !yaml.IsMissingOrNull(s) {
48 return s.YNode().Kind
49 }
50 }
51 return 0
52 }
53
54
55
56 func (l Walker) Walk() (*yaml.RNode, error) {
57 l.Schema = l.GetSchema()
58
59
60 switch l.Kind() {
61 case yaml.MappingNode:
62 if err := yaml.ErrorIfAnyInvalidAndNonNull(yaml.MappingNode, l.Sources...); err != nil {
63 return nil, err
64 }
65 return l.walkMap()
66 case yaml.SequenceNode:
67 if err := yaml.ErrorIfAnyInvalidAndNonNull(yaml.SequenceNode, l.Sources...); err != nil {
68 return nil, err
69 }
70
71
72 if schema.IsAssociative(l.Schema, l.Sources, l.InferAssociativeLists) {
73 return l.walkAssociativeSequence()
74 }
75 return l.walkNonAssociativeSequence()
76
77 case yaml.ScalarNode:
78 if err := yaml.ErrorIfAnyInvalidAndNonNull(yaml.ScalarNode, l.Sources...); err != nil {
79 return nil, err
80 }
81 return l.walkScalar()
82 case 0:
83
84 return l.walkMap()
85 default:
86 return nil, nil
87 }
88 }
89
90 func (l Walker) GetSchema() *openapi.ResourceSchema {
91 for i := range l.Sources {
92 r := l.Sources[i]
93 if yaml.IsMissingOrNull(r) {
94 continue
95 }
96
97 fm := fieldmeta.FieldMeta{}
98 if err := fm.Read(r); err == nil && !fm.IsEmpty() {
99
100 if fm.Schema.Ref.String() != "" {
101
102 s, err := openapi.Resolve(&fm.Schema.Ref, openapi.Schema())
103 if err == nil && s != nil {
104 fm.Schema = *s
105 }
106 }
107 return &openapi.ResourceSchema{Schema: &fm.Schema}
108 }
109 }
110
111 if l.Schema != nil {
112 return l.Schema
113 }
114 for i := range l.Sources {
115 r := l.Sources[i]
116 if yaml.IsMissingOrNull(r) {
117 continue
118 }
119
120 m, _ := r.GetMeta()
121 if m.Kind == "" || m.APIVersion == "" {
122 continue
123 }
124
125 s := openapi.SchemaForResourceType(yaml.TypeMeta{Kind: m.Kind, APIVersion: m.APIVersion})
126 if s != nil {
127 return s
128 }
129 }
130 return nil
131 }
132
133 const (
134 DestIndex = iota
135 OriginIndex
136 UpdatedIndex
137 )
138
139
140
141 type Sources []*yaml.RNode
142
143
144 func (s Sources) Dest() *yaml.RNode {
145 if len(s) <= DestIndex {
146 return nil
147 }
148 return s[DestIndex]
149 }
150
151
152 func (s Sources) Origin() *yaml.RNode {
153 if len(s) <= OriginIndex {
154 return nil
155 }
156 return s[OriginIndex]
157 }
158
159
160 func (s Sources) Updated() *yaml.RNode {
161 if len(s) <= UpdatedIndex {
162 return nil
163 }
164 return s[UpdatedIndex]
165 }
166
167 func (s Sources) String() string {
168 var values []string
169 for i := range s {
170 str, err := s[i].String()
171 if err != nil {
172 fmt.Fprintf(os.Stderr, "%v\n", err)
173 }
174 values = append(values, str)
175 }
176 return strings.Join(values, "\n")
177 }
178
179
180 func (s Sources) setDestNode(node *yaml.RNode, err error) (*yaml.RNode, error) {
181 if err != nil {
182 return nil, err
183 }
184 s[0] = node
185 return node, nil
186 }
187
View as plain text