これは、なにをしたくて書いたもの?
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自体は便利に使っているので、もうちょっと慣れておきたいですね。