splat式([*])— リソースリストから属性を一括取得

1. 概要

  • splat式([*])とは何か
  • リソースリストから属性を一括取得する方法
  • countfor_eachでのsplat式の違い
  • for式との使い分け
  • 実際のユースケース

splat式([*])は、リストやセット型のリソース・変数から特定の属性を一括で取り出す構文です。for式よりも簡潔に書けるのが特徴です。


2. 基本構文

# リストの全要素から特定の属性を取得
<リソースリスト>[*].<属性名>

# 例: countで作成したEC2の全IDを取得
aws_instance.web[*].id

3. countリソースとsplat式

countで複数作成したリソースの属性を一括取得する最もシンプルなユースケースです。

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"
}

variable "instance_count" {
  description = "作成するEC2インスタンス数"
  type        = number
  default     = 3
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  count         = var.instance_count
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = format("%s-web-%02d", var.environment, count.index + 1)
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# splat式で全インスタンスのIDを一括取得
output "instance_ids" {
  description = "全EC2インスタンスのID"
  value       = aws_instance.web[*].id
  # → ["i-001", "i-002", "i-003"]
}

output "public_ips" {
  description = "全EC2インスタンスのパブリックIP"
  value       = aws_instance.web[*].public_ip
}

4. splat式 vs for式

同じ結果を得るsplat式とfor式の比較です。

# splat式(簡潔)
output "instance_ids_splat" {
  value = aws_instance.web[*].id
}

# for式(同等だが冗長)
output "instance_ids_for" {
  value = [for instance in aws_instance.web : instance.id]
}

フィルタリングが必要な場合はfor式を使います。

# for式: 特定条件でフィルタ(splatではできない)
output "running_instance_ids" {
  value = [for instance in aws_instance.web : instance.id if instance.instance_state == "running"]
}

5. for_eachリソースでのsplat式

for_eachで作成したリソースはmap型なので、splat式([*])は使えません。values()と組み合わせます。

resource "aws_instance" "web_multi" {
  for_each      = toset(["web-01", "web-02", "web-03"])
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-${each.key}"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# for_eachリソースはmapなのでvalues()を使う
output "multi_instance_ids" {
  value = values(aws_instance.web_multi)[*].id
}

6. ネストした属性へのアクセス

# ネストした属性も参照可能
output "root_volume_sizes" {
  value = aws_instance.web[*].root_block_device[0].volume_size
}

# セキュリティグループIDのリストからflattening
output "all_sg_ids" {
  value = flatten(aws_instance.web[*].vpc_security_group_ids)
}

7. 関連記事


8. まとめ

  • splat式([*])はcountリソースのリストから属性を一括取得する構文
  • リソース[*].属性名という形式で使う
  • for式より簡潔だが、フィルタリングはできない
  • for_eachリソースはmap型なので、values(リソース)[*].属性名を使う
  • ネストした属性(root_block_device[0].volume_sizeなど)も参照可能

動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/expressions/splat