1. 概要
merge— 複数のmapをひとつに結合するconcat— 複数のlistをひとつに連結するflatten— ネストしたlistを平坦化する- それぞれの使いどころと組み合わせパターン
Terraformでデータ構造を動的に組み立てるとき、merge・concat・flattenは欠かせない関数です。for_eachやfor式と組み合わせることで、複雑な設定を簡潔に書けます。
2. merge — 複数のmapを結合する
merge(map1, map2, ...)は、複数のmapをひとつにまとめます。後のmapのキーが優先されます(上書き)。
# terraform consoleで確認
> merge({ a = 1, b = 2 }, { b = 3, c = 4 })
{
"a" = 1
"b" = 3 # 後のmapで上書きされた
"c" = 4
}
共通タグ + リソース固有タグのパターン
terraform {
required_version = ">= 1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
variable "environment" {
description = "環境名"
type = string
default = "dev"
}
locals {
# 全リソース共通のタグ
common_tags = {
Environment = var.environment
ManagedBy = "terraform"
}
}
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
root_block_device {
volume_size = 20
volume_type = "gp3"
encrypted = true
}
# 共通タグ + リソース固有タグを merge
tags = merge(local.common_tags, {
Name = "${var.environment}-web"
Role = "web"
})
}
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.small"
root_block_device {
volume_size = 30
volume_type = "gp3"
encrypted = true
}
tags = merge(local.common_tags, {
Name = "${var.environment}-app"
Role = "app"
})
}
複数の設定mapをマージする(後勝ち)
locals {
# デフォルト設定
defaults = {
instance_type = "t3.micro"
volume_size = 20
multi_az = false
}
# 環境固有の上書き(本番環境だけ高スペック)
prd_overrides = {
instance_type = "t3.medium"
multi_az = true
}
# 後のmapが優先される(defaultsのinstance_typeはprd_overridesで上書き)
final_config = var.environment == "prd" ? merge(local.defaults, local.prd_overrides) : local.defaults
}
3. concat — 複数のlistを連結する
concat(list1, list2, ...)は、複数のlistをひとつに連結します。
# terraform consoleで確認
> concat(["a", "b"], ["c", "d"], ["e"])
["a", "b", "c", "d", "e"]
セキュリティグループのルールを動的に組み立てる
locals {
# 全環境共通のルール
base_ingress_rules = [
{ port = 443, cidr = "0.0.0.0/0", description = "HTTPS" },
{ port = 80, cidr = "0.0.0.0/0", description = "HTTP" },
]
# 開発環境追加ルール
dev_ingress_rules = var.environment == "dev" ? [
{ port = 22, cidr = "10.0.0.0/8", description = "SSH from internal" },
] : []
# 最終的なルール一覧
all_ingress_rules = concat(local.base_ingress_rules, local.dev_ingress_rules)
}
4. flatten — ネストしたlistを平坦化する
flatten(list)は、入れ子になったlistを1次元のlistに展開します。for_eachと組み合わせて使うことが多いです。
# terraform consoleで確認
> flatten(["a", ["b", "c"], ["d", ["e"]]])
["a", "b", "c", "d", "e"]
for + flattenで2次元ループを実現する
Terraformには2重for_eachがないため、flattenで展開してからfor_eachに渡すパターンがよく使われます。
locals {
environments = ["dev", "stg", "prd"]
subnets = ["subnet-a", "subnet-b", "subnet-c"]
# 2次元をflattenして1次元リストに展開
env_subnet_pairs = flatten([
for env in local.environments : [
for subnet in local.subnets : {
env = env
subnet = subnet
}
]
])
}
# { key = value } の形にしてfor_eachに渡す
resource "aws_route_table_association" "this" {
for_each = {
for pair in local.env_subnet_pairs :
"${pair.env}-${pair.subnet}" => pair
}
subnet_id = each.value.subnet
route_table_id = "rtb-example"
}
5. 組み合わせパターン
merge + concat + flatten を組み合わせる
locals {
# 環境ごとに異なるCIDRブロックを定義
vpc_cidrs = {
dev = ["10.0.0.0/24", "10.0.1.0/24"]
prd = ["10.1.0.0/24", "10.1.1.0/24", "10.1.2.0/24"]
}
# 全環境のCIDRを1つのlistに集める
all_cidrs = flatten(values(local.vpc_cidrs))
# → ["10.0.0.0/24", "10.0.1.0/24", "10.1.0.0/24", "10.1.1.0/24", "10.1.2.0/24"]
# 追加で許可するCIDR
extra_cidrs = ["192.168.0.0/16"]
# 全部まとめる
final_cidrs = concat(local.all_cidrs, local.extra_cidrs)
}
6. 関連記事
- for式の使い方 — map/listの変換と組み合わせる
- toset / tolist / tomap — 型変換関数 — list→setの変換
- for_each — map/setで動的にリソースを作成するメタ引数
- locals(ローカル値)の使い方
- length / keys / values / contains — コレクション検査
- lookup — mapから安全に値を取り出す
7. まとめ
merge(map1, map2, ...)— mapを結合。後のmapのキーが優先(上書き)。共通タグ + 固有タグに最適concat(list1, list2, ...)— listを連結。順序を保持するflatten(list)— ネストしたlistを1次元に展開。for+for_eachの2次元ループに必須- これら3つは
for式・for_each・localsと組み合わせることで最大限の効果を発揮する
動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/merge