如何为Terraform ec2_instances模块编写Golang验收测试并关联资源测试逻辑
核心实现逻辑
打通Terraform模块验收测试和自定义Provider资源测试的核心逻辑是:将EC2模块定义与你自定义的resource_ravendb_server资源放在同一个测试Terraform配置中,依赖Terraform自身的资源依赖关系,先完成EC2实例部署,再执行自定义Provider的资源逻辑,最后在同一个测试用例中同时校验模块输出和自定义资源的状态。
具体改造步骤
- 第一步:修改测试配置函数
testAccRavenDbServerConfig的返回内容,把EC2模块和自定义资源放在同一份配置中,将EC2模块的输出作为自定义资源的入参关联二者:
locals { nodes = toset(["a", "b", "c"]) } module "ec2_instances" { source = "terraform-aws-modules/ec2-instance/aws" version = "~> 3.0" for_each = local.nodes name = "${each.key}.ravendb" ami = "ami-09e67e426f25ce0d7" instance_type = "t2.micro" key_name = "omer-tf" monitoring = false vpc_security_group_ids = ["sg-03525214aee516d50"] subnet_id = "subnet-0ee70783a7dd19aa5" associate_public_ip_address = true } # 你的自定义Provider资源,直接引用EC2模块的输出作为参数 resource "resource_ravendb_server" "test" { endpoints = [for inst in module.ec2_instances : inst.public_ip] healthcheck_database = "firewire" # 其他自定义资源需要的参数 }
- 第二步:调整测试用例逻辑,同时注册AWS Provider和自定义Provider的工厂函数,在检查步骤中同时校验EC2模块的资源属性和自定义资源的属性:
func TestAccRavenDbFullStack(t *testing.T) { var ( customResName = "resource_ravendb_server.test" // for_each创建的模块资源地址需要带上对应key ec2ResA = "module.ec2_instances[\"a\"].aws_instance.this" ec2ResB = "module.ec2_instances[\"b\"].aws_instance.this" ec2ResC = "module.ec2_instances[\"c\"].aws_instance.this" ) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) checkAwsEnv(t) }, // 同时注册测试需要的所有Provider ProviderFactories: map[string]func() (*schema.Provider, error){ "aws": func() (*schema.Provider, error) { return aws.Provider(), nil }, // 替换为你自定义Provider的名称 "ravendb": testAccProviderFactories["ravendb"], }, CheckDestroy: resource.ComposeTestCheckFunc( testAccRavenDbServerDestroy, // 可补充EC2资源销毁校验逻辑 ), Steps: []resource.TestStep{ { Config: testAccRavenDbServerConfig(), Check: resource.ComposeTestCheckFunc( // 校验EC2模块部署结果符合预期 resource.TestCheckResourceAttr(ec2ResA, "tags.Name", "a.ravendb"), resource.TestCheckResourceAttr(ec2ResB, "tags.Name", "b.ravendb"), resource.TestCheckResourceAttr(ec2ResC, "instance_type", "t2.micro"), // 校验自定义Provider资源逻辑符合预期 resource.TestCheckResourceAttr(customResName, "healthcheck_database", "firewire"), // 可补充自定义校验函数,比如直接调用RavenDB接口验证服务可用性 ), }, }, }) }
- 第三步:如果需要更深度的验收逻辑,可以自定义
CheckFunc函数,从Terraform状态中拿到EC2实例ID、自定义资源的属性值,分别调用AWS API、RavenDB接口做实际的业务校验。
注意事项
- 带
for_each的模块资源地址必须带上对应的key,格式为module.<模块名>["<key>"].<底层资源类型>.<资源名>,写错会导致属性校验失败 - 如果自定义资源的校验需要等EC2实例内部服务完全启动,可以在自定义Provider的Create逻辑中增加重试机制,避免实例还未初始化完成就校验失败
内容的提问来源于stack exchange,提问作者Omer ayende
相关产品推荐
相关产品推荐

