จะทดสอบการกำหนดค่า Terraform อย่างไร


37

หากคุณมีการกำหนดค่าTerraformที่มีความซับซ้อนในระดับปานกลางคุณจะเขียนการทดสอบเกี่ยวกับการกำหนดค่าที่สามารถดำเนินการโดยเป็นส่วนหนึ่งของขั้นตอนการรวมระบบต่อเนื่อง / การจัดส่งแบบต่อเนื่องได้อย่างไร

ตัวอย่างเช่นคุณอาจมีการกำหนดค่าหลายคลาวด์ที่ระบุสถานะที่ต้องการต่อไปนี้:

  • Azure Container Services เพื่อโฮสต์ Docker ใน Azure
  • Azure Blob Storage
  • SQL Azure
  • บริการคอนเทนเนอร์ EC2 เพื่อโฮสต์ Docker ใน AWS
  • บริการจัดเก็บ Amazon S3
  • ฐานข้อมูล Amazon RDS SQL Server

อาจเป็นไปterraform applyได้ที่จะสร้างข้างต้นจากรอยขีดข่วนหรือการเปลี่ยนจากสถานะที่ใช้งานบางส่วนไปเป็นสถานะที่ต้องการข้างต้น

ฉันทราบว่า Terraform แบ่งงานออกเป็นขั้นตอนการวางแผนการดำเนินการและขั้นตอนการสมัครซึ่งจริง ๆ แล้วทำการเปลี่ยนแปลงสถาปัตยกรรมเป้าหมาย สิ่งนี้สามารถใช้เพื่อเขียนการทดสอบเทียบกับแผนการดำเนินการได้หรือไม่หากมีกรอบในการช่วยเขียนสิ่งเหล่านี้


อาจมีประโยชน์: github.com/hashicorp/terraform/issues/5059
Tensibai

น่าสนใจแน่นอนอาจเป็นคำตอบที่คุ้มค่า
Richard Slater

ฉันไม่ได้ใช้ terraform ตัวเองดังนั้นผมจึงปล่อยให้คนที่มีประสบการณ์จริงเขียนคำตอบ :)
Tensibai

คำตอบ:


20

ปัจจุบันยังไม่มีวิธีการแก้ปัญหาที่สมบูรณ์แบบสำหรับการรวมเข้ากับ Terraform แต่มีบางหน่วยการสร้างที่อาจมีประโยชน์ในการช่วยในการเขียนการทดสอบในภาษาโปรแกรมแยกต่างหาก

Terraform สร้างไฟล์สถานะในรูปแบบ JSON ซึ่งโดยหลักการแล้วโปรแกรมภายนอกสามารถใช้เพื่อดึงข้อมูลบางอย่างเกี่ยวกับสิ่งที่ Terraform สร้างขึ้น ในขณะที่รูปแบบนี้ยังไม่ถือว่ามีความเสถียรอย่างเป็นทางการ แต่ในทางปฏิบัติแล้วการเปลี่ยนแปลงนั้นไม่บ่อยพอที่ผู้คนจะรวมเข้าด้วยกันได้สำเร็จโดยยอมรับว่าพวกเขาอาจจำเป็นต้องทำการปรับเปลี่ยนเมื่ออัพเกรด Terraform

กลยุทธ์ใดที่เหมาะสมที่นี่จะขึ้นอยู่กับว่าคุณต้องการทดสอบอะไรมาก ตัวอย่างเช่น:

  • ในสภาพแวดล้อมที่ปั่นเซิร์ฟเวอร์เสมือนเครื่องมือต่าง ๆ เช่นเซิร์ฟเวอร์สามารถใช้เพื่อทดสอบการทำงานจากมุมมองของเซิร์ฟเวอร์เหล่านี้ นี้ก็จะสามารถทำงานแยกต่างหากจาก terraform ใช้บางส่วนขั้นตอนการออกจากวงหรือเป็นส่วนหนึ่งของ terraform สมัครใช้Provisionerremote-exec วิธีนี้ช่วยให้สามารถตรวจสอบคำถามเช่น "เซิร์ฟเวอร์สามารถเข้าถึงฐานข้อมูลได้หรือไม่" แต่ไม่เหมาะสำหรับคำถามเช่น "กลุ่มความปลอดภัยของอินสแตนซ์นั้นมีข้อ จำกัด เพียงพอหรือไม่" เนื่องจากการตรวจสอบอย่างเข้มงวดที่ต้องการการเข้าถึงข้อมูลจากภายนอก

  • เป็นไปได้ที่จะเขียนการทดสอบโดยใช้เฟรมเวิร์กการทดสอบที่มีอยู่ (เช่น RSpec สำหรับ Ruby, unittestPython, ฯลฯ ) ซึ่งรวบรวมรหัสทรัพยากรหรือที่อยู่ที่เกี่ยวข้องจากไฟล์สถานะ Terraform จากนั้นใช้ SDK ของแพลตฟอร์มที่เกี่ยวข้องเพื่อดึงข้อมูลเกี่ยวกับทรัพยากรและยืนยันว่า พวกเขาตั้งค่าตามที่คาดไว้ นี่เป็นรูปแบบทั่วไปของแนวคิดก่อนหน้านี้ใช้การทดสอบจากมุมมองของโฮสต์นอกโครงสร้างพื้นฐานภายใต้การทดสอบและสามารถรวบรวมชุดข้อมูลที่กว้างขึ้นเพื่อยืนยัน

  • สำหรับความต้องการที่ถ่อมตัวมากขึ้นเราสามารถเลือกที่จะเชื่อมั่นว่าสถานะ Terraform เป็นตัวแทนที่แท้จริงของความเป็นจริง (สมมติฐานที่ถูกต้องในหลาย ๆ กรณี) และยืนยันได้โดยตรงจากสิ่งนั้น สิ่งนี้เหมาะสมที่สุดสำหรับกรณี "แบบคล้ายผ้าสำลี" ที่ง่ายที่สุดเช่นการตรวจสอบว่ามีการติดตามรูปแบบการติดแท็กทรัพยากรที่ถูกต้องเพื่อวัตถุประสงค์ในการจัดสรรต้นทุน

มีบางอภิปรายเพิ่มเติมเกี่ยวกับเรื่องนี้คือปัญหา terraform Github ที่เกี่ยวข้อง

ใน Terraform เวอร์ชันล่าสุดขอแนะนำอย่างยิ่งให้ใช้แบ็กเอนด์ระยะไกลสำหรับแอปพลิเคชันที่ไม่ใช่ของเล่นใด ๆ แต่นั่นหมายความว่าข้อมูลสถานะไม่สามารถใช้งานได้โดยตรงบนดิสก์ภายในเครื่อง อย่างไรก็ตามสแน็ปช็อตของมันสามารถดึงจากแบ็กเอนด์ระยะไกลโดยใช้terraform state pullคำสั่งซึ่งพิมพ์ข้อมูลสถานะที่จัดรูปแบบ JSON ไปยัง stdout เพื่อให้สามารถจับภาพและแยกวิเคราะห์โดยโปรแกรมเรียก


12

จากการอัปเดตสำหรับคำถามนี้ขณะนี้มีKitchen-Terraformซึ่งอนุญาตให้ทำการทดสอบไฟล์การกำหนดค่า Terraform โดยไม่ทำลายสภาพแวดล้อมการผลิต พื้นที่เก็บข้อมูลยังมีตัวอย่างสำหรับผู้ให้บริการ Terraform ที่แตกต่างกัน


12

เมื่อเร็ว ๆ นี้เราได้เปิดTerratestที่มาจากแหล่งซึ่งเป็นมีดกองทัพของเราสำหรับการทดสอบรหัสโครงสร้างพื้นฐาน

วันนี้คุณอาจทดสอบโค้ดโครงสร้างพื้นฐานทั้งหมดด้วยตนเองโดยปรับใช้ตรวจสอบและเลิกใช้งาน Terratest ช่วยให้คุณทำกระบวนการนี้โดยอัตโนมัติ:

  1. ทดสอบการเขียนใน Go
  2. ใช้ผู้ช่วยเหลือใน Terratest เพื่อเรียกใช้เครื่องมือ IaC จริง (เช่น Terraform, Packer ฯลฯ ) เพื่อปรับใช้โครงสร้างพื้นฐานจริง (เช่นเซิร์ฟเวอร์) ในสภาพแวดล้อมจริง (เช่น AWS)
  3. ใช้ตัวช่วยใน Terratest เพื่อตรวจสอบว่าโครงสร้างพื้นฐานทำงานอย่างถูกต้องในสภาพแวดล้อมนั้นโดยการร้องขอ HTTP การเรียก API การเชื่อมต่อ SSH และอื่น ๆ
  4. ใช้ผู้ช่วยเหลือใน Terratest เพื่อเลิกใช้งานทุกอย่างเมื่อสิ้นสุดการทดสอบ

นี่คือตัวอย่างทดสอบสำหรับรหัส Terraform บางส่วน:

terraformOptions := &terraform.Options {
  // The path to where your Terraform code is located
  TerraformDir: "../examples/terraform-basic-example",
}

// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)

// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer terraform.Destroy(t, terraformOptions)

// Run `terraform output` to get the value of an output variable
instanceUrl := terraform.Output(t, terraformOptions, "instance_url")

// Verify that we get back a 200 OK with the expected text
// It can take a minute or so for the Instance to boot up, so retry a few times
expected := "Hello, World"
maxRetries := 15
timeBetweenRetries := 5 * time.Second
http_helper.HttpGetWithRetry(t, instanceUrl, 200, expected, maxRetries, timeBetweenRetries)

สิ่งเหล่านี้คือการทดสอบการรวมระบบและอาจใช้เวลา 5 - 50 นาที มันไม่เร็ว (แม้ว่าจะใช้นักเทียบท่าและขั้นตอนการทดสอบคุณสามารถเร่งความเร็วบางอย่างได้) และคุณจะต้องทำงานเพื่อให้การทดสอบนั้นเชื่อถือได้ แต่คุ้มค่ากับเวลา

ตรวจสอบเอกสารrepatest Terratestสำหรับเอกสารและตัวอย่างมากมายของรหัสโครงสร้างพื้นฐานประเภทต่างๆและการทดสอบที่เกี่ยวข้องสำหรับพวกเขา


1
ผมเคยเขียนยังโพสต์บล็อกที่เดินผ่านการทดสอบหนึ่งในโครงการตัวอย่างของฉันกับ Terratest ในรายละเอียดเพิ่มเติมได้ที่: brightfame.co/blog/... มันอาจมีค่าสำหรับทุกคน ไชโยปล้น!
Rob Morgan

แฟนตัวยงของ Terratest!
jlucktay

7

นอกเหนือจากตัวเลือกอื่น ๆ ทั้งหมดที่กล่าวถึงฉันอยากจะพูดถึงว่า InSpec 2.0 ได้เพิ่มการสนับสนุนสำหรับผู้ให้บริการคลาวด์ API โดยทั่วไปคุณสามารถเขียน IaC ด้วย Terraform ต่อจากนั้นเขียนการตรวจสอบตามมาตรฐานด้วย InSpec สำหรับทรัพยากรคลาวด์ของคุณ นอกจากนี้ InSpec ยังรองรับการทดสอบการเขียนสำหรับเครื่องแต่ละเครื่องหากคุณต้องการ

นี่คือบทความจาก Christoph Hartmann (ผู้ร่วมสร้าง Inspec) เกี่ยวกับวิธีการใช้ Inspec กับ Terraform: https://lollyrock.com/articles/inspec-terraform/


5

บน Aws-Side มีhttps://github.com/k1LoW/awspec - ควรเป็นไปได้ที่จะให้อาหารใน terraform.state และการทดสอบ wheter terraform ถูกต้องแล้ว

แต่ฉันคิดว่านอกเหนือจากการทดสอบเครื่องมือระดับต่ำแล้วคุณอาจเป็นความคิดที่ดีกว่าเพื่อคิดเกี่ยวกับวิธีทดสอบโครงสร้างพื้นฐานทั้งหมด

เรากำลังพูดถึงแนวคิดนี้ที่นี่:

https://github.com/DomainDrivenArchitecture/dda-cloudspec/blob/development/README.md

สำหรับการทดสอบค่าคงที่ล่วงหน้าฉันไม่ทราบวิธีแก้ปัญหาพร้อมใช้ ...

เราทำการทดลองบางอย่างโดยใช้การผสมผสานterraform plan -out=plan.dumpและgrepสำหรับการขาดชื่อองค์ประกอบ มีการอภิปรายเกี่ยวกับรูปแบบแผนเข้าถึงได้มากขึ้นที่นี่: github.com/hashicorp/terraform/issues/11883

แต่ในขณะนี้เรากำลังใช้กระบวนการตรวจสอบแผนด้วยตนเองสำหรับส่วนสำคัญของโครงสร้างพื้นฐานของเรา


4
เป้าหมายคือการทดสอบการเปลี่ยนแปลงในการกำหนดค่า terraform จะไม่ทำลายความต้องการที่คาดหวังเมื่อปรับใช้มันสายเกินไปที่ดีที่สุดที่คุณมีความล้มเหลวในการเห็นฐานข้อมูลถูกลบไปในที่ที่ไม่ควร แต่คุณได้ทำลายสภาพแวดล้อมเป้าหมายแล้ว .. คำถามเกี่ยวกับการทดสอบรหัส terraform ไม่ใช่การทดสอบผลลัพธ์สุดท้ายการทดสอบหน่วยเทียบกับการทดสอบการรวม
Tensibai

จุดดี ... ได้เพิ่มหัวข้อสำหรับการทดสอบค่าคงที่
jerger

0

ฉันเห็นวิธีการที่สง่างามและมีเทคโนโลยีต่ำในการทดสอบ Terraform ที่แนะนำโดยapparentlymartในเธรดปัญหา GitHub มันไม่เหมาะสำหรับทุกสถานการณ์ แต่เป็นการดีในการตรวจสอบตรรกะโมดูล

สร้างโมดูลรูทที่มีโมดูลที่อยู่ภายใต้การทดสอบและตรวจสอบผลลัพธ์ที่อยู่ระหว่างการทดสอบ นี่คือตัวอย่างง่ายๆโดยใช้สองไฟล์:

  • main.tf ที่จะทำการทดสอบ
  • simple_module/outputs.tf ที่แสดงถึงโมดูลภายใต้การทดสอบ

./main.tf

terraform {
  required_version = ">= 0.12"
}

module "simple_module" {
  source = "./simple_module"
}

locals {
  expected = 1
  got      = module.simple_module.module-returns-1
}

# Test Output
output "expect-1" {
  value = upper(local.expected == local.got)
}

output "expect-other" {
  value = "other" == local.got ? upper(true) : "FALSE. Got ${local.got}"
}

./simple_module/outputs.tf

output "module-returns-1" {
  value = 1
}

ทำการทดสอบ

terraform init
terraform apply -auto-approve
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

expect-1 = TRUE
expect-other = FALSE. Got 1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.