setintersection / setunion / setsubtract / setproduct — set操作関数

1. 概要

  • setintersection — 積集合(共通要素)
  • setunion — 和集合(すべての要素)
  • setsubtract — 差集合(一方にのみある要素)
  • setproduct — 直積(デカルト積)
  • 実際のユースケース

Terraformのset操作関数は、セキュリティグループのCIDRブロック管理・IAM権限の差分比較・複数リストの組み合わせ生成などに使います。


2. setintersection — 積集合(共通要素)

setintersection(set1, set2, ...)は複数のsetに共通する要素を返します。

# terraform consoleで確認
> setintersection(["a", "b", "c"], ["b", "c", "d"])
toset(["b", "c"])

> setintersection(["1", "2", "3"], ["2", "3", "4"], ["3", "4", "5"])
toset(["3"])

複数環境で共通のCIDRブロックを特定する

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 "dev_allowed_cidrs" {
  type    = list(string)
  default = ["10.0.0.0/8", "172.16.0.0/12", "192.168.1.0/24"]
}

variable "prd_allowed_cidrs" {
  type    = list(string)
  default = ["10.0.0.0/8", "172.16.0.0/12", "203.0.113.0/24"]
}

locals {
  # dev/prd 両方で許可するCIDRブロック(積集合)
  common_cidrs = setintersection(
    toset(var.dev_allowed_cidrs),
    toset(var.prd_allowed_cidrs)
  )
  # → toset(["10.0.0.0/8", "172.16.0.0/12"])
}

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

resource "aws_security_group" "web" {
  name        = "${var.environment}-web"
  description = "${var.environment} web security group"

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = tolist(local.common_cidrs)
    description = "HTTPS from common CIDRs"
  }

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

3. setunion — 和集合(すべての要素)

setunion(set1, set2, ...)は複数のsetのすべての要素を重複なく返します。

# terraform consoleで確認
> setunion(["a", "b"], ["b", "c"], ["c", "d"])
toset(["a", "b", "c", "d"])
locals {
  # すべての環境のCIDRブロックをマージ
  all_allowed_cidrs = setunion(
    toset(var.dev_allowed_cidrs),
    toset(var.prd_allowed_cidrs)
  )
  # → toset(["10.0.0.0/8", "172.16.0.0/12", "192.168.1.0/24", "203.0.113.0/24"])
}

4. setsubtract — 差集合

setsubtract(set1, set2)はset1からset2の要素を除いた差集合を返します。

# terraform consoleで確認
> setsubtract(["a", "b", "c"], ["b", "c", "d"])
toset(["a"])

# prdにあってdevにないCIDR(prd固有のCIDR)
> setsubtract(toset(["10.0.0.0/8", "203.0.113.0/24"]), toset(["10.0.0.0/8"]))
toset(["203.0.113.0/24"])

5. setproduct — 直積(デカルト積)

setproduct(set1, set2, ...)は複数のsetのデカルト積(すべての組み合わせ)を返します。

# terraform consoleで確認
> setproduct(["ap-northeast-1a", "ap-northeast-1c"], ["public", "private"])
[
  ["ap-northeast-1a", "public"],
  ["ap-northeast-1a", "private"],
  ["ap-northeast-1c", "public"],
  ["ap-northeast-1c", "private"],
]

AZとサブネット種別の全組み合わせでサブネットを作成

data "aws_availability_zones" "available" {
  state = "available"
}

locals {
  az_types = setproduct(
    slice(data.aws_availability_zones.available.names, 0, 2),
    ["public", "private"]
  )
  # → [["ap-northeast-1a","public"], ["ap-northeast-1a","private"],
  #    ["ap-northeast-1c","public"], ["ap-northeast-1c","private"]]

  subnet_configs = {
    for pair in local.az_types :
    "${pair[0]}-${pair[1]}" => {
      az   = pair[0]
      type = pair[1]
    }
  }
}

6. 関連記事


7. まとめ

  • setintersection(set1, set2, ...) — 共通要素。dev/prd両方で使うCIDRの特定など
  • setunion(set1, set2, ...) — すべての要素を重複なく合成
  • setsubtract(set1, set2) — set1からset2の要素を除いた差集合
  • setproduct(set1, set2, ...) — デカルト積。AZ × サブネット種別の全組み合わせ生成に便利
  • これらの関数はsetを返すため、リストが必要な場合はtolist()で変換する

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