Skip to content

Commit

Permalink
Avoid recursive include of DEFAULT_SETTINGS, add sanity test (#13236)
Browse files Browse the repository at this point in the history
* Avoid recursive include of DEFAULT_SETTINGS, add sanity test to avoid similar surprises

* Implement review comments for more clear code order and readability

* Clarify comment about order of app name, which is last in order so that it can modify user settings
  • Loading branch information
AlanCoding committed Apr 20, 2023
1 parent c10ada6 commit 0867221
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 23 deletions.
23 changes: 23 additions & 0 deletions awx/main/tests/unit/test_settings.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
from split_settings.tools import include


LOCAL_SETTINGS = (
'ALLOWED_HOSTS',
'BROADCAST_WEBSOCKET_PORT',
'BROADCAST_WEBSOCKET_VERIFY_CERT',
'BROADCAST_WEBSOCKET_PROTOCOL',
'BROADCAST_WEBSOCKET_SECRET',
'DATABASES',
'DEBUG',
'NAMED_URL_GRAPH',
)


def test_postprocess_auth_basic_enabled():
locals().update({'__file__': __file__})

include('../../../settings/defaults.py', scope=locals())
assert 'awx.api.authentication.LoggedBasicAuthentication' in locals()['REST_FRAMEWORK']['DEFAULT_AUTHENTICATION_CLASSES']


def test_default_settings():
from django.conf import settings

for k in dir(settings):
if k not in settings.DEFAULTS_SNAPSHOT or k in LOCAL_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}'
44 changes: 28 additions & 16 deletions awx/settings/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,6 @@
SYSTEM_UUID = '00000000-0000-0000-0000-000000000000'
INSTALL_UUID = '00000000-0000-0000-0000-000000000000'

# Store a snapshot of default settings at this point before loading any
# customizable config files.
DEFAULTS_SNAPSHOT = {}
this_module = sys.modules[__name__]
for setting in dir(this_module):
if setting == setting.upper():
DEFAULTS_SNAPSHOT[setting] = copy.deepcopy(getattr(this_module, setting))

# If there is an `/etc/tower/settings.py`, include it.
# If there is a `/etc/tower/conf.d/*.py`, include them.
include(optional('/etc/tower/settings.py'), scope=locals())
include(optional('/etc/tower/conf.d/*.py'), scope=locals())

BASE_VENV_PATH = "/var/lib/awx/venv/"
AWX_VENV_PATH = os.path.join(BASE_VENV_PATH, "awx")

Expand Down Expand Up @@ -105,11 +92,28 @@
AWX_DISABLE_TASK_MANAGERS = False
# ======================!!!!!!! FOR DEVELOPMENT ONLY !!!!!!!=================================

from .application_name import set_application_name
# Store a snapshot of default settings at this point before loading any
# customizable config files.
this_module = sys.modules[__name__]
local_vars = dir(this_module)
DEFAULTS_SNAPSHOT = {} # define after we save local_vars so we do not snapshot the snapshot
for setting in local_vars:
if setting.isupper():
DEFAULTS_SNAPSHOT[setting] = copy.deepcopy(getattr(this_module, setting))

set_application_name(DATABASES, CLUSTER_HOST_ID)
del local_vars # avoid temporary variables from showing up in dir(settings)
del this_module
#
###############################################################################################
#
# Any settings defined after this point will be marked as as a read_only database setting
#
################################################################################################

del set_application_name
# If there is an `/etc/tower/settings.py`, include it.
# If there is a `/etc/tower/conf.d/*.py`, include them.
include(optional('/etc/tower/settings.py'), scope=locals())
include(optional('/etc/tower/conf.d/*.py'), scope=locals())

# If any local_*.py files are present in awx/settings/, use them to override
# default settings for development. If not present, we can still run using
Expand All @@ -123,3 +127,11 @@
except ImportError:
traceback.print_exc()
sys.exit(1)

# The below runs AFTER all of the custom settings are imported
# because conf.d files will define DATABASES and this should modify that
from .application_name import set_application_name

set_application_name(DATABASES, CLUSTER_HOST_ID)

del set_application_name
18 changes: 11 additions & 7 deletions awx/settings/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,21 @@

# Store a snapshot of default settings at this point before loading any
# customizable config files.
this_module = sys.modules[__name__]
local_vars = dir(this_module)
DEFAULTS_SNAPSHOT = {} # define after we save local_vars so we do not snapshot the snapshot
for setting in local_vars:
if setting.isupper():
DEFAULTS_SNAPSHOT[setting] = copy.deepcopy(getattr(this_module, setting))

del local_vars # avoid temporary variables from showing up in dir(settings)
del this_module
#
###############################################################################################
#
# Any settings defined after this point will be marked as as a read_only database setting
#
################################################################################################
DEFAULTS_SNAPSHOT = {}
this_module = sys.modules[__name__]
for setting in dir(this_module):
if setting == setting.upper():
DEFAULTS_SNAPSHOT[setting] = copy.deepcopy(getattr(this_module, setting))

# Load settings from any .py files in the global conf.d directory specified in
# the environment, defaulting to /etc/tower/conf.d/.
Expand Down Expand Up @@ -98,8 +102,8 @@
else:
raise

# The below runs AFTER all of the custom settings are imported.

# The below runs AFTER all of the custom settings are imported
# because conf.d files will define DATABASES and this should modify that
from .application_name import set_application_name

set_application_name(DATABASES, CLUSTER_HOST_ID) # NOQA
Expand Down

0 comments on commit 0867221

Please sign in to comment.