メインコンテンツへスキップ

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ブロックを使用してリソースのネストされたブロックを動的に生成することはできます