Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation examples needed for *_records_set #41

Open
baznikin opened this issue Feb 16, 2023 · 4 comments
Open

Documentation examples needed for *_records_set #41

baznikin opened this issue Feb 16, 2023 · 4 comments

Comments

@baznikin
Copy link

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 baznikin changed the title Documentation examples needed Documentation examples needed for *_records_set Feb 16, 2023
@G-Rath
Copy link
Collaborator

G-Rath commented Apr 14, 2023

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)

@DonMushr00m
Copy link

DonMushr00m commented Apr 25, 2023

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

@baznikin
Copy link
Author

@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  
    }
  }
}

@DonMushr00m
Copy link

@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
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants