DEV Community

Cover image for Module in Terraform for conditional use cases(Advanced)
terngr
terngr

Posted on

Module in Terraform for conditional use cases(Advanced)

มาต่อเรื่อง Terraform อีกซักนิดครับ การใช้เงื่อนไขใน Terraform สามารถทำได้หลายแบบ จริงๆ เน้นท่าประหลาดๆ สำหรับ Use cases ยากๆ ที่หาจากไหนไม่ได้ ถ้าหลักง่ายๆคิดว่าหาจาก Docs ได้google.com ก่อนอื่นขอปูพื้นนิดนึงครับ

condition

สามารถกำหนดเงื่อนไข precondition และ/หรือ postcondition ได้
เมื่อไม่ได้เงื่อนไขตามที่กำหนด ก็จะไม่สามารถสร้าง resources เสร็จสมบูรณ์ได้ และผลคือ Terraform apply ไม่สำเร็จ

resource "aws_instance" "example" {
  instance_type = "t3.micro"
  ami           = data.aws_ami.example.id

  lifecycle {
    # The AMI ID must refer to an AMI that contains an operating system
    # for the `x86_64` architecture.
    precondition {
      condition     = data.aws_ami.example.architecture == "x86_64"
      error_message = "The selected AMI must be for the x86_64 architecture."
    }

    # The EC2 instance must be allocated a public DNS hostname.
    postcondition {
      condition     = self.public_dns != ""
      error_message = "EC2 instance must be in a VPC that has public DNS hostnames enabled."
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

จะเห็นได้ว่า การใช้ condition, precondition, postcondition ตัว condition เองจะต้องสำเร็จอย่างเดียวเท่านั้นจึงจะทำงานต่อจนจบได้ ถ้าไม่สำเร็จ/ไม่ผ่าน ก็จะ Error แล้วจบการทำงาน แต่ถ้าเป็นเงื่อนไขที่มีทางเลือกมากกว่าหนึ่งล่ะ

ถ้าเป็นการกำหนดค่า จะใช้

<statement> ? <procedure when true> : < procedure when false>
Enter fullscreen mode Exit fullscreen mode

ตัวอย่างเช่น จะหาค่าตำแหน่งว่าเป็น East หรือ West จากตัวเลข

location = myinput < 50 ? "East" : "West"

จะได้ว่า หาก myinput มีค่าน้อยกว่า 50 จริง จะได้ location = "East"
แต่ถ้าเป็นเท็จ ก็คือ myinput มีค่าตั้งแต่ 50 ขึ้นไป จะได้ location = "West" นั่นเอง

จะเห็นได้ว่า เราสามารถกำหนดค่าที่มีทางเลือกมากกว่า 1 ได้ ไม่จำเป็นต้อง True เสมอไป

ถ้าต้องการใช้แบบ switch case หรือหลายทางเลือก ก็สามารถซ้อนกันได้

location = n < 26 ? "North" : n<50 ? "East" : West
Enter fullscreen mode Exit fullscreen mode

Resource

ถ้าเราต้องการใส่เงื่อนใน ในการสร้าง Resource ล่ะ ก็คือถ้าตรงเงื่อนไขให้สร้าง ถ้าไม่ตรงเงื่อนไขไม่สร้าง ซึ่งจะไม่เหมือนกับเคส condition ที่ต้องตรงเงื่อนไขเท่านั้น ไม่ตรงไม่ได้

เคสนี้เราสามารถใช้การ count หรือ for_each ใน resource blog มาช่วยได้
โดยถ้าเงื่อนไขที่กำหนดถูกต้อง ให้ทำการสร้าง resource นี้จำนวน count=1 ก็คือสร้างตามปกตินั่นเอง
แต่ถ้าเงื่อนไขไม่ถูกต้อง ก็ให้ทำการสร้าง resource นี้จำนวน count=0 ก็คือไม่สร้างนั่นเอง

Use case 1

ถ้าต้องการสร้าง resource แบบ count และใส่เงื่อนไขด้วย จะทำอย่างไร
เพราะการสร้าง resource แบบมีเงื่อนไขจะต้องใช้ count, และ terraform ไม่ยอมให้ทำ count ซ้อนกัน

เราจะใช้ความสามารถของ Module มาช่วยโดย
Count=n เพื่อทำการสร้าง Module จำนวน n module
แล้วในแต่ละ Module ค่อยไปสร้าง Resource Blog ตามปกติ ก็จะสามาถใช้ count กับ Resource Blog ในรูปแบบปกติได้ ถ้าตรงเงื่อนไขให้สร้าง ไม่ตรงเงื่อนไขไม่ต้องสร้างได้นั่นเอง

Use case 2

Resource ที่มีการสร้าง objects ข้างในได้จำนวนเท่ากับ 1 หรือมากกว่า 1
เช่น VM ที่มี Disk 1 หรือ มากกว่า 1 ลูก
VM ที่ Attach Network Interface Card 1 หรือมากกว่า 1 ใบ
เราสามารถสั่งให้ Terraform Resource สร้าง Disk ลูกที่ 2 ตามเงื่อนไขได้ไหม(เช่น ถ้ามีการกำหนดขนาด Disk >0 จึงค่อยสร้าง)

จะเห็นได้ว่า ในเคสนี้ การใช้ Count จะเป็นการตัดสินใจสร้าง หรือไม่สร้างในระดับ Resource VM แต่ไม่สามารถตัดสินใจระดับ Object หรือจำนวน Object ใต้ Resource ได้

เราใช้การออกแบบมาแก้ปัญหา โดยสร้าง Resource มา 2 แบบ
แบบแรก มี Disk ลูกเดียว, กำหนดเงื่อนไขการสร้าง Resource นี้ต่อเมื่อค่าความจุของ Disk 2 <1 โดยใช้ Count เป็นตัวกำหนดเงื่อนไข
แบบที่สอง มี Disk สองลูก, กำหนดเงื่อนไขการสร้าง Resource นี้ต่อเมื่อค่าความจุของ Disk 2 >0 โดยใช้ Count เป็นตัวกำหนดเงื่อนไข

สรุป

จะเห็นได้ว่า HCL ถูกออกแบบมาให้ง่ายต่อ Human ในการเข้าใจและใช้งาน แต่ไม่ได้ออกแบบมาในเชิงการ Programming, หากต้องการใส่เงื่อนไขที่ซับซ้อนหน่อยจะต้องออกแรงเพิ่มเป็นครั้งๆ ไป โดยใช้การทำเงื่อนไขที่ HCL มีให้ใช้คือ "? :" และ module
เราอาจใช้งาน module เกือบเป็น function ที่ถูกเรียกมาใช้งานก็ได้ เพราะสามารถไปทำชุดงานอีกชุด(อีก Folder) ได้ และ return ค่าได้ แต่ระวังเรื่องเงื่อนไขการเรียก Module ไม่สามารถกำหนดได้ เหตุผลคือการเรียกโมดูลต้องตายตัว จะเรียกตามเงื่อนไขไม่ได้ ต้องเรียกหรือไม่เรียกเลยเท่านั้น ในทีนี้ก็คือต้องเรียกตลอด แล้วค่อยใส่เงื่อนไขไว้ใต้ module อีกทีนั่นเองครับ

Top comments (0)