Type Constraints
Type constraint ใน variable ช่วยจับ error ตั้งแต่ตอน plan — ไม่ต้องรอ apply ถึงจะรู้ว่า input ผิด
Primitive Types
variable "name" {
type = string
}
variable "count" {
type = number
}
variable "enabled" {
type = bool
}
Collection Types
list
ลำดับสำคัญ — index ได้
variable "azs" {
type = list(string)
default = ["ap-southeast-1a", "ap-southeast-1b", "ap-southeast-1c"]
}
# Access
locals {
first_az = var.azs[0] # "ap-southeast-1a"
count = length(var.azs) # 3
}
set
ไม่มี order, ไม่มีค่าซ้ำ
variable "users" {
type = set(string)
default = ["alice", "bob", "charlie"]
}
# ใช้กับ for_each
resource "aws_iam_user" "users" {
for_each = var.users
name = each.key
}
map
key-value pair (string keys, value type เดียว)
variable "instance_types" {
type = map(string)
default = {
dev = "t2.micro"
staging = "t2.small"
prod = "t3.large"
}
}
# Access
locals {
current = var.instance_types[var.environment]
}
Structural Types
object
typed key-value (แต่ละ key มี type ต่างกันได้)
variable "database" {
type = object({
name = string
instance_class = string
storage_gb = number
multi_az = bool
tags = map(string)
})
default = {
name = "mydb"
instance_class = "db.t3.micro"
storage_gb = 20
multi_az = false
tags = { Env = "dev" }
}
}
# Access
resource "aws_db_instance" "main" {
identifier = var.database.name
instance_class = var.database.instance_class
allocated_storage = var.database.storage_gb
multi_az = var.database.multi_az
tags = var.database.tags
}
tuple
list ที่แต่ละ position มี type ต่างกัน
variable "record" {
type = tuple([string, number, bool])
default = ["alice", 30, true]
}
# Access
locals {
name = var.record[0] # "alice" (string)
age = var.record[1] # 30 (number)
active = var.record[2] # true (bool)
}
Optional Object Attributes (Terraform 1.3+)
variable "server_config" {
type = object({
name = string
instance_type = string
monitoring = optional(bool, false) # default = false
tags = optional(map(string), {}) # default = {}
})
}
User ไม่ต้องส่ง monitoring / tags — Terraform ใส่ default ให้
any Type
ยอมรับทุก type (อย่าใช้ถ้าไม่จำเป็น)
variable "config" {
type = any
}
ใช้
any เท่าที่จำเป็น- ❌
any= ไม่มี type checking → bug หาเจอยาก - ✅ ใช้ specific type ทุกครั้งที่รู้
- ✅
anyใช้ได้เวลาเขียน module ที่ต้อง flexible จริงๆ
Nested Types
variable "network" {
type = object({
vpc_cidr = string
subnets = list(object({
name = string
cidr_block = string
availability_zone = string
public = bool
}))
})
default = {
vpc_cidr = "10.0.0.0/16"
subnets = [
{ name = "public-1", cidr_block = "10.0.1.0/24", availability_zone = "ap-southeast-1a", public = true },
{ name = "public-2", cidr_block = "10.0.2.0/24", availability_zone = "ap-southeast-1b", public = true },
{ name = "private-1", cidr_block = "10.0.10.0/24", availability_zone = "ap-southeast-1a", public = false },
]
}
}
# ใช้
resource "aws_subnet" "all" {
for_each = { for s in var.network.subnets : s.name => s }
vpc_id = aws_vpc.main.id
cidr_block = each.value.cidr_block
availability_zone = each.value.availability_zone
map_public_ip_on_launch = each.value.public
tags = { Name = each.key }
}
Type Errors
ถ้า input ผิด type → Terraform error ตอน plan:
variable "count" {
type = number
}
$ terraform apply -var="count=abc"
Error: Invalid value for input variable
The given value is not suitable for var.count: a number is required.
Type Conversion
Terraform แปลง type อัตโนมัติเมื่อทำได้:
variable "port" {
type = number
}
# OK — "8080" → 8080
terraform apply -var="port=8080"
หรือใช้ function แปลงเอง:
locals {
port_str = tostring(8080) # "8080"
port_num = tonumber("8080") # 8080
port_set = toset([1, 2, 2, 3]) # [1, 2, 3]
port_list = tolist(toset([1,2,3]))
}
ตัวอย่าง: Module Inputs
modules/vpc/variables.tf
variable "name" {
type = string
description = "VPC name"
}
variable "cidr_block" {
type = string
description = "VPC CIDR block"
default = "10.0.0.0/16"
}
variable "availability_zones" {
type = list(string)
description = "List of AZs"
default = []
}
variable "tags" {
type = map(string)
description = "Tags to apply"
default = {}
}
variable "subnet_config" {
type = object({
public_count = number
private_count = number
nat_gateway = optional(bool, true)
})
description = "Subnet configuration"
}
สรุป
| Category | Types |
|---|---|
| Primitive | string, number, bool |
| Collection | list(T), set(T), map(T) |
| Structural | object({...}), tuple([...]) |
| Special | any, null |
| Optional | optional(T, default) (Terraform 1.3+) |
Best Practices:
- ใช้ specific type เสมอ (
stringไม่ใช่any) - ใช้
objectแทน multiple variables ที่เกี่ยวข้องกัน - ใช้
optional()สำหรับ field ที่อาจไม่ได้ส่งมา - Nested types ทำให้ config readable แต่อย่าซ้อนเกิน 3 ระดับ
ต่อไป → Variable Definition File