mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-10 08:20:59 +00:00
doc/glossary updates for v2.1
This commit is contained in:
250
docs/plugins.md
Normal file
250
docs/plugins.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# kustomize plugins
|
||||
|
||||
Kustomize offers a plugin framework for people to
|
||||
write their own resource generators (e.g. a helm
|
||||
chart processor, a generator that automatically
|
||||
attaches a Service and Ingress object to each
|
||||
Deployment) and their own resource transformers
|
||||
(e.g. a transformer that does some highly
|
||||
customized processing of the container command
|
||||
line).
|
||||
|
||||
## Specification in `kustomization.yaml`
|
||||
|
||||
A kustomization file has two new fields in v2.1:
|
||||
_generators_ and _transformers_.
|
||||
|
||||
Each accepts a list of strings as its arguments:
|
||||
|
||||
> ```
|
||||
> generators:
|
||||
> - relative/path/to/some/file.yaml
|
||||
> - relative/path/to/some/kustomization
|
||||
> - /absolute/path/to/some/kustomization
|
||||
> - https://github.com/org/repo/some/kustomization
|
||||
>
|
||||
> transformers:
|
||||
> - {as above}
|
||||
> ```
|
||||
|
||||
This is exactly like the syntax of the `resources` field.
|
||||
|
||||
The value of each entry in a `resources`, `generators`
|
||||
or `transformers` list must be a relative path to a
|
||||
YAML file, or a path or URL to a [kustomization].
|
||||
|
||||
[kustomization]: glossary.md#kustomization
|
||||
|
||||
In the former case the YAML is read from disk directly,
|
||||
and in the latter case a kustomization is performed,
|
||||
and its YAML output is merged with the YAML read
|
||||
directly from files. The net result in all three cases
|
||||
is an array of YAML objects.
|
||||
|
||||
_Each_ object resulting from a `generators` or
|
||||
`transformers` field is now further interpreted by
|
||||
kustomize as a _plugin configuration_ object.
|
||||
|
||||
## Configuration and execution
|
||||
|
||||
A kustomization file could have the following lines:
|
||||
|
||||
```
|
||||
generators:
|
||||
- chartInflator.yaml
|
||||
```
|
||||
|
||||
Given this, the kustomization process would expect to
|
||||
find a file called `chartInflator.yaml` in the
|
||||
kustomization [root](glossary.md#root).
|
||||
|
||||
The file `chartInflator.yaml` could contain:
|
||||
|
||||
```
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: ChartInflatorExec
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
chartName: minecraft
|
||||
```
|
||||
|
||||
The `apiVersion` and `kind` fields of the configuration
|
||||
objects are used to _locate_ the plugin.
|
||||
|
||||
The rest of the file (actually the entire file) is
|
||||
sent to the plugin as configuration - i.e. as the
|
||||
plugin's construction arguments.
|
||||
|
||||
A kustomization file could include multiple
|
||||
instantiations of the same plugin, with different
|
||||
arguments (e.g. to inflate two different helm
|
||||
charts or two instances of the same chart but with
|
||||
different values files).
|
||||
|
||||
The value order in the `generators` field doesn't
|
||||
matter, because generated objects are just added
|
||||
to a sea of objects that kustomize transforms and
|
||||
emits.
|
||||
|
||||
The specified order of transformers in the
|
||||
`transformers` field is, however, respected, as
|
||||
transformers aren't expected to be commutative.
|
||||
|
||||
Generator plugins are run after processing the
|
||||
`resources` field (which _reads_ resources), to
|
||||
_create_ additional resources.
|
||||
|
||||
The full set of resources is then passed into the
|
||||
transformation pipeline, where native (legacy)
|
||||
transformations like `namePrefix` and
|
||||
`commonLabel` are applied, followed by all the
|
||||
transformers run in the order specified.
|
||||
|
||||
|
||||
## Placement
|
||||
|
||||
[k8s object]: glossary.md#kubernetes-style-object
|
||||
|
||||
Given a configuration object (whick looks like any
|
||||
other [k8s object]), kustomize will first look for an
|
||||
_executable_ file called
|
||||
|
||||
```
|
||||
$XDG_CONFIG_HOME/kustomize/plugin/${apiVersion}/${kind}
|
||||
```
|
||||
|
||||
The default value of `XDG_CONFIG_HOME` is `$HOME/.config`.
|
||||
|
||||
If this file is not found or is not executable,
|
||||
kustomize will look for a file called `${kind}.so`
|
||||
in the same directory and attempt to load it as a
|
||||
[Go plugin](#go-plugins).
|
||||
|
||||
If both checks fails, the plugin load fails the overall
|
||||
kustomize build.
|
||||
|
||||
A `kustomize build` attempt with plugins that
|
||||
omits the flag
|
||||
|
||||
TODO: Change flag
|
||||
|
||||
> `--enable_alpha_goplugins_accept_panic_risk`
|
||||
|
||||
will fail with a warning about plugin use.
|
||||
|
||||
Flag use is an opt-in acknowledging the absence of
|
||||
plugin provenance. Its meant to give pause to
|
||||
someone who blindly downloads a kustomization from
|
||||
the internet and attempts to run it, without
|
||||
realizing that it might attempt to run 3rd party
|
||||
code.
|
||||
|
||||
|
||||
## Writing plugins
|
||||
|
||||
### Exec plugins
|
||||
|
||||
TODO: Add ptr to example.
|
||||
|
||||
A exec plugin is any executable that accepts a
|
||||
single argument on it's command line - the name of
|
||||
a YAML file containing its configuration (which it
|
||||
presumably reads if it needs additional
|
||||
configuration).
|
||||
|
||||
A generator plugin accepts nothing on `stdin`, but emits
|
||||
generated resources to `stdout`.
|
||||
|
||||
A transformer plugin accepts resource YAML on `stdin`,
|
||||
and emits those resources, possibly transformed, to
|
||||
`stdout`.
|
||||
|
||||
|
||||
### Go plugins
|
||||
|
||||
TODO: Add ptr to example.
|
||||
|
||||
[Go plugin]: https://golang.org/pkg/plugin/
|
||||
|
||||
A [Go plugin] for kustomize looks like this:
|
||||
|
||||
> ```
|
||||
> +build plugin
|
||||
>
|
||||
> package main
|
||||
>
|
||||
> import ...
|
||||
>
|
||||
> // go:generate go run sigs.k8s.io/kustomize/cmd/pluginator
|
||||
> type plugin struct{...}
|
||||
>
|
||||
> var KustomizePlugin plugin
|
||||
>
|
||||
> func (p *plugin) Config(
|
||||
> ldr ifc.Loader, rf *resmap.Factory,
|
||||
> k ifc.Kunstructured) error {...}
|
||||
>
|
||||
> func (p *plugin) Generate() (resmap.ResMap, error) {...}
|
||||
>
|
||||
> func (p *plugin) Transform(m resmap.ResMap) error {...}
|
||||
> ```
|
||||
|
||||
The use of the identifiers `plugin`,
|
||||
`KustomizePlugin` and the three method signatures
|
||||
`Configurable`, `Generator`, `Transformer` as
|
||||
shown is _required_.
|
||||
|
||||
The plugin author should of course change the
|
||||
contents of the `plugin` struct, and the three
|
||||
method bodies, and the import statements, as
|
||||
desired.
|
||||
|
||||
Here's a build command, which assumes the plugin
|
||||
source code is sitting right next to where the
|
||||
shared object (`.so`) files are expected to be:
|
||||
|
||||
```
|
||||
dir=$XDG_CONFIG_HOME/kustomize/plugin/${apiVersion}
|
||||
go build -buildmode plugin -tags=plugin \
|
||||
-o $dir/${kind}.so \
|
||||
$dir/${kind}.go
|
||||
```
|
||||
|
||||
For the person willing to compile not just a
|
||||
plugin but all of kustomze as well, a code
|
||||
generator will be provided that will convert a Go
|
||||
plugin to statically linked code in your own
|
||||
compiled version of kustomize.
|
||||
|
||||
#### Caveats
|
||||
|
||||
Go plugins allow kustomize extensions that
|
||||
|
||||
* can be tested with the same framework kustomize
|
||||
uses to test its _builtin_ generators and
|
||||
transformers,
|
||||
|
||||
* run without the performance hit of firing up a
|
||||
subprocess and marshalling/unmarshalling data
|
||||
for each plugin run.
|
||||
|
||||
Go plugins work as [defined][Go plugin], but
|
||||
fall short of what many people think of when they
|
||||
hear the word _plugin_.
|
||||
|
||||
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
|
||||
Go plugin compilation creates an [ELF] formatted
|
||||
`.so` file, which by definition has no information
|
||||
about the _provenance_ of the file.
|
||||
|
||||
One cannot know which version of Go was used,
|
||||
which packages were imported (and their version),
|
||||
what value of `GOOS` and `GOARCH` were used,
|
||||
etc. Skew between the compilation conditions of
|
||||
the main program ELF and the plugin ELF will cause
|
||||
a failure at load time.
|
||||
|
||||
Exec plugins also lack provenance - but they don't
|
||||
suffer from the skew problem.
|
||||
|
||||
Reference in New Issue
Block a user