mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 00:52:55 +00:00
Improvements to kyaml fn framework
This commit creates a new version of the alpha configuration functions framework. Goals include: - Make it easy to build multi-version APIs with the framework (not previously facilitated at all). - Simplify the framework's APIs where redundant configuration options exist (leaving the most powerful, replacing others with helpers to maintain usability they provided). - Make the Framework's APIs more consistent (e.g. between the various template types, usage of kio.Filter, field names) - Decouple responsibilities (e.g. command creation, resource list processing, generation of templating functions). - Make the framework even more powerfully pluggable (e.g. any kio.Filter can be a selector, and the selector the framework provides is itself a filter built from reusable abstractions). - Improve documentation. - Make container patches merge fields (notably list fields like `env`) correctly.
This commit is contained in:
@@ -1,106 +1,39 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package framework contains a framework for writing functions in go. The function spec
|
||||
// Package framework contains a framework for writing functions in Go. The function specification
|
||||
// is defined at: https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
|
||||
//
|
||||
// Functions are executables which generate, modify, delete or validate Kubernetes resources.
|
||||
// Functions are executables that generate, modify, delete or validate Kubernetes resources.
|
||||
// They are often used used to implement abstractions ("kind: JavaSpringBoot") and
|
||||
// cross-cutting logic ("kind: SidecarInjector").
|
||||
//
|
||||
// Functions may be run as standalone executables or invoked as part of an orchestrated
|
||||
// pipeline (e.g. kustomize).
|
||||
//
|
||||
// Example standalone usage
|
||||
// Example function implementation using framework.SimpleProcessor with a struct input
|
||||
//
|
||||
// Function template input:
|
||||
// type Spec struct {
|
||||
// Value string `yaml:"value,omitempty"`
|
||||
// }
|
||||
// type Example struct {
|
||||
// Spec Spec `yaml:"spec,omitempty"`
|
||||
// }
|
||||
//
|
||||
// # config.yaml -- this is the input to the template
|
||||
// apiVersion: example.com/v1alpha1
|
||||
// kind: Example
|
||||
// Key: a
|
||||
// Value: b
|
||||
// func runFunction(rlSource *kio.ByteReadWriter) error {
|
||||
// functionConfig := &Example{}
|
||||
//
|
||||
// Additional function inputs:
|
||||
// fn := func(items []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
// for i := range rl.Items {
|
||||
// // modify the items...
|
||||
// }
|
||||
// return items, nil
|
||||
// }
|
||||
//
|
||||
// # patch.yaml -- this will be applied as a patch
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: foo
|
||||
// namespace: default
|
||||
// annotations:
|
||||
// patch-key: patch-value
|
||||
//
|
||||
// Manually run the function:
|
||||
//
|
||||
// # build the function
|
||||
// $ go build example-fn/
|
||||
//
|
||||
// # run the function using the
|
||||
// $ ./example-fn config.yaml patch.yaml
|
||||
//
|
||||
// Go implementation
|
||||
//
|
||||
// // example-fn/main.go
|
||||
// func main() {
|
||||
//
|
||||
// // Define the template used to generate resources
|
||||
// tc := framework.TemplateCommand{
|
||||
// Merge: true, // apply inputs as patches to the template output
|
||||
// API: &struct {
|
||||
// Key string `json:"key" yaml:"key"`
|
||||
// Value string `json:"value" yaml:"value"`
|
||||
// }{},
|
||||
// Template: template.Must(template.New("example").Parse(`
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: foo
|
||||
// namespace: default
|
||||
// annotations:
|
||||
// {{ .Key }}: {{ .Value }}
|
||||
// `))}
|
||||
//
|
||||
// // Run the command
|
||||
// if err := tc.GetCommand().Execute(); err != nil {
|
||||
// fmt.Fprintf(cmd.ErrOrStderr(), "%v\n", err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// More Examples
|
||||
//
|
||||
// Example function implementation using framework.Command with flag input
|
||||
//
|
||||
// var value string
|
||||
// resourceList := &framework.ResourceList{}
|
||||
// cmd := framework.Command(resourceList, func() error {
|
||||
// for i := range resourceList.Items {
|
||||
// // modify the items...
|
||||
// }
|
||||
// return nil
|
||||
// })
|
||||
// cmd.Flags().StringVar(&value, "value", "", "annotation value")
|
||||
// if err := cmd.Execute(); err != nil { return err }
|
||||
//
|
||||
// Example function implementation using framework.ResourceList with a struct input
|
||||
//
|
||||
// type Spec struct {
|
||||
// Value string `yaml:"value,omitempty"`
|
||||
// }
|
||||
// type Example struct {
|
||||
// Spec Spec `yaml:"spec,omitempty"`
|
||||
// }
|
||||
// functionConfig := &Example{}
|
||||
//
|
||||
// rl := framework.ResourceList{FunctionConfig: functionConfig}
|
||||
// if err := rl.Read(); err != nil { return err }
|
||||
//
|
||||
// for i := range rl.Items {
|
||||
// // modify the items...
|
||||
// }
|
||||
// if err := rl.Write(); err != nil { return err }
|
||||
// p := framework.SimpleProcessor{Config: functionConfig, Filter: kio.FilterFunc(fn)}
|
||||
// err := framework.Execute(p, rlSource)
|
||||
// return errors.Wrap(err)
|
||||
// }
|
||||
//
|
||||
// Architecture
|
||||
//
|
||||
@@ -108,7 +41,7 @@
|
||||
// as output. The function itself may be configured through a functionConfig
|
||||
// (ResourceList.FunctionConfig).
|
||||
//
|
||||
// Example Function Input:
|
||||
// Example function input:
|
||||
//
|
||||
// kind: ResourceList
|
||||
// items:
|
||||
@@ -140,10 +73,9 @@
|
||||
// The framework takes care of serializing and deserializing the ResourceList.
|
||||
//
|
||||
// Generated ResourceList.functionConfig -- ConfigMaps
|
||||
//
|
||||
// Functions may also be specified imperatively and run using:
|
||||
//
|
||||
// config run DIR/ --image image/containing/function:impl -- value=foo
|
||||
// kpt fn run DIR/ --image image/containing/function:impl -- value=foo
|
||||
//
|
||||
// When run imperatively, a ConfigMap is generated for the functionConfig, and the command
|
||||
// arguments are set as ConfigMap data entries.
|
||||
@@ -165,15 +97,9 @@
|
||||
//
|
||||
// Configuring Functions
|
||||
//
|
||||
// Functions may be configured through a functionConfig (i.e. a client side custom resource),
|
||||
// Functions may be configured through a functionConfig (i.e. a client-side custom resource),
|
||||
// or through flags (which the framework parses from a ConfigMap provided as input).
|
||||
//
|
||||
// When using framework.Command, any flags registered on the cobra.Command will be parsed
|
||||
// from the functionConfig input if they are defined as functionConfig.data entries.
|
||||
//
|
||||
// When using framework.ResourceList, any flags set on the ResourceList.Flags will be
|
||||
// parsed from the functionConfig input if they are defined as functionConfig.data entries.
|
||||
//
|
||||
// Functions may also access environment variables set by the caller.
|
||||
//
|
||||
// Building a container image for the function
|
||||
|
||||
Reference in New Issue
Block a user