はじめに

tflint 利用時のメモ

想定するディレクトリ構成

  • 環境は dev, prd など 環境毎にディレクトリを切る
    • 各環境の main.tf から使用したい module を使う
  • module は 機能単位でディレクトリを切る
    • cognitoとかで切ってるけど、サービスの有効無効など、もう少し大きな単位で切っても良いイメージ
├── envs
│   ├── dev
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── swagger.yaml
│   │   ├── terraform.tfvars
│   │   └── variables.tf
│   └── prd
│       ├── main.tf
│       └── ...
└── module_aws
     ├── cognito
     │   ├── main.tf
     │   ├── outputs.tf
     │   └── variables.tf
     └── s3
         ├── main.tf
         ├── outputs.tf
         └── variables.tf

tflint の設定ファイルの読み込み優先順位: tflint/docs/user-guide/config.md at master · terraform-linters/tflint

  1. File passed by the –config option
  2. File set by the TFLINT_CONFIG_FILE environment variable
  3. Current directory (./.tflint.hcl)
  4. Home directory (~/.tflint.hcl)

awsでこんな設定をしてみた

# 結構口うるさいタイプ
plugin "terraform" {
  enabled = true
  preset  = "all"
}

# `tflint --init` needed
plugin "aws" {
  enabled = true
  # deep_check = true
  version = "0.34.0"
  source  = "github.com/terraform-linters/tflint-ruleset-aws"
}

# rule "terraform_required_version" {
#   enabled = false
# }
#
# rule "terraform_required_providers" {
#   enabled = false
# }

よくでてくるエラーは以下

  • variable.tf ではなく、variables.tf にする
  • output は outputs.tf に書く
  • outputs.tf は空でも要る
  • output, variable には description を書く

無視する方法は以下

  • 以下のように tflint-ignore を書く
    # tflint-ignore: terraform_required_version
    # tflint-ignore: terraform_required_providers

module を再帰的にチェックはしない

  • --recursive を指定しても、ロードしている module のなかまでチェックされない
  • 対象のディレクトリ(module)に移動または、–chdirで指定して、モジュールのチェックを行う必要がある
    • => 想定構成のディレクトリでは、構成のルートディレクトリから --recursive つけて tflint すればいい
      • => envs配下も、module_aws 配下もチェックされる

Terraform 的には 暗黙的 プロバイダの継承 を推奨? Providers Within Modules - Configuration Language | Terraform | HashiCorp Developer

For convenience in simple configurations, a child module automatically inherits default provider configurations from its parent. This means that explicit provider blocks appear only in the root module, and downstream modules can simply declare resources for that provider and have them automatically associated with the root provider configurations.

  • これは、provider の設定を子モジュールに暗黙的に継承することができるということ

We recommend using this approach when a single configuration for each provider is sufficient for an entire configuration.

  • 推奨するやで

Note: Only provider configurations are inherited by child modules, not provider source or version requirements. Each module must declare its own provider requirements. This is especially important for non-HashiCorp providers.

  • provider の設定だけが継承される
  • provider のソースやバージョン要件は継承されない
  • それぞれのモジュールは自分自身のプロバイダ要件を宣言しなければならない
  • provider のソースやバージョン要件は、特に非 HashiCorp プロバイダにとって重要である
  • provider のソースやバージョンを継承したいんだが、、、モジュールに定義するのが正攻法のよう
    • モジュールだからしかたないか、、、

vim ALE tflint のデフォルトの動き

  • 開いたファイルが存在するディレクトリから、上位ディレクトリに向かって .tflint.hcl を探し、configオプションで指定される
  • デフォルトは -f json のみ
  • 開いたファイルの存在するディレクトリ単位で、 tflint を実行する
    • つまり、モジュール内のファイルを開くと、モジュール内のみのチェックが行われる
      • これがけっこうミソ
      • モジュール単位で required_providers, required_version エラーが多発する

ローカルで使用するのみのモジュールの場合の required_providers, required_version はどうするか問題

  • providersの定義や、バージョン指定は、モジュール内で行うべきか?
    • => 定義がDRYでない問題
      • commonを切って、module in moduleで参照する
        • => 結局、module in module は、tflint でチェックできない
          • nullとarchiveとlocalと、、全部個別でファイル定義して、シンボリックリンク各モジュール内に貼るの?とか考えると、やりたくない
      • symlink で解決する
        • => versions.tf に全バージョンかいたら、不要だよと言われるモジュールが出てくる
        • => symlink 先のファイル開いたら、開いた先で tflint 実行されて、いっぱいエラー出る
      • module では required_providers, required_version を書かない(無視する)
        • => これが妥当?
          • => せっかくのチェックが動かないのでエラーを見過ごす。。。
            • => これが一番困る
    • => DRYではない、というのはあるが、モジュールとして、定義すべき
      • => providers.tfや version.tfなども考えたが、ファイルが複数あったややこしい
        • => module 毎に main.tf 先頭に providersもversionも書く
          • => これに一旦落ち着く