terraform-provider-dynatrace icon indicating copy to clipboard operation
terraform-provider-dynatrace copied to clipboard

[Error] [Urgent] Facing issue with id attribute in resource dynatrace_calculated_service_metric

Open anshulgargamway opened this issue 2 years ago • 4 comments

Hello Team,'

I am trying to create multiple dynatrace_calculated_service_metric resources in a loop. Now, we are passing all the required parameter via terraform as mentioned in document https://registry.terraform.io/providers/dynatrace-oss/dynatrace/1.8.4/docs/resources/calculated_service_metric

Now, all the resources are getting created successfully when we run the terraform intially. But now if we have updated the metric_key & name variable in the same file which we used earlier.

For Ex:

Intailly we have used following metric_key and name metric_key = calc:service.less_then_100ms_pos_PERF_slo_latency_metric name = less then 100ms (pos_PERF)_slo_latency_metric

We have executed terraform plan & terraform apply command all went ok required metrics is created successfully into Dynatrace. In terraform State File we have observed ID is associated with above config which looks like calc:service.less_then_100ms_pos_PERF_slo_latency_metric similar to metric_key.

Now, I want to update my terraform configs to change metric_key & name to something as mentioned below: metric_key = calc:service.less_then_200ms_pos_PERF_slo_latency_metric name = less then 200ms (pos_PERF)_slo_latency_metric

We have now executed terraform plan & terraform apply which has resulted in below exception


Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # module.pos-app-perf-calculated-metrics.dynatrace_calculated_service_metric.slo_responsetime_metric[0] will be updated in-place
  ~ resource "dynatrace_calculated_service_metric" "slo_responsetime_metric" {
        id         = "calc:service.less_then_100ms_pos_PERF_slo_latency_metric"
      ~ metric_key = "calc:service.less_then_100ms_pos_PERF_slo_latency_metric" -> "calc:service.less_then_200ms_pos_PERF_slo_latency_metric"
      ~ name       = "less then 100ms (pos_PERF)_slo_latency_metric" -> "less then 200ms (pos_PERF)_slo_latency_metric"
        # (3 unchanged attributes hidden)

      ~ conditions {
          ~ condition {
                # (1 unchanged attribute hidden)

              ~ comparison {
                    # (1 unchanged attribute hidden)

                  ~ number {
                      ~ value    = 100 -> 200
                        # (2 unchanged attributes hidden)
                    }
                }
            }
        }


        # (2 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
module.pos-app-perf-calculated-metrics.dynatrace_calculated_service_metric.slo_responsetime_metric[0]: Modifying... [id=calc:service.less_then_100ms_pos_PERF_slo_latency_metric]

module.pos-app-perf-calculated-metrics.dynatrace_calculated_service_metric.slo_responsetime_metric[0]: Modifying... [id=calc:service.less_then_100ms_pos_PERF_slo_latency_metric]
╷
│ Error: {
│   "code": 0,
│   "message": "",
│   "constraintViolations": null
│ }
│
│   with module.pos-app-perf-calculated-metrics.dynatrace_calculated_service_metric.slo_responsetime_metric[0],
│   on ../modules/dynatrace/calculated_service_metric/sloResponseTime_metric.tf line 1, in resource "dynatrace_calculated_service_metric" "slo_responsetime_metric":
│    1: resource "dynatrace_calculated_service_metric" "slo_responsetime_metric" {
│
╵

In the above issue you will notice that we have updated metric_key & name but id which was autogenerated in previous run calc:service.less_then_100ms_pos_PERF_slo_latency_metric is not changed. In the ideal scenario this should be destroyed and new calculated service metric with new ID should be created but seems like this is not happening.

Tried following workaround but wasn't successfuly

Just to workaround this situation. We tried to pass id at time of dynatrace_calculated_service_metric resource creation as mentioned by documentation id can be passed but this again resulted in another issue.

│ Error: Invalid or unknown key
│
│   with module.pos-app-perf-calculated-metrics.dynatrace_calculated_service_metric.slo_responsetime_metric,
│   on ../modules/dynatrace/calculated_service_metric/sloResponseTime_metric.tf line 7, in resource "dynatrace_calculated_service_metric" "slo_responsetime_metric":
│    7:   id = "calc:service.less_then_${element(var.required_latency_list, count.index)}ms_${local.service_name}_slo_latency_metric"
│

Can you please help in identifying the root cause or fix behind this issue. If you feel that we need some correction at our end do highlight we will fix it as per provided suggestion.

Attached our dynatrace_calculated_service_metric code which are using to create metrics

resource "dynatrace_calculated_service_metric" "slo_responsetime_metric" {
  count      = length(var.required_latency_list)
  name       = "less then ${element(var.required_latency_list, count.index)}ms (${local.service_name})_slo_latency_metric"
  enabled    = true
  entity_id  = local.assigned_entities
  metric_key = "calc:service.less_then_${element(var.required_latency_list, count.index)}ms_${local.service_name}_slo_latency_metric"
  unit       = "COUNT"
  conditions {
    condition {
      attribute = "RESPONSE_TIME"
      comparison {
        negate = false
        number {
          operator = "LOWER_THAN_OR_EQUAL"
          value    = element(var.required_latency_list, count.index)
        }
      }
    }
  }
  dimension_definition {
    name              = "Dimension"
    dimension         = "All requests"
    top_x             = 10
    top_x_aggregation = "SINGLE_VALUE"
    top_x_direction   = "DESCENDING"
  }
  metric_definition {
    metric = "REQUEST_COUNT"
  }
}

Please let me know if some more details are required.

anshulgargamway avatar Feb 06 '22 07:02 anshulgargamway

@Dynatrace-Reinhard-Pilz / @Dynatrace-Asad-Ali / @dynatrace-cla-bot : Any help over here will be great.

anshulgargamway avatar Feb 07 '22 05:02 anshulgargamway

Hello @anshulgargamway

You essentially already have identified the root cause here by taking a peek into the terraform state file. Your observation results in the fact, that the Dynatrace REST API for this specific resource unfortunately doesn't generate a unique id based on e.g. a UUID but instead bases it on the value for the metric_key attribute. In order to »find« that resource after creation again, the Terraform Provider has no choice than obeying that behavior and store it as the id of the resource.

As a result, when changing the metric_key you're also accidentally changing the id of the resource - at least as far as the Dynatrace REST API is concerned. This is the immediate reason for the Constraint Violation that doesn't contain any details.

The workaround you have tried (passing the id attribute explicitly) is something that Terraform won't allow. The 'id' attribute - although always present - is not allowed to be among the attributes you can specify within your resources. Terraform prevents that from happening.

Your suggestion to implicitly destroy the original resource and creating a new one sounds at first glance like the solution in this case. But it DOES come with a couple of risks and unknowns. First of all the Terraform Provider would have to construct the id sent to the REST API automatically - e.g. by bluntly assuming that it will be calc:service. concatenated with the metric_key. That's however not correct in many cases, especially if non alphanumeric characters are part of the metric_key. It might be possible to decypher the algorithm behind that and replicate that behavior in the Provider, but there is no guarantee for that algorithm to stay the same within the REST API.

I am going to look into ways to supporting your use case automatically. But on short notice the safe way to work around that limitation is to also change the name of your resource - which essentially tells Terraform to explicitly destroy the resource and create a new one. I guess this isn't necessarily convenient - the name slo_responsetime_metric chosen in your example likely stems from the plan to keep that name the same all the time so you can refer to it in other parts of your modules. But until further notice you will have to do a full text replace for that resource name in order to keep things stable.

I will keep this issue open until further notice, so I can spend a bit of time trying out additional solutions here. But a change in behavior won't be available right away.

best regards, Reinhard

Dynatrace-Reinhard-Pilz avatar Feb 07 '22 11:02 Dynatrace-Reinhard-Pilz

Hello @Dynatrace-Reinhard-Pilz

Thanks for your quick response. I will also try few more suggestions as you mentioned above and will come back with more details.

Additionally, will wait for your response as well to see if any possible solutions can help us.

Thanks & Regards Anshul Garg

anshulgargamway avatar Feb 07 '22 12:02 anshulgargamway

Bonjour @Dynatrace-Reinhard-Pilz

I got same error, i use dynatrace_calculated_service_metric ressource in a loog of a module to create metrics for SLO when i change a metric setting like response time, a new metric is created and previous not destroy when i destroy project, all metrics created are still available

What i can do ? Your solution is to do a full text replace for resource name in order to keep things stable. But how i can do that in a loop ? do you have an example ?

Cordialement

blaurendeau avatar May 18 '22 08:05 blaurendeau

Hello everybody. This issue will get addressed with the next release of the Terraform Provider.

Dynatrace-Reinhard-Pilz avatar Feb 24 '23 13:02 Dynatrace-Reinhard-Pilz