aws_acm_certificate 似乎已经更改了它的状态输出,可能是由于提供商更新——我做错了吗?
aws_acm_certificate seems to have changed its state output possibly due to a provider update- am I doing this wrong?
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]
}
以上是现在正确的做法吗?我会 运行 以我目前的方式处理问题吗?像上面那样做会导致 destroy/recreate(我想我可以自己导入它,但这很痛苦)。
按我的方式做不会导致意外的差异吗?
编辑
所以,更具体地针对我的问题。这是我在查看状态时看到的:
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."
},
]
...
通过使用排序,我有效地使用了计数,如果顺序发生变化,这当然会导致 destroy/recreate。但就我而言,我认为这不太可能?我也不完全理解仅使用通配符验证配置中的值与同时使用它们之间的区别。
AWS Terraform 提供程序最近升级到版本 3.0。此版本附带 a list of breaking changes. I recommend consulting the AWS provider 3.0 upgrade guide.
您遇到的问题是因为 domain_validation_options
属性现在是一个集合而不是列表。来自该指南:
Since the domain_validation_options
attribute changed from a list to a set and sets cannot be indexed in Terraform, the recommendation is to update the configuration to use the more stable resource for_each
support instead of count
我建议按照升级指南的建议使用新的 foreach
语法,以避免意外的差异。该指南指出您需要使用 terraform state mv
将旧配置状态移动到新配置,以防止重新创建资源。
你也可以用tolist
作弊。
例如将 aws_acm_certificate.mycert.domain_validation_options[*].resource_record_name
重写为 tolist(aws_acm_certificate.mycert.domain_validation_options)[*].resource_record_name
我必须在一个模块中执行此操作,因为这个特定的模块资源中已经有一个 count
,而且我知道我只会有一个条目。
这与我们刚才面临的问题相同。我们使用 for_each 根据提供的局部变量定义多个站点的托管,现在,由于我们已经使用 for_each 我们可以'不要用它来解决他们的变化..不幸的是。
我不想进行排序,所以我检查了 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
}
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]
}
以上是现在正确的做法吗?我会 运行 以我目前的方式处理问题吗?像上面那样做会导致 destroy/recreate(我想我可以自己导入它,但这很痛苦)。
按我的方式做不会导致意外的差异吗?
编辑
所以,更具体地针对我的问题。这是我在查看状态时看到的:
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."
},
]
...
通过使用排序,我有效地使用了计数,如果顺序发生变化,这当然会导致 destroy/recreate。但就我而言,我认为这不太可能?我也不完全理解仅使用通配符验证配置中的值与同时使用它们之间的区别。
AWS Terraform 提供程序最近升级到版本 3.0。此版本附带 a list of breaking changes. I recommend consulting the AWS provider 3.0 upgrade guide.
您遇到的问题是因为 domain_validation_options
属性现在是一个集合而不是列表。来自该指南:
Since the
domain_validation_options
attribute changed from a list to a set and sets cannot be indexed in Terraform, the recommendation is to update the configuration to use the more stable resourcefor_each
support instead ofcount
我建议按照升级指南的建议使用新的 foreach
语法,以避免意外的差异。该指南指出您需要使用 terraform state mv
将旧配置状态移动到新配置,以防止重新创建资源。
你也可以用tolist
作弊。
例如将 aws_acm_certificate.mycert.domain_validation_options[*].resource_record_name
重写为 tolist(aws_acm_certificate.mycert.domain_validation_options)[*].resource_record_name
我必须在一个模块中执行此操作,因为这个特定的模块资源中已经有一个 count
,而且我知道我只会有一个条目。
这与我们刚才面临的问题相同。我们使用 for_each 根据提供的局部变量定义多个站点的托管,现在,由于我们已经使用 for_each 我们可以'不要用它来解决他们的变化..不幸的是。
我不想进行排序,所以我检查了 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
}