Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helm-unittest #284

Merged
merged 12 commits into from
Feb 18, 2022
45 changes: 45 additions & 0 deletions .github/workflows/unit-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
name: Unit Tests

on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
helm-unittest:

runs-on: ubuntu-latest
# strategy:
# matrix:
# Relevant tools installed by default on ubuntu 20.04:
# - helm 3.8.0
# - jq 1.6
# - kind 0.11.1
# - kubectl 1.23.3
# - minikube 1.25.1
# - python 3.8.10
# - yamllint 1.26.3
# - yq 4.19.1
# see: https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md

steps:
- uses: actions/checkout@v2

- name: Install helm-unittest
# We should periodically check to see if another fork has taken over maintenance,
# as the de-facto "best" fork has changed several times over the years.
run: |
helm plugin install https://github.com/quintush/helm-unittest

- name: Install chart dependencies
run: |
helm dependency update

- name: Run helm-unittest
# by default looks for tests/*_test.yaml
run: |
helm unittest --color --helm3 .
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Advanced Feature: Make securityContext (on Deployments/Jobs) and podSecurityContext (on Pods) configurable. This allows dropping all capabilities, for example. You can override the securityContext for `st2actionrunner`, `st2sensorcontainer`, and `st2client` if your actions or sensors need, for example, additional capabilites that the rest of StackStorm does not need. (#271) (by @cognifloyd)
* Prefix template helpers with chart name and format helper comments as template comments. (#272) (by @cognifloyd)
* New feature: Add `extra_volumes` to all python-based st2 deployments. This can facilitate changing log levels by loading logging conf file(s) from a custom ConfigMap. (#276) (by @cognifloyd)
* Initialize basic unittest infrastructure using `helm-unittest`. Tests will be gradually added. (#284)

## v0.80.0
* Switch st2 to `v3.6` as a new default stable version (#274)
Expand Down
2 changes: 1 addition & 1 deletion templates/tests/st2tests-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ metadata:
heritage: {{ .Release.Service }}
data:
st2tests.sh: |
{{ .Files.Get "tests/st2tests.sh" | indent 4 }}
{{ .Files.Get "tests/integration/st2tests.sh" | indent 4 }}
38 changes: 36 additions & 2 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
# `stackstorm-ha` Helm chart Tests

This directory contains Helm chart tests, powered by [BATS](https://github.com/sstephenson/bats) Bash Automated Testing System.
This directory contains Helm chart integration (under `tests/integration/`) and unit tests (`tests/unit-*_test.yaml`).

## Unit tests

Unit tests (`tests/unit-*_test.yaml`) use [`helm-unittest`](https://github.com/quintush/helm-unittest).
`helm-unittest` uses a yaml-based test file to ensure that the templates generate expected features.
For example, they can ensure that custom annotations are applied consistently to all of the deployments.
Unit tests do not require a running kubernetes cluster.

Before running unit tests, install the `helm-unittest` plugin and ensure you have sub-charts installed:
```
helm plugin install https://github.com/quintush/helm-unittest
helm dependency update
```

To run the tests manually from the chart's root dir:
```
helm unittest --helm3 .
```

Note that `helm-unittest` still defaults to helm 2, so you must pass `--helm3` or `-3` for short.
`helm-unittest` does not have a configuraiton file which makes using non-standard directories (like `tests/unit/`)
very inconvenient (you would have to specify `-f tests/unit/*_test.yaml` on every invocation).
So, we keep all of the unit test files under tests, but prefix them with `unit-` to separate them from
the integration tests.
cognifloyd marked this conversation as resolved.
Show resolved Hide resolved

> Note! If you need to add unit tests, file names should follow this pattern: `tests/unit-name_your_test.yaml`
cognifloyd marked this conversation as resolved.
Show resolved Hide resolved

See https://github.com/quintush/helm-unittest/blob/master/DOCUMENT.md for details on writing unit tests.

## Integration tests

Integration tests (under `tests/integration/`) use `helm-test` and are powered by [BATS](https://github.com/sstephenson/bats) (Bash Automated Testing System).
As integratin tests, these require a running kubernetes cluster where helm can do test deployments of this chart.

Despite the minimum amount of smoke tests written, they ensure that StackStorm was really deployed,
works correctly at its core and alive end-to-end without checking deeply specific functionality or configuration.
If something is terribly wrong, - it'll show up via failed tests.
Expand All @@ -18,4 +52,4 @@ To show the test results:
kubectl logs <release-name>-st2tests
```

See https://helm.sh/docs/developing_charts/#chart-tests with more information about Helm chart tests.
See https://helm.sh/docs/topics/chart-tests/ with more information about Helm chart tests.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

old link was to helm v2 docs. This is the same doc but for helm v3.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for spotting that!

File renamed without changes.
169 changes: 169 additions & 0 deletions tests/unit-custom_annotations_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
---
suite: Custom Annotations
templates:
# primary template files
- deployments.yaml
- ingress.yaml
- jobs.yaml
- service-account.yaml
- services.yaml

# included templates must also be listed
- configmaps_packs.yaml
- configmaps_rbac.yaml
- configmaps_st2-conf.yaml
- configmaps_st2-urls.yaml
- configmaps_st2web.yaml
- secrets_datastore_crypto_key.yaml
- secrets_ssh.yaml
- secrets_st2apikeys.yaml
- secrets_st2auth.yaml
- secrets_st2chatops.yaml

tests:
- it: ServiceAccount accepts custom annotations
template: service-account.yaml
set:
serviceAccount:
create: true
serviceAccountAnnotations: &annotations
foo: bar
answer: "42"
asserts: &annotations_asserts
- isNotNull:
path: metadata.annotations
- equal:
path: metadata.annotations.foo
value: bar
- equal:
path: metadata.annotations.answer
value: "42"

- it: st2web Ingress accepts custom annotations
template: ingress.yaml
set:
st2web:
service:
hostname: some-host-name
ingress:
enabled: true
annotations: *annotations
asserts: *annotations_asserts

# st2auth, st2api, st2stream services do not accept custom annotations

- it: st2web Service accepts custom annotations
template: services.yaml
documentIndex: 3
set:
st2web:
service:
hostname: some-host-name
annotations: *annotations
asserts: *annotations_asserts

# st2chatops service does not accept custom annotations

- it: Deployments+Pods accept custom annotations
template: deployments.yaml
set:
Copy link
Member Author

@cognifloyd cognifloyd Feb 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing all the deployment annotations at once is an optimization. I had one test per deployment, but that meant one helm template run per deployment, which made things very very slow (no I didn't time the multi-minute slow runs, but I got the test run down to about a minute on my machine).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍

st2auth:
annotations: &deployment_annotations
foo: bar
answer: "42"
st2api:
annotations: *deployment_annotations
st2stream:
annotations: *deployment_annotations
st2web:
annotations: *deployment_annotations
st2rulesengine:
annotations: *deployment_annotations
st2timersengine:
annotations: *deployment_annotations
st2workflowengine:
annotations: *deployment_annotations
st2scheduler:
annotations: *deployment_annotations
st2notifier:
annotations: *deployment_annotations
st2sensorcontainer:
annotations: *deployment_annotations
st2: { packs: { sensors: [] } } # ensure only 1 sensor
st2actionrunner:
annotations: *deployment_annotations
st2garbagecollector:
annotations: *deployment_annotations
st2client:
annotations: *deployment_annotations
st2chatops:
enabled: true
annotations: *deployment_annotations
asserts:
- hasDocuments:
count: 14
# st2auth, st2api,
# st2stream, st2web,
# st2rulesengine, st2timersengine,
# st2workflowengine, st2scheduler,
# st2notifier, (1) st2sensorcontainer,
# st2actionrunner, st2garbagecollector,
# st2client, st2chatops

# deployment annotations
- isNotNull:
path: metadata.annotations
- equal:
path: metadata.annotations.foo
value: bar
- equal:
path: metadata.annotations.answer
value: "42"

# pod annotations
- isNotNull:
path: spec.template.metadata.annotations
- equal:
path: spec.template.metadata.annotations.foo
value: bar
- equal:
path: spec.template.metadata.annotations.answer
value: "42"

- it: Jobs+Pods accept custom annotations
template: jobs.yaml
set:
st2:
rbac:
enabled: true # enable rbac job
jobs:
annotations:
foo: bar
answer: "42"
asserts:
- hasDocuments:
count: 4
# job-st2-apply-rbac-defintions
# job-st2-apikey-load
# job-st2-key-load
# job-st2-register-content

# job annotations
- isNotNull:
path: metadata.annotations
- equal:
path: metadata.annotations.foo
value: bar
- equal:
path: metadata.annotations.answer
value: "42"

# pod annotations
- isNotNull:
path: spec.template.metadata.annotations
- equal:
path: spec.template.metadata.annotations.foo
value: bar
- equal:
path: spec.template.metadata.annotations.answer
value: "42"