cloudflare / terraform-provider-cloudflare

Cloudflare Terraform Provider
https://registry.terraform.io/providers/cloudflare/cloudflare
Mozilla Public License 2.0
782 stars 605 forks source link

notification policy import: only last email gets saved in tfstate #1917

Closed Done203 closed 1 year ago

Done203 commented 2 years ago

Confirmation

Terraform and Cloudflare provider version

Terraform v1.2.9 on windows_386 provider registry.terraform.io/cloudflare/cloudflare v3.23.0

Affected resource(s)

terraform import cloudflare_notification_policy. / cloudflare_notification_policy

Terraform configuration files

resource "cloudflare_notification_policy" "example_name" {
  account_id = "<account_id>"
  alert_type = "health_check_status_notification"
  enabled    = true
  name       = "example_name"

  description = ""
  email_integration {
    id = "email_1@company.com"
  }
  email_integration {
    id = "email_2@company.com"
  }
  filters {
    health_check_id = [<healthcheck_id>]
    status          = ["Healthy", "Unhealthy"]
  }
}

Link to debug output

https://gist.github.com/Done203/14d59eba0dd291c7936ad611d107b9cc

Panic output

No response

Expected output

taken from terraform.tfstate:

{ "version": 4, "terraform_version": "1.2.9", "serial": 1, "lineage": "7171fcc1-5e00-ae83-140e-8c28c867eafb", "outputs": {}, "resources": [ { "mode": "managed", "type": "cloudflare_notification_policy", "name": "shop_COMPANY_com", "provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]", "instances": [ { "schema_version": 0, "attributes": { "account_id": "", "alert_type": "health_check_status_notification", "created": "2022-07-08T12:44:02Z", "description": "", "email_integration": [ { "id": "email_1@COMPANY.com", "name": "" } "email_integration": [ { "id": "email_2@COMPANY.com", "name": "" } ], "enabled": true, "filters": [ { "enabled": [], "event_source": [], "event_type": [], "health_check_id": [ "", "" ], "input_id": [], "limit": [], "new_health": [], "packets_per_second": [], "pool_id": [], "product": [], "protocol": [], "requests_per_second": [], "services": [], "slo": [], "status": [ "Healthy", "Unhealthy" ], "target_host": [], "target_zone_name": [], "zones": [] } ], "id": "CENSORED", "modified": "2022-07-13T06:46:31Z", "name": "COMPANY.com", "pagerduty_integration": [], "webhooks_integration": [] }, "sensitive_attributes": [], "private": "CENSORED" } ] } ] }

Actual output

... "email_integration": [ { "id": "email_2@COMPANY.com", "name": "" } ...

Steps to reproduce

  1. Create a notification policy through the cloudflare website and give it multiple email addresses
  2. Import the notification with terraform

Additional factoids

When looking at the debug logs, it appears that terraform correctly requests the notification policy with all details (including the multiple email addresses), though it only saves the very last email address in the state file.

Now if my configuration file is matching the current state of the policy, terraform would still make a change since it never saved all adresses.

References

mentioned in issue #1915 (Additional factoids)

glenwinters commented 1 year ago

I have a potentially related problem. The provider correctly created the notification policy with multiple emails but shows a diff on every plan afterward.

Code:

locals {
  ddos_notification_types = ["dos_attack_l7"]
  notification_email_addresses = ["email1@example.com", "email2@example.com"]
}

resource "cloudflare_notification_policy" "DDoS_notification" {
  for_each = toset(local.ddos_notification_types)

  account_id  = var.cloudflare_account_id
  name        = "Policy for DDoS notification alerts"
  description = "Notification policy to alert when account is under DDoS attack"
  enabled     = true
  alert_type  = each.value

  dynamic "email_integration" {
    for_each = local.notification_email_addresses
    content {
      id = email_integration.value
    }
  }
}

If I do a terraform state show, it does list both email blocks:

resource "cloudflare_notification_policy" "DDoS_notification" {
    account_id  = (sensitive)
    alert_type  = "dos_attack_l7"
    created     = "2022-12-15T00:02:26Z"
    description = "Notification policy to alert when account is under DDoS attack"
    enabled     = true
    id          = "SOME_ID"
    modified    = "2023-01-04T18:44:58Z"
    name        = "Policy for DDoS notification alerts"

    email_integration {
        id = "email1@example.com"
    }
    email_integration {
        id = "email2@example.com"
    }
}

However, a terraform plan tries to re-create the resource with the first one in the list added:

  # cloudflare_notification_policy.DDoS_notification["dos_attack_l7"] will be updated in-place
  ~ resource "cloudflare_notification_policy" "DDoS_notification" {
        id          = "SOME_ID"
        name        = "Policy for DDoS notification alerts"
        # (6 unchanged attributes hidden)

      + email_integration {
          + id = "email1@example.com"
        }
      - email_integration {
          - id = "email2@example.com" -> null
        }
      + email_integration {
          + id = "email2@example.com"
        }
    }
m-barthelemy commented 1 year ago

Same issue as https://github.com/cloudflare/terraform-provider-cloudflare/issues/1917#issuecomment-1371412548 here, every time the Terraform plan will want to re-create the resource (no matter how many times we actually apply)

hazmei commented 1 year ago

Seeing the same thing as well when we have multiple email_integration block.