DEV Community

Cover image for Enumerate the Variables in Terraform.
terngr
terngr

Posted on

Enumerate the Variables in Terraform.

ความเดิมตอนที่แล้ว เราสามารถสร้างชุด VM ที่ซับซ้อนพร้อมกันหลายๆ ชุด โดยระบุแค่ค่าตั้งต้นเพียงเล็กน้อย
ทำไมใช้ for_each แทน count ใน terraform

ในตอนนี้เราจะ Enumerate ค่าใน list สั้นๆตั้งต้น ออกมาเป็นชุดที่แสดงข้อมูล VM แต่ละเครื่องแบบละเอียด เพื่อนำไปใช้ต่อกันครับ

ตอนนี้อาจจะซับซ้อนหน่อย แต่แสดงให้เห็นว่าเราสามารถเล่นแร่แปรธาตุและทำอะไรๆ กับ Variable บน Terraform ได้มากระดับหนึ่งทีเดียว ซึ่งหากต้องการ Customize code แบบ Programming มากขึ้นก็สามารถไปท่า CDK, SDK integration ได้ด้วย

เราทราบแล้วว่าการสร้าง Resources ด้วย for_each จะรับค่าจาก map หรือ set of strings เท่านั้น

สารตั้งต้น ทำให้สั้นเพื่อง่ายต่อการใช้งาน
Image description

ปลายทางที่ต้องการ จัดให้อยู่ในรูปแบบ Map โดยแจกแจง Properties ของแต่ละ VM เพื่อใช้ร่วมกับ for_each
Image description

Step 0:

สารตั้งต้น ต้องการสร้างเครื่องจำนวน 2 Group ชื่อว่า GroupA และ GroupB
โดย GroupA ให้สร้าง 2 เครื่อง ให้แต่ละเครื่องมี CPU=2 และ memory=2048
ส่วน GroupB ให้สร้าง 1 เครื่อง ให้แต่ละเครื่องมี CPU=1 และ memory=1024

vm = tolist([                                                                                                                                                                                                      
  {                                                                                                                                                                                                                  
    "group" = "GroupA"                                                                                                                                                                                               
    "count" = 2                                                                                                                                                                                                      
    "cpu" = 2                                                                                                                                                                                                        
    "memory" = 2048                                                                                                                                                                                                
  },                                                                                                                                                                                                               
  {                                                                                                                                                                                                                  
    "group" = "GroupB"                                                                                                                                                                                               
    "count" = 1                                                                                                                                                                                                      
    "cpu" = 1                                                                                                                                                                                                        
    "memory" = 1024                                                                                                                                                                                                
  },                                                                                                                                                                                                               
  {                                                                                                                                                                                                                  
    "group" = "GroupC"                                                                                                                                                                                               
    "count" = 0                                                                                                                                                                                                      
    "cpu" = 2                                                                                                                                                                                                        
    "memory" = 2048                                                                                                                                                                                                
  },                                                                                                                                                                                                             ])                    
Enter fullscreen mode Exit fullscreen mode

Step 1:

ใช้ for loop 2 ชั้น
โดย loop ชั้นแรก จะกวาดตามจำนวน Element ใน var.vm ซึ่งในที่นี้ก็คือจะกวาดตามจำนวน Group นั่นเอง ซึ่งในที่มี 3 Group คือ "GroupA", "GroupB", "GroupC"

loop ชั้นที่สอง จะกวาดตามจำนวนตัวแปร count ที่อยู่ใต้ element แต่ละตัวใน loop ชั้นแรก ซึ่งอ้างถึงตัวแปร count ได้จากตัวแปร i_name.count
ฉะนั้นในชั้นนี้ จะวิ่งตามจำนวนเครื่องที่ต้องการในแต่ละ Group นั่นเอง โดย
GroupA มีค่า Count=2 ก็จะมีการทำซ้ำ(loop) 2 รอบ,
GroupB มีค่า Count=1 ก็จะมีการทำซ้ำ(loop) 1 รอบ,
GroupA มีค่า Count=0 ก็จะมีการทำซ้ำ(loop) 0 รอบ

เมื่อรัน loop ชั้นแรกและชั้นที่สองเสร็จ จะได้การทำซ้ำ(loop) ทั้งหมด 3 รอบ เท่ากับจำนวนเครื่องที่ต้องการพอดี

หากปรับตัวเลข เป็นจำนวนที่ซับซ้อนขึ้น ก็จะได้การทำซ้ำที่มากขึ้นตาม เช่น GroupA Count=7, GroupB count=20, GroupC count=5 ก็จะได้จำนวนเครื่องทั้งหมด 32 เครื่องนั่นเอง

การทำ loop 2 ชั้น ตามจำนวน Group และตามค่าของ count ในแต่ละ Group

    for i_index, i_name in var.vm : [
      for j_index in range(0, i_name.count) : {
Enter fullscreen mode Exit fullscreen mode

Step 2:

สิ่งที่ทำในแต่ละรอบ การสร้างตัวแปรค่าใหม่ขึ้นมาจากค่าตัวแปรเดิม
จาก Step 1 เราได้สร้าง Loop 2 ชั้น เพื่อให้ทำซ้ำจำนวนรอบเท่ากับจำนวนเครื่องที่ต้องการได้แล้ว

ขั้นนี้ เราจะต้องทำสิ่งที่ต้องทำในแต่ละรอบ นั่นก็คือการกำหนดค่าให้กับ VM ในแต่ละรอบนั่นเอง

ตัวอย่างเช่น Loopชั้นแรกของ GroupA, Loopชั้นที่สอง ของ count=0 จะสร้าง VM สำหรับ GroupA โดยมี Index ของ GroupA เป็น count+1=1, และกำหนดค่า CPU, Memory ตาม GroupA

จากนั้น จะเป็น Loopชั้นแรกของ GroupA, แต่ Loop ชั้นที่สอง ของ count=1

ส่วนใน Loop ของ Group B ก็ทำเช่นเดียวกัน โดย Loop ชั้นแรกคือ GroupB, และ Loop ชั้นที่สองจะทำตามจำนวนของ count ซึ่งครั้งแรกคือ count=0 ก็จะสร้าง VM สำหรับ GroupB โดยมี Index ของ GroupB เป็น count+1=1, และกำหนดค่า CPU, Memory ตาม GroupB

การกำหนดค่าให้กับ loop แต่ละรอบ ตามค่า Group และค่า count

        name  = "${i_name.group}-${j_index+1}"
        group = i_name.group
        cpu   = i_name.cpu
        memory= i_name.memory
        index = j_index+1
Enter fullscreen mode Exit fullscreen mode

Step 3:

ประกอบ Step 1 และ 2 เข้าด้วยกัน
การประกอบ มีสิ่งที่ต้องทราบก่อนคือ
การใช้ (), [], {}
() ใช้ต่อท้าย Function เช่น flatten()
[] ใช้กับ list
{} ใช้กับ map

จากตัวแปรตั้งต้น เป็น list ของแต่ละ Group เพื่อให้เพิ่ม list ได้จำนวนมาก หรือเพิ่ม Group ได้จำนวนมากนั่นเอง ขั้นนี้ใช้ [], และเมื่อเข้าไปในแต่ละ Group จะเป็น map เพราะมี key: value ที่แน่นอน ก็คือ group, count, CPU, Memory ขั้นนี้ใช้ {}

ทั้งหมดที่ได้มา เนื่องจากเป็น map ซ้อนอยู่ใต้ชั้นของ list อีกที จึงนำมา Flatten ด้วย Function flatten ซึ่งใช้ () นั่นเอง

ชั้นนอกสุดจะเป็น function distinct() ทำการเช็คว่ามีค่าซ้ำไหม หากมีค่าใน list 2 ตัวที่ซ้ำกันก็จะนำออก
นำข้างต้นมารวมกัน จะได้เป็นการใช้งาน loop 2 ชั้น กับ list of map

  vm_list = distinct(flatten([
    for i_index, i_name in var.vm : [
      for j_index in range(0, i_name.count) : {
        name  = "${i_name.group}-${j_index+1}"
        group = i_name.group
        cpu   = i_name.cpu
        memory= i_name.memory
        index = j_index+1
      }
    ]
  ]))
Enter fullscreen mode Exit fullscreen mode

สำหรับในบรรทัด for i_index, i_name in var.vm : [
โดยปกติจะใช้ i_name เพื่อแทน element แต่ละตัวใน var.vm ซึ่งในที่นี้ก็คือแต่ละ Group นั่นเอง
แต่ครั้งนี้มีการใส่ i_index เพิ่มเข้ามาด้วย โดยจะแทน increment หรือการนับลำดับนั่นเอง ซึ่งสามารถนำ i_index ไปอ้างอิงใช้งานต่อได้หากต้องการใส่ลำดับแบบ Global เข้าไปเพิ่มเติม นอกเหนือจากการใช้ j_index ซึ่งเป็นลำดับเฉพาะแต่ละใน Group เท่านั้น

ในครั้งนี้เราจะไม่ได้ใส่ค่า i_index เข้าไป เพราะจะมีการใส่ลำดับทั้งหมด(global index) ในขั้นตอนการทำ map ขั้นสุดท้ายเพียงครั้งเดียวนั่นเอง

ทำการรัน จะได้

vm_list = [
{
    "cpu" = 2
    "group" = "GroupA"
    "index" = 1
    "memory" = 2048
    "name" = "GroupA-1"
  },
  {
    "cpu" = 2
    "group" = "GroupA"
    "index" = 2
    "memory" = 2048
    "name" = "GropuA-2"
  },
  {
    "cpu" = 1
    "group" = "GroupB"
    "index" = 1
    "memory" = 1024
    "name" = "GroupB-1"
  },
]
Enter fullscreen mode Exit fullscreen mode

สรุปในตอนนี้ เราได้ทำการ Enumerate Variable จากชื่อ Group และ จำนวน มาใส่ในตัวแปร list พร้อมทั้งระบุชื่อ Group, ลำดับ, Property ที่ต้องการซึ่งในที่นี้คือ CPU และ Memory

ตอนถัดไปจะทำการ construct map variable ขึ้นมาใช้งานครับ

1: ทำไมใช้ for_each แทน count ใน terraform
2: Enumerate the Variables in Terraform.
3: Transform list to map in Terraform

Top comments (0)