ข้ามไปยังเนื้อหา

Worked review 2: multi-environment Terragrunt live tree

Prompt คือ: “ตั้ง Terragrunt live tree ที่มี dev กับ prod environment แต่ละอันมี network unit และ app unit ที่ depend บนมัน” สิ่งที่ตามมาคือ draft แรกแบบที่ AI assistant ส่งกลับมาให้กับ prompt แบบนี้พอดี — root.hcl ที่ใช้ร่วมกัน, terragrunt.hcl สี่ไฟล์ที่ดูสมเหตุสมผลรายตัว, terragrunt.stack.hcl, และ CI snippet ที่อ่านแล้วเหมือน Terragrunt tutorial ทุกอันที่ตีพิมพ์ก่อน CLI redesign 1.1 มี bug จริง 8 ข้อ; ดู AI bug catalog สำหรับ pattern ทั่วไปเบื้องหลังแต่ละข้อ — review นี้ทำซ้ำ catalog entry 5, 6, และ 16-17 อยู่ใน live tree เดียวกันที่สอดคล้องกัน บวกอีกสี่ข้อที่เฉพาะกับ layout หลาย environment ทุกข้อที่กล่าวถึงด้านล่างพิสูจน์ด้วย terragrunt hcl validate/render/run --all/find --dag จริง กับ Terragrunt 1.1.0 และ Terraform 1.16.4 โดยใช้ backend = "local" แทน S3 backend จริง — ตามธรรมเนียมของคอร์สนี้ การพิสูจน์ offline ไม่แตะ AWS จริงเลย

# root.hcl, as generated -- realistic S3 backend (see review walk for why the proof tree below uses backend = "local" instead)
remote_state {
backend = "s3"
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
config = {
bucket = "acme-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "acme-tf-locks"
}
}
# live tree, as generated -- live/dev/network/terragrunt.hcl and live/prod/network/terragrunt.hcl (byte-identical)
include "root" {
path = find_in_parent_folders()
}
locals {
environment = "dev"
account_id = "111111111111"
region = "us-east-1"
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules/network"
}
inputs = {
environment = local.environment
}
# live tree, as generated -- live/dev/app/terragrunt.hcl and live/prod/app/terragrunt.hcl (byte-identical)
include "root" {
path = find_in_parent_folders()
}
dependency "network" {
config_path = "../network"
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules/app"
}
inputs = {
vpc_id = dependency.network.outputs.vpc_id
}
# live tree, as generated -- terragrunt.stack.hcl
unit "network" {
source = "./modules/network"
path = "network"
values = {
environment = "dev"
}
}
unit "app" {
source = "./modules/app"
path = "app"
values = {
environment = "dev"
}
}
# ci/deploy.sh, as generated -- fragment, not a collected fence
#!/usr/bin/env bash
set -euo pipefail
cd live/dev
terragrunt run-all plan --terragrunt-non-interactive
terragrunt plan-all --terragrunt-non-interactive --queue-include-dir network

อาการ — จริง รันตรง:

$ terragrunt plan-all --non-interactive --no-color
ERROR unknown command: "plan-all". Terragrunt no longer forwards unknown commands by default. Use 'terragrunt run -- plan-all ...' or a supported shortcut. Learn more: https://docs.terragrunt.com/migrate/cli-redesign/#use-the-new-run-command
$ terragrunt run-all plan --non-interactive --no-color
ERROR unknown command: "run-all". Terragrunt no longer forwards unknown commands by default. Use 'terragrunt run -- run-all ...' or a supported shortcut. Learn more: https://docs.terragrunt.com/migrate/cli-redesign/#use-the-new-run-command

🐛 หา bug ในโค้ดนี้

terragrunt run-all plan --terragrunt-non-interactive
terragrunt plan-all --terragrunt-non-interactive --queue-include-dir network
เฉลย

bug เดียวกับ AI bug catalog entry 16 — ทั้งสอง command เกลื่อนอยู่ใน tutorial ก่อน 1.1 และ training data ของ AI และทั้งคู่ถูกแทนที่ด้วย run --all ของ CLI redesign 1.1 script นี้ไม่มีทางหลุดไปแบบเงียบๆ เลย — มันพังตั้งแต่ CI run แรกเลย ดังชัดเจน วิธีแก้: terragrunt run --all --non-interactive -- plan

อาการ — จริง รันตรงกับ command run --all ที่แก้แล้ว:

$ terragrunt run --all --terragrunt-non-interactive --no-color -- plan
ERROR flag `-terragrunt-non-interactive` is not a Terragrunt flag. If this is an OpenTofu/Terraform flag, use `--` to forward it (e.g., `terragrunt run -- <command> -terragrunt-non-interactive`).

🐛 หา bug ในโค้ดนี้

terragrunt run --all --terragrunt-non-interactive --no-color -- plan
เฉลย

ทุก flag ของ Terragrunt หลุด prefix terragrunt- ใน CLI redesign เดียวกับที่แทนที่ run-all — --non-interactive, --parallelism, --queue-* เปล่าๆ ทั้งหมด พร้อม environment variable เทียบเท่า TG_* flag ที่มี prefix --terragrunt-* ถูกปฏิเสธตรงๆ ไม่ใช่ถูกเมินแบบเงียบๆ ซึ่งเป็นข่าวดีเดียวใน bug นี้: CI script เก่าพังตั้งแต่ run แรกเลย แทนที่จะทำงานต่างไปแบบเงียบๆ --queue-include-dir (ไม่มี prefix terragrunt-) ยังใช้ได้อยู่จริงวันนี้ เป็น alias soft-deprecated ของ --filter — ยืนยันด้วยการรันตรง — อันตรายจริงที่นี่จึงอยู่ที่การสะกด flag แบบก่อน 1.1 เต็มรูปแบบ ไม่ใช่ตระกูล --queue-* โดยรวม วิธีแก้: ตัด prefix terragrunt- ออกจากทุก flag: terragrunt run --all --non-interactive --no-color -- plan

# excerpt, as generated -- entries/03-find-in-parent-no-arg/unit/terragrunt.hcl
include "root" {
path = find_in_parent_folders()
}

อาการ — terragrunt hcl validate จริง ทั้ง 4 unit ในต้นเดียวกัน พังแบบเดียวกันพร้อมกันหมด:

$ terragrunt hcl validate --working-dir .
Error: Error in function call
on live/dev/network/terragrunt.hcl line 2, in include "root":
2: path = find_in_parent_folders()
Call to function "find_in_parent_folders" failed: ParentFileNotFoundError:
Could not find a terragrunt.hcl in any of the parent folders of
live/dev/network/terragrunt.hcl. Cause: Traversed all the way to the root..
The include configuration in live/dev/app/terragrunt.hcl must specify a 'path' parameter
The include configuration in live/dev/network/terragrunt.hcl must specify a 'path' parameter
... (identical for live/prod/network and live/prod/app)
4 HCL validation error(s) found

🐛 หา bug ในโค้ดนี้

include "root" {
path = find_in_parent_folders()
}
เฉลย

find_in_parent_folders() ที่เรียกโดย ไม่มี argument เลย default ไปหาไฟล์ที่ชื่อ terragrunt.hcl เป๊ะๆ — ธรรมเนียมก่อน 1.1 root config ของคอร์สนี้ เหมือนคำแนะนำ Terragrunt ปัจจุบันส่วนใหญ่ ชื่อ root.hcl เจาะจงเพื่อเลี่ยงไม่ให้ไฟล์นี้ถูกเข้าใจผิดว่าเป็น unit config ของตัวเอง terragrunt hcl validate ยังพิมพ์ warning แยกต่างหากด้วยว่าใช้ terragrunt.hcl เป็น root file “is an anti-pattern… no longer recommended” การเรียกแบบไม่มี argument จริงๆ แล้วหา root.hcl ไม่เจอเลย — เพราะมันไม่ได้หาไฟล์นั้นตั้งแต่แรก ทั้งสี่ unit พังเหมือนกันเป๊ะพร้อมกันหมด ซึ่งอย่างน้อยก็ชัดเจนและทันที วิธีแก้: find_in_parent_folders("root.hcl") ระบุชื่อไฟล์จริง

# excerpt, as generated -- entries/04-no-mock-outputs/app/terragrunt.hcl
dependency "network" {
config_path = "../network"
}

อาการ — terragrunt run --all plan จริง กับทั้งต้น สดใหม่ network ไม่เคยถูก apply เลย:

$ terragrunt run --all --non-interactive --no-color -- plan
❯❯ Run Summary 2 units
Succeeded 1
Failed 1
ERROR 2 errors occurred:
* resolving dependency "network" outputs: live/dev/network/terragrunt.hcl is a
dependency of live/dev/app/terragrunt.hcl but detected no outputs. Either the
target module has not been applied yet, or the module has no outputs.
If this dependency is accessed before the outputs are ready (which can happen
during the planning phase of an unapplied stack), consider using mock_outputs: ...
* live/dev/app/terragrunt.hcl:14,12-22: Unknown variable; There is no variable named "dependency".

🐛 หา bug ในโค้ดนี้

dependency "network" {
config_path = "../network"
}
เฉลย

ดู Dependencies Between Units สำหรับ mechanism เต็มรูปแบบ — นี่คือกลไก guardrail mock_outputs_allowed_terraform_commands ของบทนั้น แต่ปัญหาต้นตอเกิดก่อนหน้านั้นหนึ่งขั้น: ไม่ใช่ “apply ถูกตัดออกจาก allow-list” แต่ไม่มี mock_outputs ประกาศไว้เลย plan ของ network เองผ่าน; app พังเพราะมันต้องการ dependency.network.outputs.vpc_id และไม่มี state จริง ไม่มีอะไรให้ fallback เลย นี่คือ run --all plan ครั้งแรกของ environment สดใหม่พอดี — สถานการณ์ที่ mock_outputs มีไว้เพื่อปลดล็อก วิธีแก้: เพิ่ม mock_outputs = { vpc_id = "mock-vpc-id" } และ mock_outputs_allowed_terraform_commands = ["plan"]

อาการ — จริง บนไฟล์ที่ AI สร้างจริง:

$ diff live/dev/network/terragrunt.hcl live/prod/network/terragrunt.hcl
(no output -- the files are byte-identical)

ทั้งสองไฟล์ประกาศ environment = "dev", account_id = "111111111111" — รวมถึงข้างใน live/prod/network/terragrunt.hcl ด้วย

🐛 หา bug ในโค้ดนี้

live/prod/network/terragrunt.hcl
locals {
environment = "dev"
account_id = "111111111111"
}
เฉลย

bug เดียวกับ AI bug catalog entry 17 — terragrunt hcl validate/hcl format --check ผ่านทั้งคู่ ไม่มีอะไรเป็น HCL ที่ invalid เลย และด้วย backend = "local" สำหรับการพิสูจน์ offline ของคอร์สนี้ ไม่มีอะไรพังตอน plan ด้วย เทียบกับ S3 backend จริงที่เล็งไป account_id = "111111111111" จากทั้ง dev และ prod นี่คือการ deploy prod เข้า AWS account ของ dev แบบเงียบๆ มีแค่ diff บนไฟล์ทั้งสองเท่านั้นที่จับการ copy-paste ที่สะอาดขนาดนี้ได้ วิธีแก้: ย้ายค่าที่ต้องต่างกันต่อ environment ไปไว้ใน env.hcl ต่อ environment (live/dev/env.hcl, live/prod/env.hcl) แล้วให้ network/terragrunt.hcl แต่ละตัวกลายเป็นเหมือนกันกับ sibling ของมัน อ่าน include.env.locals.* แทนที่จะมี locals hardcode ของตัวเอง — วิธีแก้จริงบน tree นี้พิสูจน์ไว้ด้านล่าง

include ตัวที่สองสำหรับค่าที่ share กัน ประกาศโดยไม่มี expose = true

หัวข้อที่มีชื่อว่า “include ตัวที่สองสำหรับค่าที่ share กัน ประกาศโดยไม่มี expose = true”
# excerpt, as generated -- entries/06-include-no-expose/unit/terragrunt.hcl
include "env" {
path = find_in_parent_folders("env.hcl")
merge_strategy = "no_merge"
}
inputs = {
account_id = include.env.locals.account_id
}

อาการ — terragrunt render จริง:

$ terragrunt render --format json
Error: Unsupported attribute
on unit/terragrunt.hcl line 15:
15: account_id = include.env.locals.account_id
This object does not have an attribute named "env".

🐛 หา bug ในโค้ดนี้

include "env" {
path = find_in_parent_folders("env.hcl")
merge_strategy = "no_merge"
}
เฉลย

mechanism เดียวกับ Dry Configuration with Include — expose = true คือสิ่งที่ทำให้เนื้อหาที่ parse แล้วของ include อ่านได้ผ่าน include.NAME.* ข้างใน HCL ของ unit นี้เอง ถ้าไม่มี include ก็ยัง merge ปกติสำหรับ include ที่เป็น root (นี่คือเหตุผลที่ remote_state ของ root ยังทำงานทั่วทั้ง tree นี้อยู่) แต่ include ตัวที่ สอง ที่ไม่ใช่ root และไม่มี expose ทำให้ include.env หายไปเฉยๆ ในฐานะ reference target วิธีแก้: เพิ่ม expose = true เข้า include block ของ env

# entries/07-remote-state-cross-env/main.tf -- @expect-error No stored state was found for the given workspace in the given backend.
data "terraform_remote_state" "prod_network" {
backend = "local"
config = {
path = "../../../prod/network/terraform.tfstate"
}
}

อาการ — terraform plan จริง:

Error: Unable to find remote state
with data.terraform_remote_state.prod_network,
on main.tf line 1, in data "terraform_remote_state" "prod_network":
1: data "terraform_remote_state" "prod_network" {
No stored state was found for the given workspace in the given backend.

🐛 หา bug ในโค้ดนี้

data "terraform_remote_state" "prod_network" {
backend = "local"
config = { path = "../../../prod/network/terraform.tfstate" }
}
เฉลย

mechanism เดียวกับ AI bug catalog entry 6 ใช้กับรูปทรงที่ Terragrunt live tree ล่อ AI assistant ให้ทำพอดี: เอื้อมไปใช้ raw Terraform terraform_remote_state data source เพื่ออ่าน output ของ environment อื่นแทนที่จะใช้ Terragrunt dependency block ที่เล็งไป ../../prod/network นอกจาก hard-fail ที่พิสูจน์ไว้ที่นี่ (state ที่ไม่เคยถูก apply) pattern นี้ยังข้าม mock_outputs ไปเลย ไม่มีความรู้เรื่องลำดับ run --all เลย (Terragrunt ไม่รู้เลยว่า Terraform-level read นี้มีอยู่) และ hardcode relative path ไปยัง state file ของ environment ข้างเคียงที่พังทันทีที่ backend key ของ environment ไหนก็ตามเปลี่ยน วิธีแก้: dependency block cross-environment ที่ถูกต้อง หรือถ้า dev ไม่ควรอ่าน state ของ prod เลยจริงๆ ก็ลบ reference นี้ทิ้งไปเลย

# excerpt, as generated -- entries/08-dynamodb-no-lockfile/root.hcl
remote_state {
backend = "s3"
config = {
bucket = "acme-terraform-state"
dynamodb_table = "acme-tf-locks"
}
}

วิธีแก้:

# excerpt, as generated -- entries/08-dynamodb-no-lockfile-fixed/root.hcl
remote_state {
backend = "s3"
config = {
bucket = "acme-terraform-state"
use_lockfile = true
}
}
root.hcl
remote_state {
backend = "local"
generate = { path = "backend.tf", if_exists = "overwrite_terragrunt" }
config = { path = "${get_terragrunt_dir()}/terraform.tfstate" }
}
modules/network/main.tf
variable "environment" {
type = string
}
resource "terraform_data" "vpc" {
input = "vpc-${var.environment}"
}
output "vpc_id" {
value = terraform_data.vpc.id
}
modules/app/main.tf
variable "vpc_id" {
type = string
}
resource "terraform_data" "app" {
input = var.vpc_id
}
live/dev/env.hcl
locals {
environment = "dev"
account_id = "111111111111"
region = "us-east-1"
}
live/prod/env.hcl
locals {
environment = "prod"
account_id = "222222222222"
region = "us-east-1"
}
live/dev/network/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "no_merge"
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules/network"
}
inputs = {
environment = include.env.locals.environment
}
live/prod/network/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
merge_strategy = "no_merge"
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules/network"
}
inputs = {
environment = include.env.locals.environment
}
live/dev/app/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
dependency "network" {
config_path = "../network"
mock_outputs = { vpc_id = "mock-vpc-id" }
mock_outputs_allowed_terraform_commands = ["plan"]
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules/app"
}
inputs = {
vpc_id = dependency.network.outputs.vpc_id
}
live/prod/app/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
dependency "network" {
config_path = "../network"
mock_outputs = { vpc_id = "mock-vpc-id" }
mock_outputs_allowed_terraform_commands = ["plan"]
}
terraform {
source = "${get_terragrunt_dir()}/../../../modules/app"
}
inputs = {
vpc_id = dependency.network.outputs.vpc_id
}

สังเกตว่า live/dev/network/terragrunt.hcl กับ live/prod/network/terragrunt.hcl ตอนนี้เหมือนกันเป๊ะแล้ว (เช่นเดียวกับ app ทั้งสอง unit) — วิธีแก้ของ entry 5 ไม่ใช่ “ทำให้ไฟล์ต่างกัน” มันตรงข้ามกัน: unit กลายเป็นเหมือนกันเป๊ะ byte-ต่อ-byte และมีแค่ env.hcl เท่านั้นที่ต่างกันต่อ environment นั่นคือรูปทรงจริงของ inheritance ที่โค้ดต้นฉบับขาดหายไป

พิสูจน์จริง ทั้งต้นพร้อมกัน:

$ terragrunt hcl validate --working-dir .
(no output -- 0 errors)
$ diff live/dev/network/terragrunt.hcl live/prod/network/terragrunt.hcl
(no output -- now correctly identical; env.hcl differs instead)
$ terragrunt run --all --non-interactive --no-color --working-dir . -- plan
❯❯ Run Summary 4 units
Succeeded 4
$ terragrunt find --dag --working-dir .
live/dev/network
live/prod/network
live/dev/app
live/prod/app

terragrunt render --format json จาก live/dev/network ยืนยันว่า include.env.locals.environment resolve เป็น "dev" จริง; command เดียวกันเป๊ะจาก live/prod/network resolve เป็น "prod" — ค่าจริงที่ต่างกันจากไฟล์ unit ที่มีโครงสร้างเหมือนกันเป๊ะสองไฟล์

#Bugวิธีแก้
1run-all/plan-all ใน CI scriptrun --all — real “unknown command” rejection ทั้งคู่ ก่อนแก้
2--terragrunt-non-interactive และ flag prefix ก่อน 1.1 อื่นๆ--non-interactive เปล่าๆ ฯลฯ — real “not a Terragrunt flag” rejection ก่อนแก้
3find_in_parent_folders() ไม่มี argument, root file ชื่อ root.hclfind_in_parent_folders("root.hcl") — real “Could not find a terragrunt.hcl” ทั้ง 4 unit ก่อนแก้
4dependency "network" ไม่มี mock_outputs เลยmock_outputs + mock_outputs_allowed_terraform_commands = ["plan"] — real run --all plan พัง (1 สำเร็จ 1 พัง) บน environment สดใหม่ก่อนแก้
5dev กับ prod network unit มี locals เหมือนกันเป๊ะ (รวม account_id)ย้ายค่าที่ต้องต่างไปไว้ env.hcl ต่อ environment; ไฟล์ unit กลายเป็นเหมือนกันแทน — diff จริงพิสูจน์ทั้ง bug และวิธีแก้
6include "env" ตัวที่สองไม่มี expose = trueเพิ่ม expose = true — real “This object does not have an attribute named env” ก่อนแก้
7terraform_remote_state อ่าน state ของ environment อื่นตรงๆ จากข้างใน moduleแทนที่ด้วย dependency block ที่ถูกต้อง (หรือลบทิ้ง) — real “No stored state was found” ก่อนแก้
8root.hcl remote_state ใช้ dynamodb_table ไม่มี use_lockfileuse_lockfile = true, ลบ dynamodb_table — อ้างอิงจาก docs S3 backend จริงต้องมี credential ที่คอร์สนี้ไม่ใช้เลย

สี่ใน bug แปดข้อนี้ (1, 2, 3, 6) เป็น hard failure ที่ชัดทันที — CLI เองปฏิเสธไม่ไปต่อ ไม่ว่าจะเป็น command ที่ไม่รู้จัก, flag ที่ถูกปฏิเสธ, function ที่หาไฟล์เป้าหมายไม่เจอ, หรือ reference ไปยัง include ที่ไม่เคย expose ข้อหนึ่ง (4) เป็น hard failure แต่เกิดเฉพาะ run --all plan ครั้งแรกกับ environment สดใหม่จริงๆ เท่านั้น — มันจะดูปกติตลอดไปใน demo ที่ network มี state อยู่แล้วเสมอ ข้อหนึ่ง (7) เป็น hard failure เฉพาะ state ที่ไม่เคยถูก apply ที่ระดับ Terraform ไม่ใช่ของ Terragrunt สองข้อที่เหลือ (5, 8) ไม่ error เลย: hcl validate/hcl format ผ่านทั้งคู่กับการ copy-paste dev/prod ที่จะ deploy เข้า AWS account ผิดตัว และ argument locking ที่ deprecated แต่ยังทำงานได้ ซึ่งมีแค่การอ่าน docs (หรือ DynamoDB table ที่ถูก decommission ไปแล้ว) เท่านั้นที่จะเผยให้เห็น

  • “ถ้า terragrunt hcl validate ผ่าน แปลว่า multi-environment tree ปลอดภัยที่จะ deploy จริง” พิสูจน์แล้วด้านบน: hcl validate กับ network unit ที่เหมือนกันเป๊ะสองตัวคืนค่า error ศูนย์ข้อ — ทุกบรรทัดเป็น HCL ที่ valid ตาม syntax การ validate HCL ไม่มีแนวคิดเรื่อง “ค่านี้ควรต่างจากไฟล์ sibling นั้น” เลย
  • “find_in_parent_folders() ที่ไม่มี argument หาไฟล์ root config จริงไม่ว่าจะชื่ออะไร” พิสูจน์แล้วด้านบน: มันหาไฟล์ที่ชื่อ terragrunt.hcl เจาะจงเสมอ root file ที่ชื่อ root.hcl จริง (ธรรมเนียมของคอร์สนี้ และคำแนะนำ Terragrunt ปัจจุบัน) จึงมองไม่เห็นสำหรับการเรียกแบบเปล่า ทำให้เกิด “traversed all the way to the root” จริงกับทุก unit ในต้นพร้อมกันหมด
  • “dependency block ที่ไม่มี mock_outputs พังแค่ apply เท่านั้น ไม่เคยพัง plan” พิสูจน์แล้วด้านบน: บน environment สดใหม่สมบูรณ์ที่ dependency ไม่เคยถูก apply เลยแม้แต่ครั้งเดียว run --all plan เองก็พัง — mock_outputs ไม่ใช่แค่ safety net ตอน apply เท่านั้น มันคือสิ่งที่ทำให้ plan ครั้งแรกบน stack ที่ยังไม่ apply เป็นไปได้เลย
flowchart TD
  CI["ci/deploy.sh"] -->|"1: run-all/plan-all removed"| CI
  CI -->|"2: --terragrunt-* flags rejected"| CI
  CI --> H["terragrunt hcl validate"]
  H -->|"3: find_in_parent_folders() no arg"| H
  H -->|"6: include without expose"| H
  H --> R["terragrunt run --all plan"]
  R -->|"4: dependency, no mock_outputs -- fresh env"| R
  R --> M["module-level terraform plan"]
  M -->|"7: terraform_remote_state cross-env"| M
  D["diff dev vs prod files"] -->|"5: byte-identical locals"| D
  L["root.hcl remote_state"] -->|"8: dynamodb_table, no use_lockfile"| L
แต่ละ bug อยู่ตรงไหนในเส้นทางประเมินของ live tree นี้
find_in_parent_folders() ถูกเรียกโดยไม่มี argument ใน tree ที่ root config ชื่อ root.hcl terragrunt hcl validate จริงแสดงอะไร?
environment สดใหม่ที่ network ไม่เคยถูก apply เลย และ app มี dependency "network" block ที่ไม่มี mock_outputs เลย terragrunt run --all plan จริงแสดงอะไร?
dev กับ prod network unit เหมือนกันเป๊ะ รวม account_id ด้วย terragrunt hcl validate แสดงอะไร และอะไรจับ bug นี้ได้จริง?
include "env" ตัวที่สองประกาศด้วย merge_strategy = "no_merge" แต่ไม่มี expose = true แล้ว inputs บรรทัดหนึ่งอ่าน include.env.locals.account_id terragrunt render จริงแสดงอะไร?
module ใช้ data "terraform_remote_state" "prod_network" { config = { path = "../../../prod/network/terraform.tfstate" } } } เพื่ออ่าน environment อื่นข้าม tree และ path นั้นไม่เคยถูก apply เลย terraform plan จริงแสดงอะไร และมันข้ามอะไรที่ dependency block ที่ถูกต้องจะไม่ข้าม?