From 531673d06b640cc7bbfda265ebdee6753f1d6795 Mon Sep 17 00:00:00 2001 From: Fabricio Aguiar Date: Thu, 18 Dec 2025 14:53:47 -0300 Subject: [PATCH] move to platform flags Signed-off-by: Fabricio Aguiar (cherry picked from commit 84e065aab03d7bb7c3638eb6a40f165ada7b78fe) Signed-off-by: Fabricio Aguiar Signed-off-by: Fabricio Aguiar Signed-off-by: Fabricio Aguiar Signed-off-by: Fabricio Aguiar rh-pre-commit.version: 2.3.2 rh-pre-commit.check-secrets: ENABLED --- src/aap_eda/settings/core.py | 8 --- tests/conftest.py | 8 +++ tests/integration/api/test_feature_flags.py | 4 +- tests/integration/test_advisory_lock.py | 22 +++++++- tests/unit/test_features.py | 61 ++++++++++----------- 5 files changed, 57 insertions(+), 46 deletions(-) diff --git a/src/aap_eda/settings/core.py b/src/aap_eda/settings/core.py index 899be5f5d..8e1b5ee3d 100644 --- a/src/aap_eda/settings/core.py +++ b/src/aap_eda/settings/core.py @@ -18,14 +18,6 @@ # See https://cfpb.github.io/django-flags/ ANALYTICS_FEATURE_FLAG_NAME = "FEATURE_EDA_ANALYTICS_ENABLED" -FLAGS = { - ANALYTICS_FEATURE_FLAG_NAME: [ - { - "condition": "boolean", - "value": False, - }, - ], -} INSTALLED_APPS = [ "daphne", diff --git a/tests/conftest.py b/tests/conftest.py index 1024f4600..6b39fc256 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,6 +15,9 @@ import logging import pytest +from ansible_base.feature_flags.utils import ( + create_initial_data as seed_feature_flags, +) from django.conf import settings from aap_eda.core import enums, models @@ -88,3 +91,8 @@ def aap_credential_type(preseed_credential_types): return models.CredentialType.objects.get( name=enums.DefaultCredentialType.AAP ) + + +@pytest.fixture +def preseed_feature_flags(): + seed_feature_flags() diff --git a/tests/integration/api/test_feature_flags.py b/tests/integration/api/test_feature_flags.py index 4a34ba25e..77366fd41 100644 --- a/tests/integration/api/test_feature_flags.py +++ b/tests/integration/api/test_feature_flags.py @@ -11,7 +11,7 @@ @pytest.mark.django_db -def test_feature_flags_list_endpoint(admin_client): +def test_feature_flags_list_endpoint(admin_client, preseed_feature_flags): response = admin_client.get(f"{api_url_v1}/feature_flags_state/") assert response.status_code == status.HTTP_200_OK, response.data # Validates expected default feature flags @@ -25,6 +25,6 @@ def test_feature_flags_list_endpoint(admin_client): def test_feature_flags_toggle(flag_value): flag_name = "FEATURE_EDA_ANALYTICS_ENABLED" setattr(settings, flag_name, flag_value) - AAPFlag.objects.all().delete() + AAPFlag.objects.filter(name=flag_name).delete() seed_feature_flags() assert flag_state(flag_name) is flag_value diff --git a/tests/integration/test_advisory_lock.py b/tests/integration/test_advisory_lock.py index 9c6c30308..aa5be6bf7 100644 --- a/tests/integration/test_advisory_lock.py +++ b/tests/integration/test_advisory_lock.py @@ -1,5 +1,6 @@ import time from concurrent.futures import ThreadPoolExecutor, wait +from contextlib import ExitStack from threading import Lock from unittest import mock @@ -64,9 +65,24 @@ def _wrapper_call(shared_list): importlib.reload(module) - with mock.patch( - f"{module_data['module_path']}.{module_data['fn_mock']}", - ) as fn_mock: + patches = [ + mock.patch( + f"{module_data['module_path']}.{module_data['fn_mock']}", + ), + ] + + # Add mock for get_insights_tracking_state for analytics tests + if module_data["fn_call"] == "gather_analytics": + patches.append( + mock.patch( + "aap_eda.analytics.utils.get_insights_tracking_state", + return_value=True, + ) + ) + + with ExitStack() as stack: + mocks = [stack.enter_context(patch) for patch in patches] + fn_mock = mocks[0] def record_call(void=None): time.sleep(1) diff --git a/tests/unit/test_features.py b/tests/unit/test_features.py index 30a5ebc72..c435f5f87 100644 --- a/tests/unit/test_features.py +++ b/tests/unit/test_features.py @@ -15,6 +15,10 @@ """Unit tests for feature flags functionality.""" import pytest +from ansible_base.feature_flags.models import AAPFlag +from ansible_base.feature_flags.utils import ( + create_initial_data as seed_feature_flags, +) from aap_eda.settings import features from aap_eda.settings.features import _get_feature @@ -29,11 +33,9 @@ def clear_feature_cache(): @pytest.mark.django_db def test_get_feature_flag(settings): """Test getting feature flag values.""" - settings.FLAGS = { - settings.ANALYTICS_FEATURE_FLAG_NAME: [ - {"condition": "boolean", "value": False} - ], - } + AAPFlag.objects.filter(name=settings.ANALYTICS_FEATURE_FLAG_NAME).delete() + setattr(settings, settings.ANALYTICS_FEATURE_FLAG_NAME, False) + seed_feature_flags() assert features.ANALYTICS is False @@ -41,48 +43,41 @@ def test_get_feature_flag(settings): @pytest.mark.django_db def test_feature_flag_caching(settings): """Test that feature flag values are properly cached.""" - settings.FLAGS = { - settings.ANALYTICS_FEATURE_FLAG_NAME: [ - {"condition": "boolean", "value": True} - ] - } + AAPFlag.objects.filter(name=settings.ANALYTICS_FEATURE_FLAG_NAME).delete() + setattr(settings, settings.ANALYTICS_FEATURE_FLAG_NAME, True) + seed_feature_flags() # Clear cache to ensure settings are picked up _get_feature.cache_clear() # First access - should cache the value - first_result = features.ANALYTICS + features.ANALYTICS - # Second access should return the same cached value - second_result = features.ANALYTICS - assert first_result == second_result - - # The exact value may depend on flag implementation - assert isinstance(first_result, bool) + # Change the underlying flag value + setattr(settings, settings.ANALYTICS_FEATURE_FLAG_NAME, False) + seed_feature_flags() + # Should still get the cached value + assert features.ANALYTICS is True @pytest.mark.django_db def test_cache_invalidation(settings): """Test that cache invalidation works as expected.""" - # Set initial flag value - settings.FLAGS = { - settings.ANALYTICS_FEATURE_FLAG_NAME: [ - {"condition": "boolean", "value": True} - ] - } - _get_feature.cache_clear() + AAPFlag.objects.filter(name=settings.ANALYTICS_FEATURE_FLAG_NAME).delete() + setattr(settings, settings.ANALYTICS_FEATURE_FLAG_NAME, True) + seed_feature_flags() - # Get initial value - initial_value = features.ANALYTICS + # Populate cache + assert features.ANALYTICS is True - # Clear cache manually + # Change the flag value and clear cache + setattr(settings, settings.ANALYTICS_FEATURE_FLAG_NAME, False) + seed_feature_flags() _get_feature.cache_clear() - # Get value again - should be consistent - after_cache_clear = features.ANALYTICS - - # The cache clearing should work without errors - assert isinstance(initial_value, bool) - assert isinstance(after_cache_clear, bool) + # Feature should remain true. + # If runtime toggle, we should only be able to + # update the value after toggling it via the platform gateway + assert features.ANALYTICS is True @pytest.mark.django_db