昨天我們聊到 Dynamic Blocks,學會了怎麼在資源內部用迴圈展開子設定,減少重複、讓程式碼更乾淨。
今天我們要來看看 Functions(內建函數)和 Local Values(本地變數)。這兩個東西看似只是輔助工具,但在實務專案裡卻是讓 Terraform 程式碼 「好不好維護」的關鍵差異。
想像幾個常見場景:
[80, 443, 8080]
轉成字串,做為防火牆的名稱一部分。如果全部都硬寫在資源裡,不僅程式碼變醜,日後要改也很麻煩。
這時候,Functions 能幫我們處理「資料運算」,Locals 則能讓程式碼變「乾淨好讀」。
Terraform 提供了上百個內建 Functions,涵蓋 字串、數字、布林、清單、Map、時間、雜湊 等操作。就像程式語言的標準函式庫一樣,能讓我們處理資料更靈活。
以下是一些常見的例子:
variable "env" {
default = "prod"
}
output "name" {
value = upper("${var.env}-app") # => "PROD-APP"
}
upper()
→ 全部轉大寫lower()
→ 全部轉小寫replace("hello", "l", "x")
→ "hexxo"
variable "ports" {
default = [80, 443, 8080]
}
output "joined_ports" {
value = join(",", var.ports) # => "80,443,8080"
join()
→ 清單轉字串split(",", "80,443,8080")
→ 還原成 ["80", "443", "8080"]
length(var.ports)
→ 取得長度(結果是 3)variable "images" {
default = {
dev = "nginx:1.18"
prod = "nginx:1.24"
}
}
output "prod_image" {
value = lookup(var.images, "prod", "nginx:latest")
lookup()
會去 Map 裡找 key,如果找不到,就回傳預設值。
這樣就能避免 key 不存在時 Terraform 出錯。
variable "cidrs" {
default = ["10.0.0.0/8", "192.168.0.0/16", "0.0.0.0/0"]
}
output "internal_cidrs" {
value = slice(var.cidrs, 0, 2) # => ["10.0.0.0/8", "192.168.0.0/16"]
}
slice(list, start, end)
→ 取子清單contains(list, value)
→ 檢查是否存在element(list, index)
→ 取出特定位置元素這些小工具能幫我們省掉大量重複或硬編碼。
Functions 很好用,但如果你在一個資源裡面寫太多函數,程式碼就會變得很亂。
這時候就可以用 Local Values 來先計算,再引用。我們可以把 locals 想成中間變數:
variable "env" {
default = "prod"
}
locals {
app_name = "${var.env}-app"
}
resource "google_storage_bucket" "example" {
name = local.app_name
location = "US"
}
之後只要用 local.app_name
就好,不需要在每個地方重複拼接字串。
常見做法是先在 locals
裡,把複雜邏輯收斂起來,主程式碼就保持乾淨:
variable "ports" {
default = [80, 443, 8080]
}
locals {
firewall_name = "fw-${replace(join("-", var.ports), "8080", "custom")}"
}
output "result" {
value = local.firewall_name # => "fw-80-443-custom"
}
如果沒有 locals,這段邏輯就得直接塞在資源的 name
裡,讀起來非常混亂。
特性 | Functions | Local Values |
---|---|---|
用途 | 處理資料(字串、清單、Map 等) | 封裝計算結果,統一使用 |
範例 | join(",", var.ports) |
local.app_name = "${var.env}-app" |
適合場合 | 單純轉換、計算時 | 需要重複使用、程式碼過長時 |
優點 | 直接、快速、彈性 | 可讀性高、方便維護 |
缺點 | 太多函數會讓程式碼難讀 | 本身不做運算,還是需要 Functions 搭配 |
可以這樣理解:
假設我們要建立一台 VM,每個環境的名稱和硬碟大小都不同:
variable "env" {
default = "dev"
}
locals {
env_suffix = lower(var.env)
disk_size = var.env == "prod" ? 100 : 20
}
resource "google_compute_instance" "example" {
name = "app-${local.env_suffix}"
machine_type = "e2-medium"
boot_disk {
initialize_params {
size = local.disk_size
}
}
}
app-dev
,磁碟:20GBapp-prod
,磁碟:100GB這就是 Functions + Locals 的威力:運算交給 Functions,維護交給 Locals。
今天我們學到:
這些技巧不會改變 Terraform 建立的資源數量,但會大幅提升 可讀性與可維護性,尤其是團隊合作時,大家都能快速理解程式碼的意圖。