Skip to content

Commit 4488cca

Browse files
author
Mengqi Yu
committed
introduce starlark.SimpleFilter
1 parent 2f54baf commit 4488cca

File tree

2 files changed

+123
-19
lines changed
  • functions/go/starlark

2 files changed

+123
-19
lines changed

functions/go/starlark/config.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ package main
33
import (
44
"fmt"
55

6+
"github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/starlark/third_party/sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark"
67
corev1 "k8s.io/api/core/v1"
78
"k8s.io/apimachinery/pkg/runtime/schema"
89
"sigs.k8s.io/kustomize/kyaml/fn/framework"
9-
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
10-
"sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark"
1110
"sigs.k8s.io/kustomize/kyaml/yaml"
1211
k8syaml "sigs.k8s.io/yaml"
1312
)
@@ -127,12 +126,10 @@ func validateStarlarkRun(sr *StarlarkRun) error {
127126

128127
func (sfc *StarlarkFnConfig) Transform(rl *framework.ResourceList) error {
129128
var err error
130-
starFltr := &starlark.Filter{
131-
Name: sfc.GetName(),
132-
Program: sfc.GetSource(),
133-
FunctionFilter: runtimeutil.FunctionFilter{
134-
FunctionConfig: rl.FunctionConfig,
135-
},
129+
starFltr := &starlark.SimpleFilter{
130+
Name: sfc.GetName(),
131+
Program: sfc.GetSource(),
132+
FunctionConfig: rl.FunctionConfig,
136133
}
137134
rl.Items, err = starFltr.Filter(rl.Items)
138135
return err

functions/go/starlark/third_party/sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark/starlark.go

Lines changed: 118 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"go.starlark.net/starlark"
1515
"sigs.k8s.io/kustomize/kyaml/errors"
1616
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
17+
"sigs.k8s.io/kustomize/kyaml/kio"
1718
"sigs.k8s.io/kustomize/kyaml/kio/filters"
1819
"sigs.k8s.io/kustomize/kyaml/yaml"
1920
)
@@ -96,20 +97,29 @@ func (sf *Filter) Run(reader io.Reader, writer io.Writer) error {
9697
return errors.Wrap(err)
9798
}
9899

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 {
99110
// run the starlark as program as transformation function
100-
thread := &starlark.Thread{Name: sf.Name}
111+
thread := &starlark.Thread{Name: name}
101112

102-
ctx := &Context{resourceList: value}
113+
ctx := &Context{resourceList: resourceList}
103114
pd, err := ctx.predeclared()
104115
if err != nil {
105116
return errors.Wrap(err)
106117
}
107-
_, err = starlark.ExecFile(thread, sf.Name, sf.Program, pd)
118+
_, err = starlark.ExecFile(thread, name, starlarkProgram, pd)
108119
if err != nil {
109120
return errors.Wrap(err)
110121
}
111-
112-
return sf.writeResourceList(value, writer)
122+
return nil
113123
}
114124

115125
// inputToResourceList transforms input into a starlark.Value
@@ -124,8 +134,11 @@ func (sf *Filter) readResourceList(reader io.Reader) (starlark.Value, error) {
124134
if err != nil {
125135
return nil, errors.Wrap(err)
126136
}
137+
return rnodeToStarlarkValue(rn)
138+
}
127139

128-
// convert to a starlark value
140+
// rnodeToStarlarkValue converts a RNode to a starlark value.
141+
func rnodeToStarlarkValue(rn *yaml.RNode) (starlark.Value, error) {
129142
b, err := yaml.Marshal(rn.Document()) // convert to bytes
130143
if err != nil {
131144
return nil, errors.Wrap(err)
@@ -138,20 +151,26 @@ func (sf *Filter) readResourceList(reader io.Reader) (starlark.Value, error) {
138151
return util.Marshal(in) // convert to starlark value
139152
}
140153

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) {
143156
// convert the modified resourceList back into a slice of RNodes
144157
// by first converting to a map[string]interface{}
145158
out, err := util.Unmarshal(value)
146159
if err != nil {
147-
return errors.Wrap(err)
160+
return nil, errors.Wrap(err)
148161
}
149162
b, err := yaml.Marshal(out)
150163
if err != nil {
151-
return errors.Wrap(err)
164+
return nil, errors.Wrap(err)
152165
}
153166

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)
155174
if err != nil {
156175
return errors.Wrap(err)
157176
}
@@ -179,3 +198,91 @@ func (sf *Filter) writeResourceList(value starlark.Value, writer io.Writer) erro
179198
_, err = writer.Write([]byte(s))
180199
return err
181200
}
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

Comments
 (0)