Is there a way to test that the templating works fine for all the possible values?
(note: this is different from helm test which is used for testing the deployed chart through arbitrary code ran in a job).
What I would like to achieve is iterating over a set of values and checking the generated K8s resources for each.
Lets say we want to test whether our chart is correctly written:
The chart:
Values.yaml
app:
port: 8081
pod2:
enabled: true
AppPod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: AppPod
labels:
app: nginx
spec:
...
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: {{ $.Values.app.port| default 8080 }}
Pod2.yaml
{{- if $.Values.pod2.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: Pod2
labels:
app: nginx2
spec:
...
{{- end}}
We want to run the following tests:
So basically to test the templating logic.
What I am doing right now:
Whenever I modify something in the chart I just run helm template for different Values.yaml and check the results by hand. Doing this by hand is error prone and it becomes more time consuming the more template the chart contains.
Is there any builtin helm feature or a separate framework for this?
Yes, we do that with Rego policy rules. The set-up is not complicated, this is how it looks as part of one of our pipelines (this is a very simplified example to get you started):
# install conftest to be able to run helm unit tests
wget https://github.com/open-policy-agent/conftest/releases/download/v0.28.1/conftest_0.28.1_Linux_x86_64.tar.gz
tar xzf conftest_0.28.1_Linux_x86_64.tar.gz
chmod +x conftest
# you can call "helm template" with other override values of course, too
helm template src/main/helm/my-service/ > all.yaml
echo "running opa policies tests"
if ! ./conftest test -p src/main/helm/my-service/ all.yaml; then
echo "failure"
exit 1
fi
Inside the my-service
directory there is a policy
folder that holds the "rules" for testing (though this can be passed as an argument). Here is an example of two rules I recently wrote:
package main
deny_app_version_must_be_present[msg] {
input.kind == "Deployment"
env := input.spec.template.spec.containers[_].env[_]
msg := sprintf("env property with name '%v' must not be empty", [env.name])
"APP_VERSION" == env.name ; "" == env.value
}
deny_app_version_env_variable_must_be_present[msg] {
input.kind == "Deployment"
app_version_names := { envs | envs := input.spec.template.spec.containers[_].env[_]; envs.name == "APP_VERSION"}
count(app_version_names) != 1
msg := sprintf("'%v' env variable must be preset once", ["APP_VERSION"])
}
This validates that the container in the Deployment
has an env variable called APP_VERSION
that must be unique and non-empty.