Built-in functions เป็นหนึ่งในเครื่องมือที่ทำให้ HCL มีความยืดหยุ่นสูง ใช้ช่วย transform, คำนวณ, หรือจัดการข้อมูลใน configuration โดยไม่ต้องเขียน custom code ภายนอก ทำให้ config สั้นลงและอ่านง่ายขึ้น
บทความนี้แบ่ง functions ที่ใช้บ่อยออกเป็น 5 กลุ่ม: String, Collection, Numeric, Encoding และ Filesystem พร้อมตัวอย่างการใช้งานจริง
String Functions
upper("hello") # "HELLO"
lower("HELLO") # "hello"
title("hello world") # "Hello World"
trimspace(" hello ") # "hello"
replace("hello-world", "-", "_") # "hello_world"
split(",", "a,b,c") # ["a", "b", "c"]
join("-", ["a", "b", "c"]) # "a-b-c"
format("vm-%03d", 5) # "vm-005"
substr("terraform", 0, 5) # "terra"
startswith("terraform.io", "terra") # true
format() ใช้บ่อยมากในการสร้างชื่อ resource ที่มี pattern เช่น web-prod-001, db-staging-mysql-01 โดยไม่ต้อง concat ด้วย +
Collection Functions
length([1, 2, 3]) # 3
length({a = 1, b = 2}) # 2
concat(["a"], ["b", "c"]) # ["a", "b", "c"]
merge({a = 1}, {b = 2}) # {a = 1, b = 2}
contains(["prod", "staging"], "prod") # true
keys({a = 1, b = 2}) # ["a", "b"]
values({a = 1, b = 2}) # [1, 2]
distinct(["a", "b", "a", "c"]) # ["a", "b", "c"]
sort(["c", "a", "b"]) # ["a", "b", "c"]
reverse([1, 2, 3]) # [3, 2, 1]
merge() เป็น function ที่พลิกโฉมการจัดการ default + override ใน module — สามารถ merge tag default ของบริษัทเข้ากับ tag เฉพาะของ resource ได้ในบรรทัดเดียว
locals {
default_tags = {
Environment = "production"
Team = "platform"
ManagedBy = "terraform"
}
}
resource "aws_instance" "web" {
# ...
tags = merge(local.default_tags, {
Name = "web-server-001"
Role = "frontend"
})
}
Numeric Functions
max(10, 20, 5) # 20
min(10, 20, 5) # 5
abs(-7) # 7
ceil(4.3) # 5
floor(4.7) # 4
pow(2, 10) # 1024
# ใช้คำนวณ subnet CIDR
cidrsubnet("10.0.0.0/16", 8, 1) # "10.0.1.0/24"
cidrhost("10.0.1.0/24", 5) # "10.0.1.5"
cidrsubnet() และ cidrhost() เป็น function ที่ช่วยให้สร้าง VPC/subnet แบบ programmatic ได้ เช่นแบ่ง 10.0.0.0/16 เป็น subnet ย่อย /24 จำนวน 3 ตัวโดยอัตโนมัติ
resource "aws_subnet" "private" {
count = 3
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
# → 10.0.0.0/24, 10.0.1.0/24, 10.0.2.0/24
}
Encoding Functions
jsonencode({name = "web", port = 80})
# "{\"name\":\"web\",\"port\":80}"
jsondecode("{\"name\":\"web\"}")
# {name = "web"}
yamlencode({version = 1, services = ["web"]})
# "services:\n- web\nversion: 1\n"
base64encode("hello") # "aGVsbG8="
base64decode("aGVsbG8=") # "hello"
ใช้ encoding functions ในการเตรียม user_data ของ EC2 instance, ECS task definition, หรือ Kubernetes ConfigMap/Secret
resource "aws_instance" "web" {
# ...
user_data = base64encode(templatefile("init.sh.tpl", {
app_port = var.app_port
env = var.environment
}))
}
Filesystem Functions
file("${path.module}/init.sh")
# อ่านไฟล์ในโมดูล ส่งคืน string
filebase64("${path.module}/cert.pem")
# อ่านไฟล์เป็น base64 (ใช้กับ binary)
templatefile("${path.module}/config.tpl", {
db_host = "localhost"
db_port = 5432
})
# อ่าน template + substitute variables
# template:
# DB_HOST=${db_host}
# DB_PORT=${db_port}
fileexists("${path.module}/custom.tf") # true/false
fileset("${path.module}/scripts", "*.sh") # ["init.sh", "setup.sh"]
templatefile() เหมาะกับการสร้างไฟล์ config ที่มีค่าเปลี่ยนตาม environment เช่น nginx.conf, app config, cloud-init script โดยไม่ต้อง hardcode ค่าใน HCL
Combining Functions
Function แต่ละตัวสามารถ chain ต่อกันได้เพื่อจัดการข้อมูลซับซ้อน ตัวอย่างการ generate hostname จาก tag
locals {
instances = {
web = { role = "Frontend", env = "prod" }
api = { role = "Backend", env = "prod" }
db = { role = "Database", env = "prod" }
}
# สร้าง hostname: lowercase(role) + "-" + name + "-" + env
hostnames = {
for name, cfg in local.instances :
name => format("%s-%s-%s", lower(cfg.role), name, cfg.env)
}
# = { web = "frontend-web-prod", api = "backend-api-prod", db = "database-db-prod" }
}
Best Practices
- ใช้
terraform consoleทดสอบ function call ก่อนใส่ใน config — ช่วยให้เข้าใจพฤติกรรมก่อน apply - หลีกเลี่ยง function chain ยาวเกินไป ถ้าซับซ้อนให้แยกเป็น
localsหลายตัว - Documentation ของ built-in functions อยู่ที่ developer.hashicorp.com/terraform/language/functions — เปิดไว้ตลอดเวลาเขียน config ใหม่
- อย่าพยายามสร้าง custom function ใน HCL — ถ้าต้องการ logic ซับซ้อน ให้ใช้
externaldata source หรือ provider เฉพาะ
สรุป
Built-in functions ครอบคลุมงานส่วนใหญ่ที่ต้องทำกับข้อมูลใน configuration ตั้งแต่ string manipulation, collection operation, การคำนวณ, encoding, จนถึงการอ่านไฟล์ การใช้ function ร่วมกับ locals และ for expression จะทำให้ config มีความยืดหยุ่นและบำรุงรักษาง่าย ในบทความถัดไปจะพูดถึง conditional expression และ count/for_each ซึ่งเป็นอีกเครื่องมือสำคัญในการควบคุม resource ตามเงื่อนไข

