課題
tflint でモジュールの呼び出しも検査したい場合、 tflint --call-module-type=all
を使用します。
このときに Terraform のプライベートレジストリなどを利用しているとモジュールの情報を取得できないので、下記のようなエラーが出力されます。
Error: "pokapu" module is not found. Did you run "terraform init"?
エラーメッセージに terraform init
の実行を要求されているので、 terraform init
を実行すれば検査可能です。
ただ、下記の議論がある通り、ネストされたローカルモジュールを利用していると、各ローカルモジュールで terraform init
が必要になります。
terraform init
を実行する際は、例えば AWS の構築を行うコードの場合、AWS Provider のダウンロードが行われ、かなりの時間がかかるので、ネストされたローカルモジュールが多い場合は時間がかかって辛いです。
問題の再現構成
下記のように、モジュール内で HCP Terraform の Private Registry を参照している構成で AWS のルールセットを利用して tflint したいケースを考えます。
module "test" {
source = "./modules/test_module"
}
module "pokapu" {
source = "app.terraform.io/pokapu/pokapu/ec2dummy"
version = "1.0.0"
instance_type = "t1.2xlarge"
}
plugin "aws" {
enabled = true
version = "0.32.0"
source = "github.com/terraform-linters/tflint-ruleset-aws"
}
Private Registry のモジュールの内容は以下のようになっています:
resource "aws_instance" "this" {
ami = "ami-005e54dee72cc1d00"
instance_type = var.instance_type
}
variable "instance_type" {
type = string
}
これに対して tflint すると、aws_instance に存在しない instance_type が渡されるので、tflint に警告されるはずです。
tflint にモジュール検査までさせると terraform init を求められる
モジュールの検査をしたいので、ルートディレクトリで terraform init した後に下記を実行して検査したくなります。
tflint --recursive --disable-rule=terraform_required_version --call-module-type=all -c $(realpath .tflint.hcl)
こうすると、下記のエラーが表示されます。
│ Failed to run in modules\test_module; exit status 1
Failed to load configurations; modules\test_module\main.tf:1,1-16: "pokapu" module is not found. Did you run "terraform init"?; :
Error: "pokapu" module is not found. Did you run "terraform init"?
on modules\test_module\main.tf line 1, in module "pokapu":
1: module "pokapu" {
「terraform init
を実行していないのではないか?」というご指摘です。
terraform get でもモジュールのダウンロードをしてくれる
terraform get
というコマンドがあります。
こちらを使用すればモジュールをダウンロードしてくれるので検査してくれそうです。
terraform get
terraform -chdir=modules/test_module get
モジュールのフォルダに cd
せずに実行した方が、複数モジュールの検査を自動化しやすいと思うので -chdir
を利用しています。
このあとに下記を実行するのはどうでしょうか?
tflint --recursive --disable-rule=terraform_required_version --call-module-type=all -c $(realpath .tflint.hcl)
これで tflint による指摘を得ることができました。素早く処理できます!
2 issue(s) found:
Error: "t1.2xlarge" is an invalid value as instance_type (aws_instance_invalid_type)
on modules\test_module\main.tf line 4:
(source code not available)
Callers:
modules\test_module\main.tf:4,19-31
modules\test_module\.terraform\modules\pokapu\main.tf:3,19-36
Warning: "t1.2xlarge" is previous generation instance type. (aws_instance_previous_type)
on modules\test_module\main.tf line 4:
(source code not available)
Callers:
modules\test_module\main.tf:4,19-31
modules\test_module\.terraform\modules\pokapu\main.tf:3,19-36
Reference: https://github.com/terraform-linters/tflint-ruleset-aws/blob/v0.32.0/docs/rules/aws_instance_previous_type.md
おまけ
記事を書いていて気づきましたが、「terraform get
で良い」ということは、下記に書いてありました...
If you want to call remote modules (registry, git, etc.), you must run terraform init (or terraform get) before invoking TFLint so that modules are loaded into the .terraform directory.