Using lists of maps to create multiple dynamic blocks

Hello,

I’m trying to create some datadog synthetic monitors. For each test I want to be able to pass a list of maps defining different assertions associated to the monitors.

I’ve read some of the articles here but haven’t been able to get this working yet. My current config looks like this:

variable "ux_monitors" {
  type = map(object({
    url = string
    assertions = list(map(string))
  }))
}
resource "datadog_synthetics_test" "login_page" {
  for_each = var.ux_monitors
  type     = "api"
  subtype  = "http"
  request = {
    method = "GET"
    url    = lookup(each.value, "url")
  }

  dynamic "assertion" {
    for_each = var.ux_monitors
    content {
      type     = each.value.assertions.type
      operator = each.value.assertions.operator
      target   = each.value.assertions.target
    }
  }
ux_monitors = {
  site1 = {
    url = "https://www.mywebsite1/"
    assertions = [
      {
        name = "Check For Login"
        type = "body"
        operator = "contains"
        target = "login"
      },
      {
        name = "Check Status"
        type = "statusCode"
        operator = "is"
        target = "200"
      }
    ]
  }
  site2 = {
    url = "https://www.mywebsite1/"
    assertions = [
      {
        name = "Check For registration"
        type = "body"
        operator = "contains"
        target = "register"
      },
      {
        name = "Check Status"
        type = "statusCode"
        operator = "is"
        target = "200"
      }
    ]
  }
}

the current error I get is

Error: Unsupported attribute

  on modules/synthetic.tf line 20, in resource "datadog_synthetics_test" "login_page":
  20:       target   = each.value.assertions.target
    |----------------
    | each.value.assertions is list of map of string with 2 elements

This value does not have any attributes.

If anyone can point out where I’ve gone wrong it’ll be much appreciated.

Thanks

Hi @yoshinori-hardy,

each is the iterator symbol for the resource-level for_each, so it refers to the current element of var.ux_monitors. Inside your dynamic "assertion" block I think you want to refer to the current element of each.value.assertions, which requires the following dynamic block:

  dynamic "assertion" {
    for_each = each.value.assertions
    content {
      type     = assertion.value.type
      operator = assertion.value.operator
      target   = assertion.value.target
    }
  }

Inside the content block of the dynamic block, assertion refers to the current element of each.value.assertions.

Thanks @apparentlymart that worked a treat. And thanks for the explanation I see where I was going wrong now.