dynatrace-oss / terraform-provider-dynatrace

Apache License 2.0
70 stars 33 forks source link

Unable to fetch entity_ids for multiple locations : data "dynatrace_synthetic_locations" #500

Closed Vijayalakshmi-Yolbhavi closed 1 month ago

Vijayalakshmi-Yolbhavi commented 2 months ago

Is your feature request related to a problem? Please describe. I'm using data "dynatrace_synthetic_locations" to fetch entity_id's of multiple locations. The code works when i'm using single location. But i'm having a complex variable structure where im trying to create multiple http_monitors (below)

http_monitors = {
  "monitor1" = {
    name      = "Tf auto_test"
    frequency = 60
    locations = ["Sydney", "London"]
    enabled   = true
    #other agrs below
  }
  "monitor2" = {
     name      = "Tf auto_test"
    frequency = 60
    locations = ["Sydney"]
    enabled   = true
    #other agrs below
  }
  }

I'm unable to fetch the entity_ids in below format, for ex:

monitor1_locations = ["GEOLOCATION-2FD31C834DE4D601",  "GEOLOCATION-2FD31C834CXY4D601"]
monitor2_locations = ["GEOLOCATION-2FD31C834DE4D601"]

Describe the solution you'd like I need to fetch the entity_ids in below format, for ex:

monitor1_locations = ["GEOLOCATION-2FD31C834DE4D601",  "GEOLOCATION-2FD31C834CXY4D601"]
monitor2_locations = ["GEOLOCATION-2FD31C834DE4D601"]

Describe alternatives you've considered

  1. I have tried making use of the Dynatrace API but didn't find it feasible.
  2. Tried below code which throws error.

    
    data "dynatrace_synthetic_locations" "locations" {
    for_each = var.http_monitors
    
    name = each.value.locations[0]
    }

output "monitor_locations" { value = { for key, monitor in var.http_monitors : key => [for loc in monitor.locations : data.dynatrace_synthetic_locations.locations[loc][0].entity_id] } }


Please help me with this.

Thanks,
Vijayalakshmi
kishikawa12 commented 1 month ago

Hi @Vijayalakshmi-Yolbhavi,

Can you try the following code?

data "dynatrace_synthetic_locations" "all" {}

output "monitor_locations" {
  value = {
    for key, monitor in var.http_monitors : key => [
      for loc in monitor.locations : lookup(
        { for location in data.dynatrace_synthetic_locations.all.locations : location.name => location.entity_id... },
        loc,
        [loc]
      )[0]
    ]
  }
}

That should return..

Outputs:

monitor_locations = {
  "monitor1" = [
    "GEOLOCATION-2FD31C834DE4D601",
    "GEOLOCATION-871416B95457AB88",
  ]
  "monitor2" = [
    "GEOLOCATION-2FD31C834DE4D601",
  ]
}

Hope that helps!

Vijayalakshmi-Yolbhavi commented 1 month ago

Hi Ishikawa,

Thanks for assisting me with code. The code works fine. However, when I try to pass the output reference to the resource block, I'm seeing error.

Error: Reference to undeclared resource │ │ on main.tf line 8, in resource "dynatrace_http_monitor" "http_monitor": │ 8: locations = values(output.monitor_locations)[each.key] │ │ A managed resource "output" "monitor_locations" has not been declared in the root module.

Please note that, 1.I have declared the output in the output.tf file in the same working directory as main.tf 2.I tried re-initializing the terraform and was successful.

Please help me on this!    

Thanks,

Vijayalakshmi


From: Kodai Ishikawa @.> Sent: Wednesday, August 7, 2024 10:53 PM To: dynatrace-oss/terraform-provider-dynatrace @.> Cc: Yolbhavi. Vijayalakshmi @.>; Mention @.> Subject: [EXTERNAL] Re: [dynatrace-oss/terraform-provider-dynatrace] Unable to fetch entity_ids for multiple locations : data "dynatrace_synthetic_locations" (Issue #500)

Hi @Vijayalakshmi-Yolbhavihttps://github.com/Vijayalakshmi-Yolbhavi,

Can you try the following code?

data "dynatrace_synthetic_locations" "all" {}

output "monitor_locations" { value = { for key, monitor in var.http_monitors : key => [ for loc in monitor.locations : lookup( { for location in data.dynatrace_synthetic_locations.all.locations : location.name => location.entity_id... }, loc, [loc] )[0] ] } }

That should return..

Outputs:

monitor_locations = { "monitor1" = [ "GEOLOCATION-2FD31C834DE4D601", "GEOLOCATION-871416B95457AB88", ] "monitor2" = [ "GEOLOCATION-2FD31C834DE4D601", ] }

Hope that helps!

— Reply to this email directly, view it on GitHubhttps://github.com/dynatrace-oss/terraform-provider-dynatrace/issues/500#issuecomment-2273961802, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJYYXDDKF2WXRXSFPQDGEE3ZQJJYPAVCNFSM6AAAAABLHWKDC2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZTHE3DCOBQGI. You are receiving this because you were mentioned.Message ID: @.***>

Marks and Spencer


Unless otherwise stated: Marks and Spencer plc Registered Office: Waterside House 35 North Wharf Road London W2 1NW

Registered No. 214436 in England and Wales.

www.marksandspencer.com

Please note that electronic mail may be monitored.

This e-mail is confidential. If you received it by mistake, please let us know and then delete it from your system; you should not copy, disclose, or distribute its contents to anyone nor act in reliance on it, as this is prohibited and may be unlawful.

Facebookhttps://www.Facebook.com/marksandspencer/ Twitterhttps://www.Twitter.com/marksandspencer/ Linkedinhttps://www.linkedin.com/company/marks-and-spencer Pinteresthttps://www.Pinterest.com/marksandspencer/ Youtubehttps://www.youtube.com/user/marksandspencertv?sub_confirmation=1 Instagramhttps://www.instagram.com/marksandspencer/

Dynatrace-Reinhard-Pilz commented 1 month ago

Hello @Vijayalakshmi-Yolbhavi

The purpose of the output block is solely for printing debug information onto stdout. You cannot refer to that value later on.

If you want to refer to the monitor locations, just define them as a local instead, like this.

locals {
  monitor_locations = {
    for key, monitor in var.http_monitors : key => [
      for loc in monitor.locations : lookup(
        { for location in data.dynatrace_synthetic_locations.all.locations : location.name => location.entity_id... },
        loc,
        [loc]
      )[0]
    ]
  }
}

That allows you to refer to them using local.monitor_locations later on.

Let me know if that helps, Reinhard

Vijayalakshmi-Yolbhavi commented 1 month ago

Hi Pilz,

Thanks for the solution provided. It helped but I'm getting another error,

│ Error: size must be between 1 and 2000 │ │ with dynatrace_http_monitor.http_monitor["monitor2"], │ on main.tf line 17, in resource "dynatrace_http_monitor" "http_monitor": │ 17: resource "dynatrace_http_monitor" "http_monitor" { │

Thanks,

Vijayalakshmi


From: Reinhard Pilz @.> Sent: Thursday, August 8, 2024 2:08 PM To: dynatrace-oss/terraform-provider-dynatrace @.> Cc: Yolbhavi. Vijayalakshmi @.>; Mention @.> Subject: [EXTERNAL] Re: [dynatrace-oss/terraform-provider-dynatrace] Unable to fetch entity_ids for multiple locations : data "dynatrace_synthetic_locations" (Issue #500)

Hello @Vijayalakshmi-Yolbhavihttps://github.com/Vijayalakshmi-Yolbhavi

The purpose of the output block is solely for printing debug information onto stdout. You cannot refer to that value later on.

If you want to refer to the monitor locations, just define them as a local instead, like this.

locals { monitor_locations = { for key, monitor in var.http_monitors : key => [ for loc in monitor.locations : lookup( { for location in data.dynatrace_synthetic_locations.all.locations : location.name => location.entity_id... }, loc, [loc] )[0] ] } }

That allows you to refer to them using local.monitor_locations later on.

Let me know if that helps, Reinhard

— Reply to this email directly, view it on GitHubhttps://github.com/dynatrace-oss/terraform-provider-dynatrace/issues/500#issuecomment-2275268779, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJYYXDDINMHEZ3F4F53WV5DZQMVBXAVCNFSM6AAAAABLHWKDC2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZVGI3DQNZXHE. You are receiving this because you were mentioned.Message ID: @.***>

Marks and Spencer


Unless otherwise stated: Marks and Spencer plc Registered Office: Waterside House 35 North Wharf Road London W2 1NW

Registered No. 214436 in England and Wales.

www.marksandspencer.com

Please note that electronic mail may be monitored.

This e-mail is confidential. If you received it by mistake, please let us know and then delete it from your system; you should not copy, disclose, or distribute its contents to anyone nor act in reliance on it, as this is prohibited and may be unlawful.

Facebookhttps://www.Facebook.com/marksandspencer/ Twitterhttps://www.Twitter.com/marksandspencer/ Linkedinhttps://www.linkedin.com/company/marks-and-spencer Pinteresthttps://www.Pinterest.com/marksandspencer/ Youtubehttps://www.youtube.com/user/marksandspencertv?sub_confirmation=1 Instagramhttps://www.instagram.com/marksandspencer/

Dynatrace-Reinhard-Pilz commented 1 month ago

I would have to see the dynatrace_http_monitor block you're using to be extra sure. But it looks like the monitors you're configuring don't contain any requests.

Vijayalakshmi-Yolbhavi commented 1 month ago

Hi Pilz,

PFA terraform files for the configuration.

Thanks,

Vijayalakshmi


From: Reinhard Pilz @.> Sent: Thursday, August 8, 2024 4:46 PM To: dynatrace-oss/terraform-provider-dynatrace @.> Cc: Yolbhavi. Vijayalakshmi @.>; Mention @.> Subject: [EXTERNAL] Re: [dynatrace-oss/terraform-provider-dynatrace] Unable to fetch entity_ids for multiple locations : data "dynatrace_synthetic_locations" (Issue #500)

I would have to see the dynatrace_http_monitor block you're using to be extra sure. But it looks like the monitors you're configuring don't contain any requests.

— Reply to this email directly, view it on GitHubhttps://github.com/dynatrace-oss/terraform-provider-dynatrace/issues/500#issuecomment-2275568911, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJYYXDAWEFWBUTURMDWDJO3ZQNHSPAVCNFSM6AAAAABLHWKDC2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZVGU3DQOJRGE. You are receiving this because you were mentioned.Message ID: @.***>

Marks and Spencer


Unless otherwise stated: Marks and Spencer plc Registered Office: Waterside House 35 North Wharf Road London W2 1NW

Registered No. 214436 in England and Wales.

www.marksandspencer.com

Please note that electronic mail may be monitored.

This e-mail is confidential. If you received it by mistake, please let us know and then delete it from your system; you should not copy, disclose, or distribute its contents to anyone nor act in reliance on it, as this is prohibited and may be unlawful.

Facebookhttps://www.Facebook.com/marksandspencer/ Twitterhttps://www.Twitter.com/marksandspencer/ Linkedinhttps://www.linkedin.com/company/marks-and-spencer Pinteresthttps://www.Pinterest.com/marksandspencer/ Youtubehttps://www.youtube.com/user/marksandspencertv?sub_confirmation=1 Instagramhttps://www.instagram.com/marksandspencer/

data "dynatrace_synthetic_locations" "all" {}

locals { monitor_locations = { for key, monitor in var.http_monitors : key => [ for loc in monitor.locations : lookup( { for location in data.dynatrace_synthetic_locations.all.locations : location.name => location.entity_id... }, loc, [loc] )[0] ] } } output "locations" { value = local.monitor_locations } resource "dynatrace_http_monitor" "http_monitor" { for_each = var.http_monitors

name = each.value.name frequency = each.value.frequency locations = try(local.monitor_locations[each.key], ["GEOLOCATION-F15152A6A059C277"]) enabled = try(each.value.enabled, true) no_script = try(each.value.no_script, true) dynamic "anomaly_detection" { for_each = can(each.value.anomaly_detection) ? [1] : [] content {

  loading_time_thresholds {
    enabled = try(anomaly_detection.value.loading_time_thresholds.enabled, false)

    # Ensure at least one "threshold" block is present

    dynamic "thresholds" {
      for_each = try(anomaly_detection.value.loading_time_thresholds.thresholds, [])
      content {
        threshold {
          value_ms      = try(threshold.value.value_ms, "")
          event_index   = try(threshold.value.event_index, "")
          request_index = try(threshold.value.request_index, "")
          type          = try(threshold.value.type, "")
        }
      }
    }
  }

  outage_handling {
    global_outage = try(each.value.anomaly_detection.outage_handling.global_outage, false) # Providing a default value
    global_outage_policy {
      consecutive_runs = try(each.value.anomaly_detection.outage_handling.global_outage_policy.consecutive_runs, 0) # Providing a default value
    }
    local_outage = try(each.value.anomaly_detection.outage_handling.local_outage, false) # Providing a default value
    local_outage_policy {
      affected_locations = try(each.value.anomaly_detection.outage_handling.local_outage_policy.affected_locations, 0) # Providing a default value
      consecutive_runs   = try(each.value.anomaly_detection.outage_handling.local_outage_policy.consecutive_runs, 0)   # Providing a default value
    }
    retry_on_error = try(each.value.anomaly_detection.outage_handling.retry_on_error, false) # Providing a default value
  }
}

} dynamic "script" { for_each = can(each.value.script) && (each.value.no_script == false) ? [1] : [] content { dynamic "request" { for_each = can(each.value.script) ? each.value.script.request : [] content { description = try(request.value.description, "") method = request.value.method post_processing = try(request.value.post_processing, "") pre_processing = try(request.value.pre_processing, "") url = request.value.url body = try(request.value.body, "") request_timeout = try(request.value.request_timeout, 30) dynamic "configuration" { for_each = try(script.value.request.configuration != null, false) ? [1] : [] content { accept_any_certificate = try(request.value.configuration.accept_any_certificate, false) follow_redirects = try(request.value.configuration.follow_redirects, false) headers { dynamic "header" { for_each = request.value.configuration.headers content { name = try(header.value.name, "") value = try(header.value.value, "") } } } } } dynamic "validation" { for_each = try(script.value.request.validation != null, false) ? [1] : [] content { dynamic "rule" { for_each = script.value.request.validation.rule content { type = try(rule.value.type, "") value = try(rule.value.value, "") pass_if_found = try(rule.value.pass_if_found, false) } } } } } } } } dynamic "tags" { for_each = can(each.value.tags) ? [1] : [] content { dynamic "tag" { for_each = can(each.value.tags) ? [1] : [] content { context = try(tag.value.context, "CONTEXTLESS") key = try(tag.value.key, "") source = try(tag.value.source, "USER") value = try(tag.value.value, "") } } } } }

http_monitors = { "monitor1" = { name = "Tf loc_test" frequency = 60 locations = ["London", "Paris"]

locations = ["GEOLOCATION-F15152A6A059C277"]

enabled   = true
no_script = false
anomaly_detection = {
  loading_time_thresholds = {
    enabled = true
    thresholds = [
      {
        value_ms      = 500
        event_index   = 1
        request_index = 1
        type          = "TOTAL"
      }
    ]
  }
  outage_handling = {
    global_outage = true
    global_outage_policy = {
      consecutive_runs = 3
    }
    local_outage = true
    local_outage_policy = {
      affected_locations = 1
      consecutive_runs   = 2
    }
    retry_on_error = true
  }
}
script = {
  request = [
    {
      description     = "Sample request"
      method          = "GET"
      post_processing = "post_processing_script"
      pre_processing  = "pre_processing_script"
      url             = "https://example.com/api/endpoint"
      body            = ""
      request_timeout = 30
      tags = [
        {
          context = "CONTEXTLESS"
          key     = "test"
          source  = "USER"
          value   = "null"
        },
        {
          context = "CONTEXTLESS"
          source  = "USER"
        }
      ]

      configuration = {
        accept_any_certificate = false
        follow_redirects       = true
        headers = [
          {
            name  = "Content-Type"
            value = "application/json"
          },
          {
            name  = "Content-Type"
            value = "application/json"
          }
          # Add additional headers here
        ]
      }
      validation = {
        rule = [
          {
            type          = "httpStatusesList"
            value         = "200"
            pass_if_found = false
          },
          {
            type          = "httpStatusesList"
            value         = "400"
            pass_if_found = true
          }
          # Add additional validation rules here
        ]
      }
    }
    # Add additional requests here
  ]
}

} "monitor2" = { name = "Terraform loctest" frequency = 60 locations = ["London"]

locations = ["GEOLOCATION-F3E06A526BE3B4C4"]

enabled   = true
no_script = true
anomaly_detection = {
  loading_time_thresholds = {
    enabled = true
    thresholds = [
      {
        value_ms      = 500
        event_index   = 1
        request_index = 1
        type          = "TOTAL"
      }
    ]
  }
  outage_handling = {
    global_outage = true
    global_outage_policy = {
      consecutive_runs = 3
    }
    local_outage = true
    local_outage_policy = {
      affected_locations = 1
      consecutive_runs   = 2
    }
    retry_on_error = true
  }
}

}

Add more monitor configurations as needed

}

kishikawa12 commented 1 month ago

Hi @Vijayalakshmi-Yolbhavi ,

I tested the following code and ended with a successful apply, the only thing I did was added the variable "http_monitors" in the main.tf file since it was missing from your example.

By the way, ChatGPT can be helpful in some instances if you're having trouble with generating Terraform code. In this example, I had it create the variable block since it was missing based off of the terraform.tfvars file.

main.tf

variable "http_monitors" {
  type = map(object({
    name      = string
    frequency = number
    locations = list(string)
    enabled   = bool
    no_script = bool
    anomaly_detection = object({
      loading_time_thresholds = object({
        enabled     = bool
        thresholds  = list(object({
          value_ms      = number
          event_index   = number
          request_index = number
          type          = string
        }))
      })
      outage_handling = object({
        global_outage          = bool
        global_outage_policy   = object({
          consecutive_runs = number
        })
        local_outage           = bool
        local_outage_policy    = object({
          affected_locations = number
          consecutive_runs   = number
        })
        retry_on_error = bool
      })
    })
    script = optional(object({
      request = list(object({
        description     = string
        method          = string
        post_processing = string
        pre_processing  = string
        url             = string
        body            = string
        request_timeout = number
        tags = list(object({
          context = string
          key     = optional(string)
          source  = string
          value   = optional(string)
        }))
        configuration = object({
          accept_any_certificate = bool
          follow_redirects       = bool
          headers = list(object({
            name  = string
            value = string
          }))
        })
        validation = object({
          rule = list(object({
            type          = string
            value         = string
            pass_if_found = bool
          }))
        })
      }))
    }))
  }))
}

data "dynatrace_synthetic_locations" "all" {}

locals {
   monitor_locations = {
    for key, monitor in var.http_monitors : key => [
      for loc in monitor.locations : lookup(
        { for location in data.dynatrace_synthetic_locations.all.locations : location.name => location.entity_id... },
        loc,
        [loc]
      )[0]
    ]
  }
}

# output "locations" {
#   value = local.monitor_locations
# }

resource "dynatrace_http_monitor" "http_monitor" {
  for_each = var.http_monitors

  name      = each.value.name
  frequency = each.value.frequency
  locations = try(local.monitor_locations[each.key], ["GEOLOCATION-F15152A6A059C277"])
  enabled   = try(each.value.enabled, true)
  no_script = try(each.value.no_script, true)
  dynamic "anomaly_detection" {
    for_each = can(each.value.anomaly_detection) ? [1] : []
    content {

      loading_time_thresholds {
        enabled = try(anomaly_detection.value.loading_time_thresholds.enabled, false)

        # Ensure at least one "threshold" block is present

        dynamic "thresholds" {
          for_each = try(anomaly_detection.value.loading_time_thresholds.thresholds, [])
          content {
            threshold {
              value_ms      = try(threshold.value.value_ms, "")
              event_index   = try(threshold.value.event_index, "")
              request_index = try(threshold.value.request_index, "")
              type          = try(threshold.value.type, "")
            }
          }
        }
      }

      outage_handling {
        global_outage = try(each.value.anomaly_detection.outage_handling.global_outage, false) # Providing a default value
        global_outage_policy {
          consecutive_runs = try(each.value.anomaly_detection.outage_handling.global_outage_policy.consecutive_runs, 0) # Providing a default value
        }
        local_outage = try(each.value.anomaly_detection.outage_handling.local_outage, false) # Providing a default value
        local_outage_policy {
          affected_locations = try(each.value.anomaly_detection.outage_handling.local_outage_policy.affected_locations, 0) # Providing a default value
          consecutive_runs   = try(each.value.anomaly_detection.outage_handling.local_outage_policy.consecutive_runs, 0)   # Providing a default value
        }
        retry_on_error = try(each.value.anomaly_detection.outage_handling.retry_on_error, false) # Providing a default value
      }
    }
  }
  dynamic "script" {
    for_each = can(each.value.script) && (each.value.no_script == false) ? [1] : []
    content {
      dynamic "request" {
        for_each = can(each.value.script) ? each.value.script.request : []
        content {
          description     = try(request.value.description, "")
          method          = request.value.method
          post_processing = try(request.value.post_processing, "")
          pre_processing  = try(request.value.pre_processing, "")
          url             = request.value.url
          body            = try(request.value.body, "")
          request_timeout = try(request.value.request_timeout, 30)
          dynamic "configuration" {
            for_each = try(script.value.request.configuration != null, false) ? [1] : []
            content {
              accept_any_certificate = try(request.value.configuration.accept_any_certificate, false)
              follow_redirects       = try(request.value.configuration.follow_redirects, false)
              headers {
                dynamic "header" {
                  for_each = request.value.configuration.headers
                  content {
                    name  = try(header.value.name, "")
                    value = try(header.value.value, "")
                  }
                }
              }
            }
          }
          dynamic "validation" {
            for_each = try(script.value.request.validation != null, false) ? [1] : []
            content {
              dynamic "rule" {
                for_each = script.value.request.validation.rule
                content {
                  type          = try(rule.value.type, "")
                  value         = try(rule.value.value, "")
                  pass_if_found = try(rule.value.pass_if_found, false)
                }
              }
            }
          }
        }
      }
    }
  }
  dynamic "tags" {
    for_each = can(each.value.tags) ? [1] : []
    content {
      dynamic "tag" {
        for_each = can(each.value.tags) ? [1] : []
        content {
          context = try(tag.value.context, "CONTEXTLESS")
          key     = try(tag.value.key, "")
          source  = try(tag.value.source, "USER")
          value   = try(tag.value.value, "")
        }
      }
    }
  }
}

terraform.tfvars

http_monitors = {
  "monitor1" = {
    name      = "Tf loc_test"
    frequency = 60
    locations = ["London", "Paris"]
    #locations = ["GEOLOCATION-F15152A6A059C277"]
    enabled   = true
    no_script = false
    anomaly_detection = {
      loading_time_thresholds = {
        enabled = true
        thresholds = [
          {
            value_ms      = 500
            event_index   = 1
            request_index = 1
            type          = "TOTAL"
          }
        ]
      }
      outage_handling = {
        global_outage = true
        global_outage_policy = {
          consecutive_runs = 3
        }
        local_outage = true
        local_outage_policy = {
          affected_locations = 1
          consecutive_runs   = 2
        }
        retry_on_error = true
      }
    }
    script = {
      request = [
        {
          description     = "Sample request"
          method          = "GET"
          post_processing = "post_processing_script"
          pre_processing  = "pre_processing_script"
          url             = "https://example.com/api/endpoint"
          body            = ""
          request_timeout = 30
          tags = [
            {
              context = "CONTEXTLESS"
              key     = "test"
              source  = "USER"
              value   = "null"
            },
            {
              context = "CONTEXTLESS"
              source  = "USER"
            }
          ]

          configuration = {
            accept_any_certificate = false
            follow_redirects       = true
            headers = [
              {
                name  = "Content-Type"
                value = "application/json"
              },
              {
                name  = "Content-Type"
                value = "application/json"
              }
              # Add additional headers here
            ]
          }
          validation = {
            rule = [
              {
                type          = "httpStatusesList"
                value         = "200"
                pass_if_found = false
              },
              {
                type          = "httpStatusesList"
                value         = "400"
                pass_if_found = true
              }
              # Add additional validation rules here
            ]
          }
        }
        # Add additional requests here
      ]
    }
  }
  "monitor2" = {
    name      = "Terraform loctest"
    frequency = 60
    locations = ["London"]
    #locations = ["GEOLOCATION-F3E06A526BE3B4C4"]
    enabled   = true
    no_script = true
    anomaly_detection = {
      loading_time_thresholds = {
        enabled = true
        thresholds = [
          {
            value_ms      = 500
            event_index   = 1
            request_index = 1
            type          = "TOTAL"
          }
        ]
      }
      outage_handling = {
        global_outage = true
        global_outage_policy = {
          consecutive_runs = 3
        }
        local_outage = true
        local_outage_policy = {
          affected_locations = 1
          consecutive_runs   = 2
        }
        retry_on_error = true
      }
    }
  }
  # Add more monitor configurations as needed
}
Vijayalakshmi-Yolbhavi commented 1 month ago

Thanks Ishikawa for the help!

Thanks,

Vijayalakshmi


From: Kodai Ishikawa @.> Sent: Thursday, August 8, 2024 8:08 PM To: dynatrace-oss/terraform-provider-dynatrace @.> Cc: Yolbhavi. Vijayalakshmi @.>; Mention @.> Subject: [EXTERNAL] Re: [dynatrace-oss/terraform-provider-dynatrace] Unable to fetch entity_ids for multiple locations : data "dynatrace_synthetic_locations" (Issue #500)

Hi @Vijayalakshmi-Yolbhavihttps://github.com/Vijayalakshmi-Yolbhavi ,

I tested the following code and ended with a successful apply, the only thing I did was added the variable "http_monitors" in the main.tf file since it was missing from your example.

By the way, ChatGPT can be helpful in some instances if you're having trouble with generating Terraform code. In this example, I had it create the variable block since it was missing based off of the terraform.tfvars file.

main.tf

variable "http_monitors" { type = map(object({ name = string frequency = number locations = list(string) enabled = bool no_script = bool anomaly_detection = object({ loading_time_thresholds = object({ enabled = bool thresholds = list(object({ value_ms = number event_index = number request_index = number type = string })) }) outage_handling = object({ global_outage = bool global_outage_policy = object({ consecutive_runs = number }) local_outage = bool local_outage_policy = object({ affected_locations = number consecutive_runs = number }) retry_on_error = bool }) }) script = optional(object({ request = list(object({ description = string method = string post_processing = string pre_processing = string url = string body = string request_timeout = number tags = list(object({ context = string key = optional(string) source = string value = optional(string) })) configuration = object({ accept_any_certificate = bool follow_redirects = bool headers = list(object({ name = string value = string })) }) validation = object({ rule = list(object({ type = string value = string pass_if_found = bool })) }) })) })) })) }

data "dynatrace_synthetic_locations" "all" {}

locals { monitor_locations = { for key, monitor in var.http_monitors : key => [ for loc in monitor.locations : lookup( { for location in data.dynatrace_synthetic_locations.all.locations : location.name => location.entity_id... }, loc, [loc] )[0] ] } }

output "locations" {

value = local.monitor_locations

}

resource "dynatrace_http_monitor" "http_monitor" { for_each = var.http_monitors

name = each.value.name frequency = each.value.frequency locations = try(local.monitor_locations[each.key], ["GEOLOCATION-F15152A6A059C277"]) enabled = try(each.value.enabled, true) no_script = try(each.value.no_script, true) dynamic "anomaly_detection" { for_each = can(each.value.anomaly_detection) ? [1] : [] content {

  loading_time_thresholds {
    enabled = try(anomaly_detection.value.loading_time_thresholds.enabled, false)

    # Ensure at least one "threshold" block is present

    dynamic "thresholds" {
      for_each = try(anomaly_detection.value.loading_time_thresholds.thresholds, [])
      content {
        threshold {
          value_ms      = try(threshold.value.value_ms, "")
          event_index   = try(threshold.value.event_index, "")
          request_index = try(threshold.value.request_index, "")
          type          = try(threshold.value.type, "")
        }
      }
    }
  }

  outage_handling {
    global_outage = try(each.value.anomaly_detection.outage_handling.global_outage, false) # Providing a default value
    global_outage_policy {
      consecutive_runs = try(each.value.anomaly_detection.outage_handling.global_outage_policy.consecutive_runs, 0) # Providing a default value
    }
    local_outage = try(each.value.anomaly_detection.outage_handling.local_outage, false) # Providing a default value
    local_outage_policy {
      affected_locations = try(each.value.anomaly_detection.outage_handling.local_outage_policy.affected_locations, 0) # Providing a default value
      consecutive_runs   = try(each.value.anomaly_detection.outage_handling.local_outage_policy.consecutive_runs, 0)   # Providing a default value
    }
    retry_on_error = try(each.value.anomaly_detection.outage_handling.retry_on_error, false) # Providing a default value
  }
}

} dynamic "script" { for_each = can(each.value.script) && (each.value.no_script == false) ? [1] : [] content { dynamic "request" { for_each = can(each.value.script) ? each.value.script.request : [] content { description = try(request.value.description, "") method = request.value.method post_processing = try(request.value.post_processing, "") pre_processing = try(request.value.pre_processing, "") url = request.value.url body = try(request.value.body, "") request_timeout = try(request.value.request_timeout, 30) dynamic "configuration" { for_each = try(script.value.request.configuration != null, false) ? [1] : [] content { accept_any_certificate = try(request.value.configuration.accept_any_certificate, false) follow_redirects = try(request.value.configuration.follow_redirects, false) headers { dynamic "header" { for_each = request.value.configuration.headers content { name = try(header.value.name, "") value = try(header.value.value, "") } } } } } dynamic "validation" { for_each = try(script.value.request.validation != null, false) ? [1] : [] content { dynamic "rule" { for_each = script.value.request.validation.rule content { type = try(rule.value.type, "") value = try(rule.value.value, "") pass_if_found = try(rule.value.pass_if_found, false) } } } } } } } } dynamic "tags" { for_each = can(each.value.tags) ? [1] : [] content { dynamic "tag" { for_each = can(each.value.tags) ? [1] : [] content { context = try(tag.value.context, "CONTEXTLESS") key = try(tag.value.key, "") source = try(tag.value.source, "USER") value = try(tag.value.value, "") } } } } }

terraform.tfvars

http_monitors = { "monitor1" = { name = "Tf loc_test" frequency = 60 locations = ["London", "Paris"]

locations = ["GEOLOCATION-F15152A6A059C277"]

enabled   = true
no_script = false
anomaly_detection = {
  loading_time_thresholds = {
    enabled = true
    thresholds = [
      {
        value_ms      = 500
        event_index   = 1
        request_index = 1
        type          = "TOTAL"
      }
    ]
  }
  outage_handling = {
    global_outage = true
    global_outage_policy = {
      consecutive_runs = 3
    }
    local_outage = true
    local_outage_policy = {
      affected_locations = 1
      consecutive_runs   = 2
    }
    retry_on_error = true
  }
}
script = {
  request = [
    {
      description     = "Sample request"
      method          = "GET"
      post_processing = "post_processing_script"
      pre_processing  = "pre_processing_script"
      url             = "https://example.com/api/endpoint"
      body            = ""
      request_timeout = 30
      tags = [
        {
          context = "CONTEXTLESS"
          key     = "test"
          source  = "USER"
          value   = "null"
        },
        {
          context = "CONTEXTLESS"
          source  = "USER"
        }
      ]

      configuration = {
        accept_any_certificate = false
        follow_redirects       = true
        headers = [
          {
            name  = "Content-Type"
            value = "application/json"
          },
          {
            name  = "Content-Type"
            value = "application/json"
          }
          # Add additional headers here
        ]
      }
      validation = {
        rule = [
          {
            type          = "httpStatusesList"
            value         = "200"
            pass_if_found = false
          },
          {
            type          = "httpStatusesList"
            value         = "400"
            pass_if_found = true
          }
          # Add additional validation rules here
        ]
      }
    }
    # Add additional requests here
  ]
}

} "monitor2" = { name = "Terraform loctest" frequency = 60 locations = ["London"]

locations = ["GEOLOCATION-F3E06A526BE3B4C4"]

enabled   = true
no_script = true
anomaly_detection = {
  loading_time_thresholds = {
    enabled = true
    thresholds = [
      {
        value_ms      = 500
        event_index   = 1
        request_index = 1
        type          = "TOTAL"
      }
    ]
  }
  outage_handling = {
    global_outage = true
    global_outage_policy = {
      consecutive_runs = 3
    }
    local_outage = true
    local_outage_policy = {
      affected_locations = 1
      consecutive_runs   = 2
    }
    retry_on_error = true
  }
}

}

Add more monitor configurations as needed

}

— Reply to this email directly, view it on GitHubhttps://github.com/dynatrace-oss/terraform-provider-dynatrace/issues/500#issuecomment-2275996963, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJYYXDHGCUHDLU2SHZI457DZQN7HXAVCNFSM6AAAAABLHWKDC2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZVHE4TMOJWGM. You are receiving this because you were mentioned.Message ID: @.***>

Marks and Spencer


Unless otherwise stated: Marks and Spencer plc Registered Office: Waterside House 35 North Wharf Road London W2 1NW

Registered No. 214436 in England and Wales.

www.marksandspencer.com

Please note that electronic mail may be monitored.

This e-mail is confidential. If you received it by mistake, please let us know and then delete it from your system; you should not copy, disclose, or distribute its contents to anyone nor act in reliance on it, as this is prohibited and may be unlawful.

Facebookhttps://www.Facebook.com/marksandspencer/ Twitterhttps://www.Twitter.com/marksandspencer/ Linkedinhttps://www.linkedin.com/company/marks-and-spencer Pinteresthttps://www.Pinterest.com/marksandspencer/ Youtubehttps://www.youtube.com/user/marksandspencertv?sub_confirmation=1 Instagramhttps://www.instagram.com/marksandspencer/