Move to Runtime Platform Flags (#16148)

* move to platform flags

Signed-off-by: Fabricio Aguiar <fabricio.aguiar@gmail.com>

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED

* SonarCloud analyzes files without coverage data.
This commit is contained in:
Fabricio Aguiar
2025-11-25 15:20:04 +00:00
committed by GitHub
parent e03beb4d54
commit 2b2f2b73ac
10 changed files with 102 additions and 68 deletions

View File

@@ -1,36 +1,30 @@
import pytest
from django.test import override_settings
from flags.state import get_flags, flag_state
from ansible_base.feature_flags.models import AAPFlag
from ansible_base.feature_flags.utils import create_initial_data as seed_feature_flags
from django.conf import settings
from awx.main.models import User
@override_settings(FLAGS={})
@pytest.mark.django_db
def test_feature_flags_list_endpoint(get):
bob = User.objects.create(username='bob', password='test_user', is_superuser=False)
url = "/api/v2/feature_flags_state/"
bob = User.objects.create(username='bob', password='test_user', is_superuser=True)
url = "/api/v2/feature_flags/states/"
response = get(url, user=bob, expect=200)
assert len(response.data) == 0
assert len(get_flags()) > 0
assert len(response.data["results"]) == len(get_flags())
@override_settings(
FLAGS={
"FEATURE_SOME_PLATFORM_FLAG_ENABLED": [
{"condition": "boolean", "value": False},
{"condition": "before date", "value": "2022-06-01T12:00Z"},
],
"FEATURE_SOME_PLATFORM_FLAG_FOO_ENABLED": [
{"condition": "boolean", "value": True},
],
}
)
@pytest.mark.django_db
def test_feature_flags_list_endpoint_override(get):
bob = User.objects.create(username='bob', password='test_user', is_superuser=False)
@pytest.mark.parametrize('flag_val', (True, False))
def test_feature_flags_list_endpoint_override(get, flag_val):
bob = User.objects.create(username='bob', password='test_user', is_superuser=True)
url = "/api/v2/feature_flags_state/"
AAPFlag.objects.all().delete()
flag_name = "FEATURE_DISPATCHERD_ENABLED"
setattr(settings, flag_name, flag_val)
seed_feature_flags()
url = "/api/v2/feature_flags/states/"
response = get(url, user=bob, expect=200)
assert len(response.data) == 2
assert response.data["FEATURE_SOME_PLATFORM_FLAG_ENABLED"] is False
assert response.data["FEATURE_SOME_PLATFORM_FLAG_FOO_ENABLED"] is True
assert len(response.data["results"]) == 6
assert flag_state(flag_name) == flag_val

View File

@@ -5,11 +5,8 @@ import signal
import time
import yaml
from unittest import mock
from copy import deepcopy
from flags.state import disable_flag, enable_flag
from django.utils.timezone import now as tz_now
from django.conf import settings
from django.test.utils import override_settings
import pytest
from awx.main.models import Job, WorkflowJob, Instance
@@ -302,13 +299,14 @@ class TestTaskDispatcher:
assert str(result) == "No module named 'awx.foo'" # noqa
@pytest.mark.django_db
class TestTaskPublisher:
@pytest.fixture(autouse=True)
def _disable_dispatcherd(self):
ffs = deepcopy(settings.FLAGS)
ffs['FEATURE_DISPATCHERD_ENABLED'][0]['value'] = False
with override_settings(FLAGS=ffs):
yield
flag_name = "FEATURE_DISPATCHERD_ENABLED"
disable_flag(flag_name)
yield
enable_flag(flag_name)
def test_function_callable(self):
assert add(2, 2) == 4

View File

@@ -9,6 +9,9 @@ LOCAL_SETTINGS = (
'DEBUG',
'NAMED_URL_GRAPH',
'DISPATCHER_MOCK_PUBLISH',
# Platform flags are managed by the platform flags system and have environment-specific defaults
'FEATURE_DISPATCHERD_ENABLED',
'FEATURE_INDIRECT_NODE_COUNTING_ENABLED',
)
@@ -28,7 +31,7 @@ def test_default_settings():
continue
default_val = getattr(settings.default_settings, k, None)
snapshot_val = settings.DEFAULTS_SNAPSHOT[k]
assert default_val == snapshot_val, f'Setting for {k} does not match shapshot:\nsnapshot: {snapshot_val}\ndefault: {default_val}'
assert default_val == snapshot_val, f'Setting for {k} does not match snapshot:\nsnapshot: {snapshot_val}\ndefault: {default_val}'
def test_django_conf_settings_is_awx_settings():
@@ -69,3 +72,27 @@ def test_merge_application_name():
result = merge_application_name(settings)["DATABASES__default__OPTIONS__application_name"]
assert result.startswith("awx-")
assert "test-cluster" in result
def test_development_defaults_feature_flags(monkeypatch):
"""Ensure that development_defaults.py sets the correct feature flags."""
monkeypatch.setenv('AWX_MODE', 'development')
# Import the development_defaults module directly to trigger coverage of the new lines
import importlib.util
import os
spec = importlib.util.spec_from_file_location("development_defaults", os.path.join(os.path.dirname(__file__), "../../../settings/development_defaults.py"))
development_defaults = importlib.util.module_from_spec(spec)
spec.loader.exec_module(development_defaults)
# Also import through the development settings to ensure both paths are tested
from awx.settings.development import FEATURE_INDIRECT_NODE_COUNTING_ENABLED, FEATURE_DISPATCHERD_ENABLED
# Verify the feature flags are set correctly in both the module and settings
assert hasattr(development_defaults, 'FEATURE_INDIRECT_NODE_COUNTING_ENABLED')
assert development_defaults.FEATURE_INDIRECT_NODE_COUNTING_ENABLED is True
assert hasattr(development_defaults, 'FEATURE_DISPATCHERD_ENABLED')
assert development_defaults.FEATURE_DISPATCHERD_ENABLED is True
assert FEATURE_INDIRECT_NODE_COUNTING_ENABLED is True
assert FEATURE_DISPATCHERD_ENABLED is True

View File

@@ -461,6 +461,7 @@ class TestExtraVarSanitation(TestJobExecution):
class TestGenericRun:
@pytest.mark.django_db(reset_sequences=True)
def test_generic_failure(self, patch_Job, execution_environment, mock_me, mock_create_partition):
job = Job(status='running', inventory=Inventory(), project=Project(local_path='/projects/_23_foo'))
job.websocket_emit_status = mock.Mock()
@@ -545,6 +546,7 @@ class TestGenericRun:
private_data_dir, extra_vars, safe_dict = call_args
assert extra_vars['super_secret'] == "CLASSIFIED"
@pytest.mark.django_db
def test_awx_task_env(self, patch_Job, private_data_dir, execution_environment, mock_me):
job = Job(project=Project(), inventory=Inventory())
job.execution_environment = execution_environment
@@ -845,6 +847,7 @@ class TestJobCredentials(TestJobExecution):
[None, '0'],
],
)
@pytest.mark.django_db
def test_net_credentials(self, authorize, expected_authorize, job, private_data_dir, mock_me):
task = jobs.RunJob()
task.instance = job
@@ -901,6 +904,7 @@ class TestJobCredentials(TestJobExecution):
assert safe_env['AZURE_PASSWORD'] == HIDDEN_PASSWORD
@pytest.mark.django_db
def test_awx_task_env(self, settings, private_data_dir, job, mock_me):
settings.AWX_TASK_ENV = {'FOO': 'BAR'}
task = jobs.RunJob()