splat式は、リストや他のコレクションから特定属性を一括で取り出すためのTerraformの構文です。aws_instance.web[*].id のように、複数インスタンスのIDをまとめて取得する用途でよく使います。
0.12以降のTerraformでは、legacy splat(.*.)よりも full splat([*]) と for式の併用が推奨です。本稿では安定動作に絞り、公式ドキュメントの挙動に基づいて実装/試験の両面から解説します。
splat式は、インデックス可能なコレクション(主にリスト/タプル、set、map/objectを値化したもの)に対して、要素ごとの属性値をまとめて抽出します。代表例は resource または module を count/for_each で複数生成したときの属性抽出です。
Terraform 0.12以降は full splat [*] が第一選択です。legacy splat .*. は互換目的で残っていますが、新規コードでは避けるのが無難です。for式([for v in xs : v.attr])はフィルタや変換を加えたい場合に使います。
splat式のイメージ
入力(リスト/オブジェクトの集合)
[
{ id: "i-001", name: "app-a" },
{ id: "i-002", name: "app-b" },
{ id: "i-003", name: "app-c" }
]
|
| [*].id を適用
v
[ "i-001", "i-002", "i-003" ] ← 属性idだけを一括抽出full splatの最小例
variable "instances" {
type = list(object({ id = string, name = string }))
}
locals {
ids = var.instances[*].id
names = var.instances[*].name
}
output "ids" {
value = local.ids
}
splat式は、対象がどのコレクション種別かで順序特性が変わります。list/tupleは定義順を保持します。setは順序がないため結果順は未定義です。map/objectはキー順に依存しますが、そのままsplatすると順序は明確でないことがあります。
for_eachで作られたリソースやモジュールはobject(キー付き集合)になります。安定した順序のリストが必要なら values(...) で値リストに変換します。values(map) は keys(map) の辞書順に対応するため、結果は安定します。
for_eachリソースから安定順のIDを得る
resource "aws_instance" "web" {
for_each = { a = "10.0.0.10", c = "10.0.0.12", b = "10.0.0.11" }
ami = "ami-12345678"
instance_type = "t3.micro"
private_ip = each.value
}
# 安定(キーの辞書順a,b,c)でIDを取得
locals {
web_ids = values(aws_instance.web)[*].id
}
output "web_ids" {
value = local.web_ids
}
単純な属性抽出はsplat式が簡潔です。条件付き抽出や変換を同時に行いたい場合はfor式が適しています。legacy splat(.*.)は読みやすさや将来性の面で非推奨です。
Associate試験では、等価表現( xs[*].attr と [for x in xs : x.attr] )の理解、map/objectからの安定順リスト生成(values)の有無、filterの要否を見極める問題が出やすいです。
| 手法 | 書式例 | 長所/注意点 |
|---|---|---|
| full splat([*]) | instances[*].id | 最短で読みやすい。フィルタ不可。list/tupleで順序安定。map/objectは必要に応じてvalues()を併用。 |
| legacy splat(.*.) | instances.*.id | 後方互換目的。新規は非推奨。チーム規約で禁止にする例も。 |
| for式 | [for i in instances : upper(i.name) if i.enabled] | 抽出・変換・条件を同時に適用でき柔軟。少し冗長。順序は入力に従う。 |
等価表現とフィルタの例
locals {
# 等価: 単純抽出
ids_via_splat = aws_instance.web[*].id
ids_via_for = [for r in aws_instance.web : r.id]
# 変換+条件: for式が適任
names_upper_enabled = [
for r in aws_instance.web : upper(r.tags["Name"]) if try(r.tags["enabled"], "false") == "true"
]
}
モジュールをcount/for_eachで複数呼び出す場合、module.<NAME> はコレクションになります。module.db[*].endpoint のようにsplatでまとめて出力を取れます。for_eachの場合は values(module.db)[*].endpoint のほうが順序が明確です。
入れ子のsplatやfor式を組み合わせる場面では、flatten/compact/try/coalesce などの関数で整形・例外吸収を行うと堅牢です。
モジュールの出力を安全に収集
module "db" {
source = "./modules/db"
for_each = { a = {}, b = {}, c = {} }
}
# 安定順にエンドポイント一覧
locals {
db_endpoints = values(module.db)[*].endpoint
# ネスト: 各DBモジュールが複数のreplicaエンドポイントを返すと仮定
# module.db[each].replicas は list(string)
replica_lists = values(module.db)[*].replicas
all_replicas = flatten(local.replica_lists)
# 欠損(一部のモジュールでreplicasがnull)に強くする
safe_all_replicas = flatten([for m in values(module.db) : coalesce(m.replicas, [])])
}
output "db_endpoints" {
value = local.db_endpoints
}
plan時点で未確定な値(unknown)やnullを含むと、splatの結果にもunknown/nullが混じることがあります。結果をそのまま他の計算に渡すと型不一致や想定外の差分を生むため、try/compact/coalesce で早めに形を整えるのが安全です。
setやobjectに対するsplatは順序が未定義になりがちです。安定順が必要なら values(...) あるいは sort(keys(...)) を用いた for式で明示的に順序を固定します。
堅牢化スニペット集
# 1) 入力がnullでも空配列にしてsplat可能に
locals {
safe_ids = coalesce(var.maybe_items, [])[*].id
}
# 2) 計算時例外を抑止
locals {
try_ids = try(aws_instance.web[*].id, [])
}
# 3) objectの安定順抽出(キー昇順)
locals {
ids_ordered = [for k in sort(keys(aws_instance.web)) : aws_instance.web[k].id]
}
VPC内のプライベートサブネットをタグで絞り込み、IDの一覧を作る小さな例です。抽出はsplat、絞り込みはfor式で行い、最終的にIDだけの配列にします。
Associate試験の観点では、splatとfor式の使い分け、values()での順序安定化、compact/flattenの基本を押さえれば十分です。
サブネットID抽出サンプル
data "aws_subnets" "selected" {
tags = {
Tier = "private"
}
}
# data.aws_subnets.selected.ids は set(string)
# 順序が必要なら tolist()+sort() を併用(文字列のみ可能)
locals {
subnet_ids_unsorted = data.aws_subnets.selected.ids
subnet_ids_sorted = sort(tolist(local.subnet_ids_unsorted))
# for式で更に条件(例: CIDRが/24のみ)を追加したい場合
# data.aws_subnet.this[*] のような属性がある前提の例(実環境ではdata参照の形に合わせる)
# ids_only = [for s in values(data.aws_subnet.this) : s.id if can(regex("/24
NicheeLab を読み込み中…
quot;, s.cidr_block))] } output "subnet_ids_sorted" { value = local.subnet_ids_sorted }
Associate
問題 1
for_eachで作成した aws_instance.web から、キーの昇順(a→z)でインスタンスIDのリストを取得したい。最も簡潔で推奨される式はどれか。
正解: A
for_eachの結果はobjectです。values(obj)はkeys(obj)の辞書順に対応する安定したリストを返すため、values(aws_instance.web)[*].id が簡潔かつ順序が保証される表現です。BとCは順序が明示されず、Dはlegacy splatで新規では推奨されません。
legacy splat(.*.)はもう使ってはいけませんか?
互換性のため動作しますが、Terraform 0.12以降ではfull splat([*])とfor式が推奨です。チームのスタイルガイドでも.*.を避けることが多く、試験でも[*]やfor式が前提の設問が中心です。
for_eachのリソース/モジュールから安定した順序で値を得る方法は?
values(...)を使って値リストに変換してからsplatします。例えば values(aws_instance.web)[*].id や values(module.app)[*].endpoint のように書くと、キーの辞書順に並んだ結果が得られます。
setやunknown値を含む場合の注意点は?
setは順序がないため、必要なら tolist()+sort()で並べ替えます(ソートは文字列リストのみ可能)。plan時点のunknownやnullが混じる場合は、try(..., []) や coalesce(..., [])、compact() などで早めに形を整えると安全です。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...