Context
While integrating Cloudflare DNS with AWS ACM certificates, I ran into a recurring problem when running terraform plan
on subsequent changes after deploying the following code:
resource "aws_acm_certificate" "example" {
domain_name = "example.com"
validation_method = "DNS"
subject_alternative_names = [
"*.example.com",
"*.docs.example.com"
]
lifecycle {
create_before_destroy = true
}
}
resource "cloudflare_zone" "example" {
zone = "example.com"
type = "full"
}
resource "cloudflare_record" "certificate_validation" {
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 = cloudflare_zone.example.id
name = each.value.name
value = each.value.record
type = each.value.type
ttl = 1
proxied = false
}
Terraform
complaint was as follows (with the output sanitized):
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# cloudflare_record.certificate_validation["*.example.com"] will be updated in-place
~ resource "cloudflare_record" "certificate_validation" {
id = "09fasljhdfa087adfnkaldf97d8"
name = "_0123456789abcdedfghijklmn.example.com."
~ value = "_324fadahadkfh8327y49bjadf.kjhadfadfak.acm-validations.aws" -> "_324fadahadkfh8327y49bjadf.kjhadfadfak.acm-validations.aws."
# (10 unchanged attributes hidden)
}
# cloudflare_record.certificate_validation["*.docs.example.com"] will be updated in-place
~ resource "cloudflare_record" "certificate_validation" {
id = "089724952khadja9a6adank"
name = "_701849akdhfaakd97465Ss452.docs.example.com."
~ value = "_98472hjkadha98746kaldhf.bbhjkaddfafd.acm-validations.aws" -> "_98472hjkadha98746kaldhf.bbhjkaddfafd.acm-validations.aws."
# (10 unchanged attributes hidden)
}
Plan: 0 to add, 2 to change, 0 to destroy.
Notice how Terraform
wants to add a trailing dot to the value of the validation record (a CNAME record in Cloudflare)
Solution
The solution is to explicitly remove the trailing dot for each validation record before Terraform
compares them against what is stored in Cloudflare. With can achieve this with the help of the trimsuffix
function as shown below:
resource "cloudflare_record" "certificate_validation" {
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 = cloudflare_zone.example.id
name = each.value.name
value = trimsuffix(each.value.record, ".")
type = each.value.type
ttl = 1
proxied = false
}