Terraform のスクリプトにも lint を自動で実行できるようにします。
lint ツール
Terraform には terraform validate
コマンドがあり、設定上のかなりの問題を検知してくれます。
一方で terraform は AWS に特定の問題を検知してくれない場合があったり、description
を記述していない variables.tf 等に警告してくれるわけではありません。
terraform には TFlint という linter があるので、こちらを GitLab CI/CD に組み込んでみました。
TFlint
TFlint は単純に引数なしで実行するだけでも、そのディレクトリにあるルートモジュールを対象に HCL をパースしてその問題を検知してくれます。 チェック内容としては例えば以下のようなものがあります。
terraform apply
時によってはじめて分かるような設定内容の不整合- 使用しているパラメータ値の違反
- 各種ベストプラクティス (古い世代の EC2 インスタンスを指定しない、きちんと variables や output のドキュメントを書く)
設定内容のチェックについては、実はデフォルトでは有効になっておらず、 --deep
を指定する必要があります。
この --deep
チェックは、AWS の API を呼び出しつつリソース間の関係をチェックしていくというもの(なはず)です。
API を呼び出すがゆえに、この場合はアクセスキー ID やシークレットアクセスキーも合わせて渡す必要があります。
また、TFLint は「ルートモジュールを対象」に lint をかけてくれるものであり、再帰的に利用モジュールまで lint をかけるわけではありません。
ただ「渡している値に整合性が取れているか」については Module Inspection と呼ばれる機能でチェックが可能です。
こちらは、 --module
を指定することで有効化できます。
加えて、output や variable のドキュメントを書く、といったルールはデフォルトで有効になっていません。これは有効にしていく必要があります。
設定の渡し方
もちろん、このような linter 設定はもちろんコマンドラインで渡すことが可能です。
一方で都度設定するのは面倒なので、 .tflint.hcl
というファイルに設定を記述し、カレントディレクトリかホームディレクトリに配置しておくことで
tflint が読み込んでくれるようになります。
当該ファイルは HCL 形式なので、今回は以下のような設定としました。
config { module = true deep_check = false } rule "terraform_dash_in_resource_name" { enabled = true } rule "terraform_documented_outputs" { enabled = true } rule "terraform_documented_variables" { enabled = true } rule "terraform_module_pinned_source" { enabled = true }
GitLab CI/CD への組み込み
GitLab では GitHub Actions と同じように .gitlab-ci.yml
をプロジェクトルートに配置しておくことで自動的に CI/CD を走らせることができます。
今回は以下のような設定としてみました。
stages: - lint variables: TERRAFORM_VERSION: 0.12.24 TFLINT_VERSION: 0.15.5 tflint: stage: lint image: name: hashicorp/terraform:${TERRAFORM_VERSION} entrypoint: [""] before_script: - wget https://github.com/terraform-linters/tflint/releases/download/v${TFLINT_VERSION}/tflint_linux_amd64.zip -O tflint.zip - unzip tflint.zip -d $HOME - rm tflint.zip script: - >- find . -type f -name "*.tf" -exec dirname {} \; | sort -u | while read line; do cd $line; echo "processing $PWD ..." terraform init -backend=false && $HOME/tflint --config $CI_PROJECT_DIR/.tflint.hcl; cd -; done
Module Inspection を行うためには terraform init
が必要となるので、利用コンテナとしては hashicorp/terraform のイメージを使用します。そこに tflint のバイナリを組み込む形です。
実際にチェックを行っているのは tflint.script
の箇所です。
TFlint は先述の通りルートモジュールを対象とする linter なので、モジュールも含めてルートモジュール扱いとするため、個々のディレクトリに移動してから lint をかけます。
実行結果は以下の通り。これは terraform validate
でも検知できるレベルのエラーですが、きちんと tflint でも検知できていることがわかります。
今後
できれば --deep
チェックを組み込めればと思っているのですが、複数の AWS アカウントがあることを前提とした時にどう運用するのが良いのかなという点が悩みどころになっています。