Terraform - ใช้ลูปซ้อนกับจำนวน


18

ฉันพยายามใช้ลูปซ้อนในดิน ฉันมีตัวแปรลิสต์สองตัว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}"
}

นี่เป็นการทุบตีสิ่งที่ฉันพยายามจะทำ

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

คำตอบ:


34

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]}"
}

เนื่องจากเราต้องการสร้างเทมเพลตนโยบายสำหรับชุดค่าผสมของบัญชีและรูปภาพทุกชุดcountบนtemplate_fileบล็อกข้อมูลจะถูกคูณเข้าด้วยกัน จากนั้นเราสามารถใช้การหารและโมดูโลเพื่อกลับ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 บัญชีและรูปภาพที่แตกต่างกันซึ่งครอบคลุมการรวมทั้งหมด


2
จะทำให้คุณมีปัญหาหากคุณต้องการขยายการกำหนดค่าเช่นเพิ่มบัญชีใหม่หรือ / และรูปภาพทรัพยากรของคุณจะแมปไปยังดัชนีอื่นอย่างไรก็ตามหากการลบและสร้างใหม่นั้นไม่ใช่ปัญหา
balazs

1
@ justin-grote มีจุดคำตอบของเขา: ใน terraform 0.12 คุณจะต้องใช้ฟังก์ชั่นพื้นทุกที่ที่คุณแบ่งหรืออื่น ๆ คุณจะได้รับข้อผิดพลาดเกี่ยวกับดัชนีบางส่วน account_id = var.list_of_allowed_accounts[floor(count.index / length(var.list_of_images))]
chriscatfr

7

คำตอบที่นี่ใช้งานได้ (ฉันใช้ตอนแรก) แต่ฉันคิดว่าฉันมีทางออกที่ดีกว่าโดยใช้ฟังก์ชันsetproductของ Terraform ฉันไม่ได้เห็นตัวอย่างมากมายของมันที่ใช้รอบ interwebs แต่ setproduct ใช้สองชุด (หรือที่สำคัญกว่าสองรายการ) และสร้างรายการของชุดที่มีการเรียงสับเปลี่ยนของอินพุต ในกรณีของฉันฉันกำลังสร้างพารามิเตอร์ 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

สมองเล็ก ๆ น้อย ๆ ที่บอบบางของฉันสามารถแยกวิเคราะห์เรื่องนี้ง่ายกว่าเวทมนตร์โมดูโลในคำตอบอื่น ๆ !


ฉันจะลองวิธีแก้ปัญหาของคุณ ฉันเห็นด้วยว่ามันดูดีกว่ามาก แต่ทำไมคุณถึงใช้${length(var.list1) * length(var.list2)}แทน${length(local.product)}การนับ?
chriscatfr

ฉันจะต้องรอจนกว่าลูกค้าของฉันจะเริ่มใช้ v0.12 :( ไม่แปลกใจเลยว่าทำไมคุณถึงไม่พบแหล่งที่มามากมาย
chriscatfr

ไม่มีเหตุผล${length(local.product)}อาจทำให้มากขึ้นตั้งแต่ นอกจากนี้ฉันค่อนข้างแน่ใจsetproduct()อยู่ก่อน -12, (ข้อความที่ด้านบนของหน้าเชื่อมโยงเป็นเพียงคำเตือนทั่วไปสำหรับเอกสาร 0.11 ทั้งหมดของพวกเขาฉันคิดว่า?)
Kyle

4

FYI ถ้าใครมาที่นี่จาก Google ถ้าคุณใช้ terraform 0.12 คุณจะต้องใช้ฟังก์ชั่นการทำงานทุกที่ที่คุณแบ่งมิฉะนั้นคุณจะได้รับข้อผิดพลาดเกี่ยวกับดัชนีบางส่วน

account_id = var.list_of_allowed_accounts [ floor (count.index / length (var.list_of_images))]


ฉันหวังว่าฉันจะอ่านจนสุดหน้า SO เพื่อค้นพบอัญมณีนี้ก่อนที่ฉันจะลองวิธีการทางคณิตศาสตร์ นี่คือวิธีที่ฉันให้มันทำงานกับพื้น (count.index / 8) ขอบคุณสำหรับการโพสต์
bytejunkie

ด้วย 0.12 setproduct () จากโซลูชันของ @kyle ดูเหมือนง่ายขึ้น
chriscatfr

หากคุณอยู่ใน terraform 0.12 แล้วทำไมไม่ใช้ที่เพิ่มใหม่for, for_eachและ / หรือโครงสร้างแบบไดนามิกซ้อนบล็อกภาษาในการดำเนินการบางสิ่งบางอย่างเล็ก ๆ น้อย ๆ น้อยสับสน?
TrinitronX

0

โดยทั่วไปปัญหาอยู่ในข้อมูล "template_file" account_id ไม่สามารถกำหนดวิธีการที่คุณคิดว่ามันจะนับตั้งแต่การนับในกรณีของคุณเป็นเพียง var อื่นที่ไม่เคยได้รับเพิ่ม / เปลี่ยนแปลง แค่พูดตั้งแต่ฉันพลาดที่จะเห็นคำถามของคุณ


0

ฉันไม่มีคะแนนชื่อเสียงเพียงพอที่จะเพิ่มความคิดเห็นในคำตอบของ @ 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]}"
} 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.