diff --git a/kyaml/starlark/doc.go b/kyaml/starlark/doc.go index 734ec3fdb..70f0a2c7b 100644 --- a/kyaml/starlark/doc.go +++ b/kyaml/starlark/doc.go @@ -4,12 +4,22 @@ // Package starlark contains a kio.Filter which can be applied to resources to transform // them through starlark program. // -// The resources are provided to the program through the global variable "resourceList". +// Starlark has become a popular runtime embedding in go programs, especially for Kubernetes +// and data processing. +// Examples: https://github.com/cruise-automation/isopod, https://qri.io/docs/starlark/starlib, +// https://github.com/stripe/skycfg, https://github.com/k14s/ytt +// +// The resources are provided to the starlark program through the global variable "resourceList". // "resourceList" is a dictionary containing an "items" field with a list of resources. -// Changes to "resourceList" made by the starlark program will be reflected in the Filter output. +// The starlark modified "resourceList" is the Filter output. // // After being run through the starlark program, the filter will copy the comments from the input -// resources to restore them after they are dropped due to the serialization. +// resources to restore them -- due to them being dropped as a result of serializing the resources +// as starlark values. +// +// "resourceList" may also contain a "functionConfig" entry to configure the starlark script itself. +// Changes made by the starlark program to the "functionConfig" will be reflected in the +// Filter.FunctionConfig value. // // The Filter will also format the output so that output has the preferred field ordering // rather than an alphabetical field ordering. diff --git a/kyaml/starlark/example_test.go b/kyaml/starlark/example_test.go index bf9a8b004..c2ac8ef31 100644 --- a/kyaml/starlark/example_test.go +++ b/kyaml/starlark/example_test.go @@ -6,10 +6,14 @@ package starlark_test import ( "bytes" "fmt" + "io/ioutil" "log" + "os" + "path/filepath" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/starlark" + "sigs.k8s.io/kustomize/kyaml/yaml" ) func ExampleFilter_Filter() { @@ -91,3 +95,196 @@ run(resourceList["items"]) // - name: nginx // image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"} } + +func ExampleFilter_Filter_functionConfig() { + // input contains the items that will provided to the starlark program + input := bytes.NewBufferString(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment-1 +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment-2 +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"} +`) + + fc, err := yaml.Parse(` +kind: AnnotationSetter +spec: + value: "hello world" +`) + if err != nil { + log.Fatal(err) + } + + // fltr transforms the input using a starlark program + fltr := &starlark.Filter{ + Name: "annotate", + Program: ` +def run(items, value): + for item in items: + item["metadata"]["annotations"]["foo"] = value + +run(resourceList["items"], resourceList["functionConfig"]["spec"]["value"]) +`, + FunctionConfig: fc, + } + + // output contains the transformed resources + output := &bytes.Buffer{} + + // run the fltr against the inputs using a kio.Pipeline + err = kio.Pipeline{ + Inputs: []kio.Reader{&kio.ByteReader{Reader: input}}, + Filters: []kio.Filter{fltr}, + Outputs: []kio.Writer{&kio.ByteWriter{Writer: output}}}.Execute() + if err != nil { + log.Fatal(err) + } + + fmt.Println(output.String()) + + // Output: + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: deployment-1 + // annotations: + // foo: hello world + // spec: + // template: + // spec: + // containers: + // - name: nginx + // image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"} + //--- + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: deployment-2 + // annotations: + // foo: hello world + // spec: + // template: + // spec: + // containers: + // - name: nginx + // image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"} +} + +// ExampleFilter_Filter_file applies a starlark program in a local file to a collection of +// resource configuration read from a directory. +func ExampleFilter_Filter_file() { + // setup the configuration + d, err := ioutil.TempDir("", "") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(d) + + err = ioutil.WriteFile(filepath.Join(d, "deploy1.yaml"), []byte(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment-1 +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"} +`), 0600) + if err != nil { + log.Fatal(err) + } + + err = ioutil.WriteFile(filepath.Join(d, "deploy2.yaml"), []byte(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment-2 +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"} +`), 0600) + if err != nil { + log.Fatal(err) + } + + err = ioutil.WriteFile(filepath.Join(d, "annotate.star"), []byte(` +def run(items): + for item in items: + item["metadata"]["annotations"]["foo"] = "bar" + +run(resourceList["items"]) +`), 0600) + if err != nil { + log.Fatal(err) + } + + fltr := &starlark.Filter{ + Name: "annotate", + Path: filepath.Join(d, "annotate.star"), + } + + // output contains the transformed resources + output := &bytes.Buffer{} + + // run the fltr against the inputs using a kio.Pipeline + err = kio.Pipeline{ + Inputs: []kio.Reader{&kio.LocalPackageReader{PackagePath: d}}, + Filters: []kio.Filter{fltr}, + Outputs: []kio.Writer{&kio.ByteWriter{ + Writer: output, + ClearAnnotations: []string{"config.kubernetes.io/path"}, + }}}.Execute() + if err != nil { + log.Fatal(err) + } + + fmt.Println(output.String()) + + // Output: + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: deployment-1 + // annotations: + // foo: bar + // spec: + // template: + // spec: + // containers: + // - name: nginx + // image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"} + //--- + // apiVersion: apps/v1 + // kind: Deployment + // metadata: + // name: deployment-2 + // annotations: + // foo: bar + // spec: + // template: + // spec: + // containers: + // - name: nginx + // image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"} +} diff --git a/kyaml/starlark/starlark_test.go b/kyaml/starlark/starlark_test.go index 20abc7e22..310f1a44f 100644 --- a/kyaml/starlark/starlark_test.go +++ b/kyaml/starlark/starlark_test.go @@ -16,7 +16,7 @@ import ( "sigs.k8s.io/kustomize/kyaml/yaml" ) -func TestStarlarkFilter_Filter(t *testing.T) { +func TestFilter_Filter(t *testing.T) { var tests = []struct { name string input string