PD migrator: populate important OnCall notification rules (#5226)
# What this PR does Makes so that user notification rules from PD are migrated into both "default" and "important" OnCall user notification rules instead of just "default". Before this PR: <img width="631" alt="Screenshot 2024-11-04 at 16 54 28" src="https://github.com/user-attachments/assets/1d768736-e752-4c76-bb42-ec4b67260210"> After this PR: <img width="631" alt="Screenshot 2024-11-04 at 16 54 22" src="https://github.com/user-attachments/assets/9fdcf895-7eb7-4e7f-842e-87b3dd3fc5ab"> ## Which issue(s) this PR closes Related to [Slack thread](https://raintank-corp.slack.com/archives/C07HMCM59TK/p1730306579122409?thread_ts=1730303532.031559&cid=C07HMCM59TK) <!-- *Note*: If you want the issue to be auto-closed once the PR is merged, change "Related to" to "Closes" in the line above. If you have more than one GitHub issue that this PR closes, be sure to preface each issue link with a [closing keyword](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests#linking-a-pull-request-to-an-issue). This ensures that the issue(s) are auto-closed once the PR has been merged. --> ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes.
This commit is contained in:
parent
686ebbfb37
commit
4871b3a781
3 changed files with 108 additions and 16 deletions
|
|
@ -172,8 +172,9 @@ Configuration is done via environment variables passed to the docker container.
|
|||
|
||||
The tool is capable of migrating user notification rules from PagerDuty to Grafana OnCall.
|
||||
Notification rules from the `"When a high-urgency incident is assigned to me..."` section in PagerDuty settings are
|
||||
taken into account and will be migrated to default notification rules in Grafana OnCall for each user. Note that delays
|
||||
between notification rules may be slightly different in Grafana OnCall, see [Limitations](#limitations) for more info.
|
||||
taken into account and will be migrated to both default and important notification rules in Grafana OnCall
|
||||
for each user. Note that delays between notification rules may be slightly different in Grafana OnCall,
|
||||
see [Limitations](#limitations) for more info.
|
||||
|
||||
When running the migration, existing notification rules in Grafana OnCall will be deleted for every affected user.
|
||||
|
||||
|
|
|
|||
|
|
@ -27,21 +27,25 @@ def migrate_notification_rules(user: dict) -> None:
|
|||
rule for rule in user["notification_rules"] if rule["urgency"] == "high"
|
||||
]
|
||||
|
||||
oncall_rules = transform_notification_rules(
|
||||
notification_rules, user["oncall_user"]["id"]
|
||||
)
|
||||
for important in (False, True):
|
||||
oncall_rules = transform_notification_rules(
|
||||
notification_rules, user["oncall_user"]["id"], important
|
||||
)
|
||||
|
||||
for rule in oncall_rules:
|
||||
OnCallAPIClient.create("personal_notification_rules", rule)
|
||||
for rule in oncall_rules:
|
||||
OnCallAPIClient.create("personal_notification_rules", rule)
|
||||
|
||||
if oncall_rules:
|
||||
# delete old notification rules if any new rules were created
|
||||
for rule in user["oncall_user"]["notification_rules"]:
|
||||
OnCallAPIClient.delete("personal_notification_rules/{}".format(rule["id"]))
|
||||
if oncall_rules:
|
||||
# delete old notification rules if any new rules were created
|
||||
for rule in user["oncall_user"]["notification_rules"]:
|
||||
if rule["important"] == important:
|
||||
OnCallAPIClient.delete(
|
||||
"personal_notification_rules/{}".format(rule["id"])
|
||||
)
|
||||
|
||||
|
||||
def transform_notification_rules(
|
||||
notification_rules: list[dict], user_id: str
|
||||
notification_rules: list[dict], user_id: str, important: bool
|
||||
) -> list[dict]:
|
||||
"""
|
||||
Transform PagerDuty user notification rules to Grafana OnCall personal notification rules.
|
||||
|
|
@ -58,7 +62,9 @@ def transform_notification_rules(
|
|||
previous_delay = notification_rules[idx - 1]["start_delay_in_minutes"]
|
||||
delay -= previous_delay
|
||||
|
||||
oncall_notification_rules += transform_notification_rule(rule, delay, user_id)
|
||||
oncall_notification_rules += transform_notification_rule(
|
||||
rule, delay, user_id, important
|
||||
)
|
||||
|
||||
oncall_notification_rules = remove_duplicate_rules_between_waits(
|
||||
oncall_notification_rules
|
||||
|
|
@ -68,12 +74,12 @@ def transform_notification_rules(
|
|||
|
||||
|
||||
def transform_notification_rule(
|
||||
notification_rule: dict, delay: int, user_id: str
|
||||
notification_rule: dict, delay: int, user_id: str, important: bool
|
||||
) -> list[dict]:
|
||||
contact_method_type = notification_rule["contact_method"]["type"]
|
||||
oncall_type = PAGERDUTY_TO_ONCALL_CONTACT_METHOD_MAP[contact_method_type]
|
||||
|
||||
notify_rule = {"user_id": user_id, "type": oncall_type, "important": False}
|
||||
notify_rule = {"user_id": user_id, "type": oncall_type, "important": important}
|
||||
|
||||
if not delay:
|
||||
return [notify_rule]
|
||||
|
|
@ -82,6 +88,6 @@ def transform_notification_rule(
|
|||
"user_id": user_id,
|
||||
"type": "wait",
|
||||
"duration": transform_wait_delay(delay),
|
||||
"important": "False",
|
||||
"important": important,
|
||||
}
|
||||
return [wait_rule, notify_rule]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
from unittest.mock import call, patch
|
||||
|
||||
from lib.oncall.api_client import OnCallAPIClient
|
||||
from lib.pagerduty.resources.notification_rules import migrate_notification_rules
|
||||
|
||||
|
||||
@patch.object(OnCallAPIClient, "delete")
|
||||
@patch.object(OnCallAPIClient, "create")
|
||||
def test_migrate_notification_rules(api_client_create_mock, api_client_delete_mock):
|
||||
migrate_notification_rules(
|
||||
{
|
||||
"notification_rules": [
|
||||
{
|
||||
"contact_method": {"type": "sms_contact_method"},
|
||||
"start_delay_in_minutes": 0,
|
||||
"urgency": "high",
|
||||
},
|
||||
{
|
||||
"contact_method": {"type": "push_notification_contact_method"},
|
||||
"start_delay_in_minutes": 5,
|
||||
"urgency": "high",
|
||||
},
|
||||
],
|
||||
"oncall_user": {
|
||||
"id": "EXISTING_USER_ID",
|
||||
"notification_rules": [
|
||||
{"id": "EXISTING_RULE_ID_1", "important": False},
|
||||
{"id": "EXISTING_RULE_ID_2", "important": True},
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
assert api_client_create_mock.call_args_list == [
|
||||
call(
|
||||
"personal_notification_rules",
|
||||
{
|
||||
"user_id": "EXISTING_USER_ID",
|
||||
"type": "notify_by_sms",
|
||||
"important": False,
|
||||
},
|
||||
),
|
||||
call(
|
||||
"personal_notification_rules",
|
||||
{
|
||||
"user_id": "EXISTING_USER_ID",
|
||||
"type": "wait",
|
||||
"duration": 300,
|
||||
"important": False,
|
||||
},
|
||||
),
|
||||
call(
|
||||
"personal_notification_rules",
|
||||
{
|
||||
"user_id": "EXISTING_USER_ID",
|
||||
"type": "notify_by_mobile_app",
|
||||
"important": False,
|
||||
},
|
||||
),
|
||||
call(
|
||||
"personal_notification_rules",
|
||||
{"user_id": "EXISTING_USER_ID", "type": "notify_by_sms", "important": True},
|
||||
),
|
||||
call(
|
||||
"personal_notification_rules",
|
||||
{
|
||||
"user_id": "EXISTING_USER_ID",
|
||||
"type": "wait",
|
||||
"duration": 300,
|
||||
"important": True,
|
||||
},
|
||||
),
|
||||
call(
|
||||
"personal_notification_rules",
|
||||
{
|
||||
"user_id": "EXISTING_USER_ID",
|
||||
"type": "notify_by_mobile_app",
|
||||
"important": True,
|
||||
},
|
||||
),
|
||||
]
|
||||
assert api_client_delete_mock.call_args_list == [
|
||||
call("personal_notification_rules/EXISTING_RULE_ID_1"),
|
||||
call("personal_notification_rules/EXISTING_RULE_ID_2"),
|
||||
]
|
||||
Loading…
Add table
Reference in a new issue