"for_each" set, its attributes must be accessed on specific instances

Hi Team,

I am trying to capture output of Datadog synthetics monitors id and trying to create SLO based on those output monitor ID’s. However I was facing issue with for_each set. Need little help here to let me understand .

resource "datadog_synthetics_test" "insights_apps" {
  for_each = var.actuator
  assertion {
    operator = "lessThan"
    target   = "2000"
    type     = "responseTime"
  }

  assertion {
    operator = "is"
    target   = "200"
    type     = "statusCode"
  }

  assertion {
    operator = "is"
    property = "content-type"
    target   = "application/vnd.spring-boot.actuator.v3+json"
    type     = "header"
  }

  locations = ["${each.value["location"]}"]
  message   = "{{#is_alert}}Please check ${each.value["app_name"]} app as it seems to have errors!{{/is_alert}}\n{{^is_alert}}Event Logger App Health Check is passing!{{/is_alert}}  \n @slack-Smarsh_1-ea-archive_insights-alerts"
  name = "${each.value["app_name"]} Health Check on ${each.value["env"]}"

  options_list {
    accept_self_signed   = "false"
    allow_insecure       = "false"
    follow_redirects     = "false"
    min_failure_duration = "0"
    min_location_failed  = "1"
    monitor_name = " ${each.value["app_name"]} Health Check on ${each.value["env"]}"

    monitor_options {
      renotify_interval = "0"
    }

    monitor_priority = "1"
    no_screenshot    = "false"
    tick_every       = "600"
  }

  request_definition {
    dns_server_port         = "0"
    method                  = "GET"
    no_saving_response_body = "false"
    number_of_packets       = "0"
    port                    = "0"
    should_track_hops       = "false"
    timeout                 = "0"
    url                     = each.value["routes"]
  }

  status  = "live"
  subtype = "http"
  tags    = ["${each.value["env"]}"]
  type    = "api"
}

output "synthetic_ids"{
  value = {
    for k, v in datadog_synthetics_test.insights_apps : k => v.id
  }
}

----- Variable section-----

variable "actuator" {
  type = map(object({
    app_name = string
    location = string
    routes   = string
    env      = string
  }))
  default = {
    "US-West-2-Event-Logger" = {
      app_name = "event-logging"
      location = "aws:us-west-2"
      routes   = "https://test2.com"
      env      = "us-west-2"
    }
    "US-West-2-Archive-Insights" = {
      app_name = "archive-recon"
      location = "aws:us-west-2"
      routes   = "https://test.com"
      env      = "us-west-2"
    }
  }
}

---------------- SLO Section ----------

resource "datadog_service_level_objective" "insights_apps_slo" {
  groups      = []
  for_each    = datadog_synthetics_test.insights_apps
  monitor_ids = [each.value.id]
  name        = "Test ${each.key}"
  type        = "monitor"
  tags = [
    "sst:insights",
  ]
  thresholds {
    target         = 90
    timeframe      = "7d"
    warning        = 0
  }
}

-------------------- Errors -----------------------

╷
│ Error: Incorrect attribute value type
│
│   on actuator-tests/slo.tf line 4, in resource "datadog_service_level_objective" "insights_apps_slo":
│    4:   monitor_ids = [each.value.id]
│     ├────────────────
│     │ each.value.id is "yyq-23s-bbr"
│
│ Inappropriate value for attribute "monitor_ids": a number is required.
╵
╷
│ Error: Incorrect attribute value type
│
│   on actuator-tests/slo.tf line 4, in resource "datadog_service_level_objective" "insights_apps_slo":
│    4:   monitor_ids = [each.value.id]
│     ├────────────────
│     │ each.value.id is "83k-7s6-bst"
│
│ Inappropriate value for attribute "monitor_ids": a number is required.

Hi @bishwajitsamanta1689,

I’m not familiar with this datadog_service_level_objective resource type and so I’m just relying on its documentation for my answer here.

When I compared the information in your message with the example in the docs the first thing I noticed is that in the documentation the first example for monitor_ids is the following:

  monitor_ids = [1, 2, 3]

However, the error message in your case suggests that for your current value of each.value.id your assignment is equilvalent to the following:

  monitor_ids = ["83k-7s6-bst"]

This seems like a very different identifier format than what’s shown in the docs. Since I am not familiar with Datadog I’m not sure how to interpret this difference, but I wonder if "83k-7s6-bst" is an identifier for some other kind of object, and not an identifier for a “monitor” as this argument seems to be expecting.

Thanks @apparentlymart for your reply, I have resolved the issue. The issue was id was of string type and the monitor id was expecting as int type. so I changed the attribute and it resolved the issue.

But I need one help @apparentlymart
--------------- Output section --------
output “synthetic_ids”{
value = {
for k, v in datadog_synthetics_test.insights_apps : k => v.id
}
}

The above section I have copied from internet though it does not give me any error. But I do not know what it does… and it is also not giving output of the synthetic ID’s created.
can you help me please to understand and resolve my issue.

@apparentlymart Can you help me in explaining why do we use and the purpose
for k, v in datadog_synthetics_test.insights_apps : k => v.id