diff --git a/engine/apps/api/tests/test_labels.py b/engine/apps/api/tests/test_labels.py index 2f7e0961..a4c314bc 100644 --- a/engine/apps/api/tests/test_labels.py +++ b/engine/apps/api/tests/test_labels.py @@ -192,7 +192,7 @@ def test_labels_feature_false( make_alert_receive_channel, settings, ): - setattr(settings, "FEATURE_LABELS_ENABLED", False) + setattr(settings, "FEATURE_LABELS_ENABLED_FOR_ALL", False) organization, user, token = make_organization_and_user_with_plugin_token() client = APIClient() diff --git a/engine/apps/labels/tests/test_labels.py b/engine/apps/labels/tests/test_labels.py index 78b3790a..9d32583a 100644 --- a/engine/apps/labels/tests/test_labels.py +++ b/engine/apps/labels/tests/test_labels.py @@ -2,7 +2,27 @@ import pytest from apps.alerts.models import AlertReceiveChannel from apps.labels.models import AlertReceiveChannelAssociatedLabel, AssociatedLabel, LabelValueCache -from apps.labels.utils import get_associating_label_model +from apps.labels.utils import get_associating_label_model, is_labels_feature_enabled + + +@pytest.mark.django_db +def test_labels_feature_flag(mock_is_labels_feature_enabled_for_org, make_organization, settings): + organization = make_organization() + # returns True if feature flag is enabled + assert settings.FEATURE_LABELS_ENABLED_FOR_ALL + assert organization.id not in settings.FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS + assert is_labels_feature_enabled(organization) + + mock_is_labels_feature_enabled_for_org(organization.org_id) + # returns True if feature flag is disabled and organization is in the feature list + assert not settings.FEATURE_LABELS_ENABLED_FOR_ALL + assert organization.org_id in settings.FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS + assert is_labels_feature_enabled(organization) + + mock_is_labels_feature_enabled_for_org(12345) + # returns False if feature flag is disabled and organization is not in the feature list + assert organization.org_id not in settings.FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS + assert not is_labels_feature_enabled(organization) @pytest.mark.django_db diff --git a/engine/apps/labels/utils.py b/engine/apps/labels/utils.py index b4acbf23..56b0a1ad 100644 --- a/engine/apps/labels/utils.py +++ b/engine/apps/labels/utils.py @@ -43,12 +43,18 @@ def get_associating_label_model(obj_model_name: str) -> typing.Type["AssociatedL def is_labels_feature_enabled(organization) -> bool: - # check FEATURE_LABELS_ENABLED in settings - # checking labels feature flag per organization will be added later - + """ + Checks if labels feature enabled for all organizations (FEATURE_LABELS_ENABLED_FOR_ALL). + If not, checks if current organization's grafana org_id is in the list of organizations labels feature enabled for + (FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS) + """ logger.info( "is_labels_feature_enabled: " - f"FEATURE_LABELS_ENABLED={settings.FEATURE_LABELS_ENABLED} " + f"FEATURE_LABELS_ENABLED_FOR_ALL={settings.FEATURE_LABELS_ENABLED_FOR_ALL}, " + f"organization in FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS=" + f"{organization.id in settings.FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS}, " f"organization={organization.id}" ) - return settings.FEATURE_LABELS_ENABLED + if not settings.FEATURE_LABELS_ENABLED_FOR_ALL: + return organization.org_id in settings.FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS + return settings.FEATURE_LABELS_ENABLED_FOR_ALL diff --git a/engine/common/utils.py b/engine/common/utils.py index e70f7ab2..c8287f6d 100644 --- a/engine/common/utils.py +++ b/engine/common/utils.py @@ -1,5 +1,6 @@ import functools import html +import json import os import random import re @@ -112,6 +113,14 @@ def getenv_integer(variable_name: str, default: int) -> int: return default +def getenv_list(variable_name: str, default: list) -> list: + value = os.environ.get(variable_name) + if value is None: + return default + + return json.loads(value) + + def batch_queryset(qs, batch_size=1000): qs_count = qs.count() for start in range(0, qs_count, batch_size): diff --git a/engine/conftest.py b/engine/conftest.py index 59ab1f33..e7acc97e 100644 --- a/engine/conftest.py +++ b/engine/conftest.py @@ -180,7 +180,16 @@ def mock_apply_async(monkeypatch): @pytest.fixture(autouse=True) def mock_is_labels_feature_enabled(settings): - setattr(settings, "FEATURE_LABELS_ENABLED", True) + setattr(settings, "FEATURE_LABELS_ENABLED_FOR_ALL", True) + + +@pytest.fixture +def mock_is_labels_feature_enabled_for_org(settings): + def _mock_is_labels_feature_enabled_for_org(org_id): + setattr(settings, "FEATURE_LABELS_ENABLED_FOR_ALL", False) + setattr(settings, "FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS", [org_id]) + + return _mock_is_labels_feature_enabled_for_org @pytest.fixture diff --git a/engine/settings/base.py b/engine/settings/base.py index 260c4f96..100ff125 100644 --- a/engine/settings/base.py +++ b/engine/settings/base.py @@ -7,7 +7,7 @@ from random import randrange from celery.schedules import crontab from firebase_admin import credentials, initialize_app -from common.utils import getenv_boolean, getenv_integer +from common.utils import getenv_boolean, getenv_integer, getenv_list VERSION = "dev-oss" SEND_ANONYMOUS_USAGE_STATS = getenv_boolean("SEND_ANONYMOUS_USAGE_STATS", default=True) @@ -66,9 +66,12 @@ FEATURE_MULTIREGION_ENABLED = getenv_boolean("FEATURE_MULTIREGION_ENABLED", defa FEATURE_INBOUND_EMAIL_ENABLED = getenv_boolean("FEATURE_INBOUND_EMAIL_ENABLED", default=True) FEATURE_PROMETHEUS_EXPORTER_ENABLED = getenv_boolean("FEATURE_PROMETHEUS_EXPORTER_ENABLED", default=False) FEATURE_GRAFANA_ALERTING_V2_ENABLED = getenv_boolean("FEATURE_GRAFANA_ALERTING_V2_ENABLED", default=False) -FEATURE_LABELS_ENABLED = getenv_boolean("FEATURE_LABELS_ENABLED", default=False) GRAFANA_CLOUD_ONCALL_HEARTBEAT_ENABLED = getenv_boolean("GRAFANA_CLOUD_ONCALL_HEARTBEAT_ENABLED", default=True) GRAFANA_CLOUD_NOTIFICATIONS_ENABLED = getenv_boolean("GRAFANA_CLOUD_NOTIFICATIONS_ENABLED", default=True) +# Enable labels feature fo all organizations. This flag overrides FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS +FEATURE_LABELS_ENABLED_FOR_ALL = getenv_boolean("FEATURE_LABELS_ENABLED_FOR_ALL", default=False) +# Enable labels feature for organizations from the list. Use Grafana org_id, not OnCall id, for this flag +FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS = getenv_list("FEATURE_LABELS_ENABLED_FOR_GRAFANA_ORGS", default=list()) TWILIO_API_KEY_SID = os.environ.get("TWILIO_API_KEY_SID") TWILIO_API_KEY_SECRET = os.environ.get("TWILIO_API_KEY_SECRET")