我正在尝试编写一个 terraform 模块来创建 API 网关和关联的自定义域。
该模块允许消费者为 API 网关指定“端点类型”(即
EDGE
或 REGIONAL
)。
一开始它工作得很好,但是如果在没有先拆除所有内容的情况下更改端点类型,事情就会开始崩溃。
我已将其缩减为问题所在的
aws_api_gateway_domain_name
资源。
我对此有以下配置:
resource "aws_api_gateway_domain_name" "custom_domain" {
domain_name = local.custom_domain
regional_certificate_arn = local.domain_type == "REGIONAL" ? aws_acm_certificate.regional_domain_cert[0].arn : null
certificate_arn = local.domain_type == "EDGE" ? aws_acm_certificate.edge_domain_cert[0].arn : null
endpoint_configuration {
types = [local.domain_type]
}
security_policy = "TLS_1_2"
depends_on = [
aws_acm_certificate.edge_domain_cert,
aws_acm_certificate.regional_domain_cert,
aws_route53_record.cert_validation_record,
aws_api_gateway_rest_api.api_gateway,
]
lifecycle {
create_before_destroy = false
}
}
我在这里遇到的问题是,
endpoint_configuration
无法就地更新,因为根据其文档,AWS不支持此属性的
op:replace
功能。
导致此错误:
│ Error: updating API Gateway Domain Name (mydomain.testdomain.xyz): operation error API Gateway: UpdateDomainName, https response error StatusCode: 400, RequestID: 29ec3dcd-25c3-40e0-9f3c-0671e1ad7497, BadRequestException: /endpointConfiguration/types/0 Invalid request input
│
│ with module.example_api.aws_api_gateway_domain_name.custom_domain[0],
│ on ../../../../../Git/terraform-example/domain.tf line 45, in resource "aws_api_gateway_domain_name" "custom_domain":
│ 45: resource "aws_api_gateway_domain_name" "custom_domain" {
因此,我还尝试创建单独的
aws_api_gateway_domain_name.edge_custom_domain
和 aws_api_gateway_domain_name.regional_custom_domain
资源,我认为我可以拆除自定义域并使用适当的配置创建一个新域。然而,问题是我无法让 Terraform 在启动新域之前销毁现有的 EDGE/REGIONAL 域。
例如,使用以下资源:
resource "aws_api_gateway_domain_name" "edge_custom_domain" {
count = local.create_domain && local.domain_type == "EDGE" ? 1 : 0
domain_name = local.custom_domain
certificate_arn = aws_acm_certificate.edge_domain_cert[0].arn
endpoint_configuration {
types = ["EDGE"]
}
security_policy = "TLS_1_2"
depends_on = [
aws_acm_certificate.edge_domain_cert,
aws_acm_certificate.regional_domain_cert,
aws_route53_record.cert_validation_record,
]
lifecycle {
create_before_destroy = false
}
}
resource "aws_api_gateway_domain_name" "regional_custom_domain" {
count = local.create_domain && local.domain_type == "REGIONAL" ? 1 : 0
domain_name = local.custom_domain
regional_certificate_arn = aws_acm_certificate.regional_domain_cert[0].arn
endpoint_configuration {
types = ["REGIONAL"]
}
security_policy = "TLS_1_2"
depends_on = [
aws_acm_certificate.edge_domain_cert,
aws_acm_certificate.regional_domain_cert,
aws_route53_record.cert_validation_record,
]
lifecycle {
create_before_destroy = false
}
}
给我一个如下错误:
module.example_api.aws_api_gateway_domain_name.edge_custom_domain[0]: Creating...
╷
│ Error: creating API Gateway Domain Name (mydomain.testdomain.xyz): operation error API Gateway: CreateDomainName, https response error StatusCode: 400, RequestID: cb120eb4-dbf0-4424-a218-6a7eab16b7f7, BadRequestException: The domain name you provided already exists.
│
│ with module.example_api.aws_api_gateway_domain_name.edge_custom_domain[0],
│ on ../../../../../Git/terraform-example/domain.tf line 1, in resource "aws_api_gateway_domain_name" "edge_custom_domain":
│ 1: resource "aws_api_gateway_domain_name" "edge_custom_domain" {
我的具体问题是:实际上有可能做我想做的事情吗?
额外问题:是否有可能
aws_api_gateway_domain_name.regional_custom_domain
和aws_api_gateway_domain_name.edge_custom_domain
depends_on
彼此不引入循环?我想表达类似“如果需要的话,等待其他资源被销毁”
或者,是否可以以 terraform 式的方式更新
endpoint_configuration
? API 网关配置建议创建新的配置集,然后删除旧的配置集,尽管这对于 Terraform 来说似乎不可能。
对于两种类型的 aws_api_gateway_domain_name 使用相同的资源并使用动态块进行不同的配置怎么样?
例如:
resource "aws_api_gateway_domain_name" "custom_domain" {
count = local.create_domain ? 1 : 0
domain_name = local.custom_domain
dynamic "certificate_arn" {
for_each = local.domain_type == "EDGE" ? ["EDGE"] : []
content {
certificate_arn = aws_acm_certificate.edge_domain_cert[0].arn
}
}
dynamic "regional_certificate_arn" {
for_each = local.domain_type == "REGIONAL" ? ["REGIONAL"] : []
content {
regional_certificate_arn = aws_acm_certificate.regional_domain_cert[0].arn
}
}
dynamic "endpoint_configuration" {
for_each = local.domain_type == "EDGE" ? ["EDGE"] : ["REGIONAL"]
content {
types = endpoint_configuration.value
}
}
security_policy = "TLS_1_2"
depends_on = [
# aws_acm_certificate.edge_domain_cert, # explicit dependency not needed
# aws_acm_certificate.regional_domain_cert, # explicit dependency not needed
aws_route53_record.cert_validation_record,
]
lifecycle {
create_before_destroy = false
}
}
我没有时间测试上面的代码。