Day 26-如何测试 terraform 之一:长 code 短 code,能过测试的 code 才是好 code

本篇翻译与讲解 terraform 官方 blog 对於 test terraform 的建议

课程内容与代码会放在 Github 上: https://github.com/chechiachang/terraform-30-days

赛後文章会整理放到个人的部落格上 http://chechia.net/

追踪粉专可以收到文章的主动推播

https://ithelp.ithome.com.tw/upload/images/20210901/20120327NvpHVr2QC0.jpg


test your code

测试是程序码开发的一环,对於程序码的品质影响巨大,这里不提测试的概念。总之,测试非常重要。

以 terraform 而言,有许多时候都会需要测试

  • 测试一个 terraform module 功能
  • 测试一个 root module 产生的 infrastructure 是否符合预期
  • 测试一段 .tf 修改是否会破坏现有功能
  • ...

那应该如何测试 terraform?

testing for terraform

官方 blog 对於测试 terraform 的文件描述

将团队选择测试策略,依照成本(时间成本与费用)排序,会是个阶层金字塔

  • unit test
  • contract test
  • integration test
  • end-to-end test
  • manual test

基於这个基础想法,分别讨论如何测试 terraform

unit test

terraform fmt -check
terraform validate

实作有几个选项

contract test

检查 module 的 input 与 input format

  • 最基本的是给予 input variable type,而不要使用 any / object
  • 接着是使用 variable block 中的 validation {},为参数设定 validation,排除意外的参数

terraform 在 variable 中提供 custom validation rule 的功能

  • 绝大多数的公有云 API 对於 request argument 都有限制,可以在官方文件查找,如果 terraform 使用不合法的参数,在 apply phase (api request 出去後) 会收到 error
  • 依据 api 限制,与业务需求设置 validation 可以让 validate / plan phase 就出错
  • 软件工程中的fail-fast 原则
variable "listener_rule_priority" {
 type        = number
 default     = 1
 description = "Priority of listener rule between 1 to 50000"
 validation {
   condition     = var.listener_rule_priority > 0 && var.listener_rule_priority < 50000
   error_message = "The priority of listener_rule must be between 1 to 50000."
 }
}

contract test 可以延伸,所有在 terraform apply 之前,针对 content / format / input / output 的检查都可以

integration test

整合测试针对 terraform apply 的结果做测试,也就是 terraform module 是否正确的产出 infrastructure

  • 透过 test framework,实际对公有云发出 api request
  • 实际 apply,但是放在独立的测试空间
  • 使用测试用的 name 与 id,来与实际的环境隔离,(ex. 使用 dev / stag /prod 以外的环境产生 infrastructure)
  • 使用测试用的参数可能是 testing name / id 或是 function 产生的 (ex. random name / id)
  • 根据 apply 後的 result 做测试
  • apply 後,destroy 产生的 infrasturcture

使用 terraform test framework

  • Terratest
  • 这个下一堂会示范如何使用 terratest framework

End-to-End test

当 terraform apply 後,产生的 infrastructure,使用者是否能正常使用

这个层级的测试需要导入使用者的测试例,会需要 QA 团队协助

  • 如果 infrastructure 上部署 app,也需要 app 团队

如何对 terraform 做 end-to-end test

  • 可以锁住稳定的 app 版本
  • 使用新版的 terraform 在独立的环境 apply
  • 执行 QA team 的 end-to-end 测试,在 app 不变的状况下,改变 infra 是否会改变测试结果

End-to-End 通常会花费需多时间,但对於整体环境是非常必要的

Manual test

要如何手动测试 terraform?

如果是 app,我们会手动测试其功能

  • ex. 一个网站,连线到新版网站,并手动操作功能,来进行手动测试

回到 infrastructure,如何手动测试 infrastructure 的功能?

  • 针对公有云的 infrastructure,除非我们发现奇怪的错误讯息,不然一般都会选择稳定的 infra 产品,并相信公有云的文件,也相信产生出的 infra 品质
  • ex. 把 aws ec2 生出来後,通常不会需要进去手动测试,他就是一个功能正常的 vm
  • 更多时候 terraform 撑出来的 infrastructure 出错,多半是 terraform resource argument 填错,产生意料之外的 infra

因此对 terraform 而言,针对嵾数做 variable validation 是十分有效的

summary

笔者建议,做少少的努力就可以获得明显成效的方法

  • terraform format + validation
  • auto terraform plan + apply
  • variable custom validation

app 产品稳定的话,应该有 end-to-end test,善用 QA 团队既有的 end-to-end test

  • 锁住 app 在稳定版本
  • 最好在上 stag / prod 之前,都能完成完整的 end-to-end test
  • 如果产品规模太大, end-to-end 跑不完的话,可以针对修改部分进行测试
  • 例如更改 network infra,就要求 QA 在新环境执行 networking 相关的 end-to-end test

完成以上内容,已经满足一个『能够正常乘载 app 的 infra 的需求了』。当然,实务上只是满足需求不是终点,还有非常多可以调整优化的地方

为 terraform 额外写 integration test,可以进一步提升 module 品质,降低成本与提升效能

  • terratest integration test 可以达到 module 品管
  • 可以针对复杂的 module 做,特别是 dependency module 多,阶层复杂,参数复杂的 module
  • 简单的 module ex. 只有一个 resource,没有复杂依赖关系的 module 就不需要写 terratest,写了变成测试比 code 多太多

<<:  Day11 AR安全帽 边骑车边滑手机(用声音) 给不想要乖乖骑车的你(前提是够有钱)

>>:  【Day26】this - 物件的方法调用

Day 28 - State Monad III

嗨大家好,真希望一天能有 48 小时,不然这主题都要分到四部曲了,没错,应该会有四部曲! 抱歉了! ...

[Lesson25] Kotlin - Array

基本型态阵列 Kotlin 已经有内建一些阵列物件,如 ByteArray、IntArray、Dou...

Day1-前言

先自我介绍一下,本身是研发部门里的後端工程师,而此次是我第一次参加铁人赛,希望透过这次参加比赛,也增...

[DAY3]SQL新手的懒人笔记

[DAY3]SQL的新手懒人笔记 (大写为内建语法) 21.ORDER BY可用来排序资料,如果是字...

Day19 该如何发问问题?

大家好,我是乌木白,今天想和大家聊聊,如果在该如何去发问问题? 遇到问题该怎麽办? 在现今网路发达...