Skip to main content

Output Syntax

Output = ค่าที่ Terraform "คืน" หลัง apply — ใช้ดูค่า, ส่งให้ module อื่น, หรือ pipe ใส่ shell script

Output Block

output "<NAME>" {
value = <EXPRESSION>
description = "..."
sensitive = false
depends_on = [...]
}

ตัวอย่างพื้นฐาน

outputs.tf
output "vpc_id" {
value = aws_vpc.main.id
description = "ID of the main VPC"
}

output "public_subnet_ids" {
value = aws_subnet.public[*].id
description = "IDs of public subnets"
}

output "instance_public_ip" {
value = aws_instance.web.public_ip
description = "Public IP of web instance"
}

หลัง apply:

$ terraform apply
...
Outputs:

vpc_id = "vpc-0a1b2c3d4e5f6g7h8"
public_subnet_ids = ["subnet-aaa", "subnet-bbb"]
instance_public_ip = "54.123.45.67"

ดู Outputs

# ดูทั้งหมด
terraform output

# ดูตัวเดียว
terraform output vpc_id

# ดูแบบ raw (ไม่มี quotes — เหมาะกับ shell)
terraform output -raw instance_public_ip

# ดูแบบ JSON
terraform output -json

Use Cases

1. ส่งให้ Shell Script

#!/bin/bash
IP=$(terraform output -raw instance_public_ip)
ssh ec2-user@$IP

2. ส่งให้ Module Caller

modules/network/outputs.tf
output "vpc_id" {
value = aws_vpc.this.id
}

output "subnet_ids" {
value = aws_subnet.this[*].id
}
main.tf (caller)
module "network" {
source = "./modules/network"
# ...
}

resource "aws_instance" "web" {
subnet_id = module.network.subnet_ids[0] # ← reference module output
}

3. ส่งระหว่าง State (Remote State)

อ่านจาก state ของ project อื่น:

data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "my-tfstate"
key = "network/terraform.tfstate"
region = "ap-southeast-1"
}
}

resource "aws_instance" "app" {
subnet_id = data.terraform_remote_state.network.outputs.subnet_ids[0]
}

4. CI/CD Pipeline

GitHub Actions
- name: Deploy infrastructure
run: terraform apply -auto-approve

- name: Get outputs
id: tf
run: |
echo "url=$(terraform output -raw alb_dns)" >> $GITHUB_OUTPUT
echo "bucket=$(terraform output -raw bucket_name)" >> $GITHUB_OUTPUT

- name: Deploy app
run: aws s3 sync ./dist/ s3://${{ steps.tf.outputs.bucket }}

Output Types

Output รองรับทุก type ของ HCL:

# String
output "region" {
value = var.region
}

# Number
output "port" {
value = 8080
}

# List
output "subnet_ids" {
value = aws_subnet.public[*].id
}

# Map
output "tags" {
value = local.common_tags
}

# Object
output "database" {
value = {
host = aws_db_instance.main.address
port = aws_db_instance.main.port
name = aws_db_instance.main.db_name
}
}

# Computed/conditional
output "endpoint" {
value = var.use_https ? "https://${aws_alb.main.dns_name}" : "http://${aws_alb.main.dns_name}"
}

Description (อย่าลืม!)

output "vpc_id" {
value = aws_vpc.main.id
description = "ID of the VPC. Used by other modules to deploy resources."
}

description ปรากฏใน:

  • terraform output (เมื่อใช้ -show flag)
  • Module documentation
  • IDE intellisense

Output ที่ Computed

ค่า output อาจ "(known after apply)" ถ้า resource ยังไม่ได้สร้าง:

$ terraform plan
...
Changes to Outputs:
+ vpc_id = (known after apply)

Output Dependencies

ถ้า output ขึ้นกับ resource ที่ Terraform อาจไม่ detect → ใช้ depends_on

output "ready" {
value = "Infrastructure is ready"
depends_on = [
aws_instance.web,
aws_route53_record.dns,
aws_acm_certificate_validation.cert,
]
}

ใช้ตอน:

  • ต้องการ output ปรากฏหลัง resource สำคัญทุกตัวเสร็จ
  • ทำ "completion signal" สำหรับ external tool

Sensitive Outputs

output "db_password" {
value = random_password.db.result
sensitive = true
}

Output:

db_password = (sensitive value)

ดูค่าจริง:

terraform output db_password
# → ค่าจริง

terraform output -json
# → ค่าจริงใน JSON

ดูเพิ่มใน Sensitive Outputs

ตัวอย่าง Real-World Outputs

outputs.tf
# Network
output "vpc_id" {
value = aws_vpc.main.id
description = "VPC ID"
}

output "vpc_cidr_block" {
value = aws_vpc.main.cidr_block
description = "VPC CIDR block"
}

output "public_subnet_ids" {
value = aws_subnet.public[*].id
description = "List of public subnet IDs"
}

output "private_subnet_ids" {
value = aws_subnet.private[*].id
description = "List of private subnet IDs"
}

# Compute
output "alb_dns_name" {
value = aws_alb.main.dns_name
description = "ALB DNS name"
}

output "alb_zone_id" {
value = aws_alb.main.zone_id
description = "ALB Route53 zone ID (for alias records)"
}

# Database
output "rds_endpoint" {
value = aws_db_instance.main.endpoint
description = "RDS endpoint for application connection"
}

output "rds_address" {
value = aws_db_instance.main.address
description = "RDS hostname"
}

# Secrets (sensitive)
output "rds_password" {
value = random_password.rds.result
description = "RDS master password"
sensitive = true
}

# Computed
output "application_url" {
value = "https://${aws_route53_record.app.fqdn}"
description = "Public application URL"
}

# Map (grouped output)
output "infrastructure_summary" {
value = {
vpc_id = aws_vpc.main.id
alb_dns = aws_alb.main.dns_name
rds_endpoint = aws_db_instance.main.endpoint
bucket_name = aws_s3_bucket.data.id
}
description = "Summary of infrastructure components"
}

Best Practices

✅ DO:
- ใส่ description ทุก output
- Group related outputs (network, compute, database)
- Output เฉพาะค่าที่ "ภายนอก" ต้องใช้
- ใช้ sensitive = true กับ password/secrets

❌ DON'T:
- Output ทุก attribute (มากไป = ดูยาก)
- Hard-code prefix ใน value (ใช้ template/format)
- Output secret โดยไม่ใส่ sensitive

สรุป

  • output block = ค่าที่ Terraform "คืน" หลัง apply
  • ดูด้วย terraform output [name] (+ -raw, -json)
  • ใช้ส่งให้ module / shell script / CI/CD pipeline
  • รองรับทุก type ของ HCL
  • sensitive = true ซ่อนค่าจาก output
  • depends_on บังคับ ordering

ต่อไป → Sensitive Outputs