DZone>DevOps Zone>使用Terratest测试你的基础设施即代码
使用Terratest测试你的基础设施即代码
随着越来越多的基础设施成为代码,对你的IaC进行单元和集成测试是非常必要的。什么是IaC和测试你的基础设施代码意味着什么?
通过
-
6月23日,22 - DevOps Zone -教程
喜欢 (1)
评论
保存
鸣叫
352次浏览
加入DZone社区,获得完整的会员体验。
手动设置基础设施可能是一个耗时而忙碌的过程。这时,我们可以利用基础设施即代码 (IaC)工具来实现基础设施的自动化。IaC自动化可用于任何类型的基础设施,如虚拟机、存储等。随着越来越多的基础设施成为代码,为你的IaC进行单元和集成测试是至关重要的。我们将简要地讨论什么是IaC和测试你的基础设施代码的含义。然后,我们将深入探讨如何使用Terratest进行IaC测试。
让我们开始吧,好吗?
基础设施即代码(IaC)
基础设施即代码是指通过代码配置环境的过程,而不是通过GUI手动设置所需的基础设施和支持系统。例如,配置一个虚拟机,配置它,并为它设置监控。一些IaC的例子是Terraform、Packer、Ansible等。在基础设施即代码的帮助下,你也可以将你的基础设施跟踪到一个版本控制系统中,如Git,模块化和模板化,以便在多个环境和地区重复使用相同的代码。灾难恢复是你从编码的基础设施中得到的重要好处之一。通过IaC,你可以尽快在其他地区或环境中复制你的基础设施。
测试基础设施代码
IaC测试可以分为多个阶段。
正常性或静态分析
这是测试基础设施代码的最初始阶段。在静态分析中,我们确保我们的代码有正确的语法。它还有助于确保我们的代码符合行业标准并遵循最佳实践。林特人就属于这一类。理性测试工具的一些例子是Chef的foodcritic,Docker的hadolint,Terraform的tflint,等等。
单元测试
在单元测试的帮助下,我们评估我们的代码,而不需要实际配置基础设施。例子可以是限制你的容器以非root用户的身份运行,或者你的组只应该有TCP协议。一些单元测试的例子是Terraform的Conftest和Chefspecs的Chef Cookbooks。
以非root用户身份执行的Conftest例子。
package main
deny[msg] {
input.kind == "Deployment"
not input.spec.template.spec.securityContext.runAsNonRoot
msg := "Containers must not run as root"
}
集成测试
在集成测试中,我们希望通过实际部署到所需环境中来测试我们的IaC。例如,你部署了一台虚拟机,并在该机器上托管了一个80端口的Nginx服务器。因此,你将在部署后检查80端口是否在监听。
下面是用ServerSpec做这个的例子。
describe port(80) do
it { should be_listening }
end
在这篇文章中,我们将探讨使用Terrratest对基础设施代码进行集成测试。
Terratest是什么?我们能用它实现什么?
Terratest是一个由Gruntwork开发的Go库,它可以帮助你为用Terraform、Packer为亚马逊、谷歌等IaaS供应商编写的Infra作为代码创建和自动测试,或者为Kubernetes集群创建测试。它为你提供了各种功能和模式的任务,如。
- 测试Docker镜像,Helm图表,以及Packer模板。
- 允许与各种云提供商的API合作,如AWS和Azure。
Terratest为你的基础设施代码执行合理性和功能测试。有了Terratest,你可以很容易地发现当前基础设施代码中的问题,并尽快修复问题。我们还可以利用Terratest对您的基础设施进行合规性测试,例如,在通过您的IaC创建的任何新S3桶上启用版本控制和加密。
安装Terratest所需的二进制文件
Terratest主要需要Terraform和Go来执行。在这篇博文中,我们使用了1.0.0版的Terraform和1.17.6版的Go进行测试。
安装Terraform
按照Terraform网站的下载部分,在你的机器上安装Terraform;你可以使用软件包管理器或下载二进制文件,并使其在PATH中可用。
安装后,通过运行下面的命令来验证它是否正确安装。
terraform version
Go & test依赖性的安装可以通过以下步骤完成。
安装Go
你可以使用你的Linux发行版的软件包管理器来安装Go,或者按照Go的安装文档来安装。
go test
测试执行需要gcc
go test
命令可能需要gcc,你可以使用你的发行版的软件包管理器安装它。例如,在CentOS/Amazon Linux 2上,你可以使用yum install -y gcc
。
Terratest在行动
现在我们将使用terratest执行一些集成测试。安装步骤完成后,克隆terratest-sample资源库,开始执行terratest测试。我们先用Go编写测试,然后执行它。
首先要做的是。
- 你的测试文件名中应该有
_test
,例如sample_test.go
。这就是Go寻找测试文件的方式。 - 你的测试函数名应该以
Test
开始,T是大写字母。例如,TestFunction
就可以,但testFunction
会给你一个错误 "没有测试可以运行"。
设置AWS认证配置
我们需要AWS凭证来设置AWS中的基础设施;我们可以使用环境变量或共享凭证文件进行配置。更多细节请参考Terraform文档。
基础设施的Terraform代码可以在组件的相应文件夹中找到 对于ec2
,它在ec2_instance
,而对于API网关,它在api_gateway
。Terratest将Terraform的输出output.tf
,作为其测试的输入。下面是测试我们所使用的ec2实例上是否有相同的ssh密钥的片段。
package terratest
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/gruntwork-io/terratest/modules/terraform"
)
func TestEc2SshKey(t *testing.T) {
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform",
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
ec2SshKey := terraform.Output(t, terraformOptions, "instance_ssh_key")
assert.Equal(t, "terratest", ec2SshKey)
}
为了正确理解,我们将把它分成不同的部分。第一步,我们定义一个名为terratest的Go包,然后导入测试执行所需的不同包。
package terratest
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/gruntwork-io/terratest/modules/terraform"
)
一旦我们有了所有的先决条件,我们将创建一个函数来执行实际的测试。
func TestEc2SshKey(t *testing.T) {
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform",
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
ec2SshKey := terraform.Output(t, terraformOptions, "instance_ssh_key")
assert.Equal(t, "terratest", ec2SshKey)
}
在下面的部分,我们定义了terratest应该寻找Terraform清单的目录,即main.tf
,output.tf
,用于创建基础设施。
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform",
})
在Go中,我们使用defer方法来执行清理任务,它应该是terraform destroy
。
我们使用下面的片段来定义它。
defer terraform.Destroy(t, terraformOptions)
现在我们可以进入实际执行阶段。
通过terraform.InitAndApply
,我们正在调用Terraform函数terraform init
和apply
,我们通常使用这些函数来执行Terraform。
terraform.InitAndApply(t, terraformOptions)
如前所述,Terratest从output.tf中寻找变量定义的输出。
在下面的片段中,我们从Terraform的输出中获取ssh密钥,并将其与我们定义的ssh密钥名称匹配。
ec2SshKey := terraform.Output(t, terraformOptions, "instance_ssh_key")
assert.Equal(t, "terratest", ec2SshKey)
执行测试
将你的目录切换到你克隆资源库的位置。导航到你有测试文件的位置。
初始化Go模块,并下载依赖项。请看Terratest文档中的设置项目部分以了解更多细节。
go mod init ec2_instance
go mod tidy
最后,执行测试。
$ go test -v
--- PASS: TestEc2SshKey (98.72s)
PASS
ok command-line-arguments 98.735s
让我们用Terratest更进一步
在上一节中,我们使用Terratest进行了一些基本水平的测试。现在,我们将通过部署带有Lambda和ALB作为后端的API网关来进行高级测试。
高级功能
API网关的GET请求将由ALB提供,ANY方法将由Lambda通过API网关提供。在部署之后,我们将对网关的部署URL做一个HTTP GET请求,并检查它是否返回一个成功的代码。
注意:在我们的执行中,我们没有使用任何API_KEY
进行认证,但你应该利用它来复制API Gateway的更真实的使用。
Terraform output.tf
output "lb_address" {
value = aws_lb.load-balancer.dns_name
description = "DNS of load balancer"
}
output "api_id" {
description = "REST API id"
value = aws_api_gateway_rest_api.api.id
}
output "deployment_invoke_url" {
description = "Deployment invoke url"
value = "${aws_api_gateway_stage.test.invoke_url}/resource"
}
测试执行的代码片段
在第一种情况下,我们已经解释了基本语法,所以将直接进入测试功能。
func TestApiGateway(t *testing.T) {
//awsRegion := "eu-west-2"
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../",
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
stageUrl := terraform.Output(t, terraformOptions,"deployment_invoke_url")
time.Sleep(30 * time.Second)
statusCode := DoGetRequest(t, stageUrl)
assert.Equal(t, 200 , statusCode)
}
func DoGetRequest(t terra_test.TestingT, api string) int{
resp, err := http.Get(api)
if err != nil {
log.Fatalln(err)
}
//We Read the response status on the line below.
return resp.StatusCode
}
在上面的代码片段中,我们定义了函数DoGetRequest
,以运行一个HTTP GET测试。然后我们用这个函数的输出作为TestApiGateway
函数的输入。
测试的执行和输出
TestApiGateway 2022-03-01T06:56:18Z logger.go:66: deployment_invoke_url = "https://iuabeqgmj2.execute-api.eu-west-1.amazonaws.com/test/resource"
TestApiGateway 2022-03-01T06:56:18Z logger.go:66: lb_address = "my-demo-load-balancer-376285754.eu-west-1.elb.amazonaws.com"
TestApiGateway 2022-03-01T06:56:18Z retry.go:91: terraform [output -no-color -json deployment_invoke_url]
TestApiGateway 2022-03-01T06:56:18Z logger.go:66: Running command terraform with args [output -no-color -json deployment_invoke_url]
TestApiGateway 2022-03-01T06:56:19Z logger.go:66: "https://iuabeqgmj2.execute-api.eu-west-1.amazonaws.com/test/resource"
--- PASS: TestApiGateway (42.34s)
PASS
ok command-line-arguments 42.347s
你可以看到它已经执行了我们的测试函数TestApiGateway
,它对API网关的deployment_invoke_url
进行了HTTP GET测试并返回了测试状态。
Terratest模块的扩展性和使用Terratest的合规性测试
我们也可以利用Terratest进行合规性测试。其中一些例子可以是。
- 检查您的SQS队列或S3桶是否启用了加密功能。
- 验证您是否为API网关设置了特定的节流限制。
我们已经为API网关开发了一个Terratest检查。在这个例子中,我们正在验证是否为您的API网关添加了Authorizer
。你可以找到更多关于什么是授权者的信息。
目前,Terratest在其AWS模块中没有API网关模块。你可以在Terratest AWS模块目录中找到可用的AWS模块。其他Terratest模块,如Docker、Packer和Helm,可以在Terratest模块目录中找到。
企业和他们的客户都希望产品能更快地被运出。基础设施即代码(Infrastructure as Code)正是通过加快基础设施的配置来实现的。随着越来越多的基础设施成为代码,对测试的需求也在增加。在这篇文章中,我们讨论了像Terratest这样的工具如何在你将代码部署到生产之前帮助验证你的代码。我们展示了Terratest是如何工作的,甚至还执行了测试案例来展示它是如何完成的。Terratest的优点之一是它的可扩展性,可以通过使用模块来实现,正如文章中所谈到的。
API AWS 基础设施 基础设施即代码 Docker(软件) Terraform(软件)测试
经Akash Warkhade许可发表于DZone。点击这里查看原文。
DZone贡献者所表达的观点属于他们自己。
DZone上的热门文章
评论