I'm trying to figure out how to import in dns records from a json file. I can have an X number of these json files in the same folder and they could have 1 or more records in each json file:
[
{
"dnsName":"my-new-service",
"dnsValue":"transfer.something.com."
},
{
"dnsName":"import-service",
"dnsValue":"transfer.something.com."
}
]
I've defined my locals to jsondecode the file:
locals {
jsonfiles = fileset("${path.module}/json/", "*.json")
dnsrecords = [for f in local.jsonfiles: jsondecode(file("${path.module}/json/${f}"))]
}
Then I add it via:
resource "aws_route53_record" "Route53dns" {
for_each = { for records, hosted in flatten(local.dnsrecords): records => hosted}
zone_id = "XXXXXXXXX"
name = each.value.dnsName
ttl = 120
type = "CNAME"
records = [each.value.dnsValue]
}
The funny thing is I run this the first time, and it works great and all the route 53 records are in place. When I make changes, let's say I add 3 more json files and I remove some values in the json file, I would get this error:
│ Error: [ERR]: Error building changeset: InvalidChangeBatch: [Tried to create resource record set [name='xxx.com.', type='CNAME'] but it already exists]
│ status code: 400
Or sometimes I get this error:
│ Error: No matching records found
Any ideas on this? Does Terraform look at the order of the resource when it loops through it to determine the state?
Does Terraform look at the order of the resource when it loops through it to determine the state?
Yes, the order matters. In your case, because you have:
for_each = { for records, hosted in flatten(local.dnsrecords): records => hosted}
records
will be just an index in your list, 0,1,2,3,4
and so on. If you modify order, let say, remove record
2, TF will have to redeploy 3 and 4 under new values of 2 and 3.
Thus it would be better not to use index, and do for example:
for_each = {for hosted in flatten(local.dnsrecords):
"${hosted.dnsName}-${hosted.dnsValue}" => hosted
}
The above will not depend on the order.