terraform-provider-mailgun icon indicating copy to clipboard operation
terraform-provider-mailgun copied to clipboard

Documentation examples needed for *_records_set

Open baznikin opened this issue 2 years ago • 4 comments

Hello!

I spend few hours trying to figure out intended use scenario for receiving_records_set and sending_records_set. I wish to create DNS resources with those values but can't find clean and beautiful way.

It can't be used directly, because for_each can't iterate through set of objects.

Best solution I got is

for_each = { for record in data.mailgun_domain.domain.receiving_records_set : record.id => record }

but I can't create mailgun.domain resource and DNS resources at one run

│   39:   for_each = { for record in data.mailgun_domain.domain.sending_records_set : record.id => record }
│     ├────────────────
│     │ data.mailgun_domain.domain.sending_records_set is a set of object, known only after apply
│ 
│ The "for_each" map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this
│ resource.
│ 
│ When working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only in the map values.
│ 
│ Alternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge.

Please, let us know how it is intended to use. My situation is most common use case - register domain at mailgun and then create necessary resources.

PS: I ended by using this https://github.com/adinhodovic/terraform-mailgun-cloudflare/blob/master/main.tf unperfect example and worsen it by wraping sets with tolist()...

baznikin avatar Feb 16 '23 17:02 baznikin

You want to use it like this:

data "cloudflare_zone" "root" {
  name = local.app_root_domain
}

resource "mailgun_domain" "default" {
  name        = local.app_full_domain
  wildcard    = false
  spam_action = "disabled"
}

resource "cloudflare_record" "mailgun_records" {
  for_each = {
    for record in mailgun_domain.default.sending_records_set : record.id => {
      type  = record.record_type
      name  = record.name
      value = record.value
    }
  }

  type    = each.value.type
  name    = each.value.name
  value   = each.value.value
  zone_id = data.cloudflare_zone.root.zone_id
  proxied = false

  depends_on = [mailgun_domain.default]
}

I agree that it would be good to improve the documentation on how to use this - in the meantime, you can see some different flavors of how you can approach this problem over in #27 & related PRs (just note that at the time I was changing the original attributes, rather than introducing the new _set ones)

G-Rath avatar Apr 14 '23 20:04 G-Rath

Hi there,

I currently trying to achieve the same behavior for the namecheap provider. However I am struggling to get the for_each loop working as the namecheap provider makes use of a nested schema to define DNS records:

resource "namecheap_domain_records" "my-domain-com" {
  domain = "my-domain.com"
  mode = "OVERWRITE"
  email_type = "NONE"

  record {
    hostname = "blog"
    type = "A"
    address = "10.11.12.13"
  }

  record {
    hostname = "@"
    type = "ALIAS"
    address = "www.testdomain.com"
  }
}

I am new to terraform and would be glad to get a pointer / code snippet to point me into the right direction.

Best, Nic

DonMushr00m avatar Apr 25 '23 15:04 DonMushr00m

@forstern you should use dynamic:

resource "namecheap_domain_records" "my-domain-com" {
  domain = "my-domain.com"
  mode = "OVERWRITE"
  email_type = "NONE"

  dynamic "record" {
    for_each = <skip>
    content {
      type    = each.value.type
      # so on  
    }
  }
}

baznikin avatar Apr 25 '23 15:04 baznikin

@baznikin thanks a lot for you input! I was now able to use the mailgun provider to feed dns records to the namecheap provider. As namecheap is a little picky on how you specify the hostname, I leave my implementation here in case someone else needs it :) It might not be perfect, but it does its job.

resource "namecheap_domain_records" "domain" {
  domain     = var.sending_domain
  mode       = "OVERWRITE"
  email_type = "MX"

  record {
    hostname = "smtp"
    type     = "A"
    address  = var.smtp_server_ip
  }

  dynamic "record" {
    for_each = {
      for iter in var.receiving_records_set : iter.id => {
        type    = iter.record_type
        address = iter.value
      }
    }
    content {
      address  = record.value.address
      hostname = "@"
      type     = record.value.type
    }
  }

  dynamic "record" {
    for_each = {
      for iter2 in var.sending_records_set : iter2.id => {
        type     = iter2.record_type
        hostname = iter2.name
        address  = iter2.value
      }
    }
    content {
      address  = record.value.address
      hostname = record.value.hostname == var.sending_domain ? "@" : replace(record.value.hostname, ".${var.sending_domain}","")
      type     = record.value.type
    }
  }
}

DonMushr00m avatar Apr 25 '23 18:04 DonMushr00m