1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
# a transformer plugin performing validation
[base]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#base
[kubeval]: https://github.com/instrumenta/kubeval
[plugin]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin
kustomize doesn't validate either its input or
output beyond the validation provided by the
marshalling/unmarshalling packages it depends on.
Another tool, [kubeval], goes beyond this to do
k8s aware validation. Here's a usage example:
```shell
$ kubeval my-invalid-rc.yaml
The document my-invalid-rc.yaml contains an invalid ReplicationController
--> spec.replicas: Invalid type. Expected: integer, given: string
```
One can write a Kustomize transformer [plugin] to
run [kubeval] against the resources that have been
loaded by Kustomize.
Make a place to work:
<!-- @makeWorkplace @kubevalTest -->
```
DEMO_HOME=$(mktemp -d)
mkdir -p $DEMO_HOME/valid
mkdir -p $DEMO_HOME/invalid
PLUGINDIR=$DEMO_HOME/kustomize/plugin/someteam.example.com/v1/validator
mkdir -p $PLUGINDIR
```
## write a transformer plugin
Download the [kubeval] binary depending on the operating system
and add it to $PATH.
<!-- @downloadKubeval @kubevalTest -->
```
OS=`uname | sed -e 's/Linux/linux/' -e 's/Darwin/darwin/'`
wget https://github.com/instrumenta/kubeval/releases/download/0.9.2/kubeval-${OS}-amd64.tar.gz
tar xf kubeval-${OS}-amd64.tar.gz
export PATH=$PATH:`pwd`
```
Kustomize has the following assumption of a transformer plugin:
- The resources are passed to the transformer plugin from stdin.
- The configuration file for the transformer plugin is passed in
as the first argument.
- The working directory of the plugin is the kustomization
directory where it is used as a transformer.
- The transformed resources are written to stdout by the plugin.
- If the return code of the transformer plugin is non zero,
Kustomize regards there is an error during the transformation.
A transformer plugin for the validation can be written as a
bash script, which execute the [kubeval] binary and return proper
output and exit code.
<!-- @writePlugin @kubevalTest -->
```
cat <<'EOF' > $PLUGINDIR/Validator
#!/bin/bash
if ! [ -x "$(command -v kubeval)" ]; then
echo "Error: kubeval is not installed."
exit 1
fi
temp_file=$(mktemp)
output_file=$(mktemp)
cat - > $temp_file
kubeval $temp_file > $output_file
if [ $? -eq 0 ]; then
cat $temp_file
rm $temp_file $output_file
exit 0
fi
cat $output_file
rm $temp_file $output_file
exit 1
EOF
chmod +x $PLUGINDIR/Validator
```
## use the transformer plugin
Define a kustomization containing a valid ConfigMap
and the transformer plugin.
<!-- @writeKustomization @kubevalTest -->
```
cat <<'EOF' >$DEMO_HOME/valid/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm
data:
foo: bar
EOF
cat <<'EOF' >$DEMO_HOME/valid/validation.yaml
apiVersion: someteam.example.com/v1
kind: Validator
metadata:
name: notImportantHere
EOF
cat <<'EOF' >$DEMO_HOME/valid/kustomization.yaml
resources:
- configmap.yaml
transformers:
- validation.yaml
EOF
```
Define a kustomization containing an invalid ConfigMap
and the transformer plugin.
<!-- @writeKustomization @kubevalTest -->
```
cat <<'EOF' >$DEMO_HOME/invalid/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm
data:
- foo: bar
EOF
cat <<'EOF' >$DEMO_HOME/invalid/validation.yaml
apiVersion: someteam.example.com/v1
kind: Validator
metadata:
name: notImportantHere
EOF
cat <<'EOF' >$DEMO_HOME/invalid/kustomization.yaml
resources:
- configmap.yaml
transformers:
- validation.yaml
EOF
```
The directory structure is as the following:
```
/tmp/tmp.fAYMfLZJs4
├── invalid
│ ├── configmap.yaml
│ ├── kustomization.yaml
│ └── validation.yaml
├── kustomize
│ └── plugin
│ └── someteam.example.com
│ └── v1
│ ├── kubeval
│ └── Validator
└── valid
├── configmap.yaml
├── kustomization.yaml
└── validation.yaml
```
Define a helper function to run kustomize with the
correct environment and flags for plugins:
<!-- @defineKustomizeBd @kubevalTest -->
```
function kustomizeBd {
XDG_CONFIG_HOME=$DEMO_HOME \
kustomize build \
--enable_alpha_plugins \
$DEMO_HOME/$1
}
```
Build the valid variant
<!-- @buildValid @kubevalTest -->
```
kustomizeBd valid
```
The output contains a ConfigMap as
```yaml
apiVersion: v1
data:
foo: bar
kind: ConfigMap
metadata:
name: cm
```
Build the invalid variant
```
kustomizeBd invalid
```
The output is an error as
```shell
data: Invalid type. Expected: object, given: array
```
## cleanup
<!-- @cleanup @kubevalTest -->
```shell
rm -rf $DEMO_HOME
```
|