Terraform v0.12.12
+ provider.aws v3.0.0
+ provider.template v2.1.2
在我做这件事之前:
resource "aws_route53_record" "derps" {
name = aws_acm_certificate.mycert[0].resource_record_name
type = aws_acm_certificate.mycert[0].resource_record_type
zone_id = var.my_zone_id
records = aws_acm_certificate.mycert[0].resource_record_value
ttl = 60
}
大约一周前,这对我来说还不错。
我刚做了一个计划,却出现了一个错误:
records = [aws_acm_certificate.mycert.domain_validation_options[0].resource_record_value]
This value does not have any indices.
现在我不固定提供程序版本,所以我假设我提取了一个较新的版本,并且资源发生了更改。
在与之斗争并意识到它不是一个列表之后(尽管在做show state
时它看起来确实像一个列表(,我现在这样做是为了让它成为一个列表:
resource "aws_route53_record" "derps" {
name = sort(aws_acm_certificate.mycert.domain_validation_options[*].resource_record_name)[0]
type = sort(aws_acm_certificate.mycert.domain_validation_options[*].resource_record_type)[0]
zone_id = var.my_zone_id
records = [sort(aws_acm_certificate.mycert.domain_validation_options[*].resource_record_value)[0]]
ttl = 60
}
这导致了没有任何变化,这是好的。但是,如果我使用他们现在使用for_each的文档中的示例来执行此操作:https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation
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]
}
以上是现在正确的方法吗?我现在这样做会遇到问题吗?这样做会导致破坏/重建(我想我可以自己导入,但这很痛苦(。
按照我的方式做不会导致意想不到的差异吗?
编辑
所以,我的问题更具体。这就是我看到的状态:
terraform state show aws_acm_certificate.mycert
...
domain_name = "*.mydom.com"
domain_validation_options = [
{
domain_name = "*.mydom.com"
resource_record_name = "_11111111111.mydom.com."
resource_record_type = "CNAME"
resource_record_value = "_1111111111.11111111.acm-validations.aws."
},
{
domain_name = "mydom.com"
resource_record_name = "_11111111111.mydom.com."
resource_record_type = "CNAME"
resource_record_value = "_1111111111.111111111.acm-validations.aws."
},
]
...
通过使用sort,我有效地使用了count,如果顺序发生变化,当然会导致销毁/重新创建。但就我而言,我认为这不太可能??我也不完全理解只使用通配符验证配置中的值和同时使用它们之间的区别。
AWS Terraform提供商最近升级到3.0版本。此版本附带了一个中断更改列表。我建议参考AWS提供商3.0升级指南。
您遇到的问题是因为domain_validation_options
属性现在是一个集合而不是列表。根据该指南:
由于
domain_validation_options
属性从列表更改为集合,并且集合无法在Terraform中进行索引,因此建议更新配置以使用更稳定的资源for_each
支持,而不是count
我建议按照升级指南的建议使用新的foreach
语法,以避免意外的差异。该指南指出,您需要使用terraform state mv
将旧配置状态移动到新配置,以防止重新创建资源。
这与我们刚才面临的问题相同。。我们使用foreach根据提供的本地变量定义多个站点的托管,现在,由于我们已经使用了foreach,我们不能使用它来解决它们的更改。。不幸的
我不想进行排序,所以我检查了Jimmy写的内容,但由于输出是索引,它不适用于这种情况,我用[0]而不是[*]:修复了它
resource "aws_route53_record" "cert_validation" {
for_each = local.web_pages
allow_overwrite = true
name = tolist(aws_acm_certificate.cert[each.key].domain_validation_options)[0].resource_record_name
type = tolist(aws_acm_certificate.cert[each.key].domain_validation_options)[0].resource_record_type
records = [tolist(aws_acm_certificate.cert[each.key].domain_validation_options)[0].resource_record_value]
zone_id = var.aws_hosted_zone
ttl = 60
}
现在为我们工作;(
下面的这3组代码可以工作。(我用的是Terraform v0.15.0
(
*1st
和2nd
之间的差异是[0]
和.0
第一:
resource "aws_route53_record" "myRecord" {
zone_id = aws_route53_zone.myZone.zone_id
name = tolist(aws_acm_certificate.myCert.domain_validation_options)[0].resource_record_name
type = tolist(aws_acm_certificate.myCert.domain_validation_options)[0].resource_record_type
records = [tolist(aws_acm_certificate.myCert.domain_validation_options)[0].resource_record_value]
ttl = "60"
allow_overwrite = true
}
第二:
resource "aws_route53_record" "myRecord" {
zone_id = aws_route53_zone.myZone.zone_id
name = tolist(aws_acm_certificate.myCert.domain_validation_options).0.resource_record_name
type = tolist(aws_acm_certificate.myCert.domain_validation_options).0.resource_record_type
records = [tolist(aws_acm_certificate.myCert.domain_validation_options).0.resource_record_value]
ttl = "60"
allow_overwrite = true
}
第三:
resource "aws_route53_record" "myRecord" {
for_each = {
for dvo in aws_acm_certificate.myCert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = aws_route53_zone.myZone.zone_id
allow_overwrite = true
}
您也可以使用tolist
作弊。
例如,将aws_acm_certificate.mycert.domain_validation_options[*].resource_record_name
重写为tolist(aws_acm_certificate.mycert.domain_validation_options)[*].resource_record_name
我必须在一个模块中这样做,因为这个特定的模块资源中已经有一个count
,我知道我只会有一个条目。