😣

`terragrunt hcl validate` で `Error: Unsupported attribute` 発生した時の対応

に公開

TL;DR

dependency block に mock を追加して、validate

live/aws/production/ap-northeast-1/services/app-frontend/terragrunt.hcl
 dependency "dns" {
   config_path = "${get_parent_terragrunt_dir("root.hcl")}/live/aws/production/_global/dns"

+  # dependency 先なしで、単独で stack を検証可能にするための mock values
+  mock_outputs = {
+    zone_names = {
+      "app-frontend" = "mock.example.com"
+    }
+  }
+  # この mock_outputs を使用できるコマンドを指定
+  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
 }

何が起きたか

terragrunt hcl validate を実行してエラーが発生

でも plan は通る。どぉして😭

$ terragrunt hcl validate --working-dir live/aws/production/ap-northeast-1/services/app-frontend/


 Error: Unsupported attribute
 
   on live/aws/production/ap-northeast-1/services/app-frontend/terragrunt.hcl line 20:
   20:   custom_domain = dependency.dns.outputs.zone_names["app-frontend"]
     ├────────────────
 dependency.dns is object with 1 attribute "inputs"
 
 This object does not have an attribute named "outputs".

ERROR  1 HCL validation error(s) found
ERROR  Unable to determine underlying exit code, so Terragrunt will exit with error code 1

これは予期された正常な動作らしい。terragrunt hcl validateterragrunt plan の動作の違いによるものだそう。

1. terragrunt hcl validate の動作

  • HCL構文の静的検証のみを行う
  • dependencyのoutputsをフェッチしない
  • そのため、dependency.dnsオブジェクトにはinputs属性しか存在せず、outputsにアクセスしようとするとエラーになる

2. terragrunt plan の動作

  • HCL検証に加えて、実際にdependencyのstate/outputsをフェッチする
  • そのため、dependency.dns.outputs.zone_namesが正常に解決され、planが成功する

まぁだからといって「terragrunt hcl validate は fail してもいいよね😊」とはならないので、mock_outputs を使う

mock_outputsの仕組み

  mock_outputs = {
    zone_names = {
      "app-frontend" = "mock.example.com"
    }
  }
  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
  • mock_outputs: hcl validate に使用するダミー値
  • mock_outputs_allowed_terraform_commands: どのコマンド実行時にmockを許可するか
    • ["validate", "plan"]: validate と plan でのみ mock を使用。言い換えると、 apply 時には実際の outputs を使用する。

まとめ

このエラーは terragrunt の設計上の制約であり、Terragrunt公式もmock_outputsを推奨している。

  1. hcl validateはdependencyのstateにアクセスしない - 高速な静的検証を目的としているため
  2. run --allなどの並列実行 - すべてのmoduleがまだapplyされていない状態でも検証可能にするため
  3. CI/CDパイプライン - dependency未デプロイでも検証を通すため

参考

Discussion