Viết test cho Terraform với AI: từ plan đến assert, kiểm chứng trước khi tin
terraform test giúp kiểm tra module mà không đụng vào hạ tầng đang chạy. Cách nhờ AI viết file .tftest.hcl nhanh hơn, và cách soát đầu ra của nó trước khi merge.
Hình dung tình huống này: bạn sửa một biến trong module và đẩy lên. Pipeline vẫn xanh vì không có gì kiểm tra logic đặt tên, count hay điều kiện bên trong module. Đến lúc apply ở môi trường thật thì tên bucket sai, hoặc một resource bị tạo lại ngoài ý muốn.
Từ Terraform v1.6.0, bạn có sẵn framework test để chặn tình huống này. Phần viết file test khá lặp: dựng variables, khai báo run, viết assert. AI làm tốt loại việc này, miễn là bạn nắm framework cho phép gì và biết soát kết quả AI trả về.
terraform test giải quyết vấn đề gì
Theo tài liệu của HashiCorp, Terraform tests giúp tác giả module xác nhận rằng các thay đổi cấu hình không gây lỗi phá vỡ (breaking change). Test chạy trên các tài nguyên riêng cho test, tồn tại ngắn hạn, nên không gây rủi ro cho hạ tầng và state hiện có.
Nếu bạn duy trì module dùng chung cho team, có thể đưa terraform test vào CI để mỗi thay đổi đều được kiểm tra như code ứng dụng.
Hai chế độ: integration và unit
Đây là phần quan trọng nhất khi nhờ AI viết test, vì nó quyết định test của bạn có tạo tài nguyên thật (và tốn tiền) hay không.
Mặc định command = apply: Terraform chạy trọn vẹn một lần apply, tạo hạ tầng thật rồi mới assert. Tài liệu gọi đây là tương đương integration test.
command = plan: Terraform không tạo hạ tầng mới cho run block đó. Bạn kiểm tra logic và custom condition, tương đương unit test.
Từ v1.7.0, Terraform cho phép mock dữ liệu do provider trả về khi chạy terraform test, để viết unit test chi tiết hơn. Phần tài liệu trích ở đây chưa nêu cú pháp mock, nên hãy đọc trang gốc trước khi nhờ AI sinh phần này.
Nhận định: với PR review hằng ngày, hãy bảo AI mặc định dùng command = plan. Chỉ dùng apply cho vài test tích hợp quan trọng, chạy ở tài khoản sandbox.
Cấu trúc một file test
Terraform tự tìm file có đuôi .tftest.hcl hoặc .tftest.json. Mỗi file gồm:
0 đến 1 block test
1 đến nhiều block run
0 đến 1 block variables
0 đến nhiều block provider
Các run block chạy tuần tự theo mặc định. Thứ tự variables và provider không quan trọng vì Terraform xử lý chúng ở đầu phiên test, nhưng tài liệu khuyên đặt chúng lên đầu file.
Trong run block, tài liệu liệt kê các trường: command, planoptions (mode, refresh, replace, target), variables, module, providers, assert, expectfailures, statekey và parallel.
Assertion có thể tham chiếu mọi named value trong cấu hình chính, cũng như output của run hiện tại và các run trước đó, ví dụ output.bucketname.
Ví dụ từ tài liệu: kiểm tra logic đặt tên bucket
Cấu hình cần test:
hcl
# main.tf
provider "aws" {
region = "eu-central-1"
}
variable "bucketprefix" {
type = string
}
resource "awss3bucket" "bucket" {
bucket = "${var.bucketprefix}-bucket"
}
output "bucketname" {
value = awss3bucket.bucket.bucket
}
File test tương ứng:
hcl
# validstringconcat.tftest.hcl
variables {
bucketprefix = "test"
}
run "validstringconcat" {
command = plan
assert {
condition = awss3bucket.bucket.bucket == "test-bucket"
errormessage = "S3 bucket name did not match expected"
}
}
Lệnh chạy là terraform test. Cuối phiên, Terraform báo các assertion thất bại như một phần trạng thái passed/failed của test.
Chạy song song
Thêm block test với parallel = true để các run đủ điều kiện chạy đồng thời. Với nhiều run độc lập, cách này có thể rút ngắn thời gian chạy test trong pipeline.
hcl
test {
parallel = true
}
Từng run có thể ghi đè bằng parallel = false. Terraform chỉ chạy song song những run block có parallel bật và không phụ thuộc lẫn nhau. Mặc định giá trị này là false.
Prompt template để nhờ AI viết test
Template 1: sinh test unit từ module có sẵn.
text
Bạn là kỹ sư Terraform. Viết file test cho terraform test (đuôi .tftest.hcl).
Ràng buộc:
Mỗi run block dùng command = plan (không tạo hạ tầng thật).
Đặt block variables ở đầu file.
Mỗi assert có condition và errormessage rõ ràng.
Chỉ tham chiếu resource/output/biến có trong code bên dưới. Không bịa thuộc tính.
Nếu không chắc một thuộc tính có tồn tại, hãy ghi chú thay vì đoán.
Code module (đã bỏ secret, account ID, endpoint nội bộ):
<dán main.tf, variables.tf, outputs.tf>
Hành vi cần kiểm tra:
<ví dụ: tên tài nguyên = "<prefix>-<hậu tố>">
<ví dụ: điều kiện X thì tài nguyên Y được tạo>
Trả về: một file .tftest.hcl và danh sách giả định bạn đã đặt ra.
Template 2: soát một file test AI đã viết.
text
Review file .tftest.hcl này như reviewer khó tính:
<dán file test>
Cho tôi biết:
Assert nào luôn đúng bất kể code (tautology)?
Run block nào đang dùng command = apply mà không cần thiết?
Biến/thuộc tính nào không tồn tại trong module bên dưới?
Case nào chưa được kiểm tra (giá trị biên, biến rỗng)?
Module: <dán code module>
Soát đầu ra của AI trước khi merge
AI viết HCL nhanh nhưng dễ bịa thuộc tính hoặc viết assert vô nghĩa. Quy trình nên theo:
Đọc từng run: kiểm tra command có đúng ý không. Thiếu command nghĩa là apply thật.
Chạy terraform test cục bộ trước khi mở PR.
Phá thử test: cố ý sửa logic trong module (đổi hậu tố tên chẳng hạn) và xác nhận test fail. Test không bao giờ fail là test vô dụng.
Kiểm tra tham chiếu: mọi resource, output, biến trong condition phải có trong module.
Chạy các linter/scanner IaC mà team đang dùng trên cả module lẫn thay đổi liên quan, rồi để reviewer con người duyệt.
Với test dùng apply, chạy ở tài khoản sandbox và kiểm tra tài nguyên đã được dọn sau khi test kết thúc.
Rủi ro và an toàn dữ liệu
Không dán secret vào công cụ AI: access key, token, giá trị trong file .tfvars thật, nội dung state, account ID hay endpoint nội bộ. Dùng giá trị giả như "test" trong block variables.
Đừng để AI tự quyết apply: test tích hợp tạo tài nguyên thật, có thể phát sinh chi phí và cần credential. Hãy giới hạn quyền của role chạy test.
Phần trích dẫn chưa đầy đủ: mock provider (v1.7.0), expectfailures, module và statekey có cú pháp riêng mà phần tài liệu ở đây chưa mô tả. Hãy đối chiếu với trang chính thức trước khi áp dụng.
Checklist nhanh
[ ] Terraform từ v1.6.0 trở lên (mock cần v1.7.0 trở lên)
[ ] File test đuôi .tftest.hcl hoặc .tftest.json
[ ] variables và provider đặt đầu file
[ ] Unit test dùng command = plan; apply chỉ ở sandbox
[ ] Mỗi assert có condition và errormessage rõ
[ ] Đã cố ý làm test fail để chắc nó thực sự bắt lỗi
[ ] Không có secret trong prompt hay trong file test
[ ] Đã chạy terraform test cục bộ và có người review
Kết luận: AI giúp bạn bớt gõ phần khung của file test. Việc quyết định test kiểm tra điều gì, và có thật sự bắt được lỗi hay không, vẫn là của bạn. Hãy bắt đầu từ một module nhỏ, một run dùng command = plan, rồi mở rộng dần.