- OpenTofu言語
- 式
- 動的ブロック
dynamic
ブロック
リソースのようなトップレベルのブロック構造内では、通常、式は`name = expression`形式を使用して引数に値を代入する場合にのみ使用できます。これにより多くの用途がカバーされますが、一部のリソースタイプでは、通常は包含オブジェクトに関連付けられている(または埋め込まれている)個別のオブジェクトを表す、繰り返し可能なネストされたブロックが引数に含まれています。
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
name = "tf-test-name" # can use expressions here
setting {
# but the "setting" block is always a literal block
}
}
resource
、data
、provider
、provisioner
ブロック内でサポートされている特別なdynamic
ブロックタイプを使用して、setting
のような繰り返し可能なネストされたブロックを動的に構築できます。
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
name = "tf-test-name"
application = "${aws_elastic_beanstalk_application.tftest.name}"
solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6"
dynamic "setting" {
for_each = var.settings
content {
namespace = setting.value["namespace"]
name = setting.value["name"]
value = setting.value["value"]
}
}
}
dynamic
ブロックは、for
式と非常によく似ていますが、複雑な型付けされた値ではなく、ネストされたブロックを生成します。指定された複雑な値を反復処理し、その複雑な値の各要素に対してネストされたブロックを生成します。
- 動的ブロックのラベル(上記の例では
"setting"
)は、生成するネストされたブロックの種類を指定します。 for_each
引数は、反復処理する複雑な値を提供します。iterator
引数(オプション)は、複雑な値の現在の要素を表す一時変数の名前を設定します。省略した場合、変数の名前はdynamic
ブロックのラベル(上記の例では"setting"
)にデフォルト設定されます。labels
引数(オプション)は、生成された各ブロックに使用するブロックラベルを順に指定する文字列のリストです。この値には、一時的な反復子変数を使用できます。- ネストされた
content
ブロックは、生成された各ブロックの本体を定義します。このブロック内では、一時的な反復子変数を使用できます。
for_each
引数は任意のコレクションまたは構造化された値を受け入れるため、for
式またはスプラット式を使用して既存のコレクションを変換できます。
反復子オブジェクト(上記の例ではsetting
)には2つの属性があります。
key
は、現在の要素のマップキーまたはリスト要素のインデックスです。for_each
式がセット値を生成する場合、key
はvalue
と同一であり、使用しないでください。value
は、現在の要素の値です。
dynamic
ブロックは、構成されているリソースタイプ、データソース、プロバイダ、またはプロビジョナに属する引数のみを生成できます。OpenTofuは式を評価する前にこれらの処理を行う必要があるため、lifecycle
やprovisioner
ブロックなどのメタ引数ブロックを生成することはできません。
for_each
値は、目的のネストされたブロックごとに1つの要素を持つコレクションである必要があります。ネストされたデータ構造または複数のデータ構造からの要素の組み合わせに基づいてリソースインスタンスを宣言する必要がある場合は、OpenTofuの式と関数を使用して適切な値を導き出すことができます。このような状況の一般的な例については、flatten
関数とsetproduct
関数をご覧ください。
複数レベルのネストされたブロック構造
一部のプロバイダは、互いにネストされた複数のレベルのブロックを含むリソースタイプを定義しています。必要に応じて、他のdynamic
ブロックのcontent
部分にdynamic
ブロックをネストすることで、これらのネストされた構造を動的に生成できます。
たとえば、モジュールは次のようないくつかの複雑なデータ構造を受け入れる場合があります。
variable "load_balancer_origin_groups" {
type = map(object({
origins = set(object({
hostname = string
}))
}))
}
各オリジングループのブロック、およびグループ内の各オリジンにネストされたブロックを期待するリソースタイプを定義する場合、次のネストされたdynamic
ブロックを使用してOpenTofuに動的に生成させることができます。
dynamic "origin_group" {
for_each = var.load_balancer_origin_groups
content {
name = origin_group.key
dynamic "origin" {
for_each = origin_group.value.origins
content {
hostname = origin.value.hostname
}
}
}
}
ネストされたdynamic
ブロックを使用する場合は、各ブロックのイテレータ記号に特に注意することが重要です。上記の例では、origin_group.value
は外部ブロックの現在の要素を参照し、origin.value
は内部ブロックの現在の要素を参照します。
特定のリソースタイプが、親のいずれかと同じタイプ名を有するネストされたブロックを定義している場合、各dynamic
ブロックのiterator
引数を使用して、区別しやすい異なるイテレータ記号を選択できます。
dynamic
ブロックのベストプラクティス
dynamic
ブロックの使いすぎは、設定の可読性と保守性を低下させる可能性があるため、再利用可能なモジュールのためにクリーンなユーザーインターフェースを構築するために詳細を隠す必要がある場合にのみ使用することをお勧めします。可能な限り、常にネストされたブロックを文字どおりに記述してください。
resource
ブロックのほとんどまたはすべて引数とネストされたブロックを入力変数の直接対応する属性を使用して定義している場合、モジュールが役に立つ抽象化を作成していないことを示唆している可能性があります。呼び出し元モジュールがリソース自体を定義して、その情報を入力モジュールに渡す方が良い場合があります。この設計上のトレードオフの詳細については、モジュールを作成するタイミングとモジュールの構成を参照してください。