资讯详情

用 Terratest 为 Terraform SSH 基础设施编写自动化测试:terraform-ssh-example 模块实战解析

📅 2026/9/27 9:06:58 | 华诺云谱 👁 阅读
用 Terratest 为 Terraform SSH 基础设施编写自动化测试:terraform-ssh-example 模块实战解析
测试开发工具DevOps质量保障【免费下载链接】terratestTerratest is a Go library that makes it easier to write automated tests for your infrastructure code.项目地址https://gitcode.com/gh_mirrors/te/terratest点击查看免费下载本篇指南以仓库中的 terraform-ssh-example 示例模块 为主线讲解如何用 Terratest 为部署了 EC2 实例含公网/私网两种拓扑的 Terraform 代码编写端到端自动化测试。读完本文你将掌握模块的资源构成与参数含义、手动terraform apply的运行流程以及测试如何分阶段完成「部署 → SSH 验证 → 清理」并理解ssh、aws、terraform、teststructure等核心模块在测试链路中的底层实现。示例模块概览它部署了什么该模块是一个刻意保持精简的 AWS Terraform 模块用于演示如何用 Terratest 为 AWS Terraform 代码编写自动化测试。它会在aws_region变量指定的区域部署两台 EC2 实例一台拥有公网 IPassociate_public_ip_address true可直接从公网 SSH 访问一台只有私网 IPassociate_public_ip_address false只能从 VPC 内部访问测试中通过公网实例作为跳板机jump host / bastion host访问它两台实例都允许 SSH 请求监听端口由ssh_port变量控制默认 22。模块对应的自动化测试位于 test/terraform_ssh_example_test.go它是本文分析的核心。原文档也提示该示例仍然相当简化EC2 实例本身并不做什么实际工作若需要更接近真实世界的完整示例Terraform 模块 Web 服务器可参考 terraform-packer-example。核心资源定义main.tf在 main.tf 中可以看到完整的资源定义provider 与版本约束main.tf要求 Terraform 版本 1.0AWS Provider 版本~ 5.0公网实例aws_instance.example_publicmain.tf使用最新 Ubuntu AMIassociate_public_ip_address true绑定安全组与 Key Pair私网实例aws_instance.example_privatemain.tf结构相同但associate_public_ip_address false因此只能从 VPC 内部访问安全组aws_security_group.examplemain.tf开放 egress 全部流量ingress 仅允许var.ssh_port端口的 TCP 请求。代码注释特别提醒示例为了简单放行了0.0.0.0/0的全部来源 IP真实场景应只允许可信来源如堡垒机或 VPNUbuntu AMI 数据源data.aws_ami.ubuntumain.tf指定 Canonicalowner099720109477并通过 virtualization-type、architecture、image-type 与 name 等过滤器锁定ubuntu-jammy-22.04-amd64-server-*系列镜像most_recent true取最新版本。参数与输出模块的输入参数定义在 variables.tf如下表所示变量类型是否必填默认值说明key_pair_namestring是必填—关联到 EC2 实例、用于 SSH 访问的 EC2 Key Pair 名称aws_regionstring否us-east-1部署的 AWS 区域instance_namestring否terratest-exampleEC2 实例的 Name 标签同时用作安全组名ssh_portnumber否22EC2 实例监听 SSH 请求的端口instance_typestring否t2.micro运行的 EC2 实例类型其中key_pair_name是唯一必填项其余都有合理默认值方便快速上手。模块的输出定义在 outputs.tf共 4 项供测试脚本通过terraform output读取public_instance_id/public_instance_ip公网实例的 ID 与公网 IPprivate_instance_id/private_instance_ip私网实例的 ID 与私网 IP。手动运行模块不写测试、直接手动验证时按以下步骤操作注册 AWS 账号按 AWS CLI 支持的任一方式配置凭证如设置AWS_ACCESS_KEY_ID与AWS_SECRET_ACCESS_KEY环境变量如果使用~/.aws/config中的 profile还需导出AWS_SDK_LOAD_CONFIG为True安装 Terraform 并将其加入PATH在 examples/terraform-ssh-example 目录下执行terraform init执行terraform apply会提示输入key_pair_name或通过-var传入验证完成后执行terraform destroy清理资源。注意由于key_pair_name是必填变量手动 apply 时一般需要提前在 AWS 控制台或 CLI 中创建好 Key Pair再通过-var key_pair_name...传入。编写自动化测试TestTerraformSshExample 全流程自动化测试的全部代码在 test/terraform_ssh_example_test.go。它演示了 Terratest 测试的三种典型能力Terraform 生命周期管理、SSH/SCP 远程验证、按阶段组织测试以便本地快速迭代。主测试三个阶段测试入口TestTerraformSshExampletest/terraform_ssh_example_test.go以t.Parallel()开头可与其他测试并行整体被拆成三个阶段teardown清理通过defer注册无论测试成功失败都会执行 —— 先运行terraform destroy销毁资源再删除测试期间创建的 EC2 Key Pairsetup部署构造 Terraform 配置并执行terraform initterraform applyvalidate验证对公网/私网实例执行 SSH、SSH Agent、SCP 六类验证。阶段化的价值在于只要设置SKIP_teardowntrue这类环境变量就能跳过某个阶段避免本地反复运行时反复销毁/重建资源从而大幅缩短迭代周期。这正是 Terratest 的 teststructure 模块 提供的RunTestStage能力modules/teststructure/teststructure.go它检查SKIP_stageName环境变量是否被设置未设置才执行该阶段。setup构造 Terraform Options 与 Key PairconfigureTerraformOptionstest/terraform_ssh_example_test.go集中展示了 Terratest 的测试习惯用random.UniqueID()生成唯一 ID拼进实例名与 Key Pair 名避免与账号内已有资源、并行测试互相冲突用aws.GetRandomStableRegionContextmodules/aws/region.go随机但稳定地挑选测试区域提升代码在不同区域的兼容性验证用aws.GetRecommendedInstanceTypeContextmodules/aws/ec2.go按所选区域推荐可用的实例类型候选t2.micro、t3.micro、t2.small、t3.small规避某些区域缺少特定实例类型的问题用aws.CreateAndImportEC2KeyPairContext在测试区域内生成 2048 位 RSA 密钥对并导入 EC2底层实现见 modules/aws/keypair.go通过 EC2ImportKeyPairAPI 完成用terraform.WithDefaultRetryableErrorsmodules/terraform/options.go包装terraform.Options为最常见的可重试错误自动重试把aws_region、instance_name、instance_type、key_pair_name通过Vars注入 Terraform。随后 setup 阶段调用terraform.InitAndApplyContextmodules/terraform/apply.go一次性完成init与apply出错即测试失败同时用teststructure.SaveTerraformOptions与aws.SaveEc2KeyPair把 Options 和 Key Pair 序列化保存实现见 modules/teststructure/save_test_data.go 与 modules/aws/save_test_data.go供后续阶段通过LoadTerraformOptions/LoadEc2KeyPair反序列化复用。这里还有一个容易被忽视的细节测试开头调用了teststructure.CopyTerraformFolderToTemp(t, ../, examples/terraform-ssh-example)test/terraform_ssh_example_test.go把整个示例目录复制到随机临时目录后再运行 Terraform避免并行测试互相覆盖.terraform工作目录和terraform.tfstate文件modules/teststructure/teststructure.go。validate对公网实例直接 SSHtestSSHToPublicHosttest/terraform_ssh_example_test.go演示了最基础的远程验证通过terraform.OutputContextmodules/terraform/output.go读取public_instance_ip输出构造ssh.Host指定主机名、SSH 用户名ubuntu因为实例运行 Ubuntu AMI与之前创建的 Key Pair用retry.DoWithRetryContext重试ssh.CheckSSHCommandContextE执行echo -n Hello, World并断言输出等于预期文本。由于实例启动需要一两分钟测试配置了 30 次重试、每次间隔 5 秒再执行一次echo -n Hello, World exit 1验证「命令非零退出」也能被正确捕获并视为错误。Host结构体与命令执行底层实现在 modules/ssh/ssh.goHost支持 Key Pair、SSH Agent、密码等多种认证方式modules/ssh/ssh.goCheckSSHCommandContextE内部会解析认证方法、建立 SSH 会话并执行命令modules/ssh/ssh.go。认证方法按「覆盖 Agent → 本地 Agent → Key Pair → 密码」的优先级拼接modules/ssh/ssh.go全部缺失时返回ErrNoAuthMethod。validate经跳板机 SSH 到私网实例testSSHToPrivateHosttest/terraform_ssh_example_test.go展示了 Terratest 的跳板机bastion/jump host能力私网实例的 IP 不通过 Terraform 输出获取而是用terraform.OutputContext取private_instance_id再调用aws.GetPrivateIPOfEc2InstanceContextmodules/aws/ec2.go按实例 ID 从 AWS 查询私网 IP演示了「输出拿不到的元数据可以从 AWS API 补齐」构造 publicHost 与 privateHost 两个ssh.Host调用ssh.CheckPrivateSSHConnectionContextEmodules/ssh/ssh.go—— 该方法先连接公网主机再通过该连接拨号到私网主机JumpHost机制执行命令并返回输出。validateSSH Agent 与 SCP 验证testSSHAgentToPublicHost与testSSHAgentToPrivateHosttest/terraform_ssh_example_test.go演示了在测试进程内模拟 SSH Agent通过ssh.SSHAgentWithKeyPairmodules/ssh/agent.go创建内存中的 Agent监听 Unix socket把密钥加入 keyring并把OverrideSshAgent设进Host从而验证「不直接使用私钥文件、改走 agent 转发」的场景。testSCPToPublicHosttest/terraform_ssh_example_test.go演示文件传输验证先用ssh.SCPFileToContextEmodules/ssh/ssh.go把内容Hello, World以0644权限上传到/tmp/test.txt再用ssh.FetchContentsOfFileContextE内部执行catmodules/ssh/ssh.go读取并比对内容。这组用例说明 Terratest 的 SSH 模块不只是「执行命令」还覆盖了文件上传/下载类验证。teardown安全清理teardown 阶段test/terraform_ssh_example_test.go执行terraform.DestroyContextmodules/terraform/destroy.go销毁全部资源再调用aws.DeleteEC2KeyPairContextmodules/aws/keypair.go删除测试期间导入的 Key Pair保证账号内不遗留测试残留。运行自动化测试README 给出了运行该测试的步骤注册 AWS 账号配置 AWS 凭证AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYprofile 场景下导出AWS_SDK_LOAD_CONFIG为True安装 Terraform 并加入PATH安装 Golang并确保本仓库代码已 checkout 到本地cd testdep ensureREADME 沿用早期 dep 时代的写法当前仓库已迁移到 Go Modules仓库根目录维护有 go.mod 与 go.work可直接在仓库根执行go mod download或go work sync等现代依赖管理命令go test -v -run TestTerraformSshExample。结合阶段化设计本地迭代时还可以通过环境变量跳过阶段例如SKIP_teardowntrue go test -v -run TestTerraformSshExample从而保留资源、只反复执行 setup 与 validate。费用与注意事项重要提醒原文 WARNING该模块及其自动化测试会在你的 AWS 账号中部署真实资源并产生费用。这些资源基本属于 AWS Free Tier 覆盖范围如果免费额度尚未用完通常无需付费但所有 AWS 费用完全由你自行负责。测试代码虽然会在 teardown 阶段自动销毁资源并删除 Key Pair但建议运行前确认账号配置正确、区域选择合理并在结束后检查是否有残留资源。延伸阅读本示例更复杂、更接近生产形态的姊妹示例terraform-packer-exampleTerraform Packer Web 服务器端到端测试中用到的基础设施校验与生命周期函数可深入阅读 modules/terraform 与 modules/aws 对应源码SSH/SCP/Agent 验证的完整 API 列表见 modules/ssh/ssh.go 与 modules/ssh/agent.go测试阶段化、临时目录复制与测试数据缓存的实现见 modules/teststructure。赞分享测试开发工具DevOps质量保障【免费下载链接】terratestTerratest is a Go library that makes it easier to write automated tests for your infrastructure code.项目地址https://gitcode.com/gh_mirrors/te/terratest点击查看免费下载相关推荐Keep 集成 Okta 单点登录从环境变量配置到 JWT/JWKS 校验的完整实战指南Keep 集成 Okta 单点登录从环境变量配置到 JWT/JWKS 校验的完整实战指南 本文以 Keep 开源 AIOps 告警管理平台为背景系统讲解如何测试开发工具DevOps质量保障用 Terratest 为 GCP Terraform 模块编写自动化测试terraform-gcp-hello-world-example 实战解析用 Terratest 为 GCP Terraform 模块编写自动化测试terraform gcp hello world example 实战解析 本篇指测试开发工具DevOps质量保障Terratest 入门实战用 Go 为 Terraform 模块编写自动化测试terraform-basic-example 全解析Terratest 入门实战用 Go 为 Terraform 模块编写自动化测试terraform basic example 全解析 Terratest测试开发工具DevOps质量保障上一篇Swift Protobuf 与 Core Data 集成数据持久化的完美解决方案下一篇5分钟部署PP-OCRv6-tiny-det-GGUF面向新手的OCR模型落地教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑