Terraform

Terraform 組み込み関数 速習ガイド: length / lookup / templatefile を中心に

2026-04-19
NicheeLab編集部

Terraform の組み込み関数は、宣言をシンプルに保ちつつ可変性を扱う要となります。特に length、lookup、templatefile は Associate レベルでも頻出です。

本稿では公式仕様に沿って挙動を押さえ、試験で問われやすいポイントと実務のベストプラクティスを一気に整理します。

Terraform 表現言語と関数の基本

Terraform の関数は式として評価され、計画時に可能な限り具体化されます。未知の値が混じる(例: 外部データソース)場合は、評価を遅延できない関数はエラーになることがあります。関数は副作用を持たない純粋関数として扱われます。

型は重要です。length は文字列・リスト・セット・マップ(オブジェクト含む)に適用でき、数値やブールには適用できません。lookup はマップから値を取り出し、キーが無いときのみデフォルトを返します(キーが存在し値が null の場合は null を返す点が試験でも狙われます)。templatefile はファイルパスと変数マップを受け取り、テンプレートを展開します。

  • 関数は宣言的であり副作用なし。結果は入力のみで決まる
  • null と空コレクションは別物。length([]) は 0、length(null) はエラー
  • path.module はモジュール相対パス。templatefile と併用が定番

関数が関わる評価の流れ(概念図)

Inputs (variables, data) ---> Expressions (functions)
                                 |         \
                                 |          +--> locals
                                 v
                         Resource arguments ----> Plan ----> Apply

Files: templatefile(path.module/...) --reads--> Template --renders--> String for arguments

関数の基本: 型と評価の最小例

variable "names" { type = list(string) default = ["app", "db"] }
variable "tags"  { type = map(string)  default = {} }

locals {
  name_count = length(var.names)                 # 2
  maybe_owner = try(var.tags["owner"], null)     # 存在しないなら null
  # path.module は現在のモジュールフォルダ
}

length: 配列・マップ・文字列のサイズ判定

length は最頻出の基礎関数です。文字列の長さ、コレクション(list/set/map/tuple/object)の要素数を返します。Associate では count/for_each と組み合わせる場面が典型です。

注意点は null と未知値の扱いです。length(null) は無効な引数エラーになります。未知値が混ざる可能性がある場合は、coalesce と同型の空値でガードする、または try/can を併用します。

  • 文字列の長さは文字数基準(バイト数ではない)
  • map や object に対する length はキー数を返す
  • null ガード例: length(coalesce(var.tags, tomap({}))

length の実践パターン

variable "subnets" { type = list(string) default = [] }
variable "tags"    { type = map(string)  default = null }

locals {
  subnet_count = length(var.subnets)                         # 0 以上
  safe_tag_count = length(coalesce(var.tags, tomap({})))     # null を空マップに置換
  non_empty_name = length(trimspace(var.name)) > 0           # 文字列の空判定
}

resource "null_resource" "per_subnet" {
  count = length(var.subnets)
}

# 未知の可能性があるとき
locals {
  # try で安全に代入(型を合わせるため tomap({}) を第二引数に)
  maybe_tags = try(var.tags, tomap({}))
  tag_count  = length(maybe_tags)
}

lookup と map 添字の比較

マップから安全に値を取り出す標準手は lookup(map, key, default) です。キーが存在しないときのみ default を返し、キーが存在して値が null の場合は null を返します。この挙動は試験で問われやすいポイントです。

直接添字 map["key"] は存在しないキーでエラーになります。未知や欠損の可能性があるなら try(map["key"], default) または lookup を使います。値が空文字や空コレクションの場合にフォールバックしたいときは、trimspace・length などと条件式を組み合わせます。

  • キーの存在判定は contains(keys(map), key) が汎用
  • 値が null かどうかで分岐したい場合は try(map["k"], null) を使う
  • 空文字対策は trimspace(x) != "" のように明示する
手法存在しないキー値が null のとき主な使いどころ
lookup(m, "k", "def")def を返すnull を返す(def にはならない)キー欠損時のみ既定値を使いたい
m["k"]エラー(Invalid index)nullキーが必ず存在する前提のとき
try(m["k"], "def")def を返すdef を返す欠損や null でも強制的に既定値に寄せたい

lookup / 添字 / try の安全な取り出し例

variable "meta" { type = map(string) default = {} }

locals {
  # 欠損時のみ "dev" を使い、null は null のまま保持
  env_lookup = lookup(var.meta, "environment", "dev")

  # 欠損や null でも最終的に "dev" にしたい
  env_force_default = try(var.meta["environment"], "dev")

  # キーの存在チェック
  has_env = contains(keys(var.meta), "environment")

  # 空文字・空白ならフォールバック
  owner_raw = try(var.meta["owner"], null)
  owner = (owner_raw != null && trimspace(owner_raw) != "") ? trimspace(owner_raw) : "unknown"
}

templatefile: ファイルからテンプレートを展開

templatefile(path, vars) はファイルを読み込み、vars マップで差し込みます。path は path.module を基準に組み立てると、モジュール配布時も安全です。テンプレート内では ${var} 形式で参照し、%{ if } ディレクティブなどの制御構文も使用できます。

テンプレートへ複雑な構造を渡す場合は jsonencode や yamlencode を使ってから渡すと、シェルスクリプトやクラウドイニットとの相性が良くなります。

  • テンプレートが相対パスの場合は ${path.module}/... を使う
  • テンプレート内で参照できるのは templatefile に渡した変数のみ
  • 大きな文字列はテンプレート化し、HCL 側は最小限に保つ

templatefile の実装例(ユーザーデータを外部化)

# main.tf
variable "cluster_name" { type = string }
variable "tags" { type = map(string) default = {} }

locals {
  user_data = templatefile("${path.module}/user_data.sh.tmpl", {
    cluster_name = var.cluster_name,
    tags_json    = jsonencode(var.tags)
  })
}

# user_data.sh.tmpl(テンプレートファイルの中身の例)
#cloud-config
runcmd:
  - echo "Cluster: ${cluster_name}" > /etc/motd
  - echo 'Tags: ${tags_json}' >> /etc/motd
%{ if length(trimspace(cluster_name)) == 0 }
  - echo "WARN: cluster name is empty" >> /var/log/setup.log
%{ endif }

併用で効く補助関数: merge, coalesce, try ほか

実務では関数を組み合わせてロバストな式にします。merge はマップのマージ、coalesce は最初の非 null 値、try は最初に成功する式の値を返します。join/split、compact、distinct、toset などはコレクション整形で定番です。

未知・欠損・空を区別して扱うのがコツです。null と空文字や空コレクションは目的に応じて使い分け、必要に応じて明示的に変換します。

  • merge(map1, map2, ...) は右側が優先
  • coalesce(x, y) は x が非 null なら x。型は揃える(例: tomap({}))
  • compact(list) は空文字を除去、distinct は重複排除、toset は順序非依存化

補助関数の組み合わせ例

variable "base_tags" { type = map(string) default = { app = "web" } }
variable "extra_tags" { type = map(string) default = null }
variable "raw_subnets" { type = list(string) default = ["subnet-a", "", "subnet-b", "subnet-a"] }

locals {
  tags = merge(var.base_tags, coalesce(var.extra_tags, tomap({})))

  # 空文字除去 → 重複排除 → セット化
  subnets_clean = toset(distinct(compact(var.raw_subnets)))

  # CSV を構築
  subnet_csv = join(",", sort(tolist(subnets_clean)))

  # 失敗しうる取り出しに try
  env = try(var.extra_tags["environment"], "dev")
}

Associate 試験で問われやすいポイントと実務Tips

試験では関数の境界条件(null、欠損、空)、評価タイミング(計画時/適用時)、path 変数の使い分けが狙われます。落とし穴を押さえておくと取りこぼしが減ります。

実務では unknown を前提に安全な式にする、テンプレートは templatefile に寄せる、タグやラベルは merge と lookup/try で堅牢に構築するのが定石です。

  • lookup は「キー欠損でのみ default」。値が null なら null を返す
  • count = length(list) は素直。for_each で重複を排除したいなら toset(distinct(list))
  • templatefile のテンプレート内では templatefile に渡した変数だけが見える
  • path.module(モジュール相対)と path.root(ルート相対)の混同に注意
  • jsonencode はクラウドイニットやポリシー文書の埋め込みでよく使う

よくある落とし穴の是正例

# NG: 欠損時にエラー
# local.env = var.tags["environment"]

# OK: 欠損・null に強い
locals {
  env = try(var.tags["environment"], "dev")
}

# NG: null をそのまま length に渡す
# local.c = length(var.tags)

# OK: 同型でガード
locals {
  c = length(coalesce(var.tags, tomap({})))
}

問題で確認

Associate

問題 1

マップ var.tags からキー "team" を取り出し、キーが存在しない場合にのみ "platform" を返し、キーが存在して値が null の場合は null のままにしたい。最も適切な式はどれか。

  1. lookup(var.tags, "team", "platform")
  2. coalesce(var.tags["team"], "platform")
  3. try(var.tags["team"], null) != null ? var.tags["team"] : "platform"
  4. contains(keys(var.tags), "team") ? "platform" : var.tags["team"]

正解: A

lookup(map, key, default) はキーが存在しないときのみ default を返し、キーが存在して値が null の場合は null を返す。B はキー欠損でエラー、C は値が null の場合に default へ切り替わるため要件と異なる。D は条件が逆で要件を満たさない。

よくある質問

templatefile のテンプレート内で Terraform の変数 var.x を直接参照できますか?

できません。templatefile に渡したマップのキーのみがテンプレート内で参照可能です。必要な値は templatefile の第2引数に明示的に渡してください。

length で文字列の長さを求める際、マルチバイト文字はどう扱われますか?

文字数としてカウントされます(バイト数ではありません)。したがって length("あ") は 1 になります。

lookup と try の使い分けは?

キー欠損時のみデフォルトに落としたい場合は lookup。キー欠損や null など例外的状況をまとめて既定値に寄せたい場合は try を使います。実務では要件に応じて選び、null と空の違いを明確にします。

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

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.