Search code examples
jsonamazon-web-servicesterraformterraform-provider-awsamazon-route53

With Terraform resource aws_route53_record, import AWS route 53 records from a json file


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?


Solution

  • 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.