Skip to content

Commit 4813f5f

Browse files
authored
feat: use DAB to load dynaconf settings (#1223)
# [AAP-37673] EDA: Use DAB:Dynaconf to load Django static settings ## Description <!-- Mandatory: Provide a clear, concise description of the changes and their purpose --> It is the organization's effect to load settings using the same method. EDA used to define all settings and expose to Django settings in `aap_eda/settings/default.py`. We continue to use this file to load and expose settings through DAB:Dynaconf. We move individual settings from this file to other files: * all settings that can be overwritten are moved to `aap_eda/settings/defaults.py` * all internal used settings that are not exposed for overwriting are moved to `aap_eda/settings/core.py` * all computed or adjusted settings and logic are moved to `aap_eda/settings/post_load.py` * redis specific settings preparations are moved to `aap_eda/settings/redis.py` Closes AAP-37673 Jira: [AAP-37673](https://jira.aap.com/browse/AAP-37673) ## Type of Change <!-- Mandatory: Check one or more boxes that apply --> - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update - [ ] Test update - [ ] Refactoring (no functional changes) - [ ] Development environment change - [ ] Configuration change - [ ] CI change ## Self-Review Checklist <!-- These items help ensure quality - they complement our automated CI checks --> - [ ] I have performed a self-review of my code - [ ] I have added relevant comments to complex code sections - [ ] I have updated documentation where needed - [ ] I have considered the security impact of these changes - [ ] I have considered performance implications - [ ] I have thought about error handling and edge cases - [ ] I have tested the changes in my local environment - [ ] I have run the linters and test suite locally - [ ] I have tested the changes on integration environment ## Testing Instructions <!-- Optional for test-only changes. Mandatory for all other changes --> <!-- Must be detailed enough for reviewers to reproduce --> ### Prerequisites <!-- List any specific setup required --> ### Steps to Test 1. 2. 3. ### Expected Results <!-- Describe what should happen after following the steps --> ## Additional Context <!-- Optional but helpful information --> ### Required Actions <!-- Check if changes require work in other areas --> <!-- Remove section if no external actions needed --> - [ ] Requires documentation updates <!-- API docs, feature docs, deployment guides --> - [ ] Requires downstream repository changes <!-- Specify repos: django-ansible-base, eda-server, etc. --> - [ ] Requires infrastructure/deployment changes <!-- CI/CD, installer updates, new services --> - [ ] Requires coordination with other teams <!-- UI team, platform services, infrastructure --> - [ ] Blocked by PR/MR: #XXX | <https://github.com/example/repo/pull/XXX> <!-- Reference blocking PRs/MRs with brief context --> ### Screenshots/Logs <!-- Add if relevant to demonstrate the changes -->
1 parent 8898949 commit 4813f5f

File tree

19 files changed

+1231
-910
lines changed

19 files changed

+1231
-910
lines changed

Taskfile.dist.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
version: "3"
22

33
env:
4-
DJANGO_SETTINGS_MODULE: "aap_eda.settings.development"
4+
EDA_MODE: development
5+
DJANGO_SETTINGS_MODULE: "aap_eda.settings.default"
56

67
vars:
78
DOCKER_COMPOSE: '{{ default "docker-compose" .DOCKER_COMPOSE }}'

poetry.lock

Lines changed: 27 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ dev = ["psycopg-binary"]
3636
python = ">=3.11,<3.13"
3737
django = ">=4.2,<4.3"
3838
djangorestframework = "3.15.*"
39-
dynaconf = ">=3.1.12,<3.3"
4039
drf-spectacular = ">=0.26.5,<0.27"
4140
channels = { version = "4.0.*", extras = ["daphne"] }
4241
psycopg-binary = { version = "*", optional = true }
@@ -48,7 +47,7 @@ cryptography = ">=42,<43"
4847
kubernetes = "26.1.*"
4948
podman = "5.4.*"
5049
rq-scheduler = "^0.10"
51-
django-ansible-base = { git = "https://github.com/ansible/django-ansible-base.git", tag = "2025.1.31", extras = [
50+
django-ansible-base = { git = "https://github.com/ansible/django-ansible-base.git", tag = "2025.3.7", extras = [
5251
"channel-auth",
5352
"rbac",
5453
"redis-client",
@@ -72,6 +71,7 @@ django-flags = "^5.0.13"
7271

7372
[tool.poetry.group.test.dependencies]
7473
pytest = "*"
74+
pytest-env = "*"
7575
pytest-django = "*"
7676
pytest-asyncio = "*"
7777
requests = { version = "*", python = "<4.0" }

pytest.ini

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
[pytest]
22
asyncio_mode = auto
3-
DJANGO_SETTINGS_MODULE = aap_eda.settings.development
3+
env =
4+
EDA_MODE=development
5+
DJANGO_SETTINGS_MODULE = aap_eda.settings.default
46
log_file_level = INFO

src/aap_eda/core/tasking/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from django.conf import settings
2323
from rq import results as rq_results
2424

25-
from aap_eda.settings import default
25+
from aap_eda.settings import core as core_settings, redis as redis_settings
2626

2727
__all__ = [
2828
"Job",
@@ -131,7 +131,7 @@ def _prune_redis_kwargs(**kwargs) -> dict[str, typing.Any]:
131131
db = kwargs.get("db", None)
132132
if (db is not None) and (kwargs.get("mode", "") == "cluster"):
133133
del kwargs["db"]
134-
if db != default.DEFAULT_REDIS_DB:
134+
if db != core_settings.DEFAULT_REDIS_DB:
135135
logger.info(
136136
f"clustered redis supports only the default db"
137137
f"; db specified: {db}"
@@ -151,7 +151,7 @@ def get_redis_client(**kwargs) -> typing.Union[DABRedis, DABRedisCluster]:
151151

152152
def get_redis_status() -> dict:
153153
"""Query DAB for the status of Redis."""
154-
kwargs = default.rq_redis_client_instantiation_parameters()
154+
kwargs = redis_settings.rq_redis_client_instantiation_parameters()
155155
kwargs = _prune_redis_kwargs(**kwargs)
156156
return _get_redis_status(_create_url_from_parameters(**kwargs), **kwargs)
157157

@@ -329,7 +329,7 @@ def _get_necessary_client_connection(
329329
) -> rq.Connection:
330330
if not isinstance(connection, (DABRedis, DABRedisCluster)):
331331
connection = get_redis_client(
332-
**default.rq_redis_client_instantiation_parameters()
332+
**redis_settings.rq_redis_client_instantiation_parameters()
333333
)
334334
return connection
335335

src/aap_eda/settings/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2025 Red Hat, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from .default import * # noqa: F403

src/aap_eda/settings/core.py

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Copyright 2025 Red Hat, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Define all settings use internally, not exposed to users for overwriting.
16+
17+
INSTALLED_APPS = [
18+
"daphne",
19+
"flags",
20+
# Django apps
21+
"django.contrib.auth",
22+
"django.contrib.contenttypes",
23+
"django.contrib.sessions",
24+
"django.contrib.staticfiles",
25+
# Third party apps
26+
"rest_framework",
27+
"drf_spectacular",
28+
"django_rq",
29+
"django_filters",
30+
"ansible_base.rbac",
31+
"ansible_base.resource_registry",
32+
"ansible_base.jwt_consumer",
33+
"ansible_base.rest_filters",
34+
"ansible_base.feature_flags",
35+
# Local apps
36+
"aap_eda.api",
37+
"aap_eda.core",
38+
]
39+
40+
41+
MIDDLEWARE = [
42+
"django.middleware.security.SecurityMiddleware",
43+
"django.contrib.sessions.middleware.SessionMiddleware",
44+
"django.middleware.locale.LocaleMiddleware",
45+
"django.middleware.common.CommonMiddleware",
46+
"django.middleware.csrf.CsrfViewMiddleware",
47+
"django.contrib.auth.middleware.AuthenticationMiddleware",
48+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
49+
"crum.CurrentRequestUserMiddleware",
50+
]
51+
52+
ROOT_URLCONF = "aap_eda.urls"
53+
54+
TEMPLATES = [
55+
{
56+
"BACKEND": "django.template.backends.django.DjangoTemplates",
57+
"DIRS": [],
58+
"APP_DIRS": True,
59+
"OPTIONS": {
60+
"context_processors": [
61+
"django.template.context_processors.debug",
62+
"django.template.context_processors.request",
63+
"django.contrib.auth.context_processors.auth",
64+
],
65+
},
66+
},
67+
]
68+
69+
WSGI_APPLICATION = "aap_eda.wsgi.application"
70+
71+
ASGI_APPLICATION = "aap_eda.asgi.application"
72+
73+
# Password validation
74+
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators
75+
76+
AUTH_PASSWORD_VALIDATORS = [
77+
{
78+
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", # noqa: E501
79+
},
80+
{
81+
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", # noqa: E501
82+
},
83+
{
84+
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", # noqa: E501
85+
},
86+
{
87+
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", # noqa: E501
88+
},
89+
]
90+
91+
# Internationalization
92+
# https://docs.djangoproject.com/en/4.1/topics/i18n/
93+
94+
LANGUAGE_CODE = "en-us"
95+
96+
USE_I18N = True
97+
98+
TIME_ZONE = "UTC"
99+
100+
USE_TZ = True
101+
102+
# Default primary key field type
103+
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
104+
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
105+
106+
AUTH_USER_MODEL = "core.User"
107+
108+
REST_FRAMEWORK = {
109+
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
110+
"DEFAULT_PAGINATION_CLASS": "aap_eda.api.pagination.DefaultPagination",
111+
"PAGE_SIZE": 20,
112+
"DEFAULT_AUTHENTICATION_CLASSES": [
113+
"aap_eda.api.authentication.SessionAuthentication",
114+
"rest_framework.authentication.BasicAuthentication",
115+
"aap_eda.api.authentication.WebsocketJWTAuthentication",
116+
"ansible_base.jwt_consumer.eda.auth.EDAJWTAuthentication",
117+
],
118+
"DEFAULT_PERMISSION_CLASSES": [
119+
"rest_framework.permissions.IsAuthenticated",
120+
"ansible_base.rbac.api.permissions.AnsibleBaseObjectPermissions",
121+
],
122+
"TEST_REQUEST_DEFAULT_FORMAT": "json",
123+
"DEFAULT_METADATA_CLASS": "aap_eda.api.metadata.EDAMetadata",
124+
"EXCEPTION_HANDLER": "aap_eda.api.exceptions.api_fallback_handler",
125+
}
126+
127+
DEFAULT_REDIS_DB = 0
128+
129+
# ---------------------------------------------------------
130+
# TASKING SETTINGS
131+
# ---------------------------------------------------------
132+
RQ = {
133+
"JOB_CLASS": "aap_eda.core.tasking.Job",
134+
"QUEUE_CLASS": "aap_eda.core.tasking.Queue",
135+
"SCHEDULER_CLASS": "aap_eda.core.tasking.Scheduler",
136+
"WORKER_CLASS": "aap_eda.core.tasking.Worker",
137+
}
138+
139+
# Time window in seconds to consider a worker as dead
140+
DEFAULT_WORKER_HEARTBEAT_TIMEOUT = 60
141+
DEFAULT_WORKER_TTL = 5
142+
143+
RQ_STARTUP_JOBS = []
144+
145+
# Id of the scheduler job it's required when we have multiple instances of
146+
# the scheduler running to avoid duplicate jobs
147+
RQ_PERIODIC_JOBS = [
148+
{
149+
"func": (
150+
"aap_eda.tasks.orchestrator.enqueue_monitor_rulebook_processes"
151+
),
152+
"interval": 5,
153+
"id": "enqueue_monitor_rulebook_processes",
154+
},
155+
{
156+
"func": "aap_eda.tasks.project.monitor_project_tasks",
157+
"interval": 30,
158+
"id": "monitor_project_tasks",
159+
},
160+
]
161+
RQ_CRON_JOBS = []
162+
163+
ANSIBLE_BASE_CUSTOM_VIEW_PARENT = "aap_eda.api.views.dab_base.BaseAPIView"
164+
165+
# ---------------------------------------------------------
166+
# DJANGO ANSIBLE BASE RESOURCES REGISTRY SETTINGS
167+
# ---------------------------------------------------------
168+
ANSIBLE_BASE_RESOURCE_CONFIG_MODULE = "aap_eda.api.resource_api"
169+
170+
# ---------------------------------------------------------
171+
# DJANGO ANSIBLE BASE RBAC SETTINGS
172+
# ---------------------------------------------------------
173+
DEFAULT_ORGANIZATION_NAME = "Default"
174+
ANSIBLE_BASE_SERVICE_PREFIX = "eda"
175+
ANSIBLE_BASE_TEAM_MODEL = "core.Team"
176+
ANSIBLE_BASE_ORGANIZATION_MODEL = "core.Organization"
177+
178+
# Organization and object roles will come from create_initial_data
179+
ANSIBLE_BASE_ROLE_PRECREATE = {}
180+
181+
ANSIBLE_BASE_ALLOW_SINGLETON_USER_ROLES = True
182+
ANSIBLE_BASE_CHECK_RELATED_PERMISSIONS = ["view"]
183+
184+
DEFAULT_SYSTEM_PG_NOTIFY_CREDENTIAL_NAME = "_DEFAULT_EDA_PG_NOTIFY_CREDS"

0 commit comments

Comments
 (0)