これは、なにをしたくて書いたもの?
Terraformには、nullというプロバイダーがあります。
null Providerにはnull_resource
というリソースが含まれており、こちらを使うことで他のリソースの状態変化に合わせてコマンドを
実行させたりできていました。
Terraform 1.4で、null_resource
の代替となるterraform_data
というリソースができているようなので、少し試してみたいと思います。
terraform_dataリソース
Terraform 1.4のリリースブログは、こちら。
Terraform 1.4 improves the CLI experience for Terraform Cloud
この中に、terraform_data
リソースの内容が含まれています。以下の箇所ですね。
Native replacement for null_resource
nullプロバイダーは、Terraform Registryで3番目に多くダウンロードされているプロバイダーだそうです。
In fact it’s so widely used, it’s the 3rd most-downloaded provider in the Terraform Registry.
Terraform 1.4からは、null_resource
を置き換えるビルトインの代替としてterraform_data
リソースが追加されたそうです。
機能的には、null_resource
と同じ機能をサポートしているとか。
Terraform 1.4 introduces a new terraform_data resource as a built-in replacement for the null resource. This removes the need to include the null provider in your configuration and supports all the same capabilities as null_resource.
terraform_data
リソースのドキュメントは、こちらです。
The terraform_data Managed Resource Type | Terraform | HashiCorp Developer
簡単に試してみましょう。
環境
今回の環境は、こちら。
$ terraform version Terraform v1.6.3 on linux_amd64
操作対象は、LocalStackとします。
$ python3 -V Python 3.10.12 $ localstack --version 2.3.2
起動。
$ localstack start
CLIツールも用意。
$ awslocal --version aws-cli/2.13.32 Python/3.11.6 Linux/5.15.0-88-generic exe/x86_64.ubuntu.22 prompt/off
terraform_dataリソースを試してみる
今回はAmazon SQSキューを作成し、その時にAmazon SQSのキューの一覧をAWS CLIで出力する、というお題にしましょう。
TerraformとAWS Providerのバージョン。
versions.tf
terraform { required_version = "1.6.3" required_providers { aws = { source = "hashicorp/aws" version = "5.24.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_sqs_queue" "my_queue" { name = "my-queue" } resource "terraform_data" "trigger_describe_queue" { triggers_replace = [ aws_sqs_queue.my_queue.id ] provisioner "local-exec" { command = "awslocal sqs list-queues" } }
terraform_data
リソースを使っているのは、こちら。
resource "terraform_data" "trigger_describe_queue" { triggers_replace = [ aws_sqs_queue.my_queue.id ] provisioner "local-exec" { command = "awslocal sqs list-queues" } }
triggers_replace
というのは、このインスタンスのステートに保存され、これが参照している値が変更されると置き換えられます。
ここでprovisioner
を組み合わせて、コマンドを実行したりします。
他にも、input
などもあります。こちらは、triggers_replace
がリソースの参照や属性のみが指定可能なのに対して、リテラルを指定
できるもののようです。
ドキュメントやリリースブログでは、リビジョンをリテラルで定義してinput
で参照し、terraform_data
リソース自身の状態が
変わることをトリガーになんらかの処理を起こさせるようにしています。
Terraform 1.4 improves the CLI experience for Terraform Cloud
The terraform_data Managed Resource Type | Terraform | HashiCorp Developer
今回は、Amazon SQSキューのidが変わる(=再作成されるなど)と、aws sqs list-queues
をLocalStackのAWS CLIで行うことにします。
では、確認してみましょう。
$ terraform init
まずはterraform plan
。
$ terraform plan
Amazon SQSキューと、terraform_data
リソースが変更内容として現れます。
# aws_sqs_queue.my_queue will be created + resource "aws_sqs_queue" "my_queue" { + arn = (known after apply) + content_based_deduplication = false + deduplication_scope = (known after apply) + delay_seconds = 0 + fifo_queue = false + fifo_throughput_limit = (known after apply) + id = (known after apply) + kms_data_key_reuse_period_seconds = (known after apply) + max_message_size = 262144 + message_retention_seconds = 345600 + name = "my-queue" + name_prefix = (known after apply) + policy = (known after apply) + receive_wait_time_seconds = 0 + redrive_allow_policy = (known after apply) + redrive_policy = (known after apply) + sqs_managed_sse_enabled = (known after apply) + tags_all = (known after apply) + url = (known after apply) + visibility_timeout_seconds = 30 } # terraform_data.trigger_describe_queue will be created + resource "terraform_data" "trigger_describe_queue" { + id = (known after apply) + triggers_replace = [ + (known after apply), ] }
terraform apply
します。
$ terraform apply
実行時のログ。awslocal sqs list-queues
が実行されていることが確認できます。
aws_sqs_queue.my_queue: Creating... aws_sqs_queue.my_queue: Still creating... [10s elapsed] aws_sqs_queue.my_queue: Still creating... [20s elapsed] aws_sqs_queue.my_queue: Creation complete after 26s [id=http://localhost:4566/000000000000/my-queue] terraform_data.trigger_describe_queue: Creating... terraform_data.trigger_describe_queue: Provisioning with 'local-exec'... terraform_data.trigger_describe_queue (local-exec): Executing: ["/bin/sh" "-c" "awslocal sqs list-queues"] terraform_data.trigger_describe_queue (local-exec): { terraform_data.trigger_describe_queue (local-exec): "QueueUrls": [ terraform_data.trigger_describe_queue (local-exec): "http://localhost:4566/000000000000/my-queue" terraform_data.trigger_describe_queue (local-exec): ] terraform_data.trigger_describe_queue (local-exec): } terraform_data.trigger_describe_queue: Creation complete after 3s [id=384ac258-f685-970f-b171-5db25d36bbfe]
この状態で、差分を確認。
$ terraform plan
特に変更はありません。
aws_sqs_queue.my_queue: Refreshing state... [id=http://localhost:4566/000000000000/my-queue] terraform_data.trigger_describe_queue: Refreshing state... [id=384ac258-f685-970f-b171-5db25d36bbfe] No changes. Your infrastructure matches the configuration.
では、今度はAmazon SQSのキューを、標準キューからFIFOキューに変更してみます。
resource "aws_sqs_queue" "my_queue" { name = "my-queue.fifo" fifo_queue = true } resource "terraform_data" "trigger_describe_queue" { triggers_replace = [ aws_sqs_queue.my_queue.id ] provisioner "local-exec" { command = "awslocal sqs list-queues" } }
planで確認。
$ terraform plan
Amazon SQSキューは再作成になり、それに依存してterraform_data
リソース側も再作成扱いになります。
# aws_sqs_queue.my_queue must be replaced -/+ resource "aws_sqs_queue" "my_queue" { ~ arn = "arn:aws:sqs:us-east-1:000000000000:my-queue" -> (known after apply) + deduplication_scope = (known after apply) ~ fifo_queue = false -> true # forces replacement + fifo_throughput_limit = (known after apply) ~ id = "http://localhost:4566/000000000000/my-queue" -> (known after apply) ~ kms_data_key_reuse_period_seconds = 300 -> (known after apply) ~ name = "my-queue" -> "my-queue.fifo" # forces replacement + name_prefix = (known after apply) + policy = (known after apply) + redrive_allow_policy = (known after apply) + redrive_policy = (known after apply) ~ sqs_managed_sse_enabled = true -> (known after apply) - tags = {} -> null ~ tags_all = {} -> (known after apply) ~ url = "http://localhost:4566/000000000000/my-queue" -> (known after apply) # (6 unchanged attributes hidden) } # terraform_data.trigger_describe_queue must be replaced -/+ resource "terraform_data" "trigger_describe_queue" { ~ id = "384ac258-f685-970f-b171-5db25d36bbfe" -> (known after apply) ~ triggers_replace = [ - "http://localhost:4566/000000000000/my-queue", + (known after apply), ] } Plan: 2 to add, 0 to change, 2 to destroy.
apply。
$ terraform apply
実行ログ。
terraform_data.trigger_describe_queue: Destroying... [id=384ac258-f685-970f-b171-5db25d36bbfe] terraform_data.trigger_describe_queue: Destruction complete after 0s aws_sqs_queue.my_queue: Destroying... [id=http://localhost:4566/000000000000/my-queue] aws_sqs_queue.my_queue: Destruction complete after 2s aws_sqs_queue.my_queue: Creating... aws_sqs_queue.my_queue: Still creating... [10s elapsed] aws_sqs_queue.my_queue: Still creating... [20s elapsed] aws_sqs_queue.my_queue: Creation complete after 25s [id=http://localhost:4566/000000000000/my-queue.fifo] terraform_data.trigger_describe_queue: Creating... terraform_data.trigger_describe_queue: Provisioning with 'local-exec'... terraform_data.trigger_describe_queue (local-exec): Executing: ["/bin/sh" "-c" "awslocal sqs list-queues"] terraform_data.trigger_describe_queue (local-exec): { terraform_data.trigger_describe_queue (local-exec): "QueueUrls": [ terraform_data.trigger_describe_queue (local-exec): "http://localhost:4566/000000000000/my-queue.fifo" terraform_data.trigger_describe_queue (local-exec): ] terraform_data.trigger_describe_queue (local-exec): } terraform_data.trigger_describe_queue: Creation complete after 3s [id=b560cb0e-2b42-fa13-02b2-67537a2a2cd4]
リソースが1度破棄されて再作成されるとともに、コマンド(awslocal sqs list-queues
)が実行されていることが確認できました。
こんなところでしょうか。
おわりに
Terraform 1.4で追加された、terraform_data
リソースを試してみました。
個人的にはちょっと復習を兼ねたお題でもあったのですが、リリース内容を見ていないとふつうに置いていかれていることも
よくわかりました…。
Terraform自体は便利に使っているので、もうちょっと慣れておきたいですね。