1. 概要
zipmap— 2つのリストからmapを生成transpose— mapのキーと値を入れ替え(転置)- 実際のユースケース
zipmap(keys, values)はキーのリストと値のリストを組み合わせてmapを生成します。transpose(map)はmapのキーと値を入れ替えます(値のリストをキー、元のキーを値のリストにする)。
2. zipmap — キーと値のリストからmapを生成
# terraform consoleで確認
> zipmap(["a", "b", "c"], [1, 2, 3])
{"a" = 1, "b" = 2, "c" = 3}
> zipmap(["dev", "stg", "prd"], ["t3.micro", "t3.small", "t3.medium"])
{"dev" = "t3.micro", "prd" = "t3.medium", "stg" = "t3.small"}
リソースIDとリソース名のmapを生成する
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 "bucket_names" {
description = "S3バケット名のリスト"
type = list(string)
default = ["data", "logs", "backups"]
}
resource "aws_s3_bucket" "buckets" {
for_each = toset(var.bucket_names)
bucket = "${var.environment}-${each.key}"
tags = {
Name = "${var.environment}-${each.key}"
Environment = var.environment
ManagedBy = "terraform"
}
}
# バケット名 → ARNのmapを生成
locals {
bucket_arns = zipmap(
var.bucket_names,
[for name in var.bucket_names : aws_s3_bucket.buckets[name].arn]
)
# → {"data" = "arn:aws:s3:::dev-data", "logs" = "arn:aws:s3:::dev-logs", ...}
}
output "bucket_arns" {
value = local.bucket_arns
}
3. for式でのzipmap代替パターン
# zipmapと同等の結果をfor式で書く
locals {
names = ["web", "api", "worker"]
types = ["t3.micro", "t3.micro", "t3.small"]
# zipmap版
instance_types_zip = zipmap(local.names, local.types)
# for式版(より柔軟)
instance_types_for = {
for i, name in local.names :
name => local.types[i]
}
}
4. transpose — mapを転置する
transpose(map_of_lists)はmap of listsを転置します。元のmapの値(リスト)の各要素がキーになり、元のキーが値のリストになります。
# terraform consoleで確認
> transpose({"a" = ["1", "2"], "b" = ["1", "3"]})
{"1" = ["a", "b"], "2" = ["a"], "3" = ["b"]}
# サービス → タグのmapをタグ → サービスに転置
> transpose({
"web" = ["frontend", "public"],
"api" = ["backend", "public"],
"db" = ["backend", "private"]
})
{
"backend" = ["api", "db"],
"frontend" = ["web"],
"private" = ["db"],
"public" = ["api", "web"]
}
IAMポリシーのサービス → 許可アクションの転置
variable "service_permissions" {
description = "サービスと許可するIAMアクションのmap"
type = map(list(string))
default = {
"web-service" = ["s3:GetObject", "s3:ListBucket"]
"api-service" = ["s3:GetObject", "dynamodb:GetItem", "dynamodb:PutItem"]
"admin-service" = ["s3:GetObject", "s3:PutObject", "s3:ListBucket", "dynamodb:GetItem"]
}
}
locals {
# 転置: アクション → そのアクションを必要とするサービスのリスト
action_to_services = transpose(var.service_permissions)
# → {
# "s3:GetObject" = ["admin-service", "api-service", "web-service"],
# "s3:ListBucket" = ["admin-service", "web-service"],
# "dynamodb:GetItem" = ["admin-service", "api-service"],
# ...
# }
# s3系アクションを必要とするサービス数を確認
s3_get_services = lookup(local.action_to_services, "s3:GetObject", [])
}
resource "aws_s3_bucket" "app" {
bucket = "${var.environment}-app"
tags = {
Name = "${var.environment}-app"
Environment = var.environment
ManagedBy = "terraform"
AccessCount = tostring(length(local.s3_get_services))
}
}
5. 関連記事
- for式の使い方 — zipmapをfor式で代替するパターン
- setintersection / setunion / setsubtract / setproduct — set操作
- flatten の応用 — リストとmapの変換
6. まとめ
zipmap(keys, values)— 2つのリストからmapを生成。キーと値のペアをまとめるtranspose(map_of_lists)— map of listsを転置。値のリスト要素をキーに、元のキーを値のリストにするzipmapはfor式で代替できるが、シンプルなケースではzipmapの方が読みやすいtransposeはIAMポリシーの分析・タグの逆引きなど「どのリソースがこのアクションを使うか」の集計に便利
動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/zipmap