在 Terraform 项目上实现端到端的 Terratest 测试

使用 Terraform 可以定义、预览和部署云基础结构。 使用 Terraform 时,请使用 HCL 语法来创建配置文件。 利用 HCL 语法,可指定 Azure 这样的云提供程序和构成云基础结构的元素。 创建配置文件后,请创建一个执行计划,利用该计划,可在部署基础结构更改之前先预览这些更改。 验证了更改后,请应用该执行计划以部署基础结构。

端到端 (E2E) 测试用于在将程序部署到生产环境之前验证其是否有效。 示例场景可能是一个将两个虚拟机部署到虚拟网络中的 Terraform 模块。 你可能想要阻止这两个虚拟机相互执行 ping 操作。 在此示例中,可定义一个测试,在部署之前验证预期结果。

E2E 测试通常分三步执行。

  1. 将配置应用于测试环境。
  2. 运行代码以验证结果。
  3. 重新初始化或关闭测试环境(例如解除虚拟机的分配)。

在本文中,学习如何:

  • 了解使用 Terratest 进行端到端测试的基础知识
  • 了解如何使用 Golang 编写端到端测试
  • 了解如何使用 Azure DevOps 在将代码提交到存储库时自动触发端到端测试

1.配置环境

  • Azure 订阅:如果没有 Azure 订阅,请在开始之前创建一个免费帐户。
  • Go 编程语言安装 Go

  • 示例代码和资源:使用 DownGit 工具从 GitHub 下载 end-to-end-testing project,并将其解压缩到新的目录中,使其包含示例代码。 此目录被称为“示例目录”

2. 了解端到端测试

端对端测试会验证系统是否作为整体进行工作。 这种类型的测试与测试特定的模块不同。 在 Terraform 项目中,可通过端到端测试验证已部署的内容。 这种类型的测试与其他很多测试预部署方案的类型不同。 对于测试包含多个模块且作用于多个资源的复杂系统来说,端到端测试至关重要。 在这种情况下,只能使用端到端测试来确定各个模块是否正确交互。

本文重点介绍如何使用 Terratest 实现端到端测试。 Terratest 提供执行下列任务所需的全部管道:

  • 部署 Terraform 配置
  • 使你能够使用 Go 语言编写测试来验证已部署的内容
  • 安排分阶段执行测试
  • 拆解已部署的基础架构

3. 了解测试示例

在本文中,我们将使用 Azure/terraform 示例存储库中提供的示例。

此示例定义了一个 Terraform 配置,它将两个 Linux 虚拟机部署到同一虚拟网络中。 第一个虚拟机 (VM) 名为 vm-linux-1,具有公共 IP 地址。 仅打开端口 22 以允许 SSH 连接。 第二个 VM 名为 vm-linux-2,没有定义的公共 IP 地址。

测试验证以下场景:

  • 是否已正确部署基础结构
  • 使用端口 22 是否可打开到 vm-linux-1 的 SSH 会话
  • 使用 vm-linux-1 上的 SSH 会话是否可对 vm-linux-2 执行 ping 操作

Sample end-to-end test scenario

如果已下载示例,则可在 src/main.tf 文件中找到此方案的 Terraform 配置。 main.tf 文件包含部署上图中所示的 Azure 基础结构所需的全部内容。

如果不熟悉如何创建虚拟机,请参阅使用 Terraform 在 Azure 中创建带有基础结构的 Linux VM

注意

本文中介绍的示例方案仅用于说明目的。 为了重点介绍端到端测试,我们特意简化了操作。 建议不要使用通过公共 IP 地址公开 SSH 端口的生产虚拟机。

4. 查看测试示例

端到端测试使用 Go 语言编写,并使用 Terratest 框架。 如果已下载示例,则测试在 src/test/end2end_test.go 文件中进行定义。

以下源代码显示了使用 Terratest 的 Golang 测试的标准结构:

package test

import (
    "testing"

    "github.com/gruntwork-io/terratest/modules/terraform"
    test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
)

func TestEndToEndDeploymentScenario(t *testing.T) {
    t.Parallel()

    fixtureFolder := "../"

    // Use Terratest to deploy the infrastructure
    test_structure.RunTestStage(t, "setup", func() {
        terraformOptions := &terraform.Options{
            // Indicate the directory that contains the Terraform configuration to deploy
            TerraformDir: fixtureFolder,
        }

        // Save options for later test stages
        test_structure.SaveTerraformOptions(t, fixtureFolder, terraformOptions)

        // Triggers the terraform init and terraform apply command
        terraform.InitAndApply(t, terraformOptions)
    })

    test_structure.RunTestStage(t, "validate", func() {
        // run validation checks here
        terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder)
		    publicIpAddress := terraform.Output(t, terraformOptions, "public_ip_address")
    })

    // When the test is completed, teardown the infrastructure by calling terraform destroy
    test_structure.RunTestStage(t, "teardown", func() {
        terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder)
        terraform.Destroy(t, terraformOptions)
    })
}

如前面的代码片段中所示,该测试由 3 个阶段组成:

  • 安装程序:运行 Terraform 以部署配置
  • validate':验证是否检查和断言
  • 拆解:在测试运行后清理基础结构

下表显示了 Terratest 框架提供的一些关键功能:

  • terraform。InitAndApply:启用运行和terraform apply从 Go 代码运行terraform init
  • terraform。输出:检索部署输出变量的值。
  • terraform。销毁:从 Go 代码运行 terraform destroy 命令。
  • test_structure。LoadTerraformOptions:从状态加载 Terraform 选项,例如配置和变量
  • test_structure。SaveTerraformOptions:将 Terraform 选项(如配置和变量)保存到状态

5. 运行测试示例

以下步骤针对示例配置和部署运行测试。

  1. 打开 bash/终端窗口。

  2. 登录到 Azure 帐户。

  3. 若要运行此示例测试,需要在主目录中使用 SSH 私钥/公钥对名称 id_rsaid_rsa.pub。 将 <your_user_name> 替换为主目录的名称。

    export TEST_SSH_KEY_PATH="~/.ssh/id_rsa"
    
  4. 在示例目录中,导航到 src/test 目录。

  5. 运行测试。

    go test -v ./ -timeout 10m
    

6. 验证结果

成功运行 go test 后,将出现类似于以下输出的结果:

--- PASS: TestEndToEndDeploymentScenario (390.99s)
PASS
ok      test    391.052s

Azure 上的 Terraform 故障排除

排查在 Azure 上使用 Terraform 时遇到的常见问题

后续步骤