TL;DR
countは数を渡してリソースを複製し、for_eachは実際の値をキーにしてリソースを作る。- 配列の値ごとにリソースを作るなら、破壊的変更を避けるために
for_eachを使う。
内容
Terraform の繰り返し構文では、リソースが作られる順序は保証されず、毎回変わる。
count
count には number を渡し、リソースを複製する。
resource "terraform_data" "count_echo" {
count = 3
provisioner "local-exec" {
command = "echo \"Terraform calls ${count.index}\" >> echo.txt"
}
}配列を使って次のように書くこともできる。
locals {
name = ["taro", "hanako", "jiro"]
}
resource "aws_cloudwatch_event_rule" "sample" {
count = length(local.name)
name = element(local.name, count.index)
schedule_expression = "rate(5 minutes)"
}しかし、これは純粋なリソースの複製ではなく、同じコードを繰り返し使っているだけである。配列の途中の要素を消すと、インデックスがずれてリソースが作り直されるなどの破壊的変更が起こりうる。この場合は for_each を使うほうがよい。
for_each
for_each は、count と違って実際の値をキーにして、繰り返しリソースを作る。
locals {
name = ["taro", "hanako", "jiro"]
}
resource "aws_cloudwatch_event_rule" "sample" {
for_each = toset(local.name)
name = each.value
schedule_expression = "rate(5 minutes)"
}map を繰り返すこともできる。
locals {
person = {
taro = { name = "taro", pref = "tokyo" }
hanako = { name = "hanako", pref = "kanagawa" }
jiro = { name = "jiro", pref = "nagano" }
}
}
resource "aws_cloudwatch_event_rule" "sample" {
for_each = { for p in local.person : p.name => p }
name = "${each.value.name}-${each.value.pref}"
schedule_expression = "rate(5 minutes)"
}toset 関数
toset は、tuple や list を set に変換する関数である。set は集合なので、要素に順序も重複もなく、すべての要素が同じ型を持つ。そのため toset で変換すると、要素の順序は失われ、重複した要素は 1 つにまとめられる。