Aws_acm_certificate.app_cert.domain_validation_options是一组object,apply后才知道
Aws_acm_certificate.app_cert.domain_validation_options is a set of object, known only after apply
我一直在参加 Terraform (+ CI/CD) 研讨会,这是在早期版本的 Terraform 中讲授的,但我决定在 1.0.11 中使用 AWS 提供商 3.65.0... . 只是为了看看会有什么样的区别。我在与 ACM 打交道以获取证书时遇到障碍,我需要一些关于如何继续的建议。
我在计划阶段遇到的错误:
[ckerr@ck-vm-rhel8-localdomain recipe-app-api-devops]$ docker-compose -f deploy/docker-compose.yml run --rm terraform plan
Creating deploy_terraform_run ... done
╷
│ Error: Invalid for_each argument
│
│ on dns.tf line 44, in resource "aws_route53_record" "app_cert_validation_records":
│ 44: for_each = {
│ 45: for dvo in aws_acm_certificate.app_cert.domain_validation_options : dvo.domain_name => {
│ 46: name = dvo.resource_record_name
│ 47: type = dvo.resource_record_type
│ 48: record = dvo.resource_record_value
│ 49: }
│ 50: }
│ ├────────────────
│ │ aws_acm_certificate.app_cert.domain_validation_options is a set of object, known only after apply
│
│ The "for_each" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how
│ many instances will be created. To work around this, use the -target argument to first apply only the resources that the
│ for_each depends on.
╵
Releasing state lock. This may take a few moments...
ERROR: 1
我有一个名为 dns.tf 的文件,用于管理 DNS 和 SSL 证书,目的是让 Amazon 的证书管理器 (ACM) 获取证书。该文件看起来像这样,我已经包含了评论,希望有人能够找出我的想法哪里出了问题。
// BELIEF: this is the DNS zone we will be operating in. No issues there.
//
data "aws_route53_zone" "zone" {
name = "${var.dns_zone_name}."
}
// BELIEF: this creates a CNAME record that points to our AWS ELB instance for our application.
// This is where it departs a little from the documentation, but I'm not sure if the documentation
// is just being a bit sparse, or if the validation records are meant to also be part of this object.
//
resource "aws_route53_record" "app" {
zone_id = data.aws_route53_zone.zone.zone_id
name = "${lookup(var.subdomain, terraform.workspace)}.${data.aws_route53_zone.zone.name}"
type = "CNAME"
ttl = "300"
records = [aws_lb.api.dns_name]
}
// BELIEF: this models the certificate for our application.
//
resource "aws_acm_certificate" "app_cert" {
domain_name = aws_route53_record.app.fqdn
validation_method = "DNS"
tags = local.common_tags
lifecycle {
create_before_destroy = true
}
}
// BELIEF: to prove ownership of the domain we need to be able to prove that we can
// place certain records into the domain as part of a DNS challenge method.
// I believe this is meant to refer to just those challenge records.
// As this is the dynamic part, its unlikely that the domain validation options would
// be known ahead of time, and so this is where I'm coming unstuck.
//
resource "aws_route53_record" "app_cert_validation_records" {
allow_overwrite = true
zone_id = data.aws_route53_zone.zone.zone_id
ttl = "60"
for_each = {
for dvo in aws_acm_certificate.app_cert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
type = dvo.resource_record_type
record = dvo.resource_record_value
}
}
name = each.value.name
type = each.value.type
records = [each.value.record]
}
// BELIEF: This doesn't create anything; its just a placeholder for the validation
// process... presumably for dependency reasons.
// It basically just associates the FQDN (in the certificate) with its validation records.
//
resource "aws_acm_certificate_validation" "app_cert_validation_process" {
certificate_arn = aws_acm_certificate.app_cert.arn
validation_record_fqdns = [for record in aws_route53_record.app_cert_validation_records : record.fqdn]
}
// Reading https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate
// I don't see where the problem is.
以防万一,还有另一个资源依赖于此,即使用证书的 ELB 实例:
resource "aws_lb_listener" "api_https" {
load_balancer_arn = aws_lb.api.arn
port = 443
protocol = "HTTPS"
certificate_arn = aws_acm_certificate_validation.app_cert_validation_process.certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.api.arn
}
}
我一直在关注 https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate,这表明计划应该有效并且我应该在输出中看到文本“(申请后知道)”。
我认为,根据我迄今为止的研究,根本原因是 AWS 提供商不能/不会提前预测域验证选项是什么......然而升级文档表明,虽然这只是应用后已知的内容,但它不会导致计划失败,我不需要任何丑陋的 -target 解决方法。
我尝试使用 depends_on,但这对计划阶段没有帮助。
如果有帮助,完整代码在 https://gitlab.com/cameron.kerr.nz/recipe-app-api-devops/ 中。
感谢阅读,
卡梅伦
PS。我之前在 https://discuss.hashicorp.com/t/aws-acm-certificate-app-cert-domain-validation-options-is-a-set-of-object-known-only-after-apply/31952 中问过这个问题,但到目前为止还没有回复。
TL;DR:这修复了我测试中的示例:
resource "aws_acm_certificate" "app_cert" {
- domain_name = aws_route53_record.app.fqdn
+ domain_name = aws_route53_record.app.name
validation_method = "DNS"
但不是那么快,这只有效,因为您在 aws_route53_record.app
中创建的记录与最终的 fqdn 具有相同的名称。
根据 aws_route53_record
资源的文档,fqdn
是使用区域域和 name
参数构建的。
为了进一步说明,在工作示例中,我们可以看到 fqdn
未知,但 name
已知。 aws_route53_record.app_cert_validation_records
中的 for_each 不喜欢。
# aws_route53_record.app will be created
+ resource "aws_route53_record" "app" {
+ allow_overwrite = (known after apply)
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "foo.example.com"
+ records = [
+ "xxxx.alb.amazon.com",
]
+ ttl = 300
+ type = "CNAME"
+ zone_id = "XXXXXXXXXXX"
}
我一直在参加 Terraform (+ CI/CD) 研讨会,这是在早期版本的 Terraform 中讲授的,但我决定在 1.0.11 中使用 AWS 提供商 3.65.0... . 只是为了看看会有什么样的区别。我在与 ACM 打交道以获取证书时遇到障碍,我需要一些关于如何继续的建议。
我在计划阶段遇到的错误:
[ckerr@ck-vm-rhel8-localdomain recipe-app-api-devops]$ docker-compose -f deploy/docker-compose.yml run --rm terraform plan
Creating deploy_terraform_run ... done
╷
│ Error: Invalid for_each argument
│
│ on dns.tf line 44, in resource "aws_route53_record" "app_cert_validation_records":
│ 44: for_each = {
│ 45: for dvo in aws_acm_certificate.app_cert.domain_validation_options : dvo.domain_name => {
│ 46: name = dvo.resource_record_name
│ 47: type = dvo.resource_record_type
│ 48: record = dvo.resource_record_value
│ 49: }
│ 50: }
│ ├────────────────
│ │ aws_acm_certificate.app_cert.domain_validation_options is a set of object, known only after apply
│
│ The "for_each" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how
│ many instances will be created. To work around this, use the -target argument to first apply only the resources that the
│ for_each depends on.
╵
Releasing state lock. This may take a few moments...
ERROR: 1
我有一个名为 dns.tf 的文件,用于管理 DNS 和 SSL 证书,目的是让 Amazon 的证书管理器 (ACM) 获取证书。该文件看起来像这样,我已经包含了评论,希望有人能够找出我的想法哪里出了问题。
// BELIEF: this is the DNS zone we will be operating in. No issues there.
//
data "aws_route53_zone" "zone" {
name = "${var.dns_zone_name}."
}
// BELIEF: this creates a CNAME record that points to our AWS ELB instance for our application.
// This is where it departs a little from the documentation, but I'm not sure if the documentation
// is just being a bit sparse, or if the validation records are meant to also be part of this object.
//
resource "aws_route53_record" "app" {
zone_id = data.aws_route53_zone.zone.zone_id
name = "${lookup(var.subdomain, terraform.workspace)}.${data.aws_route53_zone.zone.name}"
type = "CNAME"
ttl = "300"
records = [aws_lb.api.dns_name]
}
// BELIEF: this models the certificate for our application.
//
resource "aws_acm_certificate" "app_cert" {
domain_name = aws_route53_record.app.fqdn
validation_method = "DNS"
tags = local.common_tags
lifecycle {
create_before_destroy = true
}
}
// BELIEF: to prove ownership of the domain we need to be able to prove that we can
// place certain records into the domain as part of a DNS challenge method.
// I believe this is meant to refer to just those challenge records.
// As this is the dynamic part, its unlikely that the domain validation options would
// be known ahead of time, and so this is where I'm coming unstuck.
//
resource "aws_route53_record" "app_cert_validation_records" {
allow_overwrite = true
zone_id = data.aws_route53_zone.zone.zone_id
ttl = "60"
for_each = {
for dvo in aws_acm_certificate.app_cert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
type = dvo.resource_record_type
record = dvo.resource_record_value
}
}
name = each.value.name
type = each.value.type
records = [each.value.record]
}
// BELIEF: This doesn't create anything; its just a placeholder for the validation
// process... presumably for dependency reasons.
// It basically just associates the FQDN (in the certificate) with its validation records.
//
resource "aws_acm_certificate_validation" "app_cert_validation_process" {
certificate_arn = aws_acm_certificate.app_cert.arn
validation_record_fqdns = [for record in aws_route53_record.app_cert_validation_records : record.fqdn]
}
// Reading https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate
// I don't see where the problem is.
以防万一,还有另一个资源依赖于此,即使用证书的 ELB 实例:
resource "aws_lb_listener" "api_https" {
load_balancer_arn = aws_lb.api.arn
port = 443
protocol = "HTTPS"
certificate_arn = aws_acm_certificate_validation.app_cert_validation_process.certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.api.arn
}
}
我一直在关注 https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate,这表明计划应该有效并且我应该在输出中看到文本“(申请后知道)”。
我认为,根据我迄今为止的研究,根本原因是 AWS 提供商不能/不会提前预测域验证选项是什么......然而升级文档表明,虽然这只是应用后已知的内容,但它不会导致计划失败,我不需要任何丑陋的 -target 解决方法。
我尝试使用 depends_on,但这对计划阶段没有帮助。
如果有帮助,完整代码在 https://gitlab.com/cameron.kerr.nz/recipe-app-api-devops/ 中。
感谢阅读, 卡梅伦
PS。我之前在 https://discuss.hashicorp.com/t/aws-acm-certificate-app-cert-domain-validation-options-is-a-set-of-object-known-only-after-apply/31952 中问过这个问题,但到目前为止还没有回复。
TL;DR:这修复了我测试中的示例:
resource "aws_acm_certificate" "app_cert" {
- domain_name = aws_route53_record.app.fqdn
+ domain_name = aws_route53_record.app.name
validation_method = "DNS"
但不是那么快,这只有效,因为您在 aws_route53_record.app
中创建的记录与最终的 fqdn 具有相同的名称。
根据 aws_route53_record
资源的文档,fqdn
是使用区域域和 name
参数构建的。
为了进一步说明,在工作示例中,我们可以看到 fqdn
未知,但 name
已知。 aws_route53_record.app_cert_validation_records
中的 for_each 不喜欢。
# aws_route53_record.app will be created
+ resource "aws_route53_record" "app" {
+ allow_overwrite = (known after apply)
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "foo.example.com"
+ records = [
+ "xxxx.alb.amazon.com",
]
+ ttl = 300
+ type = "CNAME"
+ zone_id = "XXXXXXXXXXX"
}