How to add a new lint to tflint-ruleset-aws
tflint の aws 向けの rule set は pluggable になっており、新規 rule 追加がしやすくなっています。本発表では DB Instance の engine が valid のテストを追加する PR を元に、Contribution の方法と、その lint の仕組みを解説します。
Who am I
Lead Software Engineer, Site Reliability at Quipper
- Twitter: @chaspy_
- GitHub: @chaspy
- https://chaspy.me
tflint
https://github.com/terraform-linters/tflint
A Pluggable Terraform Linter
ref: terraform planで消耗しないためにTFLintを作った話
日本人作!かっこいい!@wata727 さん作
aws 用の rule set はこちら terraform-linters/tflint-ruleset-aws
結論: tflint-ruleset-aws に Contribution した
Add lint for db_instance's engine attribute
2021/02/13 追記 Merge されました
きっかけ
@sogaoh さんのツイート(マジ感謝!)
眺める
まず aws_db_instance_invalid_type.go を眺める
これは instanceType を lint するもの。まぁこれ engine によって許可する、しないはあると思うので厳密ではないが。少なくとも instance_type field に取りうる値をテストしているようだ。
// AwsDBInstanceInvalidTypeRule checks whether "aws_db_instance" has invalid intance type.
type AwsDBInstanceInvalidTypeRule struct {
resourceType string
attributeName string
instanceTypes map[string]bool
}
// NewAwsDBInstanceInvalidTypeRule returns new rule with default attributes
func NewAwsDBInstanceInvalidTypeRule() *AwsDBInstanceInvalidTypeRule {
return &AwsDBInstanceInvalidTypeRule{
resourceType: "aws_db_instance",
attributeName: "instance_class",
instanceTypes: map[string]bool{
"db.cr1.8xlarge": true,
"db.cv11.18xlarge": true,
"db.cv11.2xlarge": true,
"db.cv11.4xlarge": true,
...
},
}
}
まぁなんかいけるやろ(たぶんいける)
でまぁとりあえず "Type" を "Engine" によしなに書き換えて PR 出した。
で、テストいるのでテストも雰囲気で書いた
ざっくりとした仕組み
すごい仕組みで tflint が aws-rulese-aws を読み込み、その中の Ruleset を読み込み、テストを実行している(全然よくわかっていません)
1. pflint が plugin を探す
- Plugin を特定の path においていけば tflint が検出してくれる
- ぶんまわして順に実行している https://github.com/terraform-linters/tflint/blob/01b09db406fd73d45c24dc8e2bd3f2edfc6c4e92/plugin/discovery.go#L90
- tflint-plugin-sdk がある
- tflint からは plugin を実行し、結果を取得している
- plugin 機構には hashicorp/go-plugin を使っている。terraform 他いろんなもので使われているぽい
2. plugin では各 rule を読み込んでテスト
- plugin.Serve https://github.com/terraform-linters/tflint-ruleset-aws/blob/6a9575c5f3ed4e2b92fb230a5220433e11ece464/main.go#L13
ちゃんと動くのか
動いた!
$ make install
go build
mkdir -p ~/.tflint.d/plugins
mv ./tflint-ruleset-aws ~/.tflint.d/plugins
$ tf init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Installing hashicorp/aws v3.27.0...
tflin- Installed hashicorp/aws v3.27.0 (signed by HashiCorp)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
$ tflint
1 issue(s) found:
Error: "mysql57" is invalid engine. (aws_db_instance_invalid_engine)
on main.tf line 4:
4: engine = "mysql57"
Reference: https://github.com/terraform-linters/tflint-ruleset-aws/blob/v0.2.1/docs/rules/aws_db_instance_invalid_engine.md
rule を追加する方法
- 既存の Rule を参考に
aws_<resource_name>_invalid_<something_you_want_to_test>.go
を書く - テストを書く
- make install して動かす
- document を書く
- PR を出す!
- merge
🎉
まとめ
- まだまだ rule は多いとは言えないので、apply 爆死を経験したら lint できないか?って考えてみよう
- できそうなら Contribution してみよう!
おしまい