TerraformのTry..Catchを試す

GCP

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.
タイトルとURLをコピーしました