PagerDuty / terraform-provider-pagerduty

Terraform PagerDuty provider
https://www.terraform.io/docs/providers/pagerduty/
Mozilla Public License 2.0
204 stars 212 forks source link

Don't break the current user rotation order when applying pagerduty_schedule ressource #585

Open harounben14 opened 2 years ago

harounben14 commented 2 years ago

Issue

We would like to preserve the current order of the users rotation for pagerduty schedule when applying the ressource. Before applying we have to reorder the list of users in the pagerduty_schedule ressource to get what we have in the current schedule. Is it possible to have a feature that allows us to say that we want to keep the current order of users and not replace it.

Terraform Version

Terraform v1.1.0

Affected Resource(s)

Pagerduty_schedule

Expected Behavior

Don't break the current user rotation from the API when applying

Feature proposition: keep_user_rotation

resource pagerduty_schedule schedules {
    layer {
        name                         = "Night's Watch"
        start                        = "2015-11-06T20:00:00-05:00"
        rotation_virtual_start       = "2015-11-06T20:00:00-05:00"
        rotation_turn_length_seconds = 604800 # 7 days
        users                        = [
            for user in pagerduty_user.users: user.id
            if contains([ for member in each.value.members: member.name ], user.name)
        ]
        **keep_user_rotation** = True
}

Provider version

required_providers {
  pagerduty = {
    source  = "pagerduty/pagerduty"
    version = "2.2.1"
  }
skoonin commented 1 year ago

I am seeing similar issues now... the apply is adding new users immediately to a schedule instead of at the handoff time. The UI includes a setting asking when to apply changes and the terraform does not offer that option.

NargiT commented 9 months ago

@imjaroiswebdev sorry for the ping but I believe this is quiet dangerous from a production point of view when a service responsibility is shared accros multiple teams.

This also break the overrides and people on call must verify if their override were not altered.

  required_providers {
    pagerduty = {
      source = "PagerDuty/pagerduty"
      version = "3.3.1"
    }
  }

Screenshot 2024-01-24 at 11-16-16 PagerDuty

image

This change is happening all the time even after 2 consecutive run.

resource "pagerduty_escalation_policy" "it_observability_onboarded" {
  name = "(Onboarded) it.observability"
  description = "Managed by Terraform, maintained by it.observability in GitHub."
  rule {
    escalation_delay_in_minutes = 240
    target {
      type = "schedule_reference"
      id = pagerduty_schedule.it_observability_default.id
    }
  }
  teams = [
    pagerduty_team.it_observability.id
  ]
}
Terraform will perform the following actions:

  # pagerduty_schedule.it_observability_default will be updated in-place
  ~ resource "pagerduty_schedule" "it_observability_default" {
        id             = "PL1JJWV"
        name           = "it.observability - Default On-Call Rotation"
      ~ teams          = [
          - "P3ZEHYL",
        ]
        # (3 unchanged attributes hidden)

        # (1 unchanged block hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
pagerduty_schedule.it_observability_default: Modifying... [id=PL1JJWV]
pagerduty_schedule.it_observability_default: Modifications complete after 1s [id=PL1JJWV]

I am confused, escalation policy is removed by terraform and then added back by PagerDuty which make schedules ignore existing overrides.

To fix it, I added to the schedule inside the escalation policy the same team, and I do not have this side effect.

resource "pagerduty_schedule" "it_observability_default" {
   ...
  teams = [pagerduty_team.it_observability.id]

But it's very odd and does not respect any of the gitops logic. I didn't test a use case where a TeamA helps TeamB and TeamA inject TeamASchedule inside TeamBEscalationPolicy.

NargiT commented 9 months ago

To reproduce Create 2 members, Mich and Joe in a team called "it.observability" Create a schedule Create an escalation policy with the previous schedule and link the escalation policy to it.observablity team Run terraform to create all these

Manually:

  1. With member Joe, override Mich slot.
  2. Run terraform again
  3. Overide is ignored
# This file is managed automatically
# https://support.pagerduty.com/docs/advanced-permissions
locals {
  it_observability_members = {
    "foo" = {
      id = pagerduty_user.foo.id
      role = "manager"
      oncall = true
    }
    "bar" = {
      id = pagerduty_user.bar.id
      role = "manager"
      oncall = true
    }
  }
}

resource "pagerduty_team" "it_observability" {
  name = "it.observability"
}

resource "pagerduty_team_membership" "members_of_it_observability" {
  team_id = pagerduty_team.it_observability.id
  for_each = local.it_observability_members
  user_id = each.value.id
  role = each.value.role
}

resource "pagerduty_schedule" "it_observability_default" {
  name = "it.observability - Default On-Call Rotation"
  description = "Created by Terraform"
  time_zone = "Europe/Berlin"
  layer {
    # every 7 day
    rotation_turn_length_seconds = 1209600
    # start from monday
    rotation_virtual_start = "2021-07-05T02:00:00+02:00"
    start = "2021-04-05T00:00:00Z"
    # uses terraform functions matchkeys()
    users = [for responder in local.it_observability_members: responder.id if responder.oncall]

    restriction {
      duration_seconds = 36000
      start_time_of_day = "08:30:00"
      type = "weekly_restriction"
      start_day_of_week = 1
    }
    restriction {
      duration_seconds = 36000
      start_time_of_day = "08:30:00"
      type = "weekly_restriction"
      start_day_of_week = 2
    }
    restriction {
      duration_seconds = 36000
      start_time_of_day = "08:30:00"
      type = "weekly_restriction"
      start_day_of_week = 3
    }
    restriction {
      duration_seconds = 36000
      start_time_of_day = "08:30:00"
      type = "weekly_restriction"
      start_day_of_week = 4
    }
    restriction {
      duration_seconds = 36000
      start_time_of_day = "08:30:00"
      type = "weekly_restriction"
      start_day_of_week = 5
    }
  }

  lifecycle {
    prevent_destroy = true
    # layer are created but not handled
    ignore_changes = [
      layer["start"],
      layer["rotation_turn_length_seconds"]
    ]
  }
}

resource "pagerduty_escalation_policy" "it_observability_onboarded" {
  name = "(Onboarded) it.observability"
  description = "Managed by Terraform, maintained by it.observability in GitHub."
  rule {
    escalation_delay_in_minutes = 240
    target {
      type = "schedule_reference"
      id = pagerduty_schedule.it_observability_default.id
    }
  }
  teams = [
    pagerduty_team.it_observability.id
  ]
}

for this simple example, adding teams = [pagerduty_team.it_observability.id] to Team schedule does not do any magic but it might have other effect on escalation policies that use multiple schedules from different teams.

TBH Teams have a very magic behaviors in general.

Side note on teams: When adding a external person to an escalation policy that belongs to a Team. The user is added automatically by pager duty to the Team to whom the escalation belongs. This is very strange from my point of view.

NargiT commented 9 months ago

Any news please ?