Add org setting to configure direct paging preferred policy (#5189)

For context:
https://raintank-corp.slack.com/archives/C01DHQ6LH1S/p1729267368387299?thread_ts=1729185737.051889&cid=C01DHQ6LH1S

Next steps:
- use the setting in frontend (add participants, add responders) and
mobile_app
  - expose setting in org settings page
This commit is contained in:
Matias Bordese 2024-10-24 13:52:40 -03:00 committed by GitHub
parent 58d73742ea
commit 9a929e2459
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 54 additions and 8 deletions

View file

@ -38,6 +38,7 @@ class OrganizationSerializer(EagerLoadingMixin, serializers.ModelSerializer):
"slack_channel",
"rbac_enabled",
"grafana_incident_enabled",
"direct_paging_prefer_important_policy",
]
read_only_fields = [
"stack_slug",

View file

@ -44,6 +44,7 @@ def test_get_organization(
"slack_channel": None,
"rbac_enabled": organization.is_rbac_permissions_enabled,
"grafana_incident_enabled": organization.is_grafana_incident_enabled,
"direct_paging_prefer_important_policy": organization.direct_paging_prefer_important_policy,
"is_resolution_note_required": False,
"env_status": mock_env_status,
"banner": mock_banner,
@ -75,7 +76,10 @@ def test_update_organization_settings(make_organization_and_user_with_plugin_tok
client = APIClient()
url = reverse("api-internal:api-organization")
data = {"is_resolution_note_required": True}
data = {
"is_resolution_note_required": True,
"direct_paging_prefer_important_policy": True,
}
assert organization.is_resolution_note_required is False
@ -83,6 +87,7 @@ def test_update_organization_settings(make_organization_and_user_with_plugin_tok
assert response.status_code == status.HTTP_200_OK
organization.refresh_from_db()
assert organization.is_resolution_note_required is True
assert organization.direct_paging_prefer_important_policy is True
@pytest.mark.django_db

View file

@ -373,7 +373,10 @@ class OnPagingUserChange(scenario_step.ScenarioStep):
# user is currently on-call
error_msg = None
try:
updated_payload = add_or_update_item(payload, DataKey.USERS, selected_user.pk, Policy.DEFAULT)
policy = Policy.DEFAULT
if selected_user.organization.direct_paging_prefer_important_policy:
policy = Policy.IMPORTANT
updated_payload = add_or_update_item(payload, DataKey.USERS, selected_user.pk, policy)
except ValueError:
updated_payload = payload
error_msg = "Cannot add user, maximum responders exceeded"
@ -449,7 +452,10 @@ class OnPagingConfirmUserChange(scenario_step.ScenarioStep):
error_msg = None
try:
updated_payload = add_or_update_item(previous_view_payload, DataKey.USERS, selected_user.pk, Policy.DEFAULT)
policy = Policy.DEFAULT
if selected_user.organization.direct_paging_prefer_important_policy:
policy = Policy.IMPORTANT
updated_payload = add_or_update_item(previous_view_payload, DataKey.USERS, selected_user.pk, policy)
except ValueError:
updated_payload = payload
error_msg = "Cannot add user, maximum responders exceeded"

View file

@ -162,9 +162,15 @@ def test_initial_unauthorized(make_organization_and_user_with_slack_identities,
)
@pytest.mark.parametrize("use_important_policy", (False, True))
@pytest.mark.django_db
def test_add_user_no_warning(make_organization_and_user_with_slack_identities, make_schedule, make_on_call_shift):
def test_add_user_no_warning(
make_organization_and_user_with_slack_identities, make_schedule, make_on_call_shift, use_important_policy
):
organization, user, slack_team_identity, slack_user_identity = make_organization_and_user_with_slack_identities()
if use_important_policy:
organization.direct_paging_prefer_important_policy = use_important_policy
organization.save()
# set up schedule: user is on call
schedule = make_schedule(
organization,
@ -195,7 +201,10 @@ def test_add_user_no_warning(make_organization_and_user_with_slack_identities, m
step.process_scenario(slack_user_identity, slack_team_identity, payload)
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
assert metadata[DataKey.USERS] == {str(user.pk): Policy.DEFAULT}
if use_important_policy:
assert metadata[DataKey.USERS] == {str(user.pk): Policy.IMPORTANT}
else:
assert metadata[DataKey.USERS] == {str(user.pk): Policy.DEFAULT}
@pytest.mark.django_db
@ -269,15 +278,20 @@ def test_add_user_raise_warning(make_organization_and_user_with_slack_identities
assert metadata[DataKey.USERS] == {}
@pytest.mark.parametrize("use_important_policy", (False, True))
@pytest.mark.django_db
def test_change_user_policy(make_organization_and_user_with_slack_identities):
def test_change_user_policy(make_organization_and_user_with_slack_identities, use_important_policy):
organization, user, slack_team_identity, slack_user_identity = make_organization_and_user_with_slack_identities()
if use_important_policy:
organization.direct_paging_prefer_important_policy = use_important_policy
organization.save()
value = Policy.IMPORTANT if not use_important_policy else Policy.DEFAULT
payload = make_paging_view_slack_payload(
selected_org=organization,
actions=[
{
"selected_option": {
"value": make_value({"action": Policy.IMPORTANT, "key": DataKey.USERS, "id": user.pk}, organization)
"value": make_value({"action": value, "key": DataKey.USERS, "id": user.pk}, organization)
}
}
],
@ -288,7 +302,7 @@ def test_change_user_policy(make_organization_and_user_with_slack_identities):
step.process_scenario(slack_user_identity, slack_team_identity, payload)
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
assert metadata[DataKey.USERS] == {str(user.pk): Policy.IMPORTANT}
assert metadata[DataKey.USERS] == {str(user.pk): value}
@pytest.mark.django_db

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.15 on 2024-10-18 16:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('user_management', '0023_organization_is_grafana_irm_enabled'),
]
operations = [
migrations.AddField(
model_name='organization',
name='direct_paging_prefer_important_policy',
field=models.BooleanField(default=False, null=True),
),
]

View file

@ -259,6 +259,8 @@ class Organization(MaintainableObject):
alert_group_table_columns: list[AlertGroupTableColumn] | None = JSONField(default=None, null=True)
grafana_incident_backend_url = models.CharField(max_length=300, null=True, default=None)
direct_paging_prefer_important_policy = models.BooleanField(default=False, null=True)
class Meta:
unique_together = ("stack_id", "org_id")