ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

使用 Terratest 为 AWS S3 Terraform 模块编写自动化测试:以 terraform-aws-s3-example 为例

使用 Terratest 为 AWS S3 Terraform 模块编写自动化测试:以 terraform-aws-s3-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点击查看免费下载导读本文以 Terratest 仓库中的 terraform-aws-s3-example 示例模块为核心完整讲解如何在 AWS 上部署一个启用版本控制Versioning与访问日志Server Access Logging的 S3 Bucket 对并通过 Terratest 的 Go 测试代码对已部署资源做自动断言验证。读完本文你将掌握 Terratest 测试 Terraform 模块的标准流程从terraform init/apply的封装调用、随机区域与唯一命名策略到使用 S3 专属断言函数校验版本控制、Bucket Policy 与日志目标的完整写法并了解每一处调用背后的源码实现。一、示例模块要解决什么问题这个示例演示了 Terratest 最典型的使用场景编写自动化测试来验证你的 AWS Terraform 基础设施代码。该模块会创建两个 S3 Buckettest_bucket源桶启用版本控制Enabled和服务器访问日志桶内不放置任何实际对象test_bucket_logs日志桶作为源桶访问日志的落盘位置接收前缀为TFStateLogs/的日志对象。两个 Bucket 都会被赋予Name与Environment标签取值分别来自tag_bucket_name与tag_bucket_environment变量。模块还提供开关with_policy开启后会为源桶附加一条 Bucket Policy将非 SSLaws:SecureTransport为false的访问请求全部拒绝强制客户端走加密通道。配套的测试文件 test/terraform_aws_s3_example_test.go 展示了如何对上述全部能力逐项做自动化验证。需要注意的是示例模块刻意保持极简Bucket 创建后只有版本控制、日志与标签配置不含任何对象如果你想看更接近真实生产形态的多服务组合示例可以继续阅读 terraform-http-example 与 terraform-ssh-example。二、模块的 Terraform 源码解析模块由三个 TF 文件构成位于 examples/terraform-aws-s3-example 目录下main.tf、variables.tf 和 outputs.tf。2.1 Provider 与默认标签main.tf 开头声明了运行前提terraform { required_version 1.0 required_providers { aws { source hashicorp/aws version ~ 5.0 } } } provider aws { region var.region default_tags { tags { gw:repo https://github.com/gruntwork-io/terratest gw:example terraform-aws-s3-example } } }这里明确要求 Terraform 版本不低于 1.0AWS Provider 使用~ 5.0系列default_tags会把gw:repo、gw:example作为账号级默认标签附加到所有资源上便于在账单或控制台溯源这些资源属于哪个示例。2.2 源桶版本控制 访问日志 私有 ACL源桶相关的资源定义在 main.tfresource aws_s3_bucket test_bucket { bucket ${local.aws_account_id}-${var.tag_bucket_name} tags { Name var.tag_bucket_name Environment var.tag_bucket_environment } } resource aws_s3_bucket_logging test_bucket { bucket aws_s3_bucket.test_bucket.id target_bucket aws_s3_bucket.test_bucket_logs.id target_prefix TFStateLogs/ } resource aws_s3_bucket_versioning test_bucket { bucket aws_s3_bucket.test_bucket.id versioning_configuration { status Enabled } } resource aws_s3_bucket_ownership_controls test_bucket { bucket aws_s3_bucket.test_bucket.id rule { object_ownership ObjectWriter } depends_on [aws_s3_bucket.test_bucket] } resource aws_s3_bucket_acl test_bucket { bucket aws_s3_bucket.test_bucket.id acl private depends_on [aws_s3_bucket_ownership_controls.test_bucket] }几个值得注意的实现细节桶名带账号 ID 前缀local.aws_account_id来自 main.tf 中的aws_caller_identity数据源桶名形如account-id-tag_bucket_name既保证全局唯一又方便识别归属账号。新版 AWS Provider 的资源拆分版本控制aws_s3_bucket_versioning、日志aws_s3_bucket_logging、所有权控制aws_s3_bucket_ownership_controls与 ACLaws_s3_bucket_acl均以独立子资源形式声明这是 AWS Provider v5 的推荐写法。ACL 的前置条件先通过object_ownership ObjectWriter声明所有权规则再设置acl private并且用depends_on显式保证顺序。2.3 日志桶可被强制销毁的日志接收端日志桶定义在 main.tfresource aws_s3_bucket test_bucket_logs { bucket ${local.aws_account_id}-${var.tag_bucket_name}-logs tags { Name ${local.aws_account_id}-${var.tag_bucket_name}-logs Environment var.tag_bucket_environment } force_destroy true } resource aws_s3_bucket_ownership_controls test_bucket_logs { bucket aws_s3_bucket.test_bucket_logs.id rule { object_ownership ObjectWriter } depends_on [aws_s3_bucket.test_bucket_logs] } resource aws_s3_bucket_acl test_bucket_logs { bucket aws_s3_bucket.test_bucket_logs.id acl log-delivery-write depends_on [aws_s3_bucket_ownership_controls.test_bucket_logs] }桶名在源桶基础上追加-logs后缀force_destroy true允许terraform destroy时连同桶内对象一并删除这是测试场景的标准配置避免清理阶段因桶非空而失败ACL 使用log-delivery-write这是 AWS 预置的日志投递权限允许 S3 日志服务向该桶写入对象。2.4 可选 Bucket Policy强制 SSL模块通过with_policy变量控制是否附加策略策略主体用aws_iam_policy_document数据源拼装见 main.tfresource aws_s3_bucket_policy bucket_access_policy { count var.with_policy ? 1 : 0 bucket aws_s3_bucket.test_bucket.id policy data.aws_iam_policy_document.s3_bucket_policy.json } data aws_iam_policy_document s3_bucket_policy { statement { effect Allow principals { identifiers [local.aws_account_id] type AWS } actions [*] resources [${aws_s3_bucket.test_bucket.arn}/*] } statement { effect Deny principals { identifiers [*] type AWS } actions [*] resources [${aws_s3_bucket.test_bucket.arn}/*] condition { test Bool variable aws:SecureTransport values [ false, ] } } }策略由两条 statement 组成Allow 本账号仅对当前 AWS 账号local.aws_account_id授予桶内对象arn/*的全部操作权限Deny 非 SSL 请求对任意主体只要aws:SecureTransport为false即 HTTP 明文请求一律拒绝。配合count var.with_policy ? 1 : 0该策略默认不创建测试中通过变量显式开启后再验证策略确实存在。2.5 变量与输出variables.tf 定义了一个必填变量与三个可选变量变量类型必填/默认值说明regionstring必填部署的 AWS 区域with_policybool默认false为true时为源桶创建强制 SSL 的 Bucket Policytag_bucket_namestring默认Test Bucket桶的Name标签值也会参与桶名拼装tag_bucket_environmentstring默认Test桶的Environment标签值outputs.tf 对外暴露四个输出bucket_id、bucket_arn、logging_target_bucket、logging_target_prefix。其中后两个正是测试代码用来做日志断言的数据来源。三、手动运行模块基线操作在动手写测试之前先按 README.md 的步骤手动跑一遍模块确认基础设施本身可部署注册 AWS 账号配置 AWS 凭证使用 AWS CLI 支持的任一方式例如设置环境变量AWS_ACCESS_KEY_ID与AWS_SECRET_ACCESS_KEY如果你通过~/.aws/config配置文件使用 profile还需要导出AWS_SDK_LOAD_CONFIG为True设置区域导出环境变量AWS_DEFAULT_REGION为你想部署的区域安装 Terraform并确保其位于PATH中在 examples/terraform-aws-s3-example 目录下执行terraform init执行terraform apply如需开启策略可附加-var with_policytrue完成后执行terraform destroy清理资源。注意此模块会真实创建两个 S3 Bucket属于 AWS 免费套餐范围内的资源但所有 AWS 费用完全由使用者承担测试完成后务必 destroy避免产生持续成本。四、用 Terratest 编写自动化测试4.1 测试代码整体结构完整的测试位于 test/terraform_aws_s3_example_test.go。文件第一行带有//go:build aws构建标签意味着它只会在显式指定aws构建约束时参与编译配合go test -tags aws使用把需要真实云账号的测试与纯单元测试区分开。测试用到了三个 Terratest 子模块import ( github.com/gruntwork-io/terratest/modules/aws/v2 github.com/gruntwork-io/terratest/modules/core/v2/random github.com/gruntwork-io/terratest/modules/terraform/v2 )对应仓库中的 modules/aws、modules/core/random 与 modules/terraform 目录以及断言库github.com/stretchr/testify/assert。4.2 命名唯一化与随机区域func TestTerraformAwsS3Example(t *testing.T) { t.Parallel() expectedName : terratest-aws-s3-example- strings.ToLower(random.UniqueID()) expectedEnvironment : Automated Testing awsRegion : aws.GetRandomStableRegionContext(t, t.Context(), nil, nil) ... }random.UniqueID()来自 modules/core/random生成一段随机后缀使每个测试运行时的桶名都不同避免与账号内其他测试相互干扰strings.ToLower保证桶名符合 S3 的命名约束aws.GetRandomStableRegionContext定义在 modules/aws/region.go会从可用区域中随机挑选一个稳定区域入参为批准的/禁用的区域列表此处均为nil表示不限制随机换区域测试是 Terratest 的推荐做法有助于发现代码在特定区域的兼容性问题。4.3 组装 Terraform 选项并注入变量terraformOptions : terraform.WithDefaultRetryableErrors(t, terraform.Options{ TerraformDir: ../examples/terraform-aws-s3-example, Vars: map[string]interface{}{ tag_bucket_name: expectedName, tag_bucket_environment: expectedEnvironment, with_policy: true, region: awsRegion, }, })TerraformDir指向模块目录Vars会以-var参数传入这里把随机名、随机区域和with_policytrue一并注入terraform.WithDefaultRetryableErrors实现在 modules/terraform/options.go它克隆原 Options并填充DefaultRetryableTerraformErrors这类常见的可重试错误映射同时把MaxRetries设为 3、TimeBetweenRetries设为默认间隔——也就是说apply/plan 过程中遇到重试即可自愈的瞬时错误时Terratest 会自动重试避免测试被偶发的 AWS 限流或传播延迟击垮。4.4 init apply 延迟 destroydefer terraform.DestroyContext(t, t.Context(), terraformOptions) terraform.InitAndApplyContext(t, t.Context(), terraformOptions)terraform.InitAndApplyContext定义在 modules/terraform/apply.go它依次执行InitContextE与ApplyContextE后者会以apply -inputfalse -auto-approve的形式运行见 apply.go全程免交互、自动批准defer terraform.DestroyContext(...)保证无论后续断言成功还是失败测试结束时都会执行terraform destroy从结构上避免资源泄漏。这是 Terratest 测试中资源回收的标准范式。4.5 逐项断言版本控制、策略与日志bucketID : terraform.OutputContext(t, t.Context(), terraformOptions, bucket_id) actualStatus : aws.GetS3BucketVersioningContext(t, t.Context(), awsRegion, bucketID) expectedStatus : Enabled assert.Equal(t, expectedStatus, actualStatus) aws.AssertS3BucketPolicyExistsContext(t, t.Context(), awsRegion, bucketID) loggingTargetBucket : aws.GetS3BucketLoggingTargetContext(t, t.Context(), awsRegion, bucketID) expectedLogsTargetBucket : bucketID -logs loggingObjectTargetPrefix : aws.GetS3BucketLoggingTargetPrefixContext(t, t.Context(), awsRegion, bucketID) expectedLogsTargetPrefix : TFStateLogs/ assert.Equal(t, expectedLogsTargetBucket, loggingTargetBucket) assert.Equal(t, expectedLogsTargetPrefix, loggingObjectTargetPrefix)这条测试链路可以拆成三个部署即验证步骤读取输出terraform.OutputContext从 outputs.tf 中取回bucket_id作为后续所有 AWS 断言的入参版本控制断言aws.GetS3BucketVersioningContext实现在 modules/aws/s3.go底层调用 AWS SDK 的GetBucketVersioning并把返回的Status转成字符串测试断言其等于Enabled策略断言aws.AssertS3BucketPolicyExistsContext实现在 modules/aws/s3.go内部先调用GetS3BucketPolicyContextE读取资源策略若策略为空则返回NoBucketPolicyError从而验证开启with_policy后桶上确实挂载了策略日志断言aws.GetS3BucketLoggingTargetContext与aws.GetS3BucketLoggingTargetPrefixContext分别实现在 modules/aws/s3.go 与 modules/aws/s3.go底层调用GetBucketLogging读取LoggingEnabled.TargetBucket与LoggingEnabled.TargetPrefix测试期望日志目标桶为bucket_id-logs、前缀为TFStateLogs/与 main.tf 的配置一一对应。值得一提的错误处理细节在 modules/aws/s3.go 的GetS3BucketLoggingTargetContextE中若res.LoggingEnabled nil即桶未开启日志会返回S3AccessLoggingNotEnabledErr类型错误让失败原因可被显式识别。整套函数遵循xxxContext失败即中断测试与xxxContextE返回 error 由调用方处理成对出现的命名约定。五、运行自动化测试原文档 README.md 给出的测试运行步骤为注册 AWS 账号并配置凭证同手动运行部分可设置AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY环境变量profile 场景下导出AWS_SDK_LOAD_CONFIG为True安装 Terraform 并加入PATH安装 Golang并将代码检出到GOPATHcd test执行依赖安装运行go test -v -run TestTerraformAwsS3Example。需要说明的是原文档第 5 步中的dep ensure是早期基于dep工具链的写法。当前仓库已全面采用 Go Modules 管理依赖根目录的 go.mod 与 go.work 可见因此实际操作时可直接在仓库根目录执行go test -tags aws -v -run TestTerraformAwsS3Example ./test/该测试文件带有//go:build aws标签需带-tags aws才会被编译执行由 Go 工具链自动解析 go.work 中列出的各个模块。测试执行期间会真实调用 AWS API 创建、断言并销毁资源因此必须确保凭证有效且账号具备 S3 相关权限。六、成本与清理提醒模块与配套测试都会在真实 AWS 账号中部署资源这会产生真实的云费用。示例用到的 S3 资源属于 AWS 免费套餐范围若免费额度尚未用完通常不会产生账单但所有费用由使用者自行负责。测试代码通过defer terraform.DestroyContext(...)保证退出前清理手动操作时则务必记得执行terraform destroy特别是日志桶设置了force_destroy true可保证桶内对象被一并清空从而顺利删除。七、从示例到生产测试的延伸这个示例是 Terratest 中Terraform 模块测试的最小完整闭环背后可延伸的要点包括测试分区真实云资源测试带//go:build aws标签与不依赖云环境的单元测试如 modules/terraform/options_test.go在仓库中分开放置CI 中可按需选择构建约束断言扩展modules/aws/s3.go 中还有AssertS3BucketServerSideEncryptionContextE校验服务端加密算法aws:kms与aws:kms:dsse精确匹配、EmptyS3BucketContext清空桶内容等更多 S3 能力可在此基础上补充加密、生命周期等断言重试与超时WithDefaultRetryableErrors只是起点modules/terraform/options.go 中还支持通过RetryableTerraformErrors、MaxRetries、TimeBetweenRetries自定义重试策略以及通过Context传递超时与取消控制更多参考如需测试包含其他 AWS 服务的组合模块可对照 terraform-http-example 与 terraform-ssh-example 两个示例继续阅读它们展示了更接近真实项目的多资源编排与对应测试写法。总之terraform-aws-s3-example把Terraform 模块 Terratest 测试的完整链路压缩在一个小而完整的样例中命名唯一化、随机区域、带重试的 apply、延迟 destroy、基于真实 AWS SDK 的断言全部有对应的仓库源码可供逐行研读是上手 Terratest 编写 AWS 基础设施测试的理想起点。赞分享测试开发工具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点击查看免费下载相关推荐用 Terratest 为 AWS ECSFargateTerraform 模块编写自动化测试terraform-aws-ecs-example 实战指南用 Terratest 为 AWS ECSFargateTerraform 模块编写自动化测试terraform aws ecs example 实战指南测试开发工具DevOps质量保障用 Terratest 为 GCP Terraform 模块编写自动化测试terraform-gcp-hello-world-example 实战解析用 Terratest 为 GCP Terraform 模块编写自动化测试terraform gcp hello world example 实战解析 本篇指测试开发工具DevOps质量保障escrcpy 远程设备隧道连接完全指南远程 ADB 服务器与 SSH 隧道实战escrcpy 远程设备隧道连接完全指南远程 ADB 服务器与 SSH 隧道实战 本指南基于 escrcpy 仓库中的 tunnels.md https://测试开发工具DevOps质量保障上一篇MATH Dataset vs 其他数学数据集为什么它是AI数学推理研究的黄金标准下一篇Selenium项目中EdgeDriver无头模式下文本输入问题的分析与解决创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表