Skip to content

[Bug]: Can't directly change alerts notification type, need to delete it first #3869

@YusDyr

Description

@YusDyr

Is there an existing issue for this?

  • I have searched the existing issues

Provider Version

1.14.0

Terraform Version

1.9.0

Terraform Edition

Terraform Open Source (OSS)

Current Behavior

When I created alerts with one notification type, such as, for example, PAGER_DUTY or SLACK and now want to change it to another notification type, such as TEAMS, I constantly got errors related to notification-specific parameters. It seems like the terraform checks first compatibility between existing notification parameters and new notification type even despite these conflicting parameters should be deleted on update.

Terraform configuration to reproduce the issue

variable "environment" {
  description = "Name of the environment where table is being deployed."
  type        = string
}

variable "alerts_no_primary" {
  description = "[no_primary] Alert settings"
  type = object({
    create        = optional(bool, true)
    enable        = optional(bool, true)
    interval_min  = optional(number, 30)
    delay_min     = optional(number, 0)
    notifications = optional(set(string), ["PD", "Teams"])
  })
  default = {}
}

variable "alerts_notifications_config" {
  description = "Alerts notification configs, currently for PD and SLACK"
  type = map(object({
    notification_type = string
    delay_min         = optional(number) # Number of minutes to wait after an alert condition is detected before sending out the first notification.
    interval_min      = optional(number) # Number of minutes to wait between successive notifications for unacknowledged alerts that are not resolved. The minimum value is 5. **NOTE** `PAGER_DUTY`, `VICTOR_OPS`, and `OPS_GENIE` notifications do not return this value. The notification interval must be configured and managed within each external service.
    team_name         = optional(string) # Label for the team that receives this notification
    channel_name      = optional(string) # Attributes for SLACK
    teams_webhook_url = optional(string) # Webhook URL for Teams in case of multiple Teams channel are used
  }))
  default = {
    "PD" = {
      notification_type = "PAGER_DUTY"
    }
    "Teams" = {
      notification_type = "MICROSOFT_TEAMS"
    }
  }
  validation {
    condition     = alltrue([for o in var.alerts_notifications_config : contains(["SLACK", "PAGER_DUTY", "MICROSOFT_TEAMS", "DATADOG"], o.notification_type)])
    error_message = "Currently only these notification_type supported: `SLACK`, `PAGER_DUTY`, `MICROSOFT_TEAMS`, `DATADOG`"
  }
  validation {
    condition     = alltrue([for o in var.alerts_notifications_config : (o.notification_type == "SLACK" ? (var.alerts_slack_token != null ? true : false) : true)])
    error_message = "For SLACK notifications `var.alerts_slack_token` shouldn't be null."
  }
  validation {
    condition     = alltrue([for o in var.alerts_notifications_config : (o.notification_type == "SLACK" ? (o.channel_name != null ? true : false) : true)])
    error_message = "For SLACK notifications `channel_name` parameter shouldn't be null."
  }
  validation {
    condition     = alltrue([for o in var.alerts_notifications_config : (o.notification_type == "PAGER_DUTY" ? (var.pager_duty_service_key != null ? true : false) : true)])
    error_message = "For Pagerduty notifications `var.pager_duty_service_key` shouldn't be null."
  }
  validation {
    condition     = alltrue([for o in var.alerts_notifications_config : (o.notification_type == "MICROSOFT_TEAMS" ? ((var.teams_webhook_url != null || o.teams_webhook_url != null) ? true : false) : true)])
    error_message = "For MS Teams notifications `var.teams_webhook_url` or subkey `teams_webhook_url` shouldn't be null."
  }
  validation {
    condition     = alltrue([for o in var.alerts_notifications_config : (o.notification_type == "DATADOG" ? (var.datadog_api_key != null ? true : false) : true)])
    error_message = "For Datadog notifications `var.datadog_api_key` shouldn't be null."
  }
}

variable "general_alerts_notifications" {
  type    = set(string)
  default = []
}

locals {

  notifications_config = {
    for k, n in var.alerts_notifications_config :
    lower(k) => (
      n.notification_type == "SLACK" ? merge(n, { api_token = var.alerts_slack_token }) :
      n.notification_type == "PAGER_DUTY" ? merge(n, { service_key = var.pager_duty_service_key, interval_min = try(n.interval_min, null) }) :
      n.notification_type == "MICROSOFT_TEAMS" ? merge(n, { microsoft_teams_webhook_url = coalesce(n.teams_webhook_url, var.teams_webhook_url) }) :
      n.notification_type == "DATADOG" ? merge(n, { datadog_api_key = var.datadog_api_key }) :
      n
    )
  }

  is_environment_prod = (
    strcontains(lower(var.environment), "prod") ||
    strcontains(lower(var.environment), "prd")
  )

  # Effective general alerts notifications:
  # - if var.general_alerts_notifications is non-empty -> use it
  # - else:
  #     - prod/prd -> ["PD", "Teams"]
  #     - others  -> ["Teams"]
  # - only keep channels defined in notifications_config
  general_alerts_notifications = distinct([
    for k in(
      length(var.general_alerts_notifications) > 0
      ? var.general_alerts_notifications
      : (
        local.is_environment_prod
        ? ["PD", "Teams"]
        : ["Teams"]
      )
    ) : lower(k)
    if contains(keys(local.notifications_config), lower(k))
  ])
}


resource "mongodbatlas_alert_configuration" "no_primary" {
  count      = var.alerts_no_primary.create ? 1 : 0
  project_id = var.project_id
  event_type = "NO_PRIMARY"
  enabled    = var.alerts_no_primary.enable

  dynamic "notification" {
    for_each = toset(
      coalescelist(
        [for k in tolist(var.alerts_no_primary.notifications) : lower(k)],
        local.general_alerts_notifications
      )
    )
    content {
      type_name                   = local.notifications_config[notification.key].notification_type
      api_token                   = lookup(local.notifications_config[notification.key], "api_token", null)
      channel_name                = lookup(local.notifications_config[notification.key], "channel_name", null)
      service_key                 = lookup(local.notifications_config[notification.key], "service_key", null)
      microsoft_teams_webhook_url = lookup(local.notifications_config[notification.key], "microsoft_teams_webhook_url", null)
      datadog_api_key             = lookup(local.notifications_config[notification.key], "datadog_api_key", null)
      interval_min                = local.notifications_config[notification.key].notification_type != "PAGER_DUTY" ? try(coalesce(var.alerts_no_primary.interval_min, local.notifications_config[notification.key].interval_min), null) : null
      delay_min                   = try(coalesce(var.alerts_no_primary.delay_min, local.notifications_config[notification.key].delay_min), null)
    }
  }

  matcher {
    field_name = "CLUSTER_NAME"
    operator   = "EQUALS"
    value      = var.cluster_name
  }
}

Steps To Reproduce

  1. Create first alerts with that config and var.environment = "dev"
  2. Change var.environment to "prod"
  3. Successfully run terraform plan
  4. Fail on terraform apply

Logs

Terraform will perform the following actions:
  # mongodbatlas_alert_configuration.host_is_down[0] will be updated in-place
  ~ resource "mongodbatlas_alert_configuration" "host_is_down" {
        id                     = "aWQ=:NjkxMjViNGIzOGRmNDAyZTYwNWYzZTIw-cHJvamVjdF9pZA==:NjRhYzU1MDRkNTFhYTczMTc0MTEzZmU0"
      ~ updated                = "2025-11-10T21:38:19Z" -> (known after apply)
        # (5 unchanged attributes hidden)
      ~ notification {
          - microsoft_teams_webhook_url = (sensitive value) -> null
          ~ notifier_id                 = "69125b4b38df402e605f3e16" -> (known after apply)
          + service_key                 = (sensitive value)
          + team_name                   = (known after apply)
          ~ type_name                   = "MICROSOFT_TEAMS" -> "PAGER_DUTY"
            # (4 unchanged attributes hidden)
        }
      + notification {
          + delay_min                   = 0
          + email_enabled               = (known after apply)
          + interval_min                = 30
          + microsoft_teams_webhook_url = (sensitive value)
          + notifier_id                 = (known after apply)
          + sms_enabled                 = (known after apply)
          + team_name                   = (known after apply)
          + type_name                   = "MICROSOFT_TEAMS"
        }
        # (1 unchanged block hidden)
    }
  # mongodbatlas_alert_configuration.no_primary[0] will be updated in-place
  ~ resource "mongodbatlas_alert_configuration" "no_primary" {
        id                     = "aWQ=:NjkxMjViNGJiNDkwYjQxOWI3MzBjYWNj-cHJvamVjdF9pZA==:NjRhYzU1MDRkNTFhYTczMTc0MTEzZmU0"
      ~ updated                = "2025-11-10T21:38:19Z" -> (known after apply)
        # (5 unchanged attributes hidden)
      ~ notification {
          - microsoft_teams_webhook_url = (sensitive value) -> null
          ~ notifier_id                 = "69125b4bb490b419b730cac4" -> (known after apply)
          + service_key                 = (sensitive value)
          + team_name                   = (known after apply)
          ~ type_name                   = "MICROSOFT_TEAMS" -> "PAGER_DUTY"
            # (4 unchanged attributes hidden)
        }
      + notification {
          + delay_min                   = 0
          + email_enabled               = (known after apply)
          + interval_min                = 30
          + microsoft_teams_webhook_url = (sensitive value)
          + notifier_id                 = (known after apply)
          + sms_enabled                 = (known after apply)
          + team_name                   = (known after apply)
          + type_name                   = "MICROSOFT_TEAMS"
        }
        # (1 unchanged block hidden)
    }
Plan: 0 to add, 2 to change, 0 to destroy.
mongodbatlas_alert_configuration.no_primary[0]: Modifying... [id=aWQ=:NjkxMjViNGJiNDkwYjQxOWI3MzBjYWNj-cHJvamVjdF9pZA==:NjRhYzU1MDRkNTFhYTczMTc0MTEzZmU0]
mongodbatlas_alert_configuration.host_is_down[0]: Modifying... [id=aWQ=:NjkxMjViNGIzOGRmNDAyZTYwNWYzZTIw-cHJvamVjdF9pZA==:NjRhYzU1MDRkNTFhYTczMTc0MTEzZmU0]
Error: error updating Alert Configuration information: %s
  with mongodbatlas_alert_configuration.host_is_down[0],
  on alerts.tf line 42, in resource "mongodbatlas_alert_configuration" "host_is_down":
  42: resource "mongodbatlas_alert_configuration" "host_is_down" {
'interval_min' must not be set if type_name is 'PAGER_DUTY', 'OPS_GENIE' or
'VICTOR_OPS'
Error: error updating Alert Configuration information: %s
  with mongodbatlas_alert_configuration.no_primary[0],
  on alerts.tf line 76, in resource "mongodbatlas_alert_configuration" "no_primary":
  76: resource "mongodbatlas_alert_configuration" "no_primary" {
'interval_min' must not be set if type_name is 'PAGER_DUTY', 'OPS_GENIE' or
'VICTOR_OPS'
[23:25:22] [ERROR] Failed running apply script

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions