Outputs and Locals
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”output เปิดเผยค่าออกจาก Terraform configuration หลัง apply ส่วน local คำนวณ expression ที่มีชื่อไว้ครั้งเดียวเพื่อใช้ซ้ำภายใน configuration เดียวกัน ทั้งสองไม่ใช่ variable และแก้ปัญหาคนละแบบกัน
ประกาศ output block
หัวข้อที่มีชื่อว่า “ประกาศ output block”output block มีชื่อ, value expression, และเลือกใส่ description กับ sensitive ได้ หลัง terraform apply เสร็จ ทุก output ที่ประกาศไว้จะ print ออกมา และเรียกดูซ้ำได้ทีหลังโดยไม่ต้อง apply ใหม่
resource "google_compute_instance" "web" { name = "web-server" machine_type = "e2-medium" zone = "us-central1-a"
boot_disk { initialize_params { image = "debian-cloud/debian-12" } }
network_interface { network = "default" access_config {} }}
output "instance_id" { description = "The unique identifier Google Cloud assigned to the instance" value = google_compute_instance.web.instance_id}
output "instance_external_ip" { description = "Public IP address of the web server" value = google_compute_instance.web.network_interface[0].access_config[0].nat_ip}
output "db_password" { description = "Generated password for the application database user" value = random_password.db.result sensitive = true}# Print every output declared in the configurationterraform output
# Print a single output by name, unquoted for use in scriptsterraform output instance_external_ip
# Print all outputs as JSON, for piping into another toolterraform output -jsonterraform output -json สำคัญกว่าที่ดูตอนแรก เพราะเปลี่ยน output ของเราให้เป็น structured data ที่ script อื่น, CI pipeline, หรือ wrapper tool อ่านต่อได้แน่นอน แทนที่จะไป parse ข้อความบน terminal ที่ format มาให้คนอ่าน sensitive = true บน db_password ทำงานเหมือนตอนอยู่บน variable เป๊ะ Terraform ซ่อนค่าใน terraform output และใน output ของ apply แต่ค่ายังถูกเขียนลง state file เป็น plain text อยู่ดี นี่คือการป้องกันตอนแสดงผล ไม่ใช่ access control
locals — named value แบบที่สาม
หัวข้อที่มีชื่อว่า “locals — named value แบบที่สาม”Terraform มี named value ที่ต่างกันสามแบบ และควรพูดให้ชัดว่าต่างกันตรงไหน variable ถูกตั้งค่าจากภายนอกโดยคนเรียก output ถูกเปิดเผยออกไปข้างนอกหลัง apply ส่วน local ไม่ใช่ทั้งสองแบบ แต่คือ expression ที่มีชื่อ ถูกคำนวณครั้งเดียวภายใน configuration เพื่อไม่ต้องเขียน expression เดิมซ้ำใน resource block ห้าที่
variable "environment" { type = string description = "Deployment environment name" default = "dev"}
variable "project_id" { type = string description = "GCP project ID"}
locals { name_prefix = "${var.project_id}-${var.environment}"
common_labels = { environment = var.environment managed_by = "terraform" }}
resource "google_compute_instance" "web" { name = "${local.name_prefix}-web" machine_type = "e2-medium" zone = "us-central1-a" labels = local.common_labels
boot_disk { initialize_params { image = "debian-cloud/debian-12" } }
network_interface { network = "default" access_config {} }}
resource "google_storage_bucket" "assets" { name = "${local.name_prefix}-assets" location = "US" labels = local.common_labels}ถ้าไม่มี local.name_prefix กับ local.common_labels string interpolation "${var.project_id}-${var.environment}" เดิม กับ labels map เดิม ต้องพิมพ์ซ้ำในทุก resource ที่ต้องใช้ และถ้าต้องแก้ naming scheme ทีหลังก็ต้องไล่หาทุกจุดที่ copy ไว้ locals block ไม่ได้ให้ caller ตั้งค่าได้แบบ variable และไม่ได้มองเห็นจากภายนอก configuration แบบ output แต่มีไว้แค่เก็บ expression ที่คำนวณแล้วให้อยู่จุดเดียว
output คือกลไกของการประกอบกัน
หัวข้อที่มีชื่อว่า “output คือกลไกของการประกอบกัน”ภายใน root configuration เดียว output ส่วนใหญ่เป็นแค่ข้อมูลไว้ดู เป็นวิธี print ค่าตอนจบของ apply หรือป้อนเข้า script ผ่าน terraform output -json ความสำคัญจริง ๆ จะเห็นชัดตอนเริ่มแยก infrastructure ออกเป็นชิ้นเล็ก ๆ ที่ manage แยกกัน
เวลา Terraform module หนึ่งเรียกอีก module หนึ่ง module ที่เรียกจะอ่าน output ของ child module เพื่อส่งค่าเชื่อมกัน — output "subnet_self_link" ของ networking module กลายเป็น input ของ variable "subnet" ใน compute module บทเรื่อง Modules ในคอร์สนี้จะพูดถึงการประกอบกันแบบนี้ลึกกว่านี้ แนวคิดเดียวกันนี้เกิดขึ้นอีกทีในสเกลที่ใหญ่กว่าใน Terragrunt เช่นกัน Terragrunt unit ที่ apply แยกกันจะอ่าน output ของอีก unit หนึ่งผ่าน dependency block ทำให้ VPC ที่ deploy อยู่ใน directory หนึ่งส่งชื่อ network ให้ database ที่ deploy อยู่คนละ directory ได้ โดยไม่ต้องมี Terraform state ร่วมกันเลย output คือสิ่งที่ทำให้การประกอบทั้งสองแบบนี้เป็นไปได้ — ถ้าไม่มี output ที่ประกาศไว้ชัดเจนและ stable ก็ไม่มีอะไรให้ module หรือ unit ที่ consume อ่านได้
flowchart LR v1["var.project_id"] --> l["local.name_prefix"] v2["var.environment"] --> l l --> r1["google_compute_instance.web"] l --> r2["google_storage_bucket.assets"] r1 --> o["output ip_address"] o --> ext["Consumed by another module or a Terragrunt dependency block"]