0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform for_each 構文いろいろ

Posted at

はじめに

今更ですが、 Terraform のループ構文である for_each を自分用備忘メモとしてまとめました。

基本的な使い方

for_each は、リストやマップを元にリソースを繰り返し生成する場合に使います。
for_each を指定すると、Terraform はリソースをループし、指定されたキーごとにリソースを作成します。

variable "buckets" {
  type = list(string)
  default = [
    "test-bucket-1",
    "test-bucket-2",
    "test-bucket-3"
  ]
}

resource "aws_s3_bucket" "toset" {
  for_each = toset(var.buckets)
  bucket = each.key
}
# plan 結果

  # aws_s3_bucket.toset["test-bucket-1"] will be created
  + resource "aws_s3_bucket" "toset" {
      + bucket                      = "test-bucket-1"
...

  # aws_s3_bucket.toset["test-bucket-2"] will be created
  + resource "aws_s3_bucket" "toset" {
      + bucket                      = "test-bucket-2"
...

  # aws_s3_bucket.toset["test-bucket-3"] will be created
  + resource "aws_s3_bucket" "toset" {
      + bucket                      = "test-bucket-3"
...

Plan: 3 to add, 0 to change, 0 to destroy.

マップでの使い方

マップを使うと、キーと値のペアでリソースを生成できます。

variable "bucket_map" {
  type = map(string)
  default = {
    "test-bucket-1" : "dev"
    "test-bucket-2" : "stg"
    "test-bucket-3" : "prod"
  }
}

resource "aws_s3_bucket" "map" {
  for_each      = var.bucket_map
  
  bucket = "${each.key}-${each.value}"
}
# plan 結果

  # aws_s3_bucket.map["test-bucket-1"] will be created
  + resource "aws_s3_bucket" "map" {
      + bucket                      = "test-bucket-1-dev"
...

  # aws_s3_bucket.map["test-bucket-2"] will be created
  + resource "aws_s3_bucket" "map" {
      + bucket                      = "test-bucket-2-stg"
...

  # aws_s3_bucket.map["test-bucket-3"] will be created
  + resource "aws_s3_bucket" "map" {
      + bucket                      = "test-bucket-3-prod"
...

Plan: 3 to add, 0 to change, 0 to destroy.

リストでのリソース生成(インデックス利用)

リストを使う場合、tolist() で明示的に set 型から list 型に変換し、リストのインデックスを使ってユニークな ID を付けることができます。
以下では、インデックス idx を利用してリソース ID をユニークにしています。

variable "buckets" {
  type    = list(string)
  default = ["apple", "banana", "orange"]
}

resource "aws_s3_bucket" "list" {
  for_each = { for idx, name in tolist(var.buckets) : idx => name }
  
  bucket = "test-${each.value}-bucket-${each.key}"
}
# plan 結果

  # aws_s3_bucket.list["0"] will be created
  + resource "aws_s3_bucket" "list" {
      + bucket                      = "test-apple-bucket-0"
...

  # aws_s3_bucket.list["1"] will be created
  + resource "aws_s3_bucket" "list" {
      + bucket                      = "test-banana-bucket-1"
...

  # aws_s3_bucket.list["2"] will be created
  + resource "aws_s3_bucket" "list" {
      + bucket                      = "test-orange-bucket-2"
...

Plan: 3 to add, 0 to change, 0 to destroy.

入れ子マップでの使い方

複雑なオブジェクトやマップの入れ子になったデータ構造を使うこともできます。
以下では、bucket_configs のそれぞれのオブジェクトから environmentforce_destroy を抽出し、リソースに設定しています。

variable "bucket_configs" {
  type = map(object({
    environment   = string
    force_destroy = bool
  }))
  default = {
    "apple"   = { environment = "dev", force_destroy = true }
    "banana"  = { environment = "stg", force_destroy = true }
    "orange"  = { environment = "prod", force_destroy = false }
  }
}
resource "aws_s3_bucket" "nest_map" {
  for_each      = var.bucket_configs
  
  bucket        = "test-${each.key}-bucket-${each.value.environment}"
  force_destroy = each.value.force_destroy
}
# plan 結果

  # aws_s3_bucket.nest_map["apple"] will be created
  + resource "aws_s3_bucket" "nest_map" {
      + bucket                      = "test-apple-bucket-dev"
      + force_destroy               = true
...

  # aws_s3_bucket.nest_map["banana"] will be created
  + resource "aws_s3_bucket" "nest_map" {
      + bucket                      = "test-banana-bucket-stg"
      + force_destroy               = true
...

  # aws_s3_bucket.nest_map["orange"] will be created
  + resource "aws_s3_bucket" "nest_map" {
      + bucket                      = "test-orange-bucket-prod"
      + force_destroy               = false
...

Plan: 3 to add, 0 to change, 0 to destroy.

条件付き for_each

フィルタを使って条件付きで for_each を使うこともできます。
以下では deploytrue のリソースのみが作成されます。

variable "bucket_configs" {
  type = map(object({
    environment   = string
    force_destroy = bool
    deploy        = bool
  }))
  default = {
    "apple"   = { environment = "dev", force_destroy = true, deploy = true }
    "banana"  = { environment = "stg", force_destroy = true, deploy = true }
    "orange"  = { environment = "prod", force_destroy = false, deploy = false }
  }
}

resource "aws_s3_bucket" "nest_map2" {
  for_each = { for key, bucket in var.bucket_configs : key => bucket if bucket.deploy }
  
  bucket        = "test-${each.key}-bucket-${each.value.environment}"
  force_destroy = each.value.force_destroy
}
# plan 結果

  # aws_s3_bucket.nest_map2["apple"] will be created
  + resource "aws_s3_bucket" "nest_map2" {
      + bucket                      = "test-apple-bucket-dev"
      + force_destroy               = true
...

  # aws_s3_bucket.nest_map2["banana"] will be created
  + resource "aws_s3_bucket" "nest_map2" {
      + bucket                      = "test-banana-bucket-stg"
      + force_destroy               = true
...

Plan: 2 to add, 0 to change, 0 to destroy.
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?