opsgenie / terraform-provider-opsgenie

Terraform OpsGenie provider
https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs
Mozilla Public License 2.0
100 stars 135 forks source link

Gotcha when creating Escalation Policies #427

Open stan-hill-oxa opened 6 months ago

stan-hill-oxa commented 6 months ago

When creating an escalation policy, the plugin crashes if you include a repeat block in the code, but set all of the values inside to null. However, if you make this block dynamic, and set the default to {} using a try block, it works. See below for details:

Terraform Version

Terraform v1.5.7

Affected Resource(s)

Terraform Configuration Files

Escalations are being passed in via YAML, like so:

escalations:
  support_escalation:
    description: Escalation Policy for Support Tickets
    rules:
      initial:
        condition: if-not-acked
        notify_type: users
        delay: 0
        recipient:
          type: team
          id: <team-id>
    repeat:
      wait_interval: 10
      count: 1
      reset_recipient_states: true
      close_alert_after_all: false

When the repeat yaml is removed from above, and all values in the terraform block are set to null, the plugin crashes. The Terraform code is below:

locals {
  escalations_raw = { for team_name, team_data in local.team_data : team_name => {
      for escalation_name, escalation_data in team_data.escalations : escalation_name => merge({"owner_team_id" = data.terraform_remote_state.opsgenie_teams.outputs.teams[team_name].id}, escalation_data)
    }
  }
  escalations = { for escalation in values(local.escalations_raw) : keys(escalation)[0] => values(escalation)[0] }
}

resource "opsgenie_escalation" "escalations" {
  for_each = local.escalations
  name          = each.key
  description   = lookup(each.value, "description", null)
  owner_team_id = lookup(each.value, "owner_team_id", null)

 dynamic "rules" {
    for_each = each.value.rules

    content {
        condition   = rules.value.condition
        notify_type = rules.value.notify_type
        delay       = rules.value.delay
        recipient {
            type = rules.value.recipient.type
            id   = rules.value.recipient.type == "schedule" ? opsgenie_schedule.schedules[rules.value.recipient.id].id : data.terraform_remote_state.opsgenie_teams.outputs.teams[rules.value.recipient.id].id
        }
    }
  }

  repeat {
    wait_interval          = try(each.value.repeat.wait_interval, null)
    count                  = try(each.value.repeat.count, null)
    reset_recipient_states = try(each.value.repeat.reset_recipient_states, null)
    close_alert_after_all  = try(each.value.repeat.close_alert_after_all, null)
  }
}

However, change that repeat block to dynamic, and it works:

  dynamic "repeat" {
    for_each = try(each.value.repeat, {})
    content {
        wait_interval          = try(each.value.repeat.wait_interval, null)
        count                  = try(each.value.repeat.count, null)
        reset_recipient_states = try(each.value.repeat.reset_recipient_states, null)
        close_alert_after_all  = try(each.value.repeat.close_alert_after_all, null)
    }
  }

Debug Output

https://gist.github.com/stan-hill-oxa/767ac5e31f32cddda8c5bad159542ba8

Expected Behavior

An opsgenie_escalation resource (i.e an Escalation Policy) is created without the repeat configuration, without using a dynamic block.

Actual Behavior

Error: The terraform-provider-opsgenie_v0.6.35 plugin crashed! - when block is not dynamic. Terraform is successful when block is dynamic.

Steps to Reproduce