TerraformのTry..Catchを試す
やりたかったこと
dev環境でだけリストに定義された名前のCloud Storageバケットを作りたい。
環境
workspaceにdevとprodがある状態。
$ terraform workspace list
default
dev
* prod
やりたいこと
dev環境だけにデバッグ用のクラウドストレージを作りたい。
locals{
buckets = {
dev = ["debug","verbose"]
}
}
resource "google_storage_bucket" "buckets" {
for_each = toset(local.buckets[terraform.workspace])
name = "bucket-${each.value}"
location = "asia-northeast1"
}
エラー
local.buckets['prod']が定義されていないのでprod環境でplanが通らない。
$ terraform workspace select prod
Switched to workspace "prod".
$ terraform plan
╷
│ Error: Invalid index
│
│ on functions.tf line 19, in resource "google_storage_bucket" "buckets":
│ 19: for_each = toset(local.buckets[terraform.workspace])
│ ├────────────────
│ │ local.buckets is object with 2 attributes
│ │ terraform.workspace is "prod"
│
│ The given key does not identify an element in this collection value.
╵
原因
toset()は引数の中身を判断してセットに変換するものの、オブジェクトがnullの場合は要素のないセットを返さずExceptionをあげるため。
解決策
TerraformのTry..Catch
Try/Catchでtoset()に失敗したときに空のマップを返してあげるようにすると、ローカル変数が未定義でもtoset()の二つ目に指定された要素数が0のセットが返ってくる。
resource "google_storage_bucket" "buckets" {
for_each = try(toset(local.buckets[terraform.workspace]),{})
name = "bucket-${each.value}"
location = "asia-northeast1"
}
実行結果
サイズが0のセットでfor_eachループがまわるようになり、prod環境のplanが通るようになったなった。
$ terraform workspace select prod
$ terraform plan
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and
found no differences, so no changes are needed.
$ terraform apply
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and
found no differences, so no changes are needed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
prod環境向けにサイズ0のリストを定義する
リソースを作る予定がない環境でも単純に空のリストを用意しておけばよい。
locals{
buckets = {
dev = ["debug","verbose"]
prod = []
}
}
resource "google_storage_bucket" "buckets" {
for_each = toset(local.buckets[terraform.workspace])
name = "bucket-${each.value}"
location = "asia-northeast1"
}
実行結果
$ terraform plan
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and
found no differences, so no changes are needed.