Terraform

Terraformのsplat式を正しく使う: リストからの一括参照を極める

2026-04-19
NicheeLab編集部

splat式は、リストや他のコレクションから特定属性を一括で取り出すためのTerraformの構文です。aws_instance.web[*].id のように、複数インスタンスのIDをまとめて取得する用途でよく使います。

0.12以降のTerraformでは、legacy splat(.*.)よりも full splat([*]) と for式の併用が推奨です。本稿では安定動作に絞り、公式ドキュメントの挙動に基づいて実装/試験の両面から解説します。

splat式の基本: full splat([*])とlegacy(.*.)

splat式は、インデックス可能なコレクション(主にリスト/タプル、set、map/objectを値化したもの)に対して、要素ごとの属性値をまとめて抽出します。代表例は resource または module を count/for_each で複数生成したときの属性抽出です。

Terraform 0.12以降は full splat [*] が第一選択です。legacy splat .*. は互換目的で残っていますが、新規コードでは避けるのが無難です。for式([for v in xs : v.attr])はフィルタや変換を加えたい場合に使います。

  • 基本形: list_or_object[*].attribute
  • legacy形: list_or_object.*.attribute (新規では非推奨)
  • 変換を伴うなら for式: [for v in list : upper(v.name)]

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) の辞書順に対応するため、結果は安定します。

  • list/tuple: 定義順を保持 → xs[*].attr で安定順
  • set: 順序なし → 必要なら tolist() + sort() (文字列のみ)のような補助が必要
  • map/object(for_each): values(obj)[*].attr がシンプルで安定

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式の比較・使い分け

単純な属性抽出はsplat式が簡潔です。条件付き抽出や変換を同時に行いたい場合はfor式が適しています。legacy splat(.*.)は読みやすさや将来性の面で非推奨です。

Associate試験では、等価表現( xs[*].attr と [for x in xs : x.attr] )の理解、map/objectからの安定順リスト生成(values)の有無、filterの要否を見極める問題が出やすいです。

  • 抽出だけ→ splat
  • 抽出+条件/変換→ for式
  • for_each→ values(...) を挟むと安定順
手法書式例長所/注意点
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 などの関数で整形・例外吸収を行うと堅牢です。

  • モジュール×for_each: values(module.mod)[*].output
  • ネスト: flatten([for m in modules : m[*].ids]) のように段階的に処理
  • 欠損吸収: 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
}

落とし穴とガード: null/unknownと順序性

plan時点で未確定な値(unknown)やnullを含むと、splatの結果にもunknown/nullが混じることがあります。結果をそのまま他の計算に渡すと型不一致や想定外の差分を生むため、try/compact/coalesce で早めに形を整えるのが安全です。

setやobjectに対するsplatは順序が未定義になりがちです。安定順が必要なら values(...) あるいは sort(keys(...)) を用いた for式で明示的に順序を固定します。

  • null対策: coalesce(var.items, [])[*].id
  • unknown混入: try(xs[*].id, []) でフォールバック
  • 順序固定: [for k in sort(keys(obj)) : obj[k].id]

堅牢化スニペット集

# 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]
}

ミニ演習: サブネットIDの抽出とフィルタ

VPC内のプライベートサブネットをタグで絞り込み、IDの一覧を作る小さな例です。抽出はsplat、絞り込みはfor式で行い、最終的にIDだけの配列にします。

Associate試験の観点では、splatとfor式の使い分け、values()での順序安定化、compact/flattenの基本を押さえれば十分です。

  • data.aws_subnetsで取得 → values()で順序安定
  • タグ条件でfor式フィルタ
  • 最終的なID配列はsplatまたはfor式で抽出

サブネット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のリストを取得したい。最も簡潔で推奨される式はどれか。

  1. values(aws_instance.web)[*].id
  2. aws_instance.web[*].id
  3. [for r in aws_instance.web : r.id]
  4. aws_instance.web.*.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() などで早めに形を整えると安全です。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Terraform

Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける

Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...

Terraform

Terraform Authoring & Ops Pro: 上位資格の範囲と対策

上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...

Terraform

Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす

Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...

Terraform

Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義

Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...

Terraform

Terraform Data Source徹底理解:既存リソースの参照で壊さず足す

Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...

Terraformの記事一覧 (101件)
© 2026 NicheeLab All rights reserved.