- OpenTofu言語
- 式
- For式
for
式
for
式は、別の複合型の値を変換することによって、複合型の値を生成します。入力値の各要素は、結果内の1つまたはゼロの値に対応でき、任意の式を使用して各入力要素を出力要素に変換できます。
たとえば、var.list
が文字列のリストである場合、次の式はすべて大文字の文字列のタプルを生成します。
[for s in var.list : upper(s)]
このfor
式は、var.list
の各要素を反復処理し、s
をそれぞれの要素に設定して式upper(s)
を評価します。次に、その式の実行結果すべてを同じ順序で持つ新しいタプル値を構築します。
入力型
for
式の入力(in
キーワードの後)は、リスト、セット、タプル、マップ、またはオブジェクトにすることができます。
上記の例では、単一の一時的なシンボルs
のみを持つfor
式を示しましたが、for
式は必要に応じて、各アイテムのキーまたはインデックスも使用するために、一時的なシンボルのペアを宣言できます。
[for k, v in var.map : length(k) + length(v)]
上記のようなマップまたはオブジェクト型の場合、k
シンボルは、現在の要素のキーまたは属性名を参照します。リストとタプルで2つのシンボル形式を使用することもできます。その場合、追加のシンボルはゼロから始まる各要素のインデックスであり、通常は、より具体的な名前を選択するのに役立つ場合を除き、i
またはidx
というシンボル名が付けられます。
[for i, v in var.list : "${i} is ${v}"]
インデックスまたはキーのシンボルは常にオプションです。for
キーワードの後に単一のシンボルのみを指定した場合、そのシンボルは常に、入力コレクションの各要素の値を表します。
結果型
for
式を囲む括弧の種類によって、生成される結果の型が決まります。
上記の例では、[
と]
を使用しており、これによりタプルが生成されます。代わりに{
と}
を使用すると、結果はオブジェクトになり、=>
記号で区切られた2つの結果式を指定する必要があります。
{for s in var.list : s => upper(s)}
この式は、属性がvar.list
の元の要素で、対応する値が大文字バージョンであるオブジェクトを生成します。たとえば、結果の値は次のようになります。
{
foo = "FOO"
bar = "BAR"
baz = "BAZ"
}
for
式単独では、オブジェクト値またはタプル値のいずれかしか生成できませんが、OpenTofuの自動型変換規則により、リスト、マップ、およびセットが期待される場所で結果を通常使用できます。
要素のフィルタリング
for
式には、オプションのif
句を含めて、ソースコレクションから要素をフィルタリングし、ソース値よりも少ない要素を持つ値を生成することもできます。
[for s in var.list : upper(s) if s != ""]
for
式でコレクションをフィルタリングする一般的な理由の1つは、いくつかの基準に基づいて、単一のソースコレクションを2つの個別のコレクションに分割することです。たとえば、入力のvar.users
が、各オブジェクトに属性is_admin
があるオブジェクトのマップである場合、管理者と非管理者のオブジェクトを持つ個別のマップを生成したい場合があります。
variable "users" {
type = map(object({
is_admin = bool
}))
}
locals {
admin_users = {
for name, user in var.users : name => user
if user.is_admin
}
regular_users = {
for name, user in var.users : name => user
if !user.is_admin
}
}
要素の順序付け
for
式は、順序付けされていない型(マップ、オブジェクト、セット)から順序付けされた型(リスト、タプル)に変換できるため、OpenTofuは、順序付けされていないコレクションの要素に暗黙の順序を選択する必要があります。
マップとオブジェクトの場合、OpenTofuはキーまたは属性名で要素を並べ替え、辞書順ソートを使用します。
文字列のセットの場合、OpenTofuは値を基準に要素を並べ替え、辞書順ソートを使用します。
他の型のセットの場合、OpenTofuは将来のバージョンで変更される可能性のある任意の順序を使用します。構成の他の場所で結果が順序付けられていないことを明確にするために、式の結果をセットに変換することをお勧めします。toset
関数を使用すると、for
式の結果をセット型に簡潔に変換できます。
toset([for e in var.set : e.example])
結果のグループ化
結果の型がオブジェクト({
および}
区切り文字を使用)の場合、通常、指定されたキー式は結果内のすべての要素で一意である必要があり、そうでない場合、OpenTofuはエラーを返します。
結果として得られるキーが一意ではない場合があるため、OpenTofuはその状況をサポートするために、キーごとに複数の要素をサポートするように結果を変更する特別なグループ化モードをサポートしています。
グループ化モードを有効にするには、値の式の後に記号...
を追加します。例えば
variable "users" {
type = map(object({
role = string
}))
}
locals {
users_by_role = {
for name, user in var.users : user.role => name...
}
}
上記は、モジュールが、ユーザー名がマップキーである、各ユーザーが単一の「ロール」を持つさまざまなユーザーを記述するマップを期待している状況を表しています。ユーザー名は入力内のマップキーであるため一意であることが保証されていますが、多くのユーザーが単一のロール名を共有する可能性があります。
local.users_by_role
式は、入力マップを反転して、キーがロール名で、値がユーザー名になるようにしますが、この式は(name
の後の...
により)グループ化モードであるため、結果は次のような文字列のリストのマップになります。
{
"admin": [
"ps",
],
"maintainer": [
"am",
"jb",
"kl",
"ma",
],
"viewer": [
"st",
"zq",
],
}
要素の順序付けルールにより、OpenTofuはfor
式の評価の一環として、ユーザー名をユーザー名で字句的にソートするため、グループ化後の各ロールに関連付けられたユーザー名は字句的にソートされます。
繰り返し構成ブロック
for
式メカニズムは、式内の他のコレクション値からコレクション値を構築するためのもので、それらを複合値を期待する個々のリソース引数に割り当てることができます。
一部のリソースタイプは、ネストされたブロックタイプも定義します。これは通常、何らかの方法で包含リソースに属する別のオブジェクトを表します。for
式を使用してネストされたブロックを動的に生成することはできませんが、dynamic
ブロックを使用してリソースのネストされたブロックを動的に生成することはできます。