mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-14 10:30:59 +00:00
Merge pull request #1246 from monopole/pluginDocGetsOwnDir
Add another detailed plugin example.
This commit is contained in:
@@ -12,7 +12,7 @@ English | [简体中文](zh/README.md)
|
|||||||
* [Kustomize Fields](fields.md) - explanations of the fields
|
* [Kustomize Fields](fields.md) - explanations of the fields
|
||||||
in a [kustomization](glossary.md#kustomization) file.
|
in a [kustomization](glossary.md#kustomization) file.
|
||||||
|
|
||||||
* [Plugins](plugins.md) - extending kustomize with
|
* [Plugins](plugins) - extending kustomize with
|
||||||
custom generators and transformers.
|
custom generators and transformers.
|
||||||
|
|
||||||
* [Workflows](workflows.md) - steps one might take in
|
* [Workflows](workflows.md) - steps one might take in
|
||||||
@@ -23,6 +23,8 @@ English | [简体中文](zh/README.md)
|
|||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
|
||||||
|
* [3.0](v3.0.0.md) - Late June 2019. Plugin developer release.
|
||||||
|
|
||||||
* [2.1](v2.1.0.md) - 18 June 2019. Plugins, ordered resources, etc.
|
* [2.1](v2.1.0.md) - 18 June 2019. Plugins, ordered resources, etc.
|
||||||
|
|
||||||
* [2.0](v2.0.0.md) - Mar 2019.
|
* [2.0](v2.0.0.md) - Mar 2019.
|
||||||
|
|||||||
@@ -1,222 +0,0 @@
|
|||||||
# Exec plugin on linux in 30 seconds
|
|
||||||
|
|
||||||
Full plugin docs [here](plugins.md).
|
|
||||||
|
|
||||||
This demo writes and uses a somewhat ridiculous
|
|
||||||
_exec_ plugin (written in bash) that generates a
|
|
||||||
`ConfigMap`.
|
|
||||||
|
|
||||||
|
|
||||||
## Make a place to work
|
|
||||||
|
|
||||||
```
|
|
||||||
DEMO=$(mktemp -d)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Create a kustomization
|
|
||||||
|
|
||||||
Make a kustomization directory to
|
|
||||||
hold all your config:
|
|
||||||
|
|
||||||
```
|
|
||||||
MYAPP=$DEMO/myapp
|
|
||||||
mkdir -p $MYAPP
|
|
||||||
```
|
|
||||||
|
|
||||||
Make a deployment config:
|
|
||||||
|
|
||||||
```
|
|
||||||
cat <<'EOF' >$MYAPP/deployment.yaml
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: the-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: the-container
|
|
||||||
image: monopole/hello:1
|
|
||||||
command: ["/hello",
|
|
||||||
"--port=8080",
|
|
||||||
"--date=$(THE_DATE)",
|
|
||||||
"--enableRiskyFeature=$(ENABLE_RISKY)"]
|
|
||||||
ports:
|
|
||||||
- containerPort: 8080
|
|
||||||
env:
|
|
||||||
- name: THE_DATE
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: the-map
|
|
||||||
key: today
|
|
||||||
- name: ALT_GREETING
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: the-map
|
|
||||||
key: altGreeting
|
|
||||||
- name: ENABLE_RISKY
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: the-map
|
|
||||||
key: enableRisky
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
Make a service config:
|
|
||||||
|
|
||||||
```
|
|
||||||
cat <<EOF >$MYAPP/service.yaml
|
|
||||||
kind: Service
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: the-service
|
|
||||||
spec:
|
|
||||||
type: LoadBalancer
|
|
||||||
ports:
|
|
||||||
- protocol: TCP
|
|
||||||
port: 8666
|
|
||||||
targetPort: 8080
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
Now make a config file for the plugin
|
|
||||||
you're about to write.
|
|
||||||
|
|
||||||
This config file is just another k8s resource
|
|
||||||
object. The values of its `apiVersion` and `kind`
|
|
||||||
fields are used to _find_ the plugin code on your
|
|
||||||
filesystem (more on this later).
|
|
||||||
|
|
||||||
```
|
|
||||||
cat <<'EOF' >$MYAPP/cmGenerator.yaml
|
|
||||||
apiVersion: myDevOpsTeam
|
|
||||||
kind: SillyConfigMapGenerator
|
|
||||||
metadata:
|
|
||||||
name: whatever
|
|
||||||
argsOneLiner: Bienvenue true
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, make a kustomization file
|
|
||||||
referencing all of the above:
|
|
||||||
|
|
||||||
```
|
|
||||||
cat <<EOF >$MYAPP/kustomization.yaml
|
|
||||||
commonLabels:
|
|
||||||
app: hello
|
|
||||||
resources:
|
|
||||||
- deployment.yaml
|
|
||||||
- service.yaml
|
|
||||||
generators:
|
|
||||||
- cmGenerator.yaml
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
Review the files
|
|
||||||
```
|
|
||||||
ls -C1 $MYAPP
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Make a home for plugins
|
|
||||||
|
|
||||||
Plugins must live in a particular place for
|
|
||||||
kustomize to find them.
|
|
||||||
|
|
||||||
This demo will use the ephemeral directory:
|
|
||||||
|
|
||||||
```
|
|
||||||
PLUGIN_ROOT=$DEMO/kustomize/plugin
|
|
||||||
```
|
|
||||||
|
|
||||||
The plugin config defined above in
|
|
||||||
`$MYAPP/cmGenerator.yaml` specifies:
|
|
||||||
|
|
||||||
> ```
|
|
||||||
> apiVersion: myDevOpsTeam
|
|
||||||
> kind: SillyConfigMapGenerator
|
|
||||||
> ```
|
|
||||||
|
|
||||||
This means the plugin must live in a directory
|
|
||||||
named:
|
|
||||||
|
|
||||||
```
|
|
||||||
MY_PLUGIN_DIR=$PLUGIN_ROOT/myDevOpsTeam/sillyconfigmapgenerator
|
|
||||||
|
|
||||||
mkdir -p $MY_PLUGIN_DIR
|
|
||||||
```
|
|
||||||
|
|
||||||
The directory name is the plugin config's
|
|
||||||
_apiVersion_ followed by its lower-cased _kind_.
|
|
||||||
|
|
||||||
A plugin gets its own directory to hold itself,
|
|
||||||
its tests and any supplemental data files it
|
|
||||||
might need.
|
|
||||||
|
|
||||||
## Create the plugin
|
|
||||||
|
|
||||||
There are two kinds of plugins, _exec_ and _Go_.
|
|
||||||
|
|
||||||
Make an _exec_ plugin, installing it to the
|
|
||||||
correct directory and file name. The file name
|
|
||||||
must match the plugin's _kind_ (in this case,
|
|
||||||
`SillyConfigMapGenerator`):
|
|
||||||
|
|
||||||
```
|
|
||||||
cat <<'EOF' >$MY_PLUGIN_DIR/SillyConfigMapGenerator
|
|
||||||
#!/bin/bash
|
|
||||||
# Skip the config file name argument.
|
|
||||||
shift
|
|
||||||
today=`date +%F`
|
|
||||||
echo "
|
|
||||||
kind: ConfigMap
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: the-map
|
|
||||||
data:
|
|
||||||
today: $today
|
|
||||||
altGreeting: "$1"
|
|
||||||
enableRisky: "$2"
|
|
||||||
"
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
By definition, an _exec_ plugin must be executable:
|
|
||||||
|
|
||||||
```
|
|
||||||
chmod a+x $MY_PLUGIN_DIR/SillyConfigMapGenerator
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Download kustomize 2.1.0
|
|
||||||
|
|
||||||
```
|
|
||||||
mkdir -p $DEMO/bin
|
|
||||||
gh=https://github.com/kubernetes-sigs/kustomize/releases/download
|
|
||||||
url=$gh/v2.1.0/kustomize_2.1.0_linux_amd64
|
|
||||||
curl -o $DEMO/bin/kustomize -L $url
|
|
||||||
chmod u+x $DEMO/bin/kustomize
|
|
||||||
```
|
|
||||||
|
|
||||||
## Review the layout
|
|
||||||
|
|
||||||
```
|
|
||||||
tree $DEMO
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build your app, using the plugin:
|
|
||||||
|
|
||||||
```
|
|
||||||
XDG_CONFIG_HOME=$DEMO $DEMO/bin/kustomize build --enable_alpha_plugins $MYAPP
|
|
||||||
```
|
|
||||||
|
|
||||||
Above, if you had set
|
|
||||||
|
|
||||||
> ```
|
|
||||||
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
|
|
||||||
> ```
|
|
||||||
|
|
||||||
there would be no need to use `XDG_CONFIG_HOME` in the
|
|
||||||
_kustomize_ command above.
|
|
||||||
|
|
||||||
1
docs/execPluginIn30sec.md
Symbolic link
1
docs/execPluginIn30sec.md
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
plugins/execPluginGuidedExample.md
|
||||||
@@ -21,7 +21,7 @@ What things should be created (and optionally subsequently customized)?
|
|||||||
|[configMapGenerator](#configmapgenerator)| list |Each entry in this list results in the creation of one ConfigMap resource (it's a generator of n maps).|
|
|[configMapGenerator](#configmapgenerator)| list |Each entry in this list results in the creation of one ConfigMap resource (it's a generator of n maps).|
|
||||||
|[secretGenerator](#secretgenerator)| list |Each entry in this list results in the creation of one Secret resource (it's a generator of n secrets)|
|
|[secretGenerator](#secretgenerator)| list |Each entry in this list results in the creation of one Secret resource (it's a generator of n secrets)|
|
||||||
|[generatorOptions](#generatoroptions)|string|generatorOptions modify behavior of all ConfigMap and Secret generators|
|
|[generatorOptions](#generatoroptions)|string|generatorOptions modify behavior of all ConfigMap and Secret generators|
|
||||||
|[generators](#generators)|list|[plugin](plugins.md) configuration files|
|
|[generators](#generators)|list|[plugin](plugins) configuration files|
|
||||||
|
|
||||||
|
|
||||||
## Transformers
|
## Transformers
|
||||||
@@ -40,7 +40,7 @@ What transformations (customizations) should be applied?
|
|||||||
| [replicas](#replicas) | list | Replicas modifies the number of replicas of a resource. |
|
| [replicas](#replicas) | list | Replicas modifies the number of replicas of a resource. |
|
||||||
|[patchesStrategicMerge](#patchesstrategicmerge)| list |Each entry in this list should resolve to a partial or complete resource definition file.|
|
|[patchesStrategicMerge](#patchesstrategicmerge)| list |Each entry in this list should resolve to a partial or complete resource definition file.|
|
||||||
|[patchesJson6902](#patchesjson6902)| list |Each entry in this list should resolve to a kubernetes object and a JSON patch that will be applied to the object.|
|
|[patchesJson6902](#patchesjson6902)| list |Each entry in this list should resolve to a kubernetes object and a JSON patch that will be applied to the object.|
|
||||||
|[transformers](#transformers)|list|[plugin](plugins.md) configuration files|
|
|[transformers](#transformers)|list|[plugin](plugins) configuration files|
|
||||||
|
|
||||||
|
|
||||||
## Meta
|
## Meta
|
||||||
@@ -173,7 +173,7 @@ generatorOptions:
|
|||||||
|
|
||||||
### generators
|
### generators
|
||||||
|
|
||||||
A list of generator [plugin](plugins.md) configuration files.
|
A list of generator [plugin](plugins) configuration files.
|
||||||
|
|
||||||
```
|
```
|
||||||
generators:
|
generators:
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ A chunk of code used by kustomize, but not necessarily
|
|||||||
compiled into kustomize, to generate and/or transform a
|
compiled into kustomize, to generate and/or transform a
|
||||||
kubernetes resource as part of a kustomization.
|
kubernetes resource as part of a kustomization.
|
||||||
|
|
||||||
Details [here](plugins.md).
|
Details [here](plugins).
|
||||||
|
|
||||||
## resource
|
## resource
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
# kustomize plugins
|
# kustomize plugins
|
||||||
|
|
||||||
See also: [linux exec plugin in 30 sec](execPluginIn30sec.md)
|
Quick guides:
|
||||||
|
|
||||||
|
* [linux exec plugin in 60 sec](execPluginGuidedExample.md)
|
||||||
|
* [linux Go plugin in 60 sec](goPluginGuidedExample.md)
|
||||||
|
|
||||||
Kustomize offers a plugin framework allowing
|
Kustomize offers a plugin framework allowing
|
||||||
people to write their own resource _generators_
|
people to write their own resource _generators_
|
||||||
and _transformers_.
|
and _transformers_.
|
||||||
|
|
||||||
[generator options]: ../examples/generatorOptions.md
|
[generator options]: ../../examples/generatorOptions.md
|
||||||
[transformer configs]: ../examples/transformerconfigs
|
[transformer configs]: ../../examples/transformerconfigs
|
||||||
|
|
||||||
Write a plugin when changing [generator options]
|
Write a plugin when changing [generator options]
|
||||||
or [transformer configs] doesn't meet your needs.
|
or [transformer configs] doesn't meet your needs.
|
||||||
@@ -53,7 +56,7 @@ The value of each entry in a `resources`,
|
|||||||
relative path to a YAML file, or a path or URL
|
relative path to a YAML file, or a path or URL
|
||||||
to a [kustomization].
|
to a [kustomization].
|
||||||
|
|
||||||
[kustomization]: glossary.md#kustomization
|
[kustomization]: ../glossary.md#kustomization
|
||||||
|
|
||||||
In the former case the YAML is read from disk directly,
|
In the former case the YAML is read from disk directly,
|
||||||
and in the latter case a kustomization is performed,
|
and in the latter case a kustomization is performed,
|
||||||
@@ -76,7 +79,7 @@ generators:
|
|||||||
|
|
||||||
Given this, the kustomization process would expect to
|
Given this, the kustomization process would expect to
|
||||||
find a file called `chartInflator.yaml` in the
|
find a file called `chartInflator.yaml` in the
|
||||||
kustomization [root](glossary.md#kustomization-root).
|
kustomization [root](../glossary.md#kustomization-root).
|
||||||
|
|
||||||
This is the _plugin's configuration file_.
|
This is the _plugin's configuration file_.
|
||||||
|
|
||||||
@@ -93,7 +96,7 @@ chartName: minecraft
|
|||||||
__The `apiVersion` and `kind` fields are
|
__The `apiVersion` and `kind` fields are
|
||||||
used to locate the plugin.__
|
used to locate the plugin.__
|
||||||
|
|
||||||
[k8s object]: glossary.md#kubernetes-style-object
|
[k8s object]: ../glossary.md#kubernetes-style-object
|
||||||
|
|
||||||
> Thus, these fields are required. They are also
|
> Thus, these fields are required. They are also
|
||||||
> required because a kustomize plugin
|
> required because a kustomize plugin
|
||||||
@@ -103,9 +106,9 @@ To get the plugin ready to generator or transform,
|
|||||||
it is given the entire contents of the
|
it is given the entire contents of the
|
||||||
configuration file.
|
configuration file.
|
||||||
|
|
||||||
[NameTransformer]: ../plugin/builtin/prefixsuffixtransformer/PrefixSuffixTransformer_test.go
|
[NameTransformer]: ../../plugin/builtin/prefixsuffixtransformer/PrefixSuffixTransformer_test.go
|
||||||
[ChartInflator]: ../plugin/someteam.example.com/v1/chartinflator/ChartInflator_test.go
|
[ChartInflator]: ../../plugin/someteam.example.com/v1/chartinflator/ChartInflator_test.go
|
||||||
[plugins]: ../plugin/builtin
|
[plugins]: ../../plugin/builtin
|
||||||
|
|
||||||
For more examples of plugin configuration YAML,
|
For more examples of plugin configuration YAML,
|
||||||
browse the unit tests below the [plugins] root,
|
browse the unit tests below the [plugins] root,
|
||||||
@@ -209,9 +212,9 @@ provided in the kustomization file).
|
|||||||
> unless a flag `-g` is provided, switching the
|
> unless a flag `-g` is provided, switching the
|
||||||
> exec plugin to behave as a generator.
|
> exec plugin to behave as a generator.
|
||||||
|
|
||||||
[helm chart inflator]: ../plugin/someteam.example.com/v1/chartinflator
|
[helm chart inflator]: ../../plugin/someteam.example.com/v1/chartinflator
|
||||||
[bashed config map]: ../plugin/someteam.example.com/v1/bashedconfigmap
|
[bashed config map]: ../../plugin/someteam.example.com/v1/bashedconfigmap
|
||||||
[sed transformer]: ../plugin/someteam.example.com/v1/sedtransformer
|
[sed transformer]: ../../plugin/someteam.example.com/v1/sedtransformer
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
|
|
||||||
@@ -271,10 +274,10 @@ file to be added to the `generators` or
|
|||||||
`transformers` field in the kustomization file.
|
`transformers` field in the kustomization file.
|
||||||
Do one or the other or both as desired.
|
Do one or the other or both as desired.
|
||||||
|
|
||||||
[secret generator]: ../plugin/someteam.example.com/v1/secretsfromdatabase
|
[secret generator]: ../../plugin/someteam.example.com/v1/secretsfromdatabase
|
||||||
[service generator]: ../plugin/someteam.example.com/v1/someservicegenerator
|
[service generator]: ../../plugin/someteam.example.com/v1/someservicegenerator
|
||||||
[string prefixer]: ../plugin/someteam.example.com/v1/stringprefixer
|
[string prefixer]: ../../plugin/someteam.example.com/v1/stringprefixer
|
||||||
[date prefixer]: ../plugin/someteam.example.com/v1/dateprefixer
|
[date prefixer]: ../../plugin/someteam.example.com/v1/dateprefixer
|
||||||
|
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
@@ -287,7 +290,7 @@ Do one or the other or both as desired.
|
|||||||
`TestTransformedTransformers` test in the `target` package.
|
`TestTransformedTransformers` test in the `target` package.
|
||||||
* [date prefixer] - prefix the current date to resource names, a simple
|
* [date prefixer] - prefix the current date to resource names, a simple
|
||||||
example used to modify the string prefixer plugin just mentioned.
|
example used to modify the string prefixer plugin just mentioned.
|
||||||
* All the builtin plugins [here](../plugin/builtin).
|
* All the builtin plugins [here](../../plugin/builtin).
|
||||||
User authored plugins are
|
User authored plugins are
|
||||||
on the same footing as builtin operations.
|
on the same footing as builtin operations.
|
||||||
|
|
||||||
229
docs/plugins/execPluginGuidedExample.md
Normal file
229
docs/plugins/execPluginGuidedExample.md
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
# Exec plugin on linux in 60 seconds
|
||||||
|
|
||||||
|
This is a (no reading) 60 second copy/paste guided
|
||||||
|
example. Full plugin docs [here](README.md).
|
||||||
|
|
||||||
|
This demo writes and uses a somewhat ridiculous
|
||||||
|
_exec_ plugin (written in bash) that generates a
|
||||||
|
`ConfigMap`.
|
||||||
|
|
||||||
|
This is a guide to try it without damaging your
|
||||||
|
current setup.
|
||||||
|
|
||||||
|
#### requirements
|
||||||
|
|
||||||
|
* linux, git, curl, Go 1.12
|
||||||
|
|
||||||
|
|
||||||
|
## Make a place to work
|
||||||
|
|
||||||
|
```
|
||||||
|
DEMO=$(mktemp -d)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create a kustomization
|
||||||
|
|
||||||
|
Make a kustomization directory to
|
||||||
|
hold all your config:
|
||||||
|
|
||||||
|
```
|
||||||
|
MYAPP=$DEMO/myapp
|
||||||
|
mkdir -p $MYAPP
|
||||||
|
```
|
||||||
|
|
||||||
|
Make a deployment config:
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<'EOF' >$MYAPP/deployment.yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: the-deployment
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: the-container
|
||||||
|
image: monopole/hello:1
|
||||||
|
command: ["/hello",
|
||||||
|
"--port=8080",
|
||||||
|
"--date=$(THE_DATE)",
|
||||||
|
"--enableRiskyFeature=$(ENABLE_RISKY)"]
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
env:
|
||||||
|
- name: THE_DATE
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: the-map
|
||||||
|
key: today
|
||||||
|
- name: ALT_GREETING
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: the-map
|
||||||
|
key: altGreeting
|
||||||
|
- name: ENABLE_RISKY
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: the-map
|
||||||
|
key: enableRisky
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Make a service config:
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<EOF >$MYAPP/service.yaml
|
||||||
|
kind: Service
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: the-service
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8666
|
||||||
|
targetPort: 8080
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Now make a config file for the plugin
|
||||||
|
you're about to write.
|
||||||
|
|
||||||
|
This config file is just another k8s resource
|
||||||
|
object. The values of its `apiVersion` and `kind`
|
||||||
|
fields are used to _find_ the plugin code on your
|
||||||
|
filesystem (more on this later).
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<'EOF' >$MYAPP/cmGenerator.yaml
|
||||||
|
apiVersion: myDevOpsTeam
|
||||||
|
kind: SillyConfigMapGenerator
|
||||||
|
metadata:
|
||||||
|
name: whatever
|
||||||
|
argsOneLiner: Bienvenue true
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, make a kustomization file
|
||||||
|
referencing all of the above:
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<EOF >$MYAPP/kustomization.yaml
|
||||||
|
commonLabels:
|
||||||
|
app: hello
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
generators:
|
||||||
|
- cmGenerator.yaml
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Review the files
|
||||||
|
```
|
||||||
|
ls -C1 $MYAPP
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Make a home for plugins
|
||||||
|
|
||||||
|
Plugins must live in a particular place for
|
||||||
|
kustomize to find them.
|
||||||
|
|
||||||
|
This demo will use the ephemeral directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
PLUGIN_ROOT=$DEMO/kustomize/plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
The plugin config defined above in
|
||||||
|
`$MYAPP/cmGenerator.yaml` specifies:
|
||||||
|
|
||||||
|
> ```
|
||||||
|
> apiVersion: myDevOpsTeam
|
||||||
|
> kind: SillyConfigMapGenerator
|
||||||
|
> ```
|
||||||
|
|
||||||
|
This means the plugin must live in a directory
|
||||||
|
named:
|
||||||
|
|
||||||
|
```
|
||||||
|
MY_PLUGIN_DIR=$PLUGIN_ROOT/myDevOpsTeam/sillyconfigmapgenerator
|
||||||
|
|
||||||
|
mkdir -p $MY_PLUGIN_DIR
|
||||||
|
```
|
||||||
|
|
||||||
|
The directory name is the plugin config's
|
||||||
|
_apiVersion_ followed by its lower-cased _kind_.
|
||||||
|
|
||||||
|
A plugin gets its own directory to hold itself,
|
||||||
|
its tests and any supplemental data files it
|
||||||
|
might need.
|
||||||
|
|
||||||
|
## Create the plugin
|
||||||
|
|
||||||
|
There are two kinds of plugins, _exec_ and _Go_.
|
||||||
|
|
||||||
|
Make an _exec_ plugin, installing it to the
|
||||||
|
correct directory and file name. The file name
|
||||||
|
must match the plugin's _kind_ (in this case,
|
||||||
|
`SillyConfigMapGenerator`):
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<'EOF' >$MY_PLUGIN_DIR/SillyConfigMapGenerator
|
||||||
|
#!/bin/bash
|
||||||
|
# Skip the config file name argument.
|
||||||
|
shift
|
||||||
|
today=`date +%F`
|
||||||
|
echo "
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: the-map
|
||||||
|
data:
|
||||||
|
today: $today
|
||||||
|
altGreeting: "$1"
|
||||||
|
enableRisky: "$2"
|
||||||
|
"
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
By definition, an _exec_ plugin must be executable:
|
||||||
|
|
||||||
|
```
|
||||||
|
chmod a+x $MY_PLUGIN_DIR/SillyConfigMapGenerator
|
||||||
|
```
|
||||||
|
|
||||||
|
## Download kustomize 3.0.0
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir -p $DEMO/bin
|
||||||
|
gh=https://github.com/kubernetes-sigs/kustomize/releases/download
|
||||||
|
url=$gh/v3.0.0-pre/kustomize_3.0.0-pre_linux_amd64
|
||||||
|
curl -o $DEMO/bin/kustomize -L $url
|
||||||
|
chmod u+x $DEMO/bin/kustomize
|
||||||
|
```
|
||||||
|
|
||||||
|
## Review the layout
|
||||||
|
|
||||||
|
```
|
||||||
|
tree $DEMO
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build your app, using the plugin:
|
||||||
|
|
||||||
|
```
|
||||||
|
XDG_CONFIG_HOME=$DEMO $DEMO/bin/kustomize build --enable_alpha_plugins $MYAPP
|
||||||
|
```
|
||||||
|
|
||||||
|
Above, if you had set
|
||||||
|
|
||||||
|
> ```
|
||||||
|
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
|
||||||
|
> ```
|
||||||
|
|
||||||
|
there would be no need to use `XDG_CONFIG_HOME` in the
|
||||||
|
_kustomize_ command above.
|
||||||
|
|
||||||
308
docs/plugins/goPluginGuidedExample.md
Normal file
308
docs/plugins/goPluginGuidedExample.md
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
# Go Plugin Guided Example for Linux
|
||||||
|
|
||||||
|
This is a (no reading) 60 second copy/paste guided
|
||||||
|
example. Full plugin docs [here](README.md).
|
||||||
|
|
||||||
|
[SopsEncodedSecrets repository]: https://github.com/monopole/sopsencodedsecrets
|
||||||
|
[Go plugin]: https://golang.org/pkg/plugin
|
||||||
|
|
||||||
|
This demo uses a Go plugin, `SopsEncodedSecrets`,
|
||||||
|
that lives in the [sopsencodedsecrets repository].
|
||||||
|
This is an inprocess [Go plugin], not an
|
||||||
|
sub-process exec plugin that happens to be written
|
||||||
|
in Go (which is another option for Go authors).
|
||||||
|
|
||||||
|
This is a guide to try it without damaging your
|
||||||
|
current setup.
|
||||||
|
|
||||||
|
#### requirements
|
||||||
|
|
||||||
|
* linux, git, curl, Go 1.12
|
||||||
|
* Google cloud (gcloud) install
|
||||||
|
* a Google account (will use Google kms -
|
||||||
|
volunteers needed to convert to a GPG example).
|
||||||
|
|
||||||
|
## Make a place to work
|
||||||
|
|
||||||
|
```
|
||||||
|
DEMO=$(mktemp -d)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Install kustomize
|
||||||
|
|
||||||
|
Need v3.0.0 for what follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
GOBIN=$DEMO/bin go get sigs.k8s.io/kustomize/v3/cmd/kustomize@v3.0.0-pre
|
||||||
|
```
|
||||||
|
|
||||||
|
## Make a home for plugins
|
||||||
|
|
||||||
|
A kustomize plugin is fully determined by
|
||||||
|
its configuration file and source code.
|
||||||
|
|
||||||
|
[required fields]: https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields
|
||||||
|
|
||||||
|
Kustomize plugin configuration files are formatted
|
||||||
|
as kubernetes resource objects, meaning
|
||||||
|
`apiVersion`, `kind` and `metadata` are [required
|
||||||
|
fields] in these config files.
|
||||||
|
|
||||||
|
The kustomize program reads the config file
|
||||||
|
(because the config file name appears in the
|
||||||
|
`generators` or `transformers` field in the
|
||||||
|
kustomization file), then locates the Go plugin's
|
||||||
|
object code at the following location:
|
||||||
|
|
||||||
|
> ```
|
||||||
|
> $XGD_CONFIG_HOME/kustomize/plugin/$apiVersion/$lKind/$kind.so
|
||||||
|
> ```
|
||||||
|
|
||||||
|
where `lKind` holds the lowercased kind. The
|
||||||
|
plugin is then loaded and fed its config, and the
|
||||||
|
plugin's output becomes part of the overall
|
||||||
|
`kustomize build` process.
|
||||||
|
|
||||||
|
The same plugin might be used multiple times in
|
||||||
|
one kustomize build, but with different config
|
||||||
|
files. Also, kustomize might customize config
|
||||||
|
data before sending it to the plugin, for whatever
|
||||||
|
reason. For these reasons, kustomize owns the
|
||||||
|
mapping between plugins and config data; it's not
|
||||||
|
left to plugins to find their own config.
|
||||||
|
|
||||||
|
This demo will house the plugin it uses at the
|
||||||
|
ephemeral directory
|
||||||
|
|
||||||
|
```
|
||||||
|
PLUGIN_ROOT=$DEMO/kustomize/plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
and ephemerally set `XGD_CONFIG_HOME` on a command
|
||||||
|
line below.
|
||||||
|
|
||||||
|
### What apiVersion and kind?
|
||||||
|
|
||||||
|
At this stage in the development of kustomize
|
||||||
|
plugins, plugin code doesn't know or care what
|
||||||
|
`apiVersion` or `kind` appears in the config file
|
||||||
|
sent to it.
|
||||||
|
|
||||||
|
The plugin could check these fields, but it's the
|
||||||
|
remaining fields that provide actual configuration
|
||||||
|
data, and at this point the successful parsing of
|
||||||
|
these other fields are the only thing that matters
|
||||||
|
to a plugin.
|
||||||
|
|
||||||
|
This demo uses a plugin called _SopsEncodedSecrets_,
|
||||||
|
and it lives in the [SopsEncodedSecrets repository].
|
||||||
|
|
||||||
|
Somewhat arbitrarily, we'll chose to install
|
||||||
|
this plugin with
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion=mygenerators
|
||||||
|
kind=SopsEncodedSecrets
|
||||||
|
```
|
||||||
|
|
||||||
|
### Define the plugin's home dir
|
||||||
|
|
||||||
|
By convention, the ultimate home of the plugin
|
||||||
|
code and supplemental data, tests, documentation,
|
||||||
|
etc. is the lowercase form of its kind.
|
||||||
|
|
||||||
|
```
|
||||||
|
lKind=$(echo $kind | awk '{print tolower($0)}')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Download the SopsEncodedSecrets plugin
|
||||||
|
|
||||||
|
In this case, the repo name matches the lowercase
|
||||||
|
kind already, so we just clone the repo and get
|
||||||
|
the proper directory name automatically:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir -p $PLUGIN_ROOT/${apiVersion}
|
||||||
|
cd $PLUGIN_ROOT/${apiVersion}
|
||||||
|
git clone git@github.com:monopole/sopsencodedsecrets.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Remember this directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
MY_PLUGIN_DIR=$PLUGIN_ROOT/${apiVersion}/${lKind}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Try the plugin's own test
|
||||||
|
|
||||||
|
Plugins may come with their own tests.
|
||||||
|
This one does, and it hopefully passes:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd $MY_PLUGIN_DIR
|
||||||
|
go test SopsEncodedSecrets_test.go
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the object code for use by kustomize:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd $MY_PLUGIN_DIR
|
||||||
|
go build -buildmode plugin -o ${kind}.so ${kind}.go
|
||||||
|
```
|
||||||
|
|
||||||
|
This step may succeed, but kustomize might
|
||||||
|
ultimately fail to load the plugin because of
|
||||||
|
dependency [skew].
|
||||||
|
|
||||||
|
[skew]: https://github.com/kubernetes-sigs/kustomize/blob/master/docs/plugins.md#caveats
|
||||||
|
[used in this demo]: #install-kustomize
|
||||||
|
|
||||||
|
On load failure
|
||||||
|
|
||||||
|
* be sure to build the plugin with the same
|
||||||
|
version of Go (`go1.12`) on the same `$GOOS`
|
||||||
|
(`linux`) and `$GOARCH` (`amd64`) used to build
|
||||||
|
the kustomize being [used in this demo].
|
||||||
|
|
||||||
|
* change the plugin's dependencies in `go.mod` to
|
||||||
|
match those used to build kustomize (check the
|
||||||
|
`go.mod` used in the tagged commit).
|
||||||
|
|
||||||
|
Lacking tools and metadata to allow this to be
|
||||||
|
automated, there won't be a Go plugin ecosystem.
|
||||||
|
|
||||||
|
Kustomize has adopted a Go plugin architecture as
|
||||||
|
to ease accept new generators and transformers
|
||||||
|
(just write a plugin), and to be sure that native
|
||||||
|
operations (also constructed and tested as
|
||||||
|
plugins) are compartmentalized, orderable and
|
||||||
|
reusable instead of bizarrely woven throughout the
|
||||||
|
code as a individual special cases.
|
||||||
|
|
||||||
|
## Create a kustomization
|
||||||
|
|
||||||
|
Make a kustomization directory to
|
||||||
|
hold all your config:
|
||||||
|
|
||||||
|
```
|
||||||
|
MYAPP=$DEMO/myapp
|
||||||
|
mkdir -p $MYAPP
|
||||||
|
```
|
||||||
|
|
||||||
|
Make a config file for the SopsEncodedSecrets plugin.
|
||||||
|
|
||||||
|
Its `apiVersion` and `kind` allow the plugin to be
|
||||||
|
found:
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<EOF >$MYAPP/secGenerator.yaml
|
||||||
|
apiVersion: ${apiVersion}
|
||||||
|
kind: ${kind}
|
||||||
|
metadata:
|
||||||
|
name: forbiddenValues
|
||||||
|
namespace: production
|
||||||
|
file: myEncryptedData.yaml
|
||||||
|
keys:
|
||||||
|
- ROCKET
|
||||||
|
- CAR
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
This plugin expects to find more data in
|
||||||
|
`myEncryptedData.yaml`; we'll get to that shortly.
|
||||||
|
|
||||||
|
Make a kustomization file referencing the plugin
|
||||||
|
config:
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<EOF >$MYAPP/kustomization.yaml
|
||||||
|
commonLabels:
|
||||||
|
app: hello
|
||||||
|
generators:
|
||||||
|
- secGenerator.yaml
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Now for the hard part. Generate the real encrypted data.
|
||||||
|
|
||||||
|
|
||||||
|
### Assure you have a Google Cloud sops key ring.
|
||||||
|
|
||||||
|
We're going to use [sops](https://github.com/mozilla/sops) to encode a file.
|
||||||
|
|
||||||
|
Try this:
|
||||||
|
|
||||||
|
```
|
||||||
|
gcloud kms keys list --location global --keyring sops
|
||||||
|
```
|
||||||
|
|
||||||
|
If it succeeds, presumably you've already
|
||||||
|
created keys and placed them in a keyring called `sops`.
|
||||||
|
If not, do this:
|
||||||
|
|
||||||
|
```
|
||||||
|
gcloud kms keyrings create sops --location global
|
||||||
|
gcloud kms keys create sops-key --location global \
|
||||||
|
--keyring sops --purpose encryption
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract your keyLocation for use below:
|
||||||
|
```
|
||||||
|
keyLocation=$(\
|
||||||
|
gcloud kms keys list --location global --keyring sops |\
|
||||||
|
grep GOOGLE | cut -d " " -f1)
|
||||||
|
echo $keyLocation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install `sops`
|
||||||
|
|
||||||
|
```
|
||||||
|
GOBIN=$DEMO/bin go install go.mozilla.org/sops/cmd/sops
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create data encrypted with your Google Cloud key
|
||||||
|
|
||||||
|
Create raw data to encrypt:
|
||||||
|
```
|
||||||
|
cat <<EOF >$MYAPP/myClearData.yaml
|
||||||
|
VEGETABLE: carrot
|
||||||
|
ROCKET: saturn-v
|
||||||
|
FRUIT: apple
|
||||||
|
CAR: dymaxion
|
||||||
|
EOF
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Encrypt the data into file the plugin wants to read:
|
||||||
|
|
||||||
|
```
|
||||||
|
$DEMO/bin/sops --encrypt \
|
||||||
|
--gcp-kms $keyLocation \
|
||||||
|
$MYAPP/myClearData.yaml >$MYAPP/myEncryptedData.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Review the files
|
||||||
|
```
|
||||||
|
tree $DEMO
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Build your app, using the plugin:
|
||||||
|
|
||||||
|
```
|
||||||
|
XDG_CONFIG_HOME=$DEMO $DEMO/bin/kustomize build --enable_alpha_plugins $MYAPP
|
||||||
|
```
|
||||||
|
|
||||||
|
This should emit a kubernetes secret, with
|
||||||
|
encrypted data for the names `ROCKET` and `CAR`.
|
||||||
|
|
||||||
|
Above, if you had set
|
||||||
|
|
||||||
|
> ```
|
||||||
|
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
|
||||||
|
> ```
|
||||||
|
|
||||||
|
there would be no need to use `XDG_CONFIG_HOME` in the
|
||||||
|
_kustomize_ command above.
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
[bases]: glossary.md#base
|
[bases]: glossary.md#base
|
||||||
[_base_]: glossary.md#base
|
[_base_]: glossary.md#base
|
||||||
[kustomize inventory object documentation]: inventory_object.md
|
[kustomize inventory object documentation]: inventory_object.md
|
||||||
[kustomize plugin documentation]: plugins.md
|
[kustomize plugin documentation]: plugins
|
||||||
[root]: glossary.md#kustomization-root
|
[root]: glossary.md#kustomization-root
|
||||||
[transformer configs]: ../examples/transformerconfigs
|
[transformer configs]: ../examples/transformerconfigs
|
||||||
[v1.0.9]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v1.0.9
|
[v1.0.9]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v1.0.9
|
||||||
|
|||||||
51
docs/v3.0.0.md
Normal file
51
docs/v3.0.0.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# kustomize 3.0.0
|
||||||
|
|
||||||
|
This release is [v2.1.0](v2.1.0.md), with some
|
||||||
|
post v2.1.0 bugs fixed and a `v3` in Go package
|
||||||
|
paths.
|
||||||
|
|
||||||
|
The `v3` puts plugin developers (both _Go_ plugin
|
||||||
|
authors and _exec_ plugin authors who happen to
|
||||||
|
use Go) on a solid footing.
|
||||||
|
|
||||||
|
|
||||||
|
### Go Module implications
|
||||||
|
|
||||||
|
[doc]: https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher
|
||||||
|
|
||||||
|
Per the Go modules [doc], a release that's already
|
||||||
|
tagged v2 or higher should increment the major
|
||||||
|
version when performing their first Go
|
||||||
|
module-based release.
|
||||||
|
|
||||||
|
This advice applies to kustomize, since it was
|
||||||
|
already at major version 2 when switching to Go
|
||||||
|
modules.
|
||||||
|
|
||||||
|
[versioning policy]: versioningPolicy.md
|
||||||
|
|
||||||
|
The other reason for `v3` is that the `go` tool
|
||||||
|
assumes Go modules obey semantic versioning, which
|
||||||
|
means packages used in v2.1 should have the same
|
||||||
|
API as packages in v2.0.
|
||||||
|
|
||||||
|
This is not the case in kustomize. Historically,
|
||||||
|
kustomize's [versioning policy] has only addressed
|
||||||
|
the command line tool's behavior and the fields in
|
||||||
|
a kustomization file. The underlying packages
|
||||||
|
were an implementation detail, avaiable for use at
|
||||||
|
the author's risk.
|
||||||
|
|
||||||
|
With the introduction of plugins, the packages -
|
||||||
|
in particular `loader` and `resmap` - become part
|
||||||
|
of an API formally exposed to plugin authors, so
|
||||||
|
the API changes must be respected.
|
||||||
|
|
||||||
|
Over time, _informed by package use_, the API
|
||||||
|
surface should shrink, but such shrinkage will
|
||||||
|
require a major version increment.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
* [kustomization.yaml](kustomization.yaml) - 包含
|
* [kustomization.yaml](kustomization.yaml) - 包含
|
||||||
[kustomization](../glossary.md#kustomization) 所有字段的示例文件。
|
[kustomization](../glossary.md#kustomization) 所有字段的示例文件。
|
||||||
|
|
||||||
* [插件](../plugins.md) - 使用自定义的资源生成器和资源转换器来拓展 kustomize 功能。
|
* [插件](../plugins) - 使用自定义的资源生成器和资源转换器来拓展 kustomize 功能。
|
||||||
|
|
||||||
* [工作流](workflows.md) - 使用定制及使用现成配置使用的一些步骤。
|
* [工作流](workflows.md) - 使用定制及使用现成配置使用的一些步骤。
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
[stable chart]: https://github.com/helm/charts/tree/master/stable
|
[stable chart]: https://github.com/helm/charts/tree/master/stable
|
||||||
[Helm charts]: https://github.com/helm/charts
|
[Helm charts]: https://github.com/helm/charts
|
||||||
[_minecraft_]: https://github.com/helm/charts/tree/master/stable/minecraft
|
[_minecraft_]: https://github.com/helm/charts/tree/master/stable/minecraft
|
||||||
[plugin]: ../docs/plugins.md
|
[plugin]: ../docs/plugins
|
||||||
|
|
||||||
[Helm charts] aren't natively read by kustomize, but
|
[Helm charts] aren't natively read by kustomize, but
|
||||||
kustomize has a [plugin] system that allows one to
|
kustomize has a [plugin] system that allows one to
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ them, etc.
|
|||||||
## Secret values from anywhere
|
## Secret values from anywhere
|
||||||
|
|
||||||
A general alternative is to enshrine secret
|
A general alternative is to enshrine secret
|
||||||
value generation in a [plugin](../docs/plugins.md).
|
value generation in a [plugin](../docs/plugins).
|
||||||
|
|
||||||
The values can then come in via, say, an
|
The values can then come in via, say, an
|
||||||
authenticated and authorized RPC to a password
|
authenticated and authorized RPC to a password
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[base]: ../../docs/glossary.md#base
|
[base]: ../../docs/glossary.md#base
|
||||||
[kubeval]: https://github.com/instrumenta/kubeval
|
[kubeval]: https://github.com/instrumenta/kubeval
|
||||||
[plugin]: ../../docs/plugins.md
|
[plugin]: ../../docs/plugins
|
||||||
|
|
||||||
kustomize doesn't validate either its input or
|
kustomize doesn't validate either its input or
|
||||||
output beyond the validation provided by the
|
output beyond the validation provided by the
|
||||||
|
|||||||
Reference in New Issue
Block a user