mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-14 02:20:53 +00:00
One plugin per dir.
This commit is contained in:
237
plugin/doc.go
Normal file
237
plugin/doc.go
Normal file
@@ -0,0 +1,237 @@
|
||||
// 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
|
||||
Reference in New Issue
Block a user