terraform - 对于仅在应用后确定的资源的 terraform 计数是否有解决方法?
问题描述
在一个 terraform 模块中,我有一个本地用于为 ACM 证书中的所有 SAN 创建 route53 验证记录。
locals {
my_domains = [ "some.net", "foo.com", "yack.meep" ]
validation_domains = [for k, v in aws_acm_certificate.this.domain_validation_options : tomap(v) if contains(local.my_domains, v.domain_name)]
}
从上面看,validation_domains
包含证书上所有主机名的列表(即所有 my_domains 以及验证它们所需的记录),我可以将其与 r53 记录一起用于验证。但是,我想使用 r53 中的域列表过滤此列表:
locals {
cert_domains = [ "some.net", "foo.com", "*.yack.meep" ]
r53_domains = [ "some.net", "yack.meep" ]
valiation_domains = distinct(flatten([
for k, v in aws_acm_certificate.this.domain_validation_options : [
for verify in local.r53_domains : tomap(v) if length(regexall("${verify}$", v.domain_name)) > 0
]
]))
}
现在,这只会在以来自的项目结尾的域上返回 ACM 验证local.r53_domains
- 但是,因为我正在使用带有 ACM 返回值的regexall
函数(或者它是函数?),我收到错误:length
count = length(local.validation_domains)
The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created.
除了使用 创建目标之外-target
,是否有任何可以考虑的方法可以在配置后应用过滤?一种“懒惰”的解决方案如何?
这发生在 TF 0.13.x 中,不确定以后版本中是否有任何功能可能会有所帮助....
TIA。
解决方案
这里的一般规则是,您需要编写一个以已知长度列表结尾的表达式,即使列表中的值不完全已知。这意味着length(...)
它将返回一个已知数字,这足以count
知道您声明的资源实例的数量。
此规则也适用于for_each
,但方式略有不同:如果所有键都已知,则可以知道映射的长度,因此只要我们对所有键都有已知值,就可以安全地使用其值未知的映射按键。
对于aws_acm_certificate
并且aws_acm_certificate_validation
特别是有一个使用在文档aws_route53_record
中创建所需记录的示例:aws_acm_certificate_validation
resource "aws_acm_certificate" "example" {
domain_name = "example.com"
subject_alternative_names = ["www.example.com", "example.org"]
validation_method = "DNS"
}
data "aws_route53_zone" "example_com" {
name = "example.com"
private_zone = false
}
data "aws_route53_zone" "example_org" {
name = "example.org"
private_zone = false
}
resource "aws_route53_record" "example" {
for_each = {
for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
zone_id = dvo.domain_name == "example.org" ? data.aws_route53_zone.example_org.zone_id : data.aws_route53_zone.example_com.zone_id
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = each.value.zone_id
}
resource "aws_acm_certificate_validation" "example" {
certificate_arn = aws_acm_certificate.example.arn
validation_record_fqdns = [for record in aws_route53_record.example : record.fqdn]
}
resource "aws_lb_listener" "example" {
# ... other configuration ...
certificate_arn = aws_acm_certificate_validation.example.certificate_arn
}
这个例子可以工作,因为aws_acm_certificate
资源类型的设计使得domain_validation_options
元素的数量在计划时总是已知的,特别是domain_name
属性也总是已知的,因此适合用作 中的映射键for_each
。
您的示例具有过滤掉一些元素的额外约束,您应该能够通过向表达式添加if
子句for
并确保该条件的结果仅取决于 AWS 提供商在计划时可以知道的值来实现.
推荐阅读
- java - 如何设置我的 for 循环计数从 1 而不是 0 开始?
- python - ValueError:字段“id”需要一个数字,但得到“处理中”
- android - CameraX 的 OnImageCapturedListener 报错
- sql - sql:将选择解包为标量
- python - 让所有snakemake在SGE集群的临时暂存空间中运行
- .net - TimeZoneInfo.TransitionTime 的 IsFixedDateRule 值错误
- google-app-engine - 如何将最新版本的 cloudbuild.yaml 单独保存在云存储中
- ios - 通过自定义 UITableViewCell 上的 UISwipeGestureRecognizer 更新 CoreData?
- docker - docker-compose 没有映射端口
- reactjs - 在 GatsbyJS 中更新元标记