😣
`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 validate と terragrunt 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を推奨している。
- hcl validateはdependencyのstateにアクセスしない - 高速な静的検証を目的としているため
- run --allなどの並列実行 - すべてのmoduleがまだapplyされていない状態でも検証可能にするため
- CI/CDパイプライン - dependency未デプロイでも検証を通すため
Discussion