Terraformコマンドのサブコマンドにはvalidateやtestがあり、Terraformさえインストールしていればバリデーションやテストを実行できます。これで十分といえば十分なのですが、validateはコードの妥当性を検証するのみで、testは自分でテストコードを書かないといけません。例えば、存在しないインスタンスタイプを指定してしまったとしても、コードの記述方法が狂っていなければvalidateで検出できませんし、テストコードを書かなければtestでも検出できないわけです。この手のテストコードを網羅的に記述し、メンテナンスし続けるのも大変です。そこで今回はコード以外の妥当性もチェックできるtflintを紹介します。
tflint
tflintは外部からルールセットを読み込んでTerraformのコードをlintします。ルールセットはtflintのGitHub Orgで公開されているものもありますし、AWSが公開しているルールなどもあります。
設定
tflintはカレントディレクトリの./.tflint.hcl
か、ホーム直下の~/.tflint.hcl
を読み込みます。コマンドラインオプションで変更することも可能です。
設定ファイルのドキュメントはこちらです。
設定ファイルの書き方は以下のようになります。
config { ... } plugin "plugin_name" { ... } rule "rule_name" { ... }
configブロック
configはtflint自体の設定を記述しておけます。ほとんどの設定はコマンドラインオプションで変更可能です。複数人で同じ設定を共有する場合にはconfigブロックを追加してリポジトリに入れておけばよさそうですね。
pluginブロック
使用するプラグインを指定します。プラグインとはルールセットのことで、これを指定しないとなんのチェックもされずにtflintが完走してしまいます。
プラグインの指定方法は以下です。
plugin "terraform" { enabled = true version = "0.5.0" source = "github.com/terraform-linters/tflint-ruleset-terraform" preset = "recommended" }
enabled
このプラグインを有効化・無効化するオプションです。Bool値で設定します。このオプションは必須です。version
このオプションはプラグインのバージョンを指定します。プラグインのバージョンはプラグインが公開されているリポジトリのReleasesと一致します。Releasesで設定されているバージョンの先頭のv
はバージョン文字列に含めません。source
プラグインが公開されているリポジトリのURLです。github.com/org/repo-name
のフォーマットで指定します。
preset
オプションはtflintのオプションではなく、プラグインの方で定義されているオプションです。今回の場合だとtflint-ruleset-terraformが入力を求めているオプションです。どういう設定ができるのかはプラグインのリポジトリにあるドキュメントを見てください。
以下はtflint-ruleset-terraformで使用できるオプションのドキュメントです。
ruleブロック
ルールセットを適用したら過剰に反応されるのはlinterあるあるだと思います。プロジェクトに合わせてルールの有効化・無効化をして調整します。
rule "terraform_deprecated_index" { enabled = false }
以下はtflint-ruleset-terraformで使用できるルールの一覧です。
使う
今回はTerraformとAWSのプラグインを使用したいので.tflint.htl
は以下のものを使用します。
plugin "aws" { enabled = true version = "0.29.0" source = "github.com/terraform-linters/tflint-ruleset-aws" } plugin "terraform" { enabled = true version = "0.5.0" source = "github.com/terraform-linters/tflint-ruleset-terraform" }
Terraformのコードはmain.tf 1つだけ用意して、内容は以下のようにしてみます。
provider "aws" { region = "ap-northeast-1" } resource "aws_instance" "this" { ami = "ami-06cd52961ce9f0d85" instance_type = "t1.nano" }
この状態で一度実行してみましょう。
$ tflint 6 issue(s) found: Warning: terraform "required_version" attribute is required (terraform_required_version) on line 0: (source code not available) Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_required_version.md Warning: Missing version constraint for provider "aws" in `required_providers` (terraform_required_providers) on main.tf line 5: 5: resource "aws_instance" "this" { Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_required_providers.md Error: "t1.nano" is an invalid value as instance_type (aws_instance_invalid_type) on main.tf line 7: 7: instance_type = "t1.nano" Warning: "t1.nano" is previous generation instance type. (aws_instance_previous_type) on main.tf line 7: 7: instance_type = "t1.nano" Reference: https://github.com/terraform-linters/tflint-ruleset-aws/blob/v0.29.0/docs/rules/aws_instance_previous_type.md Warning: Module should include an empty outputs.tf file (terraform_standard_module_structure) on outputs.tf line 1: (source code not available) Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_standard_module_structure.md Warning: Module should include an empty variables.tf file (terraform_standard_module_structure) on variables.tf line 1: (source code not available) Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_standard_module_structure.md
6つ問題が発生しました。分割して見ていきましょう。
以下2つの警告はバージョン指定が必要だと言っています。
Warning: terraform "required_version" attribute is required (terraform_required_version) on line 0: (source code not available) Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_required_version.md Warning: Missing version constraint for provider "aws" in `required_providers` (terraform_required_providers) on main.tf line 5: 5: resource "aws_instance" "this" { Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_required_providers.md
Terraformはバージョン依存の処理もあるので指定しておいた方が無難でしょう。terraform {}
ブロックを追加します。
terraform { required_version = "~> 1.6.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.32.0" } } } provider "aws" { region = "ap-northeast-1" } resource "aws_instance" "this" { ami = "ami-06cd52961ce9f0d85" instance_type = "t1.nano" }
以下2つの警告とエラーはインスタンスタイプについて言及しています。t1.nano
というインスタンスタイプが妥当ではないというエラーと、t1
は旧型のインスタンスタイプであると言う警告が出ています。
Error: "t1.nano" is an invalid value as instance_type (aws_instance_invalid_type) on main.tf line 7: 7: instance_type = "t1.nano" Warning: "t1.nano" is previous generation instance type. (aws_instance_previous_type) on main.tf line 7: 7: instance_type = "t1.nano" Reference: https://github.com/terraform-linters/tflint-ruleset-aws/blob/v0.29.0/docs/rules/aws_instance_previous_type.md
t3.nano
などに変更します。
以下2つの警告はファイルが足りないと言っています。
Warning: Module should include an empty outputs.tf file (terraform_standard_module_structure) on outputs.tf line 1: (source code not available) Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_standard_module_structure.md Warning: Module should include an empty variables.tf file (terraform_standard_module_structure) on variables.tf line 1: (source code not available) Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_standard_module_structure.md
今回使用しているコードはoutputもvariableも必要としていないのでルールの方を無効化します。
plugin "aws" { enabled = true version = "0.29.0" source = "github.com/terraform-linters/tflint-ruleset-aws" } plugin "terraform" { enabled = true version = "0.5.0" source = "github.com/terraform-linters/tflint-ruleset-terraform" } rule "terraform_standard_module_structure" { enabled = false }
出ていたエラーと警告の部分は修正できたのでもう一度tflintを実行してみます。
$ tflint
エラーも警告も消えて正常終了しました。
ちなみに、初期のコードでterraform validate
を実行してみるとこうなります。
terraform validate Success! The configuration is valid.
なんのエラーも警告も検知しません。構文に間違いはなかったので当然です。
まとめ
tflintを使うと構文以外の妥当性もチェックできます。今回はTerraformとAWSをターゲットに試してみましたが、Google CloudやAzureのルールセットもありました。GitHub Actionsでも使用しやすいようにMarketplaceに用意されていたり、reviewdogと連携したActionsが公開されていたりするので、CIに設定するのもよさそうです。