terraformループ処理

下記3種類のループ処理が存在する
- count
- for_each
- for

countを試してみる
resource "aws_iam_user" "main" {
count = length(var.users)
name = var.users[count.index]
}
variable "users" {
type = list(string)
default = ["user1", "user2", "user3"]
}
planの結果は下記。リソースはaws_iam_user.main[0]
の名前で作成される
# aws_iam_user.main[0] will be created
+ resource "aws_iam_user" "main" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "user1"
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
# aws_iam_user.main[1] will be created
+ resource "aws_iam_user" "main" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "user2"
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
# aws_iam_user.main[2] will be created
+ resource "aws_iam_user" "main" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "user3"
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
Plan: 3 to add, 0 to change, 0 to destroy.
メタ引数が何か分からなかったので調べてみた
If a resource or module block includes a count argument whose value is a whole number, Terraform will create that many instances.
リソースを複数作成するためのものなのでメタ引数と呼んでるように見える
ただし、リソースを削除する場合は注意する必要がある
resource "aws_iam_user" "main" {
count = length(var.users)
name = var.users[count.index]
}
variable "users" {
type = list(string)
default = ["user1", "user3"]
}
例えば上記のように修正した場合は、plan結果が下記の様になる
# aws_iam_user.main[1] will be updated in-place
~ resource "aws_iam_user" "main" {
id = "user2"
~ name = "user2" -> "user3"
tags = {}
# (6 unchanged attributes hidden)
}
# aws_iam_user.main[2] will be destroyed
# (because index [2] is out of range for count)
- resource "aws_iam_user" "main" {
- arn = "arn:aws:iam::992382441056:user/user3" -> null
- force_destroy = false -> null
- id = "user3" -> null
- name = "user3" -> null
- path = "/" -> null
- tags_all = {} -> null
- unique_id = "AIDA6ODU2KZQGFGUQJEZZ" -> null
# (1 unchanged attribute hidden)
}
Plan: 0 to add, 1 to change, 1 to destroy.
本来はuser2を削除したいだけだが、user3が削除され、user2 -> user3に置き換える処理をしてしまう
その様な場合は、for_each
を使用することで対応できる

for_eachを試してみる
for_eachはリソース全体のコピーを複数作成したり、リソースコードブロック内で定義されているインラインコードブロックのコピーを複数作成することができる
また、for_eachの引数にはmap or set(string)を渡す必要がある
If a resource or module block includes a for_each argument whose value is a map or a set of strings, Terraform creates one instance for each member of that map or set.
set(string)を渡してみた
resource "aws_iam_user" "main" {
for_each = var.users
name = each.value
}
variable "users" {
type = set(string)
default = ["user1", "user2", "user3"]
}
mapも渡してみた
resource "aws_iam_user" "main" {
for_each = {
name1 = "user1"
name2 = "user2"
name3 = "user3"
}
name = each.value
}
下記の様にfor, for_eachを利用して引数を渡す方法もよく使われるらしい
resource "aws_iam_user" "main" {
for_each = { for i in local.iam_users : i.name => i }
name = each.value.name
}
locals {
iam_users = [
{
name = "user1"
},
{
name = "user2"
},
{
name = "user3"
},
]
}