これは、なにをしたくて書いたもの?
Terraform 1.6で、Terraformのtesting framework(terraform testコマンド)が追加されたようなので、試してみようかなと。
Terraform 1.6 adds a test framework for enhanced code validation
今までTerraformのテストといえばlintとTerratestだったと思いますが、選択肢が広がりそうですね。
- GitHub - terraform-linters/tflint: A Pluggable Terraform Linter
- Terratest | Automated tests for your infrastructure code.
Terraform testing framework
Terraform 1.6に関するリリースブログはこちら。
Terraform 1.6 adds a test framework for enhanced code validation
この中に、Terraform test frameworkという見出しがあります。
これは、過去に提供してきた実験的機能を置き換え、テストフレームワークを導入するもののようです。
実験的機能というのは、0.15で追加されたterraform testのことのようです。
Module Testing Experiment - Configuration Language | Terraform | HashiCorp Developer
また、Terraformには以前から以下のような機能がありました。
- Custom Conditions / Input Variable Validation
- Custom Conditions / Preconditions and Postconditions
- Custom Conditions / Checks with Assertions
とはいえ、これらではテストのニーズを満たすことができません。そこで登場するのがTerraform test frameworkです、と。
Terraform testing frameworkは、ざっくり以下の感じのもののようです。
terraform testで実行する- テストファイルは、ファイル名の末尾が
.tftest.hclとなる runブロックで定義されたテストに基づいて、構成をプロビジョニングする- カスタムアサーションを評価
- テスト終了時には、プロビジョニングしたリソースを破棄
つまり、実際にリソースを作成して、検証して破棄するという流れになります。
Terraform testing frameworkに関するドキュメントは、このあたりですね。
まず、CLIについて追ってみましょう。概要から。
Testing Terraform - Terraform CLI | Terraform | HashiCorp Developer
testing frameworkは、単体テストおよびインテグレーションテストをターゲットにしています。
terraform testコマンドで実行し、構成ディレクトリ内でテストファイルを見つけてテストを行います(ざっくり〜と書いた内容と同じ)。
テストファイルは、独自の構文で書くことになります。
Tests - Configuration Language | Terraform | HashiCorp Developer
コマンド自体の説明を見てみます。
Command: test | Terraform | HashiCorp Developer
terraform testは、以下の動作を行うようです。
- 現在のディレクトリと指定されたテストディレクトリ(デフォルトで
tests)でテストファイルを検索し、テストを実行する - テストファイルの仕様に従って、
terraform planおよびterraform applyを行う - テストファイルの仕様に従って、プランファイルとステートファイルの検証を行う
- ステートはメモリー上で保持し、空から開始して既存のステートに影響を与えない
- テスト用のインフラリソースを作成し、テストの終了時に破棄する。破棄できなかった場合は、対象のリソースのリストをレポートする
使いそうなオプションとしては、テストファイルを限定する-filter、テストディレクトリを指定する-test-directory(デフォルトではtests)、
テストファイル内のrunに基づいて各ブロックのプランおよびステートを出力する-verboseあたりでしょうか。
あとは、チュートリアルを見てみましょう。
Write Terraform Tests | Terraform | HashiCorp Developer
チュートリアルを見ていると、テスト内でテストのヘルパーモジュール(通常の.tfファイル)を作成することもあるようですね。
ドキュメントを眺めるのはこれくらいにして、実際に使っていってみましょう。
環境
今回の環境は、こちら。
$ terraform version Terraform v1.6.0 on linux_amd64
テスト対象のリソース作成には、LocalStackを使うことにします。
$ python3 -V Python 3.10.12 $ localstack --version 2.3.2
起動。
$ localstack start
$ awslocal --version aws-cli/2.13.25 Python/3.11.5 Linux/5.15.0-86-generic exe/x86_64.ubuntu.22 prompt/off
テスト対象のモジュールを作成する
まずはテスト対象のルートモジュールを作成します。今回は、Amazon S3バケットを作ることにしましょう。
versions.tf
terraform { required_version = "1.6.0" required_providers { aws = { source = "hashicorp/aws" version = "5.20.0" } } }
main.tf
provider "aws" { access_key = "mock_access_key" secret_key = "mock_secret_key" region = "us-east-1" s3_use_path_style = true skip_credentials_validation = true skip_metadata_api_check = true skip_requesting_account_id = true endpoints { apigateway = "http://localhost:4566" cloudformation = "http://localhost:4566" cloudwatch = "http://localhost:4566" dynamodb = "http://localhost:4566" es = "http://localhost:4566" firehose = "http://localhost:4566" iam = "http://localhost:4566" kinesis = "http://localhost:4566" lambda = "http://localhost:4566" route53 = "http://localhost:4566" redshift = "http://localhost:4566" s3 = "http://localhost:4566" secretsmanager = "http://localhost:4566" ses = "http://localhost:4566" sns = "http://localhost:4566" sqs = "http://localhost:4566" ssm = "http://localhost:4566" stepfunctions = "http://localhost:4566" sts = "http://localhost:4566" } } resource "aws_s3_bucket" "standalone_bucket" { bucket = var.standalone_bucket_name } resource "aws_s3_bucket" "with_content_bucket" { bucket = var.with_content_bucket_name } resource "aws_s3_object" "content" { bucket = aws_s3_bucket.with_content_bucket.bucket key = var.content_key content = var.content_value }
variables.tf
variable "standalone_bucket_name" { type = string } variable "with_content_bucket_name" { type = string } variable "content_key" { type = string default = "test.txt" } variable "content_value" { type = string default = "Hello World" }
outputs.tf
output "standalone_bucket_name" { value = aws_s3_bucket.standalone_bucket.bucket } output "with_content_bucket_name" { value = aws_s3_bucket.with_content_bucket.bucket } output "content_key" { value = aws_s3_object.content.key }
とりあえず、標準モジュール構成に習ってみました。
. ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf 0 directories, 4 files
確認しておきましょう。
$ terraform init $ terraform plan -var 'standalone_bucket_name=my-bucket' -var 'with_content_bucket_name=my-with-content-bucket' $ terraform apply -var 'standalone_bucket_name=my-bucket' -var 'with_content_bucket_name=my-with-content-bucket'
OKですね。
Apply complete! Resources: 3 added, 0 changed, 0 destroyed. Outputs: content_key = "test.txt" standalone_bucket_name = "my-bucket" with_content_bucket_name = "my-with-content-bucket"
$ awslocal s3 ls 2023-10-08 21:07:29 my-with-content-bucket 2023-10-08 21:07:29 my-bucket $ awslocal s3 ls my-with-content-bucket/ 2023-10-08 21:07:29 11 test.txt $ awslocal s3 cp s3://my-with-content-bucket/test.txt - Hello World
大丈夫そうなので、リソースを破棄しておきます。
$ terraform destroy -var 'standalone_bucket_name=my-bucket' -var 'with_content_bucket_name=my-with-content-bucket'
テストを書いてみる
それでは、テストを書いてみます。テストはデフォルトではtestsディレクトリに置くらしいので、今回はこれに習うことにします。
$ mkdir tests
こんなテストを作成。テストはHCL(HashiCorp Configuration Language)で記述します。
tests/create_s3_buckets.tftest.hcl
run "create_buckets" { assert { condition = aws_s3_bucket.standalone_bucket.bucket == "my-bucket" error_message = "standalone S3 bucket name did not match expected" } assert { condition = aws_s3_bucket.with_content_bucket.bucket == "my-with-content-bucket" error_message = "with content S3 bucket name did not match expected" } assert { condition = aws_s3_object.content.key == "test.txt" error_message = "content key did not match expected" } }
terraform testを実行してみます。
$ terraform test
すると、変数の指定がないと怒られます。
tests/create_s3_buckets.tftest.hcl... in progress
run "create_buckets"... fail
╷
│ Error: No value for required variable
│
│ on variables.tf line 1:
│ 1: variable "standalone_bucket_name" {
│
│ The module under test for run block "create_buckets" has a required variable "standalone_bucket_name" with no set value. Use a -var or -var-file command line argument or add this variable
│ into a "variables" block within the test file or run block.
╵
╷
│ Error: No value for required variable
│
│ on variables.tf line 5:
│ 5: variable "with_content_bucket_name" {
│
│ The module under test for run block "create_buckets" has a required variable "with_content_bucket_name" with no set value. Use a -var or -var-file command line argument or add this
│ variable into a "variables" block within the test file or run block.
╵
tests/create_s3_buckets.tftest.hcl... tearing down
tests/create_s3_buckets.tftest.hcl... fail
Failure! 0 passed, 1 failed.
では、variablesを追加して指定。
run "create_buckets" { variables { standalone_bucket_name = "my-bucket" with_content_bucket_name = "my-with-content-bucket" } assert { condition = aws_s3_bucket.standalone_bucket.bucket == "my-bucket" error_message = "standalone S3 bucket name did not match expected" } assert { condition = aws_s3_bucket.with_content_bucket.bucket == "my-with-content-bucket" error_message = "with content S3 bucket name did not match expected" } assert { condition = aws_s3_object.content.key == "test.txt" error_message = "content key did not match expected" } }
実行。
$ terraform test
今度はOKでした。
tests/create_s3_buckets.tftest.hcl... pass Success! 1 passed, 0 failed.
書いたテストを見返してみましょう。
テストファイルに記述できる内容は、こちらです。
Tests - Configuration Language | Terraform | HashiCorp Developer
runブロックには、Terraformのコマンドをどのように実行するのかと、変数やアサーションを定義します。
アサーションの定義はCustom Conditionと同じです。
Custom Conditions - Configuration Language | Terraform | HashiCorp Developer
conditionには確認する内容をboolで評価できるもので指定し、失敗した場合はerror_messageに指定した内容が表示されます。
失敗するアサーションにしてみましょう。
assert { condition = aws_s3_bucket.standalone_bucket.bucket == "bucket" error_message = "standalone S3 bucket name did not match expected" } assert { condition = aws_s3_object.content.key == "test" error_message = "content key did not match expected" }
確認。
$ terraform test
すると、このような結果になりました。
│ Error: Test assertion failed │ │ on tests/create_s3_buckets.tftest.hcl line 8, in run "create_buckets": │ 8: condition = aws_s3_bucket.standalone_bucket.bucket == "bucket" │ ├──────────────── │ │ aws_s3_bucket.standalone_bucket.bucket is "my-bucket" │ │ standalone S3 bucket name did not match expected ╵ ╷ │ Error: Test assertion failed │ │ on tests/create_s3_buckets.tftest.hcl line 18, in run "create_buckets": │ 18: condition = aws_s3_object.content.key == "test" │ ├──────────────── │ │ aws_s3_object.content.key is "test.txt" │ │ content key did not match expected
テストも失敗ですね。
Failure! 0 passed, 1 failed.
また、テストのステップを見返してみます。
tests/create_s3_buckets.tftest.hcl... in progress run "create_buckets"... pass tests/create_s3_buckets.tftest.hcl... tearing down tests/create_s3_buckets.tftest.hcl... pass
「in progress」と出力されているところで、実際にリソースが作成されます。この時に実際のリソースを見てみると、リソースが作成されて
いることが確認できると思います。そして「tearing down」で削除されます。
なので、実際にリソースが作成されることは把握しておくことが大切ですね。
variablesは、runと同じ並びに書くこともできます。
tests/create_s3_buckets2.tftest.hcl
variables { standalone_bucket_name = "my-bucket" with_content_bucket_name = "my-with-content-bucket" } run "create_buckets" { assert { condition = aws_s3_bucket.standalone_bucket.bucket == "my-bucket" error_message = "standalone S3 bucket name did not match expected" } assert { condition = aws_s3_bucket.with_content_bucket.bucket == "my-with-content-bucket" error_message = "with content S3 bucket name did not match expected" } assert { condition = aws_s3_object.content.key == "test.txt" error_message = "content key did not match expected" } }
こうすると、runブロックが複数ある場合はトップレベルで指定したvariablesの内容が渡されることになります。また、runブロック内で
variablesを定義して、トップレベルで定義した内容を上書きすることもできます。
outputの内容を参照することもできます。
tests/create_s3_buckets_condition_outputs.tftest.hcl
run "create_buckets" { variables { standalone_bucket_name = "my-bucket" with_content_bucket_name = "my-with-content-bucket" } assert { condition = output.standalone_bucket_name == "my-bucket" error_message = "standalone S3 bucket name did not match expected" } assert { condition = output.with_content_bucket_name == "my-with-content-bucket" error_message = "with content S3 bucket name did not match expected" } assert { condition = output.content_key == "test.txt" error_message = "content key did not match expected" } }
今回は、例示がリソースの属性を見ていることが多いので、リソースの属性を見ることにします。
planとapplyでテストしてみる
runブロックではTerraformのコマンドが実行されると書きましたが、デフォルトではterraform applyが行われます。
これをterraform planに変更することもできます。またrunブロックにはterraform plan用のオプションもあるようですね。
こんな感じにしてみました。
tests/create_s3_buckets_plan_and_apply.tftest.hcl
variables { standalone_bucket_name = "my-bucket" with_content_bucket_name = "my-with-content-bucket" } run "create_buckets_plan" { command = plan assert { condition = aws_s3_bucket.standalone_bucket.bucket == "my-bucket" error_message = "standalone S3 bucket name did not match expected" } # Condition expression could not be evaluated at this time. This means you have executed a `run` block with `command = plan` and one of the values your condition depended on is not known # until after the plan has been applied. Either remove this value from your condition, or execute an `apply` command from this `run` block. # assert { # condition = aws_s3_bucket.standalone_bucket.arn == "arn:aws:s3:::my-bucket" # error_message = "standalone S3 bucket arn did not match expected" # } assert { condition = aws_s3_bucket.with_content_bucket.bucket == "my-with-content-bucket" error_message = "with content S3 bucket name did not match expected" } # Condition expression could not be evaluated at this time. This means you have executed a `run` block with `command = plan` and one of the values your condition depended on is not known # until after the plan has been applied. Either remove this value from your condition, or execute an `apply` command from this `run` block. # assert { # condition = aws_s3_bucket.with_content_bucket.arn == "arn:aws:s3:::my-with-content-bucket" # error_message = "with content S3 bucket arn did not match expected" # } assert { condition = aws_s3_object.content.key == "test.txt" error_message = "content key did not match expected" } } run "create_buckets_apply" { command = apply assert { condition = aws_s3_bucket.standalone_bucket.bucket == "my-bucket" error_message = "standalone S3 bucket name did not match expected" } assert { condition = aws_s3_bucket.standalone_bucket.arn == "arn:aws:s3:::my-bucket" error_message = "standalone S3 bucket arn did not match expected" } assert { condition = aws_s3_bucket.with_content_bucket.bucket == "my-with-content-bucket" error_message = "with content S3 bucket name did not match expected" } assert { condition = aws_s3_bucket.with_content_bucket.arn == "arn:aws:s3:::my-with-content-bucket" error_message = "with content S3 bucket arn did not match expected" } assert { condition = aws_s3_object.content.key == "test.txt" error_message = "content key did not match expected" } }
ポイントは、以下の指定ですね。
command = plan
一見、planとapplyで差がないように見えますが、以下のようにplanでは確認できないものもあります。
# Condition expression could not be evaluated at this time. This means you have executed a `run` block with `command = plan` and one of the values your condition depended on is not known
# until after the plan has been applied. Either remove this value from your condition, or execute an `apply` command from this `run` block.
# assert {
# condition = aws_s3_bucket.standalone_bucket.arn == "arn:aws:s3:::my-bucket"
# error_message = "standalone S3 bucket arn did not match expected"
# }
# Condition expression could not be evaluated at this time. This means you have executed a `run` block with `command = plan` and one of the values your condition depended on is not known
# until after the plan has been applied. Either remove this value from your condition, or execute an `apply` command from this `run` block.
# assert {
# condition = aws_s3_bucket.with_content_bucket.arn == "arn:aws:s3:::my-with-content-bucket"
# error_message = "with content S3 bucket arn did not match expected"
# }
これはエラーメッセージとterraform planの結果を実際に見ると想像がつきますが、「known after apply」つまりterraform apply後でないと
わからない値については、command = planを指定した時にアサーションすることができません。
# aws_s3_bucket.standalone_bucket will be created
+ resource "aws_s3_bucket" "standalone_bucket" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = "my-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)
}
コメントにも書いていますが、ムリに使っても以下のようなエラーメッセージが返ってきます。
│ Error: Unknown condition value │ │ on tests/create_s3_buckets_plan_and_apply.tftest.hcl line 17, in run "create_buckets_plan": │ 17: condition = aws_s3_bucket.standalone_bucket.arn == "arn:aws:s3:::my-bucket" │ ├──────────────── │ │ aws_s3_bucket.standalone_bucket.arn is a string │ │ Condition expression could not be evaluated at this time. This means you have executed a `run` block with `command = plan` and one of the values your condition depended on is not known │ until after the plan has been applied. Either remove this value from your condition, or execute an `apply` command from this `run` block.
モジュールを使う
テスト内でモジュールを使うこともできます。
たとえば、今回のテストでは最初にterraform applyした時と同じ値をvariablesに指定しています。
よって、terraform applyして
$ terraform plan -var 'standalone_bucket_name=my-bucket' -var 'with_content_bucket_name=my-with-content-bucket'
テストを実行すると(今回はひとつのテストファイルに絞っています)
$ terraform test -filter=tests/create_s3_buckets.tftest.hcl
以下のようにリソースが競合するので失敗します。
│ Error: creating Amazon S3 (Simple Storage) Bucket (my-bucket): bucket already exists
│
│ with aws_s3_bucket.standalone_bucket,
│ on main.tf line 33, in resource "aws_s3_bucket" "standalone_bucket":
│ 33: resource "aws_s3_bucket" "standalone_bucket" {
│
╵
╷
│ Error: creating Amazon S3 (Simple Storage) Bucket (my-with-content-bucket): bucket already exists
│
│ with aws_s3_bucket.with_content_bucket,
│ on main.tf line 37, in resource "aws_s3_bucket" "with_content_bucket":
│ 37: resource "aws_s3_bucket" "with_content_bucket" {
│
╵
この後、クリーンアップが動きますがすでに作成済みのリソースは削除されません。テスト内で、作成に成功したリソースのみを
削除するようです。
では、テストで作成するリソースが既存のものと競合しないようにvariablesを設定すればいいわけですが、今回はこれをランダムに
してみましょう。
5桁のランダム整数を生成するモジュールを作成。
tests/setup/random/main.tf
terraform { required_providers { random = { source = "hashicorp/random" version = "3.5.1" } } } resource "random_integer" "bucket_prefix" { min = 10000 max = 99999 } output "bucket_prefix" { value = random_integer.bucket_prefix.id }
このモジュールを実行するrunブロックを含む、テストファイルを作成。
tests/create_s3_buckets_with_module.tftest.hcl
run "generate_random" { module { source = "./tests/setup/random" } } run "create_buckets" { variables { standalone_bucket_name = "${run.generate_random.bucket_prefix}-my-bucket" with_content_bucket_name = "${run.generate_random.bucket_prefix}-my-with-content-bucket" } assert { condition = aws_s3_bucket.standalone_bucket.bucket == "${run.generate_random.bucket_prefix}-my-bucket" error_message = "standalone S3 bucket name did not match expected" } assert { condition = aws_s3_bucket.standalone_bucket.arn == "arn:aws:s3:::${run.generate_random.bucket_prefix}-my-bucket" error_message = "standalone S3 bucket arn did not match expected" } assert { condition = aws_s3_bucket.with_content_bucket.bucket == "${run.generate_random.bucket_prefix}-my-with-content-bucket" error_message = "with content S3 bucket name did not match expected" } assert { condition = aws_s3_bucket.with_content_bucket.arn == "arn:aws:s3:::${run.generate_random.bucket_prefix}-my-with-content-bucket" error_message = "with content S3 bucket arn did not match expected" } assert { condition = aws_s3_object.content.key == "test.txt" error_message = "content key did not match expected" } }
ポイントはこちらですね。
run "generate_random" { module { source = "./tests/setup/random" } }
moduleのsourceには、terraformコマンドを実行する位置からのパスを指定する必要があります。このファイルからの相対パスでは
ありません。
また、モジュールのoutputは以下のようにrun.[ブロック名].[output名]で参照できます。
run "create_buckets" { variables { standalone_bucket_name = "${run.generate_random.bucket_prefix}-my-bucket" with_content_bucket_name = "${run.generate_random.bucket_prefix}-my-with-content-bucket" } assert { condition = aws_s3_bucket.standalone_bucket.bucket == "${run.generate_random.bucket_prefix}-my-bucket" error_message = "standalone S3 bucket name did not match expected" }
では、実行。
$ terraform test
すると、モジュールがインストールされていないと言われるので
╷
│ Error: Module not installed
│
│ on tests/create_s3_buckets_with_module.tftest.hcl line 2, in run "generate_random":
│ 2: module {
│
│ This module is not yet installed. Run "terraform init" to install all modules required by this configuration.
╵
terraform initを実行します。testsディレクトリ内や、モジュールのあるディレクトリに移動する必要はありません。
$ terraform init
今度はテストに成功します。
tests/create_s3_buckets_with_module.tftest.hcl... in progress run "generate_random"... pass run "create_buckets"... pass tests/create_s3_buckets_with_module.tftest.hcl... tearing down tests/create_s3_buckets_with_module.tftest.hcl... pass
アサーションを工夫する
アサーションは、boolで指定すればいいものを書けばよいのでした。
Custom Conditions / Condition Expressions
Terraformのドキュメントでは単純に値を等値比較しているものが多いのですが、関数なども使えるのかなと。
というわけで、先ほどのモジュールを使ったランダム整数の箇所を正規表現で確認するようにしてみました。
tests/create_s3_buckets_assertion.tftest.hcl
run "generate_random" { module { source = "./tests/setup/random" } } run "create_buckets" { variables { standalone_bucket_name = "${run.generate_random.bucket_prefix}-my-bucket" with_content_bucket_name = "${run.generate_random.bucket_prefix}-my-with-content-bucket" } assert { condition = regex("\\d{5}-my-bucket", aws_s3_bucket.standalone_bucket.bucket) == aws_s3_bucket.standalone_bucket.bucket error_message = "standalone S3 bucket name did not match expected" } assert { condition = regex("\\d{5}-my-with-content-bucket", aws_s3_bucket.with_content_bucket.bucket) == aws_s3_bucket.with_content_bucket.bucket error_message = "with content S3 bucket name did not match expected" } assert { condition = aws_s3_object.content.key == "test.txt" error_message = "content key did not match expected" } }
結局、最後は等値比較しているのですが。正規表現あたりは、使いたくなるのでは?という気がしたので。
文字列内に${}を埋め込む以外にもいろいろやりたくなることはあると思うので、関数を使うことも考えておくとよいのかなと。
オマケ
使わなかったもの
今回、触れていない要素としてproviderとexpect_failuresがあります。
providerを使うと、メインとなる構成ファイルで使用しているTerraform Providerをオーバーライドできるようです。aliasも考慮される
ようです。
expect_failuresは、メインとなる構成ファイルでcheckを使用している場合で、かつテストでそれが失敗することがわかっている場合は
抑止できる機能です。
Custom Conditions / Checks with Assertions
実行するテストを絞り込む
terraform testは、terraform applyを行ってリソースを作成するので、時間がかかるリソースを作成する場合はテストにも時間がかかります。
こういう時にterraform testで一括して実行すると時間がかかるので、-filterオプションで実行するテストを指定すると便利かもしれません。
$ terraform test -filter=tests/create_s3_buckets.tftest.hcl
とはいえ、そういう状況ではテストをたくさん作らない方がいい気はしますが…。
デバッグする
各モジュールがどのような動作をしているか確認したい場合は、-verboseオプションを付けて実行するとよいでしょう。
※ -filterは実行するテストを絞っているだけです
$ terraform test -filter=tests/create_s3_buckets_with_module.tftest.hcl -verbose
すると、こんな感じで作成されたリソースの結果などを確認できます。
$ terraform test -filter=tests/create_s3_buckets_with_module.tftest.hcl -verbose
tests/create_s3_buckets_with_module.tftest.hcl... in progress
run "generate_random"... pass
# random_integer.bucket_prefix:
resource "random_integer" "bucket_prefix" {
id = "41773"
max = 99999
min = 10000
result = 41773
}
Outputs:
bucket_prefix = "41773"
run "create_buckets"... pass
# aws_s3_bucket.standalone_bucket:
resource "aws_s3_bucket" "standalone_bucket" {
arn = "arn:aws:s3:::41773-my-bucket"
bucket = "41773-my-bucket"
bucket_domain_name = "41773-my-bucket.s3.amazonaws.com"
bucket_regional_domain_name = "41773-my-bucket.s3.us-east-1.amazonaws.com"
force_destroy = false
hosted_zone_id = "Z3AQBSTGFYJSTF"
id = "41773-my-bucket"
object_lock_enabled = false
region = "us-east-1"
request_payer = "BucketOwner"
tags_all = {}
grant {
id = "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
permissions = [
"FULL_CONTROL",
]
type = "CanonicalUser"
}
versioning {
enabled = false
mfa_delete = false
}
}
# aws_s3_bucket.with_content_bucket:
resource "aws_s3_bucket" "with_content_bucket" {
arn = "arn:aws:s3:::41773-my-with-content-bucket"
bucket = "41773-my-with-content-bucket"
bucket_domain_name = "41773-my-with-content-bucket.s3.amazonaws.com"
bucket_regional_domain_name = "41773-my-with-content-bucket.s3.us-east-1.amazonaws.com"
force_destroy = false
hosted_zone_id = "Z3AQBSTGFYJSTF"
id = "41773-my-with-content-bucket"
object_lock_enabled = false
region = "us-east-1"
request_payer = "BucketOwner"
tags_all = {}
grant {
id = "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
permissions = [
"FULL_CONTROL",
]
type = "CanonicalUser"
}
versioning {
enabled = false
mfa_delete = false
}
}
# aws_s3_object.content:
resource "aws_s3_object" "content" {
bucket = "41773-my-with-content-bucket"
bucket_key_enabled = false
content = "Hello World"
content_type = "application/octet-stream"
etag = "b10a8db164e0754105b7a99be72e3fe5"
force_destroy = false
id = "test.txt"
key = "test.txt"
storage_class = "STANDARD"
tags_all = {}
}
Outputs:
content_key = "test.txt"
standalone_bucket_name = "41773-my-bucket"
with_content_bucket_name = "41773-my-with-content-bucket"
╷
│ Warning: AWS account ID not found for provider
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
│ See https://www.terraform.io/docs/providers/aws/index.html#skip_requesting_account_id for implications.
│
│ (and one more similar warning elsewhere)
╵
tests/create_s3_buckets_with_module.tftest.hcl... tearing down
╷
│ Warning: AWS account ID not found for provider
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
│ See https://www.terraform.io/docs/providers/aws/index.html#skip_requesting_account_id for implications.
│
│ (and one more similar warning elsewhere)
╵
tests/create_s3_buckets_with_module.tftest.hcl... pass
Success! 2 passed, 0 failed.
こちらの警告は今まで端折っていたのですが、LocalStackを使っている関係で出ているので今回は無視で
╷
│ Warning: AWS account ID not found for provider
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
│ See https://www.terraform.io/docs/providers/aws/index.html#skip_requesting_account_id for implications.
│
│ (and one more similar warning elsewhere)
╵
こんなところでしょうか。
おわりに
Terraform 1.6で追加された、Terraform testing frameworkを試してみました。
実際にリソースを作るのが良い時もあればそうでない時もある気はしますが、Terratestとは異なりHCLでテストを書けるのが良いですね。
使えるところでは使っていきましょう。