@@ -14,6 +14,7 @@ import (
14
14
"go.starlark.net/starlark"
15
15
"sigs.k8s.io/kustomize/kyaml/errors"
16
16
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
17
+ "sigs.k8s.io/kustomize/kyaml/kio"
17
18
"sigs.k8s.io/kustomize/kyaml/kio/filters"
18
19
"sigs.k8s.io/kustomize/kyaml/yaml"
19
20
)
@@ -96,20 +97,29 @@ func (sf *Filter) Run(reader io.Reader, writer io.Writer) error {
96
97
return errors .Wrap (err )
97
98
}
98
99
100
+ err = runStarlark (sf .Name , sf .Program , value )
101
+ if err != nil {
102
+ return errors .Wrap (err )
103
+ }
104
+
105
+ return sf .writeResourceList (value , writer )
106
+ }
107
+
108
+ // runStarlark runs the starlark script
109
+ func runStarlark (name , starlarkProgram string , resourceList starlark.Value ) error {
99
110
// run the starlark as program as transformation function
100
- thread := & starlark.Thread {Name : sf . Name }
111
+ thread := & starlark.Thread {Name : name }
101
112
102
- ctx := & Context {resourceList : value }
113
+ ctx := & Context {resourceList : resourceList }
103
114
pd , err := ctx .predeclared ()
104
115
if err != nil {
105
116
return errors .Wrap (err )
106
117
}
107
- _ , err = starlark .ExecFile (thread , sf . Name , sf . Program , pd )
118
+ _ , err = starlark .ExecFile (thread , name , starlarkProgram , pd )
108
119
if err != nil {
109
120
return errors .Wrap (err )
110
121
}
111
-
112
- return sf .writeResourceList (value , writer )
122
+ return nil
113
123
}
114
124
115
125
// inputToResourceList transforms input into a starlark.Value
@@ -124,8 +134,11 @@ func (sf *Filter) readResourceList(reader io.Reader) (starlark.Value, error) {
124
134
if err != nil {
125
135
return nil , errors .Wrap (err )
126
136
}
137
+ return rnodeToStarlarkValue (rn )
138
+ }
127
139
128
- // convert to a starlark value
140
+ // rnodeToStarlarkValue converts a RNode to a starlark value.
141
+ func rnodeToStarlarkValue (rn * yaml.RNode ) (starlark.Value , error ) {
129
142
b , err := yaml .Marshal (rn .Document ()) // convert to bytes
130
143
if err != nil {
131
144
return nil , errors .Wrap (err )
@@ -138,20 +151,26 @@ func (sf *Filter) readResourceList(reader io.Reader) (starlark.Value, error) {
138
151
return util .Marshal (in ) // convert to starlark value
139
152
}
140
153
141
- // resourceListToOutput converts the output of the starlark program to the filter output
142
- func ( sf * Filter ) writeResourceList ( value starlark.Value , writer io. Writer ) error {
154
+ // starlarkValueToRNode converts the output of the starlark program to a RNode.
155
+ func starlarkValueToRNode ( value starlark.Value ) ( * yaml. RNode , error ) {
143
156
// convert the modified resourceList back into a slice of RNodes
144
157
// by first converting to a map[string]interface{}
145
158
out , err := util .Unmarshal (value )
146
159
if err != nil {
147
- return errors .Wrap (err )
160
+ return nil , errors .Wrap (err )
148
161
}
149
162
b , err := yaml .Marshal (out )
150
163
if err != nil {
151
- return errors .Wrap (err )
164
+ return nil , errors .Wrap (err )
152
165
}
153
166
154
- rl , err := yaml .Parse (string (b ))
167
+ return yaml .Parse (string (b ))
168
+ }
169
+
170
+ // writeResourceList converts the output of the starlark program to bytes and
171
+ // write to the writer.
172
+ func (sf * Filter ) writeResourceList (value starlark.Value , writer io.Writer ) error {
173
+ rl , err := starlarkValueToRNode (value )
155
174
if err != nil {
156
175
return errors .Wrap (err )
157
176
}
@@ -179,3 +198,91 @@ func (sf *Filter) writeResourceList(value starlark.Value, writer io.Writer) erro
179
198
_ , err = writer .Write ([]byte (s ))
180
199
return err
181
200
}
201
+
202
+ // SimpleFilter transforms a set of resources through the provided starlark
203
+ // program. It doesn't touch the id annotation. It doesn't copy comments.
204
+ type SimpleFilter struct {
205
+ // Name of the starlark program
206
+ Name string
207
+ // Program is a starlark script which will be run against the resources
208
+ Program string
209
+ // FunctionConfig is the functionConfig for the function.
210
+ FunctionConfig * yaml.RNode
211
+ }
212
+
213
+ func (sf * SimpleFilter ) String () string {
214
+ return fmt .Sprintf (
215
+ "name: %v program: %v" , sf .Name , sf .Program )
216
+ }
217
+
218
+ func (sf * SimpleFilter ) Filter (nodes []* yaml.RNode ) ([]* yaml.RNode , error ) {
219
+ in , err := WrapResources (nodes , sf .FunctionConfig )
220
+ if err != nil {
221
+ return nil , errors .Wrap (err )
222
+ }
223
+ value , err := rnodeToStarlarkValue (in )
224
+ if err != nil {
225
+ return nil , errors .Wrap (err )
226
+ }
227
+
228
+ err = runStarlark (sf .Name , sf .Program , value )
229
+ if err != nil {
230
+ return nil , errors .Wrap (err )
231
+ }
232
+
233
+ rn , err := starlarkValueToRNode (value )
234
+ if err != nil {
235
+ return nil , errors .Wrap (err )
236
+ }
237
+ updatedNodes , _ , err := UnwrapResources (rn )
238
+ return updatedNodes , err
239
+ }
240
+
241
+ // WrapResources wraps resources and an optional functionConfig in a resourceList
242
+ func WrapResources (nodes []* yaml.RNode , fc * yaml.RNode ) (* yaml.RNode , error ) {
243
+ var ynodes []* yaml.Node
244
+ for _ , rnode := range nodes {
245
+ ynodes = append (ynodes , rnode .YNode ())
246
+ }
247
+ m := map [string ]interface {}{
248
+ "apiVersion" : kio .ResourceListAPIVersion ,
249
+ "kind" : kio .ResourceListKind ,
250
+ "items" : []interface {}{},
251
+ }
252
+ out , err := yaml .FromMap (m )
253
+ if err != nil {
254
+ return nil , err
255
+ }
256
+ _ , err = out .Pipe (
257
+ yaml .Lookup ("items" ),
258
+ yaml .Append (ynodes ... ))
259
+ if err != nil {
260
+ return nil , err
261
+ }
262
+ if fc != nil {
263
+ _ , err = out .Pipe (
264
+ yaml .SetField ("functionConfig" , fc ))
265
+ if err != nil {
266
+ return nil , err
267
+ }
268
+ }
269
+
270
+ return out , nil
271
+ }
272
+
273
+ // UnwrapResources unwraps the resources and the functionConfig from a resourceList
274
+ func UnwrapResources (in * yaml.RNode ) ([]* yaml.RNode , * yaml.RNode , error ) {
275
+ items , err := in .Pipe (yaml .Lookup ("items" ))
276
+ if err != nil {
277
+ return nil , nil , errors .Wrap (err )
278
+ }
279
+ nodes , err := items .Elements ()
280
+ if err != nil {
281
+ return nil , nil , errors .Wrap (err )
282
+ }
283
+ fc , err := in .Pipe (yaml .Lookup ("functionConfig" ))
284
+ if err != nil {
285
+ return nil , nil , errors .Wrap (err )
286
+ }
287
+ return nodes , fc , nil
288
+ }
0 commit comments