conftestは--combine
オプションをつけると複数リソースに対するテストが書けるよというお話です。
conftestって何?
conftestとは、yamlファイルやjsonファイルなどの構造化されたデータに対してテストをすることができるツールです。
つまり、kubernetesのマニフェストファイルに対してテストを実施することができます。
Rego
conftestのポリシーファイルはRego言語で書かれます。
以下は公式リポジトリのexampleです。
package main
deny[msg] {
input.kind == "Deployment"
not input.spec.template.spec.securityContext.runAsNonRoot
msg := "Containers must not run as root"
}
deny[msg] {
input.kind == "Deployment"
not input.spec.selector.matchLabels.app
msg := "Containers must provide app label for pod selectors"
}
manifest.yamlに対してconftest test manifest.yaml
を実行すると、それぞれのdenyテストの中の評価式がすべて真であればそのテストは引っかかります。
詳しい使い方は公式のページを読んでください。
複数リソースに対するテストも書きたい
普通にconftest test
を実行すると、マニフェストを一つずつしかテストできません。上記の例で言えば、input
に一つのリソースのマニフェストが代入されてテストが実行されます。
しかし、--combine
オプションをつけて実行すると、input
に{path: ファイルパス, contents: マニフェスト}
から成る配列が代入されます。
package main
# すべてのDeoloymentを得る
deployments[deploy] {
input[i].contents.kind == "Deployment"
deploy := input[i].contents
}
# すべてのConfigMapのnameを得る
configMapNames[name] {
input[i].contents.kind == "ConfigMap"
name := input[i].contents.metadata.name
}
# DeploymentでマウントしているConfigMapが存在するかどうかをテストする
violation_mounting_configmap_exists[msg] {
deployment := deployments[i]
volumes := deployment.spec.template.spec.volumes
mountingConfigMapName := volumes[j].configMap.name
not configMapNames[mountingConfigMapName]
msg := sprintf("Deployment`%v`のvolumesで`%v`という名前のConfigMapが指定されているが、その名前を持つConfigMapは存在しない", [deployment.metadata.name, mountingConfigMapName])
}
例えばこのようなテストファイルを書いた上で、複数マニフェストを含むmanifest.yamlに対してconftest test manifest.yaml --combine
を実行すると、DeploymentがマウントしているConfigMapが存在しないときにテストで弾いてくれます。