Outputs and Locals
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”local คือ expression ที่มีชื่อ คำนวณครั้งเดียวแล้วนำกลับมาใช้ซ้ำภายใน configuration ส่วน output คือการดึงค่าออกจาก configuration ให้มองเห็นได้หลัง apply — รวมกับ variable แล้วทั้งสามตัวนี้คือ named value สามแบบที่แยกจากกันชัดเจนใน Terraform
Locals: คำนวณค่าครั้งเดียวแล้วใช้ซ้ำ
หัวข้อที่มีชื่อว่า “Locals: คำนวณค่าครั้งเดียวแล้วใช้ซ้ำ”variable ถูกตั้งค่าโดยคนที่เรียกใช้ configuration และ output ถูกเปิดเผยให้คนที่นำไปใช้ต่อ ส่วน local ไม่ใช่ทั้งสองอย่าง แต่เป็นความสะดวกภายใน เป็นชื่อที่ตั้งให้กับ expression เพื่อไม่ต้องเขียน expression เดิมซ้ำทุกครั้งที่ต้องใช้ผลลัพธ์ ไม่มีใครนอก configuration ตั้งค่า local ได้ และไม่มีใครนอก configuration อ่านค่าได้โดยตรงเช่นกัน
locals { name_prefix = "${var.environment}-${var.project}"
common_tags = { Project = var.project Environment = var.environment ManagedBy = "terraform" }
instance_count = var.environment == "prod" ? 5 : 2}
resource "aws_instance" "web" { count = local.instance_count ami = var.ami_id instance_type = var.instance_type
tags = merge(local.common_tags, { Name = "${local.name_prefix}-web-${count.index}" })}
resource "aws_s3_bucket" "app_data" { bucket = "${local.name_prefix}-app-data" tags = local.common_tags}local.common_tags ถูกคำนวณครั้งเดียวจาก var.project กับ var.environment แล้วถูกอ้างอิงทั้งจาก aws_instance.web และ aws_s3_bucket.app_data ถ้าไม่มี local ตัวนี้ expression merge(...) เดิมกับคู่ key-value ทั้งสามตัวต้องถูก copy ไปใส่ทุก resource block ที่ต้องใช้ แล้วถ้าวันหนึ่งต้องเปลี่ยน scheme การ tag ก็ต้องไล่หาทุก copy ที่ว่านั้น local.instance_count ทำหน้าที่คล้ายกันกับ conditional เล็ก ๆ การตัดสินใจ “5 ตัวใน prod, 2 ตัวที่อื่น” ถูกเขียนไว้ครั้งเดียวแล้วอ้างอิงด้วยชื่อทุกที่ที่ต้องใช้ local ไม่มีทางถูก assign โดย caller และไม่ปรากฏใน terraform plan ในฐานะสิ่งที่ override ได้ — แต่เป็นแค่ชื่อของค่าที่คำนวณไว้ภายใน configuration นี้เท่านั้น
Outputs: เปิดเผยค่าหลัง apply
หัวข้อที่มีชื่อว่า “Outputs: เปิดเผยค่าหลัง apply”output block รับค่าที่มีอยู่ภายใน configuration ปกติแล้วคือ attribute ของ resource ที่เพิ่งรู้ค่าได้หลัง apply แล้วทำให้ค่านั้นมองเห็นได้จากภายนอก configuration description ไว้บอกความหมายของค่า และ sensitive = true ซ่อนค่าจาก CLI output ทั่วไปเหมือนกับที่ทำบน variable
output "web_instance_ids" { description = "IDs of the EC2 instances created for the web tier" value = aws_instance.web[*].id}
output "app_data_bucket_arn" { description = "ARN of the S3 bucket used for application data" value = aws_s3_bucket.app_data.arn}
output "db_password" { description = "Master password generated for the RDS instance" value = aws_db_instance.main.password sensitive = true}# List every output and its valueterraform output
# Print one output's value, unquoted for scriptingterraform output web_instance_ids
# Machine-readable output, for piping into jq or another toolterraform output -json app_data_bucket_arnterraform output เฉย ๆ จะ print ทุก output ที่ declare ไว้หลัง apply ล่าสุด terraform output <name> print เฉพาะตัวเดียว และ terraform output -json render ค่า (หรือทุกค่า ถ้าไม่ระบุชื่อ) ออกมาเป็น JSON ซึ่งเหมาะกับตอนที่ CI pipeline หรือ script อื่นต้องเอาผลลัพธ์ไปใช้แบบ programmatic ไม่ใช่ให้คนอ่านเป็น plain text sensitive = true บน db_password ทำงานเหมือนกับตอนอยู่บน variable เป๊ะ ๆ Terraform จะ print (sensitive value) ใน output ของ plan/apply และใน terraform output เฉย ๆ แต่ terraform output db_password ยังคง print ค่าจริงออกมาถ้าระบุชื่อตรง ๆ และค่ายังถูกเก็บเป็น plain text ใน state อยู่ดี นี่คือการป้องกันตอนแสดงผลบน terminal กับ log ไม่ใช่ access control
Outputs คือกลไกของการ compose
หัวข้อที่มีชื่อว่า “Outputs คือกลไกของการ compose”ภายใน root configuration เดียว output ส่วนใหญ่เป็นแค่ข้อมูลไว้ดู เป็นวิธีสะดวกในการโชว์ค่าให้คนที่รัน terraform apply เห็นเฉย ๆ ความสำคัญจริง ๆ จะเห็นชัดตอนที่ configuration ไม่ได้เป็นก้อนเดียวโดด ๆ อีกต่อไป เวลาแยก infrastructure ออกเป็น module, module ไม่มีทางอื่นเลยที่จะส่งค่าที่คำนวณไว้กลับไปให้ผู้เรียกใช้ได้ นอกจากผ่าน output block ของตัวเอง — module เรื่อง Modules ในคอร์สนี้จะพูดถึง module.<name>.<output> แบบละเอียดทีหลัง เวลาแยก infrastructure ออกเป็น Terragrunt unit ที่ deploy แยกกันแทน dependency block จะอ่าน output ของ unit อื่นเพื่อเชื่อม unit เข้าด้วยกันโดยไม่ต้อง hard-code ค่าใด ๆ ระหว่างกันเลย — pattern นี้จะมี module Terragrunt แยกไว้พูดถึงทีหลัง ทั้งสองกรณีใช้กลไกเดียวกันกับที่เห็นตรงนี้ ค่าถูกรู้ขึ้นมาภายใน configuration หนึ่ง output block เปิดเผยออกมา แล้วสิ่งอื่น ไม่ว่าจะเป็น parent module หรือ dependent unit ก็นำไปใช้ต่อ
flowchart LR ve["var.environment"] --> lp["local.name_prefix"] vp["var.project"] --> lp lp --> ri["aws_instance.web"] lp --> rb["aws_s3_bucket.app_data"] rb --> ob["output app_data_bucket_arn"] ob --> dep["dependency block or module output reference"]