terraform test: 基本機能
この記事は 3-shake Advent Calendar 2023 17 日目の記事です!
この記事に書いてあること
この記事を含め 3 回に渡って terraform test の機能を紹介します。
- terraform test: 基本機能 <- 今ここ
- terraform test: 応用機能
- terraform test: 細かい挙動
terraform test とはなにか
概要
terraform test は Terraform module を実際に plan / apply して動作を確認するツールです。
ドキュメントにも明記されている通り、主な使用用途は module の動作確認になります。
できること
terraform test でできることの一例は下記のとおりです。
- terraform plan をした結果が想定どおりかをテストする。
- terraform apply をした結果が想定どおりかをテストする。
- arn のような plan 時点では
(known after apply)
となってしまうプロパティの確認 - plan ではエラーが出ないが、apply に失敗するケースの確認
- 指定したリージョンで作ろうとしたサービスが使えないなど
- arn のような plan 時点では
- terraform apply をした後に、別のリソースを使用してテストする。
- 例えば、hashicorp/http provider を使用して、http リクエストのステータスコードを確認したり
- null_resource + local-exec とかを使えば複雑なこともできそう
- テスト用のリソースの作成と削除
- テスト対象のリソースを作成する前に、依存するリソースを作成することもできる。
- 例えば EKS cluster を作成する module をテストする前に VPC を作成するなど
- テスト対象のリソースを作成する前に、依存するリソースを作成することもできる。
何が嬉しいのか
terraform test の嬉しいことは下記の点です。
- Terraform module のテストが簡単になる
- 依存するリソースやテスト対象のリソースを別々に terraform apply して目視で確認、リソースの削除を一度に行うことができ、負荷が下がります。
- テストの負荷が減るとテストをするモチベーションが増します。
- Terraform module のテストを CI に組み込みやすくなる。
- コマンド一つで必要リソースの作成、テスト、リソースの削除ができるので CI に組み込む負荷が低くなります。
- exit code で失敗がわかるので検知が容易です。
terraform test 機能説明: 基本編
基本的な使い方
terraform test
では、 .tftest.hcl
(もしくは .tftest.json
) というファイルに run
ブロックでテスト内容を定義することでテストを実行できます。
公式ドキュメントに記載されている S3 Bucket を作成する terraform をもとにサンプルを記載します。
# main.tf
provider "aws" {
region = "eu-central-1"
}
variable "bucket_prefix" {
type = string
}
resource "aws_s3_bucket" "bucket" {
bucket = "${var.bucket_prefix}-bucket"
}
output "bucket_name" {
value = aws_s3_bucket.bucket.bucket
}
上記のような terraform コードに対して、 run
ブロック内に assert
ブロックにて期待する動作を定義することでテストを行うことができます。
下記のサンプルコードでは、terraform plan を実行し、 S3 Bucket の名前が想定通りかを確認するコードです。
# valid_string_concat.tftest.hcl
variables {
bucket_prefix = "test"
}
run "valid_string_concat" {
command = plan
assert {
condition = aws_s3_bucket.bucket.bucket == "test-bucket"
error_message = "S3 bucket name did not match expected"
}
}
上記のコードがあるディレクトリで下記のコマンドを実行することでテストが実行できます。
terraform test
テストの結果は下記のように表示されます。
valid_string_concat.tftest.hcl... in progress
run "valid_string_concat"... pass
valid_string_concat.tftest.hcl... tearing down
valid_string_concat.tftest.hcl... pass
Success! 1 passed, 0 failed.
テスト結果では、 run
ブロックごとに 1 ケースとして扱われ、 pass / fail の数が表示されます。
また、デフォルトでは plan や apply の結果は表示されません。
plan / apply 結果を表示する
terraform test
を実行しただけだと、テストの結果 (success or fail) しか表示されません。
plan や apply の結果を確認したい場合、-verbose
オプションを付けます。
terraform test -verbose
-verbose
オプションをつけると、テスト結果は下記のようになります。
plan の場合は下記のように通常の terraform plan 結果が表示されます。
valid_string_concat.tftest.hcl... in progress
run "valid_string_concat"... pass
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_s3_bucket.bucket will be created
+ resource "aws_s3_bucket" "bucket" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = "test-bucket"
+ bucket_domain_name = (known after apply)
+ bucket_prefix = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ object_lock_enabled = (known after apply)
+ policy = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ tags_all = (known after apply)
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ bucket_name = "test-bucket"
valid_string_concat.tftest.hcl... tearing down
valid_string_concat.tftest.hcl... pass
Success! 1 passed, 0 failed.
apply の場合は下記のような形となり、 plan のときに (known after apply)
となっていたプロパティに値が入っていることがわかります。
valid_string_concat.tftest.hcl... in progress
run "valid_string_concat"... pass
# aws_s3_bucket.bucket:
resource "aws_s3_bucket" "bucket" {
arn = "arn:aws:s3:::saikyo-tftest-sample-bucket"
bucket = "saikyo-tftest-sample-bucket"
bucket_domain_name = "saikyo-tftest-sample-bucket.s3.amazonaws.com"
bucket_regional_domain_name = "saikyo-tftest-sample-bucket.s3.eu-central-1.amazonaws.com"
force_destroy = false
hosted_zone_id = "Z21DNDUVLTQW6Q"
id = "saikyo-tftest-sample-bucket"
object_lock_enabled = false
region = "eu-central-1"
request_payer = "BucketOwner"
tags_all = {}
grant {
id = "bf298b76840af7a84e1c52e0f05d1315347776dc9b7a3583b4aaed70df26e4f9"
permissions = [
"FULL_CONTROL",
]
type = "CanonicalUser"
}
server_side_encryption_configuration {
rule {
bucket_key_enabled = false
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
versioning {
enabled = false
mfa_delete = false
}
}
Outputs:
bucket_name = "saikyo-tftest-sample-bucket"
valid_string_concat.tftest.hcl... tearing down
valid_string_concat.tftest.hcl... pass
Success! 1 passed, 0 failed.
テストファイルのディレクトリ構成
terraform test はテスト対象の terraform コードがあるディレクトリで実行することを想定しています。
テストコードは、カレントディレクトリ内または tests/
ディレクトリ内の .tftest.hcl
か .tftest.json
を検出して実行します。
variables
terraform test
では、variables
ブロックを使用することでテスト対象の module に variable の値を渡すことができます。
下記は variables
ブロックにより module に値を渡すサンプルコードです。
# variable_precedence.tftest.hcl
variables {
bucket_prefix = "test"
}
run "uses_root_level_value" {
command = plan
assert {
condition = aws_s3_bucket.bucket.bucket == "test-bucket"
error_message = "S3 bucket name did not match expected"
}
}
run "overrides_root_level_value" {
command = plan
variables {
bucket_prefix = "other"
}
assert {
condition = aws_s3_bucket.bucket.bucket == "other-bucket"
error_message = "S3 bucket name did not match expected"
}
}
variables を指定できる場所は下記の二箇所あります。
どこに記載するかによって variable の効果範囲が異なります。
No. | 場所 | 効果範囲 |
---|---|---|
1 | tftest.hcl の直下 | tftest.hcl 内のすべての run ブロック |
2 |
run ブロック内 |
variable を設定した run ブロック |
効果範囲を変えることにより、一度 apply してから、variable を変更するようなテストもできます。
(例えば特定の variable の変更が replace を伴わないことを確認するなど)
providers
terraform test
では、provider
ブロックを使用することでテスト実行時の provider 設定を変更することができます。
下記は provider
ブロックによりテストで使用可能な AWS アカウントを制限するサンプルコードです。
# provider.tftest.hcl
provider "aws" {
allowed_account_ids = [
"123456789012",
]
}
variables {
bucket_prefix = "test"
}
run "test" {
command = plan
assert {
condition = aws_s3_bucket.bucket.bucket == "test-bucket"
error_message = "S3 bucket name did not match expected"
}
}
terraform test で参照できる値
assert
で参照できるリソースは、テスト対象の terraform コードから直接呼び出し可能な Named Values となります。
具体的には下記の値となります。
- Resources
- Input variables
- Local values
- Child module outputs
- Data sources
- Filesystem and workspace info
- Block-local values
基本編はここまでとなります。
次は terraform test の応用機能を紹介します!
Discussion