helmで単体テスト
をみて、helmでの単体テスト、ほしかったものや!terratestいいやん!と、goで実装して、よし、いい感じ、なるほどなるほど、結構簡単に実装できるなあ、とりあえず別のツールがないかhelm unittestで検索してみようで見つけてしまったもの 利用しようと思っていたユースケースが一般的すぎて、yaml数行で上位互換の機能がすでに実装済みであることを見つけたときの悲しさ…、にまさる独自実装しなくて済んだ喜び
TDDで開発されていない限り、テストでほしいものは以前できたことからの差分なはず。helmチャートの場合、変更を加えるのは新しい引数を付けたいとかであることが多い。すると簡単に過去のマニフェスト生成を取れて、そこから意図した結果のマニフェストに変更することは人間に優しい。あとは期待したマニフェストを生成できるチャートとなるように変更を加えるという作業が一般的
helm-unittestを使うとこのフローを簡単に回せて、かつ意図しない変更をしていないことを確認できる
試しにnginx-ingress( https://github.com/nginxinc/helm-charts )で出力したマニフェストが意図した出力になるようにvaluesを安全に変更するフローを見てみる
過去のスナップショットを取って比較するための設定ファイル。これがhelm-unittestをインストールする以外に唯一必要な仕掛け
suite: test all
templates:
- controller-configmap.yaml
- controller-deployment.yaml
- controller-service.yaml
- controller-serviceaccount.yaml
- rbac.yaml
tests:
- it: should work
asserts:
- matchSnapshot: {}
-uでデフォルトの設定時のスナップショットを取る。スナップショットは__snapshot__フォルダに保存される
% helm unittest -u .
### Chart [ nginx-ingress ] .
PASS test all tests/all_test.yaml
Charts: 1 passed, 1 total
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshot: 6 passed, 6 total
Time: 103.507667ms
スナップショット側を先に書き換えて、意図した出力にする。例としてipv6を無効化してみる
% diff tests/__snapshot__/all_test.yaml.snap tests/__snapshot__/all_test.yaml.snap.org
69c69
< - -disable-ipv6=true
---
> - -disable-ipv6=false
テストを走らせると変更(テストケースとの差分)が検知される
% helm unittest .
### Chart [ nginx-ingress ] .
FAIL test all tests/all_test.yaml
- should work
- asserts[0] `matchSnapshot` fail
Template: nginx-ingress/templates/controller-deployment.yaml
DocumentIndex: 0
Path:
Expected to match snapshot 2:
--- Expected
+++ Actual
@@ -54,3 +54,3 @@
- -include-year=false
- - -disable-ipv6=true
+ - -disable-ipv6=false
- -enable-tls-passthrough=false
Snapshot Summary: 1 snapshot failed in 1 test suite. Check changes and use `-u` to update snapshot.
Charts: 1 failed, 0 passed, 1 total
Test Suites: 1 failed, 0 passed, 1 total
Tests: 1 failed, 0 passed, 1 total
Snapshot: 1 failed, 5 passed, 6 total
Time: 137.791375ms
サンプルの変更ではチャート自体への修正は必要なく、valuesファイルを設定すれば良い。のでそのとおりに変更する
% diff values.yaml values-test.yaml
417c417
< disableIPV6: false
---
> disableIPV6: true
変更したvaluesファイルを食わせて、再度テストを走らせて意図した出力が出ていることを確認する
% diff tests/all_test.yaml tests/all_test.yaml.org
10,11d9
< values:
< - ./values-test.yaml
% helm unittest .
### Chart [ nginx-ingress ] .
PASS test all tests/all_test.yaml
Charts: 1 passed, 1 total
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshot: 6 passed, 6 total
Time: 109.755209ms
あまりにも便利すぎて涙した
最後のフォルダ構造はこんな感じ
% tree tests
tests
├── __snapshot__
│ ├── all_test.yaml.snap
│ └── all_test.yaml.snap.org
├── all_test.yaml
├── all_test.yaml.org
└── values-test.yaml
一般的にhelmチャートにおいてvaluesの一覧とにらめっこして結果出力されるマニフェストを人間側で想像する。しかし、往々にしてドキュメントが古かったり解釈の違いで、意図しないマニフェストが出力されたり、思わぬ副作用をもらったりする
上記のフローで変更をすれば、先に生成されるべきマニフェストファイルを得られるため、あとからつじつまを合わせることができる。ぱっと思いつくユースケースとしてClusterRole/ClusterRoleBindingで書かれたチャートをRole/RoleBindingで動かす際にもっと楽にできそう。日々のチャートの変更も安心して実施できることだろう