Terraformでネストされたループを使用しようとしています。 2つのリスト変数list_of_allowed_accounts
とlist_of_images
があり、リストlist_of_images
を反復処理してから、リストlist_of_allowed_accounts
を反復処理しようとしています。
これが私のterraformコードです。
variable "list_of_allowed_accounts" {
type = "list"
default = ["111111111", "2222222"]
}
variable "list_of_images" {
type = "list"
default = ["Alpine", "Java", "jenkins"]
}
data "template_file" "ecr_policy_allowed_accounts" {
template = "${file("${path.module}/ecr_policy.tpl")}"
vars {
count = "${length(var.list_of_allowed_accounts)}"
account_id = "${element(var.list_of_allowed_accounts, count.index)}"
}
}
resource "aws_ecr_repository_policy" "repo_policy_allowed_accounts" {
count = "${length(var.list_of_images)}"
repository = "${element(aws_ecr_repository.images.*.id, count.index)}"
count = "${length(var.list_of_allowed_accounts)}"
policy = "${data.template_file.ecr_policy_allowed_accounts.rendered}"
}
これは、私がやろうとしていることと同等のbashです。
for image in Alpine Java jenkins
do
for account_id in 111111111 2222222
do
// call template here using variable 'account_id' and 'image'
done
done
Terraformはこの種のネストされた反復を直接サポートしていませんが、算術演算でそれを偽造することができます。
variable "list_of_allowed_accounts" {
type = "list"
default = ["1111", "2222"]
}
variable "list_of_images" {
type = "list"
default = ["Alpine", "Java", "jenkins"]
}
data "template_file" "ecr_policy_allowed_accounts" {
count = "${length(var.list_of_allowed_accounts) * length(var.list_of_images)}"
template = "${file("${path.module}/ecr_policy.tpl")}"
vars {
account_id = "${var.list_of_allowed_accounts[count.index / length(var.list_of_images)]}"
image = "${var.list_of_images[count.index % length(var.list_of_images)]}"
}
}
resource "aws_ecr_repository_policy" "repo_policy_allowed_accounts" {
count = "${data.template_file.ecr_policy_allowed_accounts.count}"
repository = "${var.list_of_images[count.index % length(var.list_of_images)]}"
policy = "${data.template_file.ecr_policy_allowed_accounts.*.rendered[count.index]}"
}
アカウントと画像のすべての組み合わせに対してポリシーテンプレートを作成する必要があるため、template_file
データブロックのcount
は、2つが乗算されます。次に、除算とモジュロ演算を使用して、count.index
から各リストの個別のインデックスに戻ることができます。
ポリシーテンプレートのコピーがなかったので、プレースホルダーを使用しました。したがって、この構成では次の計画が与えられました。
+ aws_ecr_respository_policy.repo_policy_allowed_accounts.0
policy: "policy allowing 1111 to access Alpine"
repository: "Alpine"
+ aws_ecr_respository_policy.repo_policy_allowed_accounts.1
policy: "policy allowing 1111 to access Java"
repository: "Java"
+ aws_ecr_respository_policy.repo_policy_allowed_accounts.2
policy: "policy allowing 1111 to access jenkins"
repository: "jenkins"
+ aws_ecr_respository_policy.repo_policy_allowed_accounts.3
policy: "policy allowing 2222 to access Alpine"
repository: "Alpine"
+ aws_ecr_respository_policy.repo_policy_allowed_accounts.4
policy: "policy allowing 2222 to access Java"
repository: "Java"
+ aws_ecr_respository_policy.repo_policy_allowed_accounts.5
policy: "policy allowing 2222 to access jenkins"
repository: "jenkins"
各ポリシーインスタンスは、アカウントIDと画像の異なるペアに適用され、すべての組み合わせをカバーします。
ここでの答えは機能します(私は最初にそれらを使用しました)が、Terraformの setproduct 関数を使用したより良い解決策があると思います。私はインターウェブの周りで使用される多くの例を見たことはありませんが、setproductは2つのセット(さらに重要なことに、2つのリスト)を取り、入力のすべての順列でセットのリストを生成します。私の場合、SSMパラメータを作成しています。
variable "list1" {
type = "list"
default = ["outer1", "outer2"]
}
variable "list2" {
type = "list"
default = ["inner1", "inner2", "inner3"]
}
locals {
product = "${setproduct(var.list1, var.list2)}"
}
resource "aws_ssm_parameter" "params" {
count = "${length(var.list1) * length(var.list2)}"
name = "/${element(local.product, count.index)[0]}/${element(local.product, count.index)[1]}"
type = "String"
value = "somevalue"
overwrite = false
lifecycle { ignore_changes = ["value"] }
}
これにより、次の名前のSSMパラメータが作成されます。
/outer1/inner1
/outer1/inner2
/outer1/inner3
/outer2/inner1
/outer2/inner2
/outer2/inner3
私の弱々しい小さな脳は、他の答えのモジュロマジックよりも少し簡単にこれを解析できます!
ちなみに、Googleから誰かがここに来た場合、terraform 0.12を使用している場合は、除算を行うすべての場所でfloor関数を使用する必要があります。そうしないと、部分インデックスに関するエラーが発生します。
account_id = var.list_of_allowed_accounts [floor(count.index/length(var.list_of_images))]
@ Martin Atkins が提供する回答にコメントを追加するのに十分な評判ポイントがないため、少し変更して彼の回答を投稿します。回避策 Terraformの問題20567
variable "list_of_allowed_accounts" {
type = "list"
default = ["1111", "2222"]
}
variable "list_of_images" {
type = "list"
default = ["Alpine", "Java", "jenkins"]
}
# workaround for TF issue https://github.com/hashicorp/terraform/issues/20567
locals {
policy_count = "${length(var.list_of_allowed_accounts) * length(var.list_of_images)}"
}
data "template_file" "ecr_policy_allowed_accounts" {
count = "${local.policy_count}"
template = "${file("${path.module}/ecr_policy.tpl")}"
vars {
account_id = "${var.list_of_allowed_accounts[count.index / length(var.list_of_images)]}"
image = "${var.list_of_images[count.index % length(var.list_of_images)]}"
}
}
resource "aws_ecr_repository_policy" "repo_policy_allowed_accounts" {
count = "${local.policy_count}"
repository = "${var.list_of_images[count.index % length(var.list_of_images)]}"
policy = "${data.template_file.ecr_policy_allowed_accounts.*.rendered[count.index]}"
}
基本的に問題はデータ「template_file」にあります。ケースのカウントは増分または変更されることのない別の変数であるため、account_idは想定どおりに設定できません。ちょうどあなたの質問が何であるかを正確に見逃しているので言っています。