March 19, 2020

Helm Chart で生成された manifests をテストする

#helm | #test |

chart のテストは https://helm.sh/docs/topics/chart_tests/#helm にあるように、実際に helm install する必要があります。
そうではなくて、単純に吐き出される manifests が期待したものかどうかをテストしたいというケースもあると思います(僕はあった)。

helm template --execute (v3 だと --show-only) を使って出力されたファイルを使ってテストをする方法もありますが、あまりスマートとは言えない感じがします。
そこで terratest を使ってテストを書く方法についてメモがてら残します。

とりあえず適当に chart を作ります。

❯ helm create sample-chart
Createing sample-chart

今回は次のような単純な Pod を例にします。

❯ tree
.
├── Chart.yaml
├── charts
├── templates
│   ├── _helpers.tpl
│   └── pod.yaml
└── values.yaml

❯ cat values.yaml
image:
  repository: nginx
  tag: latest


❯ cat templates/pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - image: {{ $.Values.image.repository }}:{{ $.Values.image.tag }}
      name: nginx
      ports:
        - containerPort: 80
          name: http

tests ディレクトリを用意し、 go mod init <repository> を実行します。

❯ mkdir tests
❯ cd tests
❯ go mod init github.com/mrtc0/sample-charts

そして次のようなテストを書きます。

package test

import (
	"testing"

	"github.com/gruntwork-io/terratest/modules/helm"
	corev1 "k8s.io/api/core/v1"
)

func TestOssecConfig(t *testing.T) {
	helmChartPath := "../"
	options := &helm.Options{
		SetFiles: map[string]string{"test": "../values.yaml"},
	}

	output := helm.RenderTemplate(
		t, options, helmChartPath, "sample-chart",
		[]string{"templates/pod.yaml"},
	)

	var pod corev1.Pod
	helm.UnmarshalK8SYaml(t, output, &pod)

	expectImage := "nginx"
	actualImage := pod.Spec.Containers[0].Image
	if actualImage == "nginx" {
		t.Errorf("expected : %s, but got %s", expectImage, actualImage)
	}
}

go test すると内部で helm template --set-file test=../values.yaml --show-only templates/pod.yaml sample-chart ../ 相当のコマンドが実行されます。
helm.UnmarshalK8SYaml() で生成された manifests を対応したリソースの構造体に Unmarshal してあげることで、リソースのテストができます。

❯ go test
TestOssecConfig 2020-03-19T20:03:45+09:00 command.go:87: Running command helm with args [template --set-file test=/private/tmp/c/sample-chart/values.yaml --show-only templates/pod.yaml sample-chart ../]
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158: ---
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158: # Source: sample-chart/templates/pod.yaml
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158: apiVersion: v1
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158: kind: Pod
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158: metadata:
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158:   name: nginx
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158: spec:
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158:   containers:
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158:     - image: nginx:latest
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158:       name: nginx
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158:       ports:
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158:         - containerPort: 80
TestOssecConfig 2020-03-19T20:03:46+09:00 command.go:158:           name: http
PASS
ok      github.com/mrtc0/sample-chart   1.043s

注意点

  • helm v3 以上しか対応していない
    • https://github.com/gruntwork-io/terratest/pull/467
    • v2 までは --show-only-x もしくは --execute であるが、バージョンによって分岐をしていない
    • PR のコメントを見る感じ v2 の対応はしない雰囲気…
    • なので、 helmenv などで対応

このエントリーをはてなブックマークに追加

© Kohei Morita 2020