vague memory

うろ覚えを無くしていこうともがき苦しむ人の備忘録

Terraform for_each で map 使用時の index 取得

Terraform v0.12.6 から利用できるようになった for_each で count.index の様な連番付与が行えないか調べました。

for_each の利点無くなるので結果的に使わなかったのですが、何かに使えるかもしれないのでメモ。 定義した変数を基にするのであれば、そこに含めてしまえば良いので出番は無いでしょう。

version

  • >= v0.12.6
$ terraform version
Terraform v0.14.6
+ provider registry.terraform.io/hashicorp/aws v3.28.0

以下、便宜的に resource aws_sns_topic を指定していますが特に意味は無いです。

map

locals {
  # map定義
  servers = {
    "serverA" = { role = "web" }
    "serverB" = { role = "ap" }
    "serverC" = { role = "db" }
  }
  # mapからindex作成
  servers_index = [for k, v in local.servers : k]
}

# resource定義
resource "aws_sns_topic" "sns_topic" {
  for_each = local.servers
  name     = "${each.key}-${each.value.role}-${index(local.servers_index, each.key)}"
}

plan

  # aws_sns_topic.sns_topic["serverA"] will be created
  + resource "aws_sns_topic" "sns_topic" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverA-web-0"
      + policy = (known after apply)
    }

  # aws_sns_topic.sns_topic["serverB"] will be created
  + resource "aws_sns_topic" "sns_topic" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverB-ap-1"
      + policy = (known after apply)
    }

  # aws_sns_topic.sns_topic["serverC"] will be created
  + resource "aws_sns_topic" "sns_topic" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverC-db-2"
      + policy = (known after apply)
    }

list

  • for_each に list は直接渡せないため変換が必要
The given "for_each" argument value is unsuitable: the "for_each" argument
must be a map, or set of strings, and you have provided a value of type tuple.
locals {
  # list定義
  server_list = [
    "serverA", "serverB", "serverC"
  ]
  # listからmapに変換
  server_list_to_map = { for i, j in local.server_list : j => { index = i } }
}

# tosetを使用した場合、key,valueが同値となる
# > each.key and each.value are the same for a set
resource "aws_sns_topic" "sns_topic_list" {
  for_each = toset(local.server_list)
  name     = "${each.key}-${each.value}"
}
# 変換したmapを使用
resource "aws_sns_topic" "sns_topic_list_to_map" {
  for_each = local.server_list_to_map
  name     = "${each.key}-${each.value.index}"
}

plan

  # aws_sns_topic.sns_topic_list["serverA"] will be created
  + resource "aws_sns_topic" "sns_topic_list" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverA-serverA"
      + policy = (known after apply)
    }

  # aws_sns_topic.sns_topic_list["serverB"] will be created
  + resource "aws_sns_topic" "sns_topic_list" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverB-serverB"
      + policy = (known after apply)
    }

  # aws_sns_topic.sns_topic_list["serverC"] will be created
  + resource "aws_sns_topic" "sns_topic_list" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverC-serverC"
      + policy = (known after apply)
    }

  # aws_sns_topic.sns_topic_list_to_map["serverA"] will be created
  + resource "aws_sns_topic" "sns_topic_list_to_map" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverA-0"
      + policy = (known after apply)
    }

  # aws_sns_topic.sns_topic_list_to_map["serverB"] will be created
  + resource "aws_sns_topic" "sns_topic_list_to_map" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverB-1"
      + policy = (known after apply)
    }

  # aws_sns_topic.sns_topic_list_to_map["serverC"] will be created
  + resource "aws_sns_topic" "sns_topic_list_to_map" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "serverC-2"
      + policy = (known after apply)
    }