Dynamic blocks with dynamic key?


I’m trying to send a map to a module in order to come and fill in a block but I can’t find how to dynamically fill in the key.

Exemple i have variable :

variable "monitor_thresholds" {
  type = map(number)
  description = "Alert thresholds of the monitor."
  default = {
    critical = 1
    critical_recovery = 2

And i want create block :

resource "datadog_monitor" "monitor_limit_custom_metric" {
  name                = "[${var.business_department}] ${var.name}"
  type                = var.type
  query               = var.query
  message             = var.message
  tags                = var.tags
  notify_audit        = var.notify_audit
  locked              = var.locked
  timeout_h           = var.timeout_h
  new_host_delay      = var.new_host_delay
  require_full_window = var.require_full_window
  notify_no_data      = var.notify_no_data
  renotify_interval   = var.renotify_interval
  escalation_message  = var.escalation_message
  include_tags        = var.include_tags
  priority            = var.priority

  dynamic "monitor_thresholds" {
    for_each = var.monitor_thresholds
    content {
      monitor_thresholds.key = monitor_thresholds.value

But i can’t use monitor_thresholds.key in key.

It’s possible to do this in HCL ?

The goal being that the monitor_thresholds field is fully dynamic and that I can send the module values ​​of the style:

module "monitor-limit-free-custom-metrics" {
  source              = "../terraform-modules/monitoring-datadog-terraform-monitor"
  monitor_thresholds  = {
    critical = 2
    ok = 1
    warning = 1
  priority = 2

I believe that what you want to do here is to something equal to the following:

content {
      critical    = monitor_thresholds.critical
      ok           = monitor_thresholds.critical
      warning = monitor_thresholds.warning

Or are you supplying more than one blocks? If that’s the case, you could use each.value eg. each.value.critical

The concern is that if I make the declaration with this method, I am forcing to define values.
Except these are optional values

I see.

You could use lookup() to check if the key is set, otherwise return null. Not 100% sure if it would work, but that’s the direction I would take it.
critical = lookup(monitor_thresholds, "critical", null)

or perhaps, in this case:
critical = lookup(each.value, "critical", null)

Yeah, it’s work !!!

  monitor_thresholds {
    critical = lookup(var.monitor_thresholds, "critical", null)
    critical_recovery = lookup(var.monitor_thresholds, "critical_recovery", null)
    ok = lookup(var.monitor_thresholds, "ok", null)
    warning = lookup(var.monitor_thresholds, "warning", null)
    warning_recovery = lookup(var.monitor_thresholds, "warning_recovery", null)

I see that I formatted that a big weirdly, I’ll blame it on being tired :sweat_smile: But you got the syntax correct, glad that it got you pointed in the right direction :blush:

Now I’m wondering if it’s possible to make the thing even more dynamic and where I don’t have to define every key :stuck_out_tongue:

That isn’t possible. Resource arguments inside blocks like this are a fixed data structure rather than a map, so the fields are always static to allow Terraform to statically validate the arguments you’ve provided.

1 Like

Arf ok thank you for the details.