Closed3

terraformループ処理

harayuharayu

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.

メタ引数が何か分からなかったので調べてみた
https://developer.hashicorp.com/terraform/language/meta-arguments/count#the-count-meta-argument

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を使用することで対応できる

harayuharayu

for_eachを試してみる
for_eachはリソース全体のコピーを複数作成したり、リソースコードブロック内で定義されているインラインコードブロックのコピーを複数作成することができる
また、for_eachの引数にはmap or set(string)を渡す必要がある

https://developer.hashicorp.com/terraform/language/meta-arguments/for_each

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"
    },
  ]
}
このスクラップは2024/08/25にクローズされました