# What this PR does Adds Service and Business Service migration to the Pager Duty Migrator. To test, in addition to the OnCall configs, you need to crate a Grafana Service Account with `Admin` permission and generate a token. You will set `GRAFANA_SERVICE_ACCOUNT_URL`, per the README, to `https://<namespace>:<token>@<server>` The namespace is the stack id, in the format of `stacks-<stack id>` Service migration is configurable, filterable, and idempotent. ## Which issue(s) this PR closes Related to [issue link here] <!-- *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) - [ ] 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. --------- Co-authored-by: Joey Orlando <joey.orlando@grafana.com> Co-authored-by: GitHub Actions <actions@github.com> Co-authored-by: grafana-irm-app[bot] <165293418+grafana-irm-app[bot]@users.noreply.github.com> Co-authored-by: Joey Orlando <joseph.t.orlando@gmail.com>
66 lines
1.9 KiB
Python
66 lines
1.9 KiB
Python
import requests
|
|
|
|
from lib.base_config import ONCALL_API_TOKEN, ONCALL_API_URL
|
|
from lib.network import api_call as _api_call
|
|
|
|
|
|
class OnCallAPIClient:
|
|
@classmethod
|
|
def api_call(cls, method: str, path: str, **kwargs) -> requests.Response:
|
|
return _api_call(
|
|
method,
|
|
ONCALL_API_URL,
|
|
path,
|
|
headers={"Authorization": ONCALL_API_TOKEN},
|
|
**kwargs,
|
|
)
|
|
|
|
@classmethod
|
|
def list_all(cls, path: str) -> list[dict]:
|
|
response = cls.api_call("get", path)
|
|
|
|
data = response.json()
|
|
results = data["results"]
|
|
|
|
while data["next"]:
|
|
response = cls.api_call("get", data["next"])
|
|
|
|
data = response.json()
|
|
results += data["results"]
|
|
|
|
return results
|
|
|
|
@classmethod
|
|
def create(cls, path: str, payload: dict) -> dict:
|
|
response = cls.api_call("post", path, json=payload)
|
|
return response.json()
|
|
|
|
@classmethod
|
|
def delete(cls, path: str) -> None:
|
|
try:
|
|
cls.api_call("delete", path)
|
|
except requests.exceptions.HTTPError as e:
|
|
# ignore 404s on delete so deleting resources manually while running the script doesn't break it
|
|
if e.response.status_code != 404:
|
|
raise
|
|
|
|
@classmethod
|
|
def update(cls, path: str, payload: dict) -> dict:
|
|
response = cls.api_call("put", path, json=payload)
|
|
return response.json()
|
|
|
|
@classmethod
|
|
def list_users_with_notification_rules(cls):
|
|
oncall_users = cls.list_all("users")
|
|
oncall_notification_rules = cls.list_all(
|
|
"personal_notification_rules/?important=false"
|
|
)
|
|
|
|
for user in oncall_users:
|
|
user["notification_rules"] = [
|
|
rule
|
|
for rule in oncall_notification_rules
|
|
if rule["user_id"] == user["id"]
|
|
]
|
|
|
|
return oncall_users
|