Lưu ý về null và ” “, try và coalesce khi khai báo biến Terraform
Vấn đề với try và default value của biến:
Ta có đoạn code như sau:
variable "example" {
type = string
default = null
}
resource "aws_instance" "example_instance" {
ami = var.example != null ? var.example : "ami-0e047ce9149262f82"
instance_type = "t2.micro"
}
output "ami_variable" {
value = aws_instance.example_instance.ami
}
Kết quả:
Outputs:
ami_variable = "ami-0e047ce9149262f82"
1. Đặt default value là null và sử dụng try:
Sửa lại code như sau:
variable "example" {
type = string
default = null
}
resource "aws_instance" "example_instance" {
ami = try(var.example, "ami-0e047ce9149262f82")
instance_type = "t2.micro"
}
output "ami_variable" {
value = aws_instance.example_instance.ami
}
Terraform apply:
aws_instance.example_instance: Refreshing state... [id=i-0d5ad3a92ec224e76]
╷
│ Error: Missing required argument
│
│ with aws_instance.example_instance,
│ on a.tf line 12, in resource "aws_instance" "example_instance":
│ 12: ami = try(var.example, "ami-0e047ce9149262f82")
│
│ "ami": one of `ami,launch_template` must be specified
Nếu đặt default là null, mà dùng try thì sẽ lỗi! Tuy nhiên nếu đảo ngược lại vị trí như sau:
variable "example" {
type = string
default = null
}
resource "aws_instance" "example_instance" {
ami = try("ami-0e047ce9149262f82", var.example)
instance_type = "t2.micro"
}
output "ami_variable" {
value = aws_instance.example_instance.ami
}
Thì kết quả trả về lại như sau:
Outputs:
ami_variable = "ami-0e047ce9149262f82"
Và nếu ta khai báo trong tfvars:
example = "ami-0464f90f5928bccb8"
Khi thực hiện apply lại:
Outputs:
ami_variable = "ami-0e047ce9149262f82"
try( ) không nhận giá trị mà ta truyền vào tfvars nữa, dù ta có destroy đi tạo lại do đã nhận được giá trị not null là ami-0464f90f5928bccb8 rồi.
Trường hợp này, kể cả dùng coalesce cũng không nhận giá trị tfvars do coalesce có đặc điểm tương tự try: nhận giá trị đầu tiên không phải null.
2. Default value là “” và sử dụng try:
variable "example" {
type = string
default = ""
}
resource "aws_instance" "example_instance" {
ami = try(var.example, "ami-0e047ce9149262f82")
instance_type = "t2.micro"
}
output "ami_variable" {
value = aws_instance.example_instance.ami
}
Sẽ gặp lỗi như sau:
aws_instance.example_instance: Creating...
╷
│ Error: creating EC2 Instance: MissingParameter: The request must contain the parameter ImageId
│ status code: 400, request id: 8f5bc7e5-11ce-482b-ba6e-a1fe23d0f4bf
│
│ with aws_instance.example_instance,
│ on a.tf line 6, in resource "aws_instance" "example_instance":
│ 6: resource "aws_instance" "example_instance" {
│
Với trường hợp đặt default là “” và không khai báo tfvars, sẽ chỉ đúng khi sử dụng coalesce!
Thử với coalesce:
Không sử dụng try nữa, mà dùng coalesce:
variable "example" {
type = string
default = null
}
resource "aws_instance" "example_instance" {
ami = coalesce(var.example, "ami-0e047ce9149262f82")
instance_type = "t2.micro"
}
output "ami_variable" {
value = aws_instance.example_instance.ami
}
Kết quả:
Outputs:
ami_variable = "ami-0e047ce9149262f82"
Tiếp tục sửa như sau:
variable "example" {
type = string
default = ""
}
resource "aws_instance" "example_instance" {
ami = coalesce(var.example, "ami-0e047ce9149262f82")
instance_type = "t2.micro"
}
output "ami_variable" {
value = aws_instance.example_instance.ami
}
Kết quả:
Outputs:
ami_variable = "ami-0e047ce9149262f82"
Bonus:
Trường hợp nếu tạo các AWS policy document khi sử dụng Terraform để tạo, mà lại dùng try, nếu không truyền policy nào thì chúng ta nên để default value = null, vì nếu để bằng “” thì try sẽ hiểu giá trị policy document = “”, mà IAM policy document lại không thể có giá trị là “”, sẽ dẫn tới việc Terraform cố gắng tạo resource rất lâu, rồi cuối cùng trả lỗi!