mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-18 02:45:17 +00:00
238 lines
5.9 KiB
Go
238 lines
5.9 KiB
Go
// Copyright 2019 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
/*
|
|
Package plugin contains builtin and example
|
|
plugins, tests and test libraries, and a code
|
|
generator for converting a plugin to statically
|
|
loadable code (see pluginator).
|
|
|
|
|
|
HOW PLUGINS RUN
|
|
|
|
Assume a file 'secGen.yaml' containing
|
|
|
|
apiVersion: someteam.example.com/v1
|
|
kind: SecretGenerator
|
|
metadata:
|
|
name: makesecrets
|
|
name: mySecret
|
|
behavior: merge
|
|
envs:
|
|
- db.env
|
|
- fruit.env
|
|
|
|
If this file were referenced by a kustomization
|
|
file in its 'generators' field, kustomize would
|
|
|
|
* Read 'secGen.yaml'.
|
|
|
|
* Use the value of $XGD_CONFIG_HOME and
|
|
'apiversion' and to find an executable
|
|
named 'SecretGenerator' to use as
|
|
an exec plugin, or failing that,
|
|
|
|
* use the same info to load a Go plugin
|
|
object file called 'SecretGenerator.so'.
|
|
|
|
* Send either the file name 'secGen.yaml' as
|
|
the first arg to the exec plugin, or send its
|
|
contents to the go plugin's Config method.
|
|
|
|
* Use the plugin to generate and/or transform.
|
|
|
|
|
|
GO PLUGINS
|
|
|
|
A .go file can be a Go plugin if it declares
|
|
'main' as it's package, and exports a symbol to
|
|
which useful functions are attached.
|
|
|
|
It can further be used as a _kustomize_ plugin if
|
|
the symbol is named 'KustomizePlugin' and the
|
|
attached functions implement the Configurable,
|
|
Generator and Transformer interfaces.
|
|
|
|
A plugin won't load into some program foo/main.go
|
|
if there is any package version mismatch in the
|
|
dependencies of the plugin and the dependencies of
|
|
foo/main.go. Control this with matching
|
|
declarations in go.mod files. The versions of the
|
|
builtin packages "fmt", "io", "os" (not normally
|
|
listed in go.mod) etc have the same version as the
|
|
compiler.
|
|
|
|
|
|
ONE PLUGIN PER DIRECTORY
|
|
|
|
For kustomize (and perhaps anyone), it's simplest
|
|
to put each plugin into its own directory.
|
|
|
|
Go plugins must be in package `main`, and so
|
|
having more than one plugin in a directory means
|
|
their loading symbols have to differ, which makes
|
|
it hard to standardize around how they get loaded,
|
|
or it means one must use build tags to suppress
|
|
full directory compilation - which creates
|
|
difficulties using IDEs, the `go mod` tool, `go
|
|
test ./...`, etc.
|
|
|
|
A one plugin per directory policy makes it easy to
|
|
define the plugin as a module, with its own
|
|
`go.mod` file - which is vital for resolving
|
|
package version dependency mismatches at load
|
|
time. It also makes it easy to create a plugin
|
|
tarball (source, test, go.mod, plugin data files,
|
|
etc.) for distribution.
|
|
|
|
|
|
BUILTIN PLUGIN CONFIGURATION
|
|
|
|
For performance reasons, all builting plugins are
|
|
Go plugins (not exec plugins).
|
|
|
|
Using "SecretGenerator" as an example in what
|
|
follows.
|
|
|
|
The plugin config file looks like
|
|
|
|
---------------------------------------------
|
|
apiVersion: builtin
|
|
kind: SecretGenerator
|
|
metadata:
|
|
name: whatever
|
|
otherField1: whatever
|
|
otherField2: whatever
|
|
...
|
|
---------------------------------------------
|
|
|
|
The apiVersion must be 'builtin'. The kind is the
|
|
CamelCase name of the plugin.
|
|
|
|
For non-builtins the apiVersion can be any legal
|
|
apiVersion value, e.g. 'someteam.example.com/v1beta1'
|
|
|
|
The builtin source must be at:
|
|
|
|
repo=$GOPATH/src/sigs.k8s.io/kustomize
|
|
${repo}/plugin/${apiVersion}/LOWERCASE(${kind})/${kind}.go
|
|
|
|
(dropping the ".go" for exec plugins).
|
|
|
|
k8s wants 'kind' values to follow CamelCase, while
|
|
Go style doesn't like but does allow such names.
|
|
|
|
The lowercased value of kind is used as the name of the
|
|
directory holding the plugin, its test, and any
|
|
optional associated files (possibly a go.mod file).
|
|
|
|
|
|
PLUGIN SOURCE
|
|
|
|
* Pattern
|
|
|
|
secretgenerator.go
|
|
---------------------------------------------
|
|
//go:generate go run sigs.k8s.io/kustomize/cmd/pluginator
|
|
package main
|
|
import ...
|
|
type plugin struct{...}
|
|
var KustomizePlugin plugin
|
|
func (p *plugin) Config(
|
|
ldr ifc.Loader,
|
|
rf *resmap.Factory,
|
|
c []byte) error {...}
|
|
func (p *plugin) Generate(
|
|
) (resmap.ResMap, error) {...}
|
|
func (p *plugin) Transform(
|
|
m resmap.ResMap) error {...}
|
|
---------------------------------------------
|
|
|
|
The plugin name doesn't appear in the file itself.
|
|
|
|
* Compilation
|
|
|
|
repo=$GOPATH/src/sigs.k8s.io/kustomize
|
|
dir=$repo/plugin/builtin
|
|
go build -buildmode plugin \
|
|
-o $dir/secretgenerator.so \
|
|
$dir/secretgenerator.go
|
|
|
|
|
|
|
|
BUILTIN PLUGIN GENERATION
|
|
|
|
The pluginator program is a code generator that
|
|
converts kustomize generator (G) and/or
|
|
transformer (T) Go plugins to statically linkable
|
|
code.
|
|
|
|
It arises from following requirements:
|
|
|
|
* extension
|
|
|
|
kustomize does two things - generate or
|
|
transform k8s resources. Plugins let
|
|
users write their own G&T's without
|
|
having to fork kustomize and learn its
|
|
internals.
|
|
|
|
* dogfooding
|
|
|
|
A G&T extension framework one can trust
|
|
should be used by its authors to deliver
|
|
builtin G&T's.
|
|
|
|
* distribution
|
|
|
|
kustomize should be distributable via
|
|
`go get` and should run where Go
|
|
programs are expected to run.
|
|
|
|
The extension requirement led to the creation
|
|
of a framework that accommodates writing a
|
|
G or T as either
|
|
|
|
* an 'exec' plugin (any executable file
|
|
runnable as a kustomize subprocess), or
|
|
|
|
* as a Go plugin - see
|
|
https://golang.org/pkg/plugin.
|
|
|
|
The dogfooding (and an implicit performance
|
|
requirement) requires a 'builtin' G or T to
|
|
be written as a Go plugin.
|
|
|
|
The distribution ('go get') requirement demands
|
|
conversion of Go plugins to statically linked
|
|
code, hence this program.
|
|
|
|
|
|
TO GENERATE CODE
|
|
|
|
repo=$GOPATH/src/sigs.k8s.io/kustomize
|
|
cd $repo/plugin/builtin
|
|
go generate ./...
|
|
|
|
This creates
|
|
|
|
$repo/plugin/builtin/SecretGenerator.go
|
|
|
|
etc.
|
|
|
|
Generated plugins are used in kustomize via
|
|
|
|
---------------------------------------------
|
|
package whatever
|
|
import "sigs.k8s.io/kustomize/plugin/builtin
|
|
...
|
|
g := builtin.NewSecretGenerator()
|
|
g.Config(l, rf, k)
|
|
resources, err := g.Generate()
|
|
err = g.Transform(resources)
|
|
// Eventually emit resources.
|
|
---------------------------------------------
|
|
|
|
*/
|
|
package plugin
|