3

I need to create a datadog synthetics monitors with the resource datadog_synthetics_test

I need to monitor multiples cluster, with multiple point of view :

# Clusters
variable "datadog_gke_clusters" {
  default = [
    # NPRD
    {
      name        = "cluster01"
      environment = "nprd"
      url = {
        private = "https://private.domain-priv.com"
        public  = "https://public.domain.com"
      }
    },
    # PROD
    {
      name        = "cluster02"
      environment = "nprd"
      url = {
        private = "https://private.domain-priv.com"
        public  = "https://public.domain.com"
      }
    }
  ]
}

# Point of views
variable "gke_slo" {
  description = "Response time threshold in ms to respond to a request."
  default = [
    {
      zone              = private
      monitor_threshold = 50
    },
    {
      zone              = public
      monitor_threshold = 100
    },
  ]
}

for_each need a map or a list of strings

resource "datadog_synthetics_test" "gke-monitoring" {
  for_each = ... # cartesian product of lists

  type    = "api"
  subtype = "http"
  ....
}

There is a function [setproduct(sets...)][1] which produce a list which combine values of each list, but not a map.

I would need to produce a map which look like this :

  {
    "cluster01-private" = {
      name        = "cluster01"
      environment = "nprd"
      url = {
        private = "https://private.cluster01.domain-priv.com"
        public  = "https://public.cluster01.domain.com"
      }
      zone              = private
      monitor_threshold = 50
    },
    "cluster01-public" = {
      name        = "cluster01"
      environment = "nprd"
      url = {
        private = "https://private.cluster01.domain-priv.com"
        public  = "https://public.cluster01.domain.com"
      }
      zone              = public
      monitor_threshold = 100
    },
    # PROD
    .... etc
  }

How could I do that ?

3 Answers 3

3

In 2 steps, you can first create your cartesian product in a variable:

locals {
  datadog_gke_clusters_by_pov = flatten([
    for cluster in var.datadog_gke_clusters : [
      for pov in var.gke_slo_ : {
        cluster    = cluster
        pov        = pov
      }
    ]
  ])
}

And then use this new variable in your resource block:

resource "datadog_synthetics_test" "gke-monitoring" {
  for_each = {
    for valuue in local.datadog_gke_clusters_by_pov : "${valuue.cluster.name}-${valuue.pov.zone_name}" => valuue
  }
...
# here you can use each.value.cluster.* and each.value.pov.*
}

Have a good day!

2

As in Terraform, a loop "products" a result (a map, a list, an object...), in this case, you have to avoid nested loop:

# Clusters
variable "datadog_gke_clusters" {
  type = list(object({
    name        = string
    environment = string
    url = object({
      private = string
      public  = string
    })
  }))
  default = [
    # NPRD
    {
      name        = "cluster01"
      environment = "nprd"
      url = {
        private = "https://private.domain-priv.com"
        public  = "https://public.domain.com"
      }
    },
    # PROD
    {
      name        = "cluster02"
      environment = "nprd"
      url = {
        private = "https://private.domain-priv.com"
        public  = "https://public.domain.com"
      }
    }
  ]
}

# Point of views
variable "gke_slo" {
  type = list(object({
    zone              = string
    monitor_threshold = number
  }))
  description = "Response time threshold in ms to respond to a request."
  default = [
    {
      zone              = "private"
      monitor_threshold = 50
    },
    {
      zone              = "public"
      monitor_threshold = 100
    },
  ]
}

locals {
  result = {
    for tuple in setproduct(var.datadog_gke_clusters, var.gke_slo): "${tuple[0].name}_${tuple[1].zone}" => {
      name              = tuple[0].name
      environment       = tuple[0].environment
      url               = tuple[0].url
      zone              = tuple[1].zone
      monitor_threshold = tuple[1].monitor_threshold
    }
  }
}

output "result" {
  value = local.result
}

Here we use setproduct to produce a list(list(tuple(cluster,pov)) and then we can iterate on the first list to produce the expected result.

0

Your loop is being nested.

Use this instead.

# Clusters
variable "datadog_gke_clusters" {
  type = list(object({
    name        = string
    environment = string
    url = object({
      private = string
      public  = string
    })
  }))
  default = [
    # NPRD
    {
      name        = "cluster01"
      environment = "nprd"
      url = {
        private = "https://private.domain-priv.com"
        public  = "https://public.domain.com"
      }
    },
    # PROD
    {
      name        = "cluster02"
      environment = "nprd"
      url = {
        private = "https://private.domain-priv.com"
        public  = "https://public.domain.com"
      }
    }
  ]
}

# Point of views
variable "gke_slo" {
  type = list(object({
    zone              = string
    monitor_threshold = number
  }))
  description = "Response time threshold in ms to respond to a request."
  default = [
    {
      zone              = "private"
      monitor_threshold = 50
    },
    {
      zone              = "public"
      monitor_threshold = 100
    },
  ]
}

locals {
  result = {
    for tuple in setproduct(var.datadog_gke_clusters, var.gke_slo): "${tuple[0].name}_${tuple[1].zone}" => {
      name              = tuple[0].name
      environment       = tuple[0].environment
      url               = tuple[0].url
      zone              = tuple[1].zone
      monitor_threshold = tuple[1].monitor_threshold
    }
  }
}

output "result" {
  value = local.result
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.