starlark

package
v0.13.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 16, 2022 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package starlark contains a kio.Filter which can be applied to resources to transform them through starlark program.

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. 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 -- 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.

The resourceList variable adheres to the kustomize function spec as specified by: https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md

All items in the resourceList are resources represented as starlark dictionaries/ The items in the resourceList respect the io spec specified by: https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/config-io.md

The starlark language spec can be found here: https://github.com/google/starlark-go/blob/master/doc/spec.md

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Context

type Context struct {
	// contains filtered or unexported fields
}

type Filter

type Filter struct {
	Name string

	// Program is a starlark script which will be run against the resources
	Program string

	// URL is the url of a starlark program to fetch and run
	URL string

	// Path is the path to a starlark program to read and run
	Path string

	runtimeutil.FunctionFilter
}

Filter transforms a set of resources through the provided program

func (*Filter) Filter

func (sf *Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error)
Example
package main

import (
	"bytes"
	"fmt"
	"log"

	"sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark"
	"sigs.k8s.io/kustomize/kyaml/kio"
)

func main() {
	// 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"}
`)

	// fltr transforms the input using a starlark program
	fltr := &starlark.Filter{
		Name: "annotate",
		Program: `
def run(items):
  for item in items:
    item["metadata"]["annotations"]["foo"] = "bar"

run(ctx.resource_list["items"])
`,
	}

	// 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.Println(err)
	}

	fmt.Println(output.String())

}
Output:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-1
  annotations:
    foo: bar
    internal.config.kubernetes.io/path: 'deployment_deployment-1.yaml'
    config.kubernetes.io/path: 'deployment_deployment-1.yaml'
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
    internal.config.kubernetes.io/path: 'deployment_deployment-2.yaml'
    config.kubernetes.io/path: 'deployment_deployment-2.yaml'
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}
Example (File)

ExampleFilter_Filter_file applies a starlark program in a local file to a collection of resource configuration read from a directory.

package main

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark"
	"sigs.k8s.io/kustomize/kyaml/kio"
	"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
)

func main() {
	// setup the configuration
	d, err := os.MkdirTemp("", "")
	if err != nil {
		log.Println(err)
	}
	defer os.RemoveAll(d)

	err = os.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.Println(err)
	}

	err = os.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.Println(err)
	}

	err = os.WriteFile(filepath.Join(d, "annotate.star"), []byte(`
def run(items):
  for item in items:
    item["metadata"]["annotations"]["foo"] = "bar"

run(ctx.resource_list["items"])
`), 0600)
	if err != nil {
		log.Println(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{
				kioutil.PathAnnotation,
				kioutil.LegacyPathAnnotation,
			},
		}}}.Execute()
	if err != nil {
		log.Println(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"}
Example (FunctionConfig)
package main

import (
	"bytes"
	"fmt"
	"log"

	"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
	"sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark"
	"sigs.k8s.io/kustomize/kyaml/kio"
	"sigs.k8s.io/kustomize/kyaml/yaml"
)

func main() {
	// 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.Println(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(ctx.resource_list["items"], ctx.resource_list["functionConfig"]["spec"]["value"])
`,
		FunctionFilter: runtimeutil.FunctionFilter{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.Println(err)
	}

	fmt.Println(output.String())

}
Output:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-1
  annotations:
    foo: hello world
    internal.config.kubernetes.io/path: 'deployment_deployment-1.yaml'
    config.kubernetes.io/path: 'deployment_deployment-1.yaml'
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
    internal.config.kubernetes.io/path: 'deployment_deployment-2.yaml'
    config.kubernetes.io/path: 'deployment_deployment-2.yaml'
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}

func (*Filter) Run

func (sf *Filter) Run(reader io.Reader, writer io.Writer) error

func (*Filter) String

func (sf *Filter) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL