Remove kv plugins from docs.

This commit is contained in:
jregan
2019-05-22 16:47:26 -07:00
parent d8f3bffe63
commit 78cdff6d09
8 changed files with 478 additions and 609 deletions

View File

@@ -1,20 +1,36 @@
# 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).
Kustomize offers a plugin framework allowing
people to write their own resource _generators_
and _transformers_.
[generator options]: ../examples/generatorOptions.md
[transformer configs]: ../examples/transformerconfigs
Write a plugin when changing [generator options]
or [transformer configs] doesn't meet your needs.
[12-factor]: https://12factor.net
* A _generator_ plugin could be a helm chart
inflator, or a plugin that emits all the
components (deployment, service, scaler,
ingress, etc.) needed by someone's [12-factor]
application, based on a smaller number of free
variables.
* A _transformer_ plugin might perform special
container command line edits, or any other
transformation that exceeds the power of the
builtin transformations (`namePrefix`,
`commonLabels`, etc.).
## Specification in `kustomization.yaml`
Start by adding a `generators` and/or `transformers`
field to your kustomization.
Each field is a string array:
Each field accepts a string list:
> ```
> generators:
@@ -27,11 +43,13 @@ Each field is a string array:
> - {as above}
> ```
This is exactly like the syntax of the `resources` field.
This is exactly like the syntax of the `resources`
field.
The value of each entry in a `resources`, `generators`
or `transformers` array must be a relative path to a
YAML file, or a path or URL to a [kustomization].
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
@@ -39,9 +57,9 @@ 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.
is a set of YAML objects.
_Each_ object resulting from a `generators` or
Each object resulting from a `generators` or
`transformers` field is now further interpreted by
kustomize as a _plugin configuration_ object.
@@ -58,6 +76,8 @@ Given this, the kustomization process would expect to
find a file called `chartInflator.yaml` in the
kustomization [root](glossary.md#kustomization-root).
This is the _plugin's configuration file_.
The file `chartInflator.yaml` could contain:
```
@@ -68,50 +88,51 @@ metadata:
chartName: minecraft
```
The `apiVersion` and `kind` fields of the configuration
objects are used to _locate_ the plugin.
__The `apiVersion` and `kind` fields 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.
[k8s object]: glossary.md#kubernetes-style-object
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).
> Thus, these fields are required. They are also
> required because a kustomize plugin
> configuration object is also a [k8s object].
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.
To get the plugin ready to generator or transform,
it is given the entire contents of the
configuration file.
The specified order of transformers in the
`transformers` field should be respected, as
transformers cannot be expected to be commutative.
[NameTransformer]: ../plugin/builtin/nametransformer/NameTransformer_test.go
[ChartInflator]: ../plugin/someteam.example.com/v1/chartinflator/ChartInflator_test.go
[plugins]: ../plugin/builtin
## Execution
Plugins are only used during a run of the
`kustomize build` command.
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.
For more examples of plugin configuration YAML,
browse the unit tests below the [plugins] root,
e.g. the tests for [ChartInflator] or
[NameTransformer].
## Placement
[k8s object]: glossary.md#kubernetes-style-object
Each plugin gets its own dedicated directory named
Given a plugin configuration object (it looks like any
other [k8s object]), kustomize will first look for an
```
$XDG_CONFIG_HOME/kustomize/plugin
/${apiVersion}/LOWERCASE(${kind})
```
The default value of `XDG_CONFIG_HOME` is
`$HOME/.config`.
The one-plugin-per-directory requirement eases
creation of a plugin tarball (source, test, plugin
data files, etc.) for sharing.
In the case of a [Go plugin](#go-plugins), it also
allows one to provide a `go.mod` file for the
single plugin, easing resolution of package
version dependency skew.
When loading, kustomize will first look for an
_executable_ file called
```
@@ -119,24 +140,45 @@ $XDG_CONFIG_HOME/kustomize/plugin
/${apiVersion}/LOWERCASE(${kind})/${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.
If both checks fail, the plugin load fails the overall
`kustomize build`.
A `kustomize build` attempt with plugins that
## Execution
Plugins are only used during a run of the
`kustomize build` command.
Generator plugins are run after processing the
`resources` field (which itself is in some sense a
generator in that it emits resources for further
processing).
The full set of resources is then passed into the
transformation pipeline, wherein builtin
transformations like `namePrefix` and
`commonLabel` are applied (if they were specified
in the kustomization file), followed by the
user-specified transformers in the `transformers`
field.
The specified order of transformers in the
`transformers` field should be respected, as
transformers cannot be expected to be commutative.
A `kustomize build` that tries to use plugins but
omits the flag
_TODO: Change flag_
> `--enable_alpha_goplugins_accept_panic_risk`
will fail with a warning about plugin use.
_TODO: Change flag_
Flag use is an opt-in acknowledging the absence of
plugin provenance. It's meant to give pause to
@@ -147,34 +189,44 @@ code in plugin form. The plugin would have to be
installed already, but nevertheless the flag is a
reminder.
## Writing plugins
### Exec plugins
[chartinflator]: ../plugin/someteam.example.com/v1/chartinflator/ChartInflator
See this example [helm chart inflator][chartInflator].
A exec plugin is any executable that accepts a
A _exec plugin_ is any executable that accepts a
single argument on its command line - the name of
a YAML file containing its configuration.
a YAML file containing its configuration (the file name
provided in the kustomization file).
> TODO: more restrictions on plugin to allow the same exec
> plugin to be specified in a config under both the
> `generators` and `transformers` fields.
> - first arg could be the fixed string
> `generate` or `transform`,
> (the name of the configuration file moves to
> (the name of the configuration file moves to
> the 2nd arg), or
> - by default an exec plugin behaves as a tranformer
> unless a flag `-g` is provided, switching the
> exec plugin to behave as a generator.
[helm chart inflator]: ../plugin/someteam.example.com/v1/chartinflator
[bashed config map]: ../plugin/someteam.example.com/v1/bashedconfigmap
[sed transformer]: ../plugin/someteam.example.com/v1/sedtransformer
#### Examples
* [helm chart inflator] - A generator that inflates a helm chart.
* [bashed config map] - Super simple configMap generation from bash.
* [sed transformer] - Define your unstructured edits using a
plugin like this one.
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
and emits those resources, presumably transformed, to
`stdout`.
kustomize uses an exec plugin adapter to provide
@@ -184,9 +236,6 @@ marshalled resources on `stdin` and capture
### Go plugins
[Go plugin]: https://golang.org/pkg/plugin/
[servicegenerator]: ../plugin/someteam.example.com/v1/someservicegenerator/SomeServiceGenerator.go
See this example [service generator][serviceGenerator].
A [Go plugin] for kustomize looks like this:
@@ -213,60 +262,90 @@ A [Go plugin] for kustomize looks like this:
> 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_.
Use of the identifiers `plugin`, `KustomizePlugin`
and implementation of the method signature
`Config` is required.
The plugin author will change the
contents of the `plugin` struct, and the three
method bodies, and add imports as desired.
Implementing the `Generator` or `Transformer`
method allows (respectively) the plugin's config
file to be added to the `generators` or
`transformers` field in the kustomization file.
Do one or the other or both 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:
[secret generator]: ../plugin/someteam.example.com/v1/secretsfromdatabase
[service generator]: ../plugin/someteam.example.com/v1/someservicegenerator
[string prefixer]: ../plugin/someteam.example.com/v1/stringprefixer
[date prefixer]: ../plugin/someteam.example.com/v1/dateprefixer
#### Examples
* [secret generator] - Generate secrets from a database.
* [service generator] - Generate a service from a name and port argument.
* [string prefixer] - uses the value in `metadata/name` as the prefix.
This particular example exists to show how a plugin can
transform the behavior of a plugin. See the
`TestTransformedTransformers` test in the `target` package.
* [date prefixer] - prefix the current date to resource names, a simple
example used to modify the string prefixer plugin just mentioned.
* All the builtin plugins [here](../plugin/builtin).
User authored plugins are
on the same footing as builtin operations.
A plugin can be both a generator and a
transformer. The `Generate` method will run along
with all the other generators before the
`Transform` method runs.
Here's a build command that sensibly assumes the
plugin source code sits in the directory where
kustomize expects to find `.so` files:
```
d=$XDG_CONFIG_HOME/kustomize/plugin/${apiVersion}/LOWERCASE(${kind})
go build -buildmode plugin -o $d/${kind}.so $d/${kind}.go
d=$XDG_CONFIG_HOME/kustomize/plugin\
/${apiVersion}/LOWERCASE(${kind})
go build -buildmode plugin \
-o $d/${kind}.so $d/${kind}.go
```
#### 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 cost of firing up a
subprocess and marshalling/unmarshalling all
resource data for each plugin run.
Go plugins allow kustomize extensions that run
without the cost marshalling/unmarshalling all
resource data to/from a subprocess for each plugin
run.
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
Go plugins work as [defined][Go plugin], but fall
short of what many people think of when they hear
the word _plugin_. Go plugin compilation creates
an [ELF] formatted `.so` file, which by definition
has no information about the _provenance_ of the
file.
short of common notions associated with the word
_plugin_. Go plugin compilation creates an [ELF]
formatted `.so` file, which by definition has no
information about the provenance of the object
code. Skew between the compilation conditions
(versions of package dependencies, `GOOS`,
`GOARCH`) of the main program ELF and the plugin
ELF will cause plugin load failure.
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 won't
complain about compilation skew.
Exec plugins also lack provenance, but don't
suffer from the skew problem.
In either case, a sensible way to share a plugin
is as a tar file of source code, tests and
associated data, unpackable under
`$XDG_CONFIG_HOME/kustomize/plugin` (exactly where
one would develop a plugin).
In either case, at the time of writing the proper
way to share a plugin is as a tar file of source code
and associated data, developed and unpacked under
`kustomize/plugin`. In the case of a Go plugin, the
end user must compile it (described above), and may
need to compile kustomize as well. If people use
Go plugins, more tooling will be built to make
plugin sharing easier.
[Go modules]: https://github.com/golang/go/wiki/Modules
In the case of a Go plugin, an end user accepting
a shared plugin must compile both kustomize and
the plugin. Tooling could be built to make Go
_plugin sharing_ easier, but this requires some
critical mass of _plugin authoring_, which in turn
is hampered by confusion around sharing.
[Go modules], once they are more widely adopted,
will solve one of the biggest plugin sharing
difficulties - ambiguous plugin vs host
dependencies.