Terraform tfvars引用资源属性报错的解决方法咨询
你正在使用terraform-aws-cloudfront模块,期望按如下方式调用自定义模块:
# main.tf module "cloudfront" { source = "./cloudfront-module" create_distribution = var.cf_create_distribution aliases = var.cf_aliases enabled = var.cf_enabled default_root_object = var.cf_default_root_object create_origin_access_identity = var.cf_create_origin_access_identity origin_access_identities = var.cf_origin_access_identities origin = var.cf_origin custom_error_response = var.cf_custom_error_response geo_restriction = var.cf_geo_restriction default_cache_behavior = var.cf_default_cache_behavior viewer_certificate = var.cf_viewer_certificate }
.tfvars配置内容如下:
# .tfvars ... cf_default_cache_behavior = { target_origin_id = "${local.bucket_name}.s3.amazonaws.com" viewer_protocol_policy = "redirect-to-https" allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] cached_methods = ["GET", "HEAD"] compress = true cache_policy_id = data.aws_cloudfront_cache_policy.this.id use_forwarded_values = false response_headers_policy_id = "67f7725c-6f97-4210-82d7-5512b31e9d03" } cf_viewer_certificate = { acm_certificate_arn = aws_acm_certificate.this.arn ssl_support_method = "sni-only" } ...
执行Terraform命令时报错如下:
Error: Variables not allowed on ./config/some.tfvars line 30: 30: cache_policy_id = data.aws_cloudfront_cache_policy.this.id Variables may not be used here. Error: Variables not allowed on ./config/some.tfvars line 47: 47: acm_certificate_arn=aws_acm_certificate.this.arn Variables may not be used here.
核心疑问:若需要在.tfvars中引用前置部署资源的属性,是否有可行的替代实现方案?
*.tfvars文件的设计定位是传入静态字面量参数,不支持引用resource、data源、local值这类Terraform运行时才会完成计算的表达式,这是Terraform的硬性规则,没有办法直接在tfvars里写这类引用。
方案1:将动态值拼接逻辑转移到Terraform业务代码中
tfvars里仅存放可静态确定的参数,动态属性在调用模块的main.tf中做合并后传入。示例写法:# main.tf 调用模块时合并动态值 module "cloudfront" { source = "./cloudfront-module" # 其他静态参数正常传var create_distribution = var.cf_create_distribution aliases = var.cf_aliases enabled = var.cf_enabled # ... 其余静态参数省略 # 合并默认缓存行为的动态值 default_cache_behavior = merge( var.cf_default_cache_behavior, { cache_policy_id = data.aws_cloudfront_cache_policy.this.id } ) # 合并证书配置的动态值 viewer_certificate = merge( var.cf_viewer_certificate, { acm_certificate_arn = aws_acm_certificate.this.arn } ) }对应tfvars里删掉
cache_policy_id和acm_certificate_arn这两个动态字段即可。方案2:将动态依赖逻辑下沉到自定义模块内部
如果你封装的./cloudfront-module是内部复用模块,可以直接把这类资源依赖的逻辑写在模块内部,对外不需要暴露需要传动态属性的变量。比如模块内部直接声明aws_cloudfront_cache_policy数据源、直接关联同栈部署的acm证书资源,对外仅暴露缓存策略名称、证书域名这类静态入参即可,从根源上避免跨层传动态值的问题。方案3:用结构化配置文件存静态配置,代码层合并动态值
如果需要把配置和代码完全拆分,可以用yaml/json文件存放所有静态参数,在Terraform代码里通过yamldecode()/jsondecode()加载静态配置后,再merge进动态计算的资源属性,最终传给模块,不要用tfvars承载带引用逻辑的内容。
内容的提问来源于stack exchange,提问作者Evgeniy Pozdnyakov

