概要
Terraformのfor_eachでの配列のとりあつかい
- index関数を使い要素のインデックス取得
背景
Terraform 0.12からfor_eachを使い、複数のresource、dataの作成が簡便にかつ簡潔にできるようになった。
for_eachで渡せる型は、mapもしくはstringのセットになる。
以下のように定義することで、複数必要な定義が一括で定義が可能となる
例
- GCP上で複数のsource リポジトリの作成
locals {
repositories = [
"demo-1",
"demo-2"
]
}
resource "google_sourcerepo_repository" "repositories" {
depends_on = [google_project_service.google_project_service["sourcerepo"]]
for_each = toset(local.repositories)
name = each.value
}
上記のgoogle_sourcerepo_repository
リソースのようにnameのみ定義すればよい場合、配列を渡すことで簡便に複数のリソースを定義できる。しかし、リソースの要素を変えなければいけない場合、配列のみで定義するには工夫が必要である。
例えば、GCPのCloud Armorを定義する'compute_security_policy' リソースのruleブロックのpriorityは、重複定義が許されない。そのため、IPアドレス範囲のみの配列を渡し上記のように実行した、重複エラーが発生する。
配列のインデックスを取得し、プライオリティに追加することでそれらの問題は解決する。
そこでインデックスの取得について記載する。
実施環境
- Terraform 0.12.21
実行方法
index関数を用いることで、要素と一致するindex
を取得できる。
indexを使い、下記のように定義することで、indexを取得し当該値を用い演算をすることでpriorityを変更することができる。
下記、uptime-source-ips.jsonは、GCPのGUI(Cloud Console)画面より取得されるCloud MonitoringエージェントのIPアドレス一覧表となっている。
locals {
ips = jsondecode(file("./uptime-source-ips.json"))
}
resource "google_compute_security_policy" "stackdriver-monitoring" {
name = "monitoring-rules"
dynamic "rule" {
for_each = toset(local.armor.ips)
content {
action = "allow"
priority = 1000 + index(local.ips, rule.value)
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = [rule.value.ipAddress]
}
}
}
}
rule {
action = "deny(403)"
priority = "2147483647"
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = ["*"]
}
}
description = "default rule"
}
}
まとめ
for_eachに配列を渡すときの操作は癖があるから注意が必要