- OpenTofu言語
- 関数
- flatten
flatten
関数
flatten
はリストを受け取り、リストである要素をリストの内容の平坦化されたシーケンスに置き換えます。
例
> flatten([["a", "b"], [], ["c"]])
["a", "b", "c"]
ネストされたリストの中に直接ネストされたリストがある場合、それらも再帰的に平坦化されます。
> flatten([[["a", "b"], []], ["c"]])
["a", "b", "c"]
マップなどにある間接的にネストされたリストは、平坦化されません。
for_each
のためのネストされた構造の平坦化
リソース for_each
と dynamic
ブロックの言語機能は、どちらも各繰り返しに対して1つの要素を持つコレクション値を必要とします。
入力データ構造が、for_each
引数で使用するのに適した形状になっていない場合があります。そのような場合、flatten
はネストされたデータ構造をフラットなデータ構造に変換する際に役立つ便利な関数になります。
たとえば、次のような変数を宣言するモジュールについて考えてみましょう。
variable "networks" {
type = map(object({
cidr_block = string
subnets = map(object({ cidr_block = string }))
}))
}
上記は、トップレベルのネットワークとそれらのサブネットなど、自然にツリーを形成するオブジェクトをモデル化するのに適した方法です。トップレベルのネットワークの繰り返しでは、結果のインスタンスがマップ要素と1対1で対応する形式になっているため、この変数を直接使用できます。
resource "aws_vpc" "example" {
for_each = var.networks
cidr_block = each.value.cidr_block
}
ただし、単一の resource
ブロックで *サブネット* をすべて宣言するためには、最初に構造をフラット化して、各トップレベルの要素が単一のサブネットを表すコレクションを生成する必要があります。
locals {
# flatten ensures that this local value is a flat list of objects, rather
# than a list of lists of objects.
network_subnets = flatten([
for network_key, network in var.networks : [
for subnet_key, subnet in network.subnets : {
network_key = network_key
subnet_key = subnet_key
network_id = aws_vpc.example[network_key].id
cidr_block = subnet.cidr_block
}
]
])
}
resource "aws_subnet" "example" {
# local.network_subnets is a list, so we must now project it into a map
# where each key is unique. We'll combine the network and subnet keys to
# produce a single unique key per instance.
for_each = {
for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
}
vpc_id = each.value.network_id
availability_zone = each.value.subnet_key
cidr_block = each.value.cidr_block
}
上記の結果、サブネットオブジェクトごとに1つのサブネットインスタンスが生成され、サブネットとそれらを含むネットワークとの関連性が保持されます。
関連関数
setproduct
は、複数のリストまたは値のセットのすべての組み合わせを見つけます。これはfor_each
構造で使用するコレクションを準備する際に役立ちます。