Added Django and API requirements to AWX Contributor Docs for POC (#16093)

* Requirements POC docs from Claude Code eval

* Removed unnecessary reference.

* Excluded custom DRF configurations per @AlanCoding

* Implement review changes from @chrismeyersfsu

---------

Co-authored-by: Peter Braun <pbraun@redhat.com>
This commit is contained in:
TVo 2025-10-16 10:38:37 -06:00 committed by GitHub
parent f3fd9945d6
commit 0d9483b54c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 2032 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,725 @@
=====================================================
Django Development Requirements
=====================================================
**AWX Codebase Best Practices**
:Version: 1.0
:Date: September 2025
:Based on: AWX Enterprise Django Application Analysis
:Generated by: Claude Code AI
----
.. contents:: Table of Contents
:depth: 3
:local:
----
1. Project Structure
====================
1.1 Modular Application Architecture
------------------------------------
**REQUIRED**: Organize Django project with clear separation of concerns::
awx/
├── __init__.py # Version management and environment detection
├── main/ # Core business logic and models
├── api/ # REST API layer (Django REST Framework)
├── ui/ # Frontend integration
├── conf/ # Configuration management
├── settings/ # Environment-specific settings
├── templates/ # Django templates
└── static/ # Static assets
**Requirements**:
- Each functional area must have its own Django app
- Use descriptive app names that reflect business domains
- Separate API logic from core business logic
1.2 Pre-Management Command Code
--------------------------------
This section describes the code that runs before every management command.
AWX persistent services (i.e. wsrelay, heartbeat, dispatcher) all have management commands as entry points. So if you want to write a new persistent service, make a management command.
System jobs are implemented as management commands too.
**REQUIRED**: Implement custom Django management integration:
.. code-block:: python
# awx/__init__.py
def manage():
"""Custom management function with environment preparation"""
prepare_env()
from django.core.management import execute_from_command_line
# Version validation for production
if not MODE == 'development':
validate_production_requirements()
execute_from_command_line(sys.argv)
**Requirements**:
- Environment detection (development/production modes)
- Production deployment validation
- Custom version checking mechanisms
- Database version compatibility checks
----
2. Settings Management
======================
2.1 Environment-Based Settings Architecture
-------------------------------------------
**REQUIRED**: Use ``django-split-settings`` for modular configuration::
# settings/defaults.py - Base configuration
# settings/development.py - Development overrides
# settings/production.py - Production security settings
# settings/testing.py - Test-specific configuration
**Settings Pattern**:
.. code-block:: python
# development.py
from .defaults import *
from split_settings.tools import optional, include
DEBUG = True
ALLOWED_HOSTS = ['*']
# Include optional local settings
include(optional('local_settings.py'))
2.2 Sourcing config from files
-------------------------------
**REQUIRED**: Sourcing config from multiple files (in a directory) on disk:
.. code-block:: python
# External settings loading
EXTERNAL_SETTINGS = os.environ.get('AWX_SETTINGS_FILE')
if EXTERNAL_SETTINGS:
include(EXTERNAL_SETTINGS, scope=locals())
3. URL Patterns and Routing
============================
3.1 Modular URL Architecture
-----------------------------
**REQUIRED**: Implement hierarchical URL organization with namespacing:
.. code-block:: python
# urls.py
def get_urlpatterns(prefix=None):
"""Dynamic URL pattern generation with prefix support"""
if not prefix:
prefix = '/'
else:
prefix = f'/{prefix}/'
return [
path(f'api{prefix}', include('awx.api.urls', namespace='api')),
path(f'ui{prefix}', include('awx.ui.urls', namespace='ui')),
]
urlpatterns = get_urlpatterns()
3.2 Environment-Specific URL Inclusion
--------------------------------------
**REQUIRED**: Conditional URL patterns based on environment:
This example allows the Django debug toolbar to work.
.. code-block:: python
# Development-only URLs
if settings.DEBUG:
try:
import debug_toolbar
urlpatterns += [path('__debug__/', include(debug_toolbar.urls))]
except ImportError:
pass
**OPTIONAL**: If you want to include your own debug logic and endpoints:
.. code-block:: python
if MODE == 'development':
# Only include these if we are in the development environment
from awx.api.swagger import schema_view
from awx.api.urls.debug import urls as debug_urls
urlpatterns += [re_path(r'^debug/', include(debug_urls))]
urlpatterns += [
re_path(r'^swagger(?P<format>\.json|\.yaml)/$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
re_path(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]
**Requirements**:
- Use Django's ``include()`` for modular organization
- Implement URL namespacing for API versioning
- Support dynamic URL prefix configuration
- Separate URL patterns by functional area
----
4. Model Design
===============
4.1 Abstract Base Models
------------------------
**REQUIRED**: Use abstract base models for common functionality:
.. code-block:: python
# models/base.py
class BaseModel(models.Model):
"""Common fields and methods for all models"""
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class AuditableModel(BaseModel):
"""Models requiring audit trail"""
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
abstract = True
4.2 Mixin-Based Architecture
----------------------------
**REQUIRED**: Implement reusable model behaviors through mixins:
.. code-block:: python
# models/mixins.py
class ResourceMixin(models.Model):
"""Common resource management functionality"""
class Meta:
abstract = True
class ExecutionEnvironmentMixin(models.Model):
"""Execution environment configuration"""
class Meta:
abstract = True
4.3 Model Organization
----------------------
**REQUIRED**: Organize models by domain functionality::
models/
├── __init__.py
├── base.py # Abstract base models
├── mixins.py # Reusable model behaviors
├── inventory.py # Inventory-related models
├── jobs.py # Job execution models
├── credential.py # Credential management
└── organization.py # Organization models
**Requirements**:
- One file per logical domain until the domain gets too big, create a folder for it instead. In the past, credentials were broken out into logical domains until they were moved out of AWX, then they were collapsed back down to a single file.
- Use consistent naming conventions
- Implement comprehensive model validation
- Custom managers for complex queries
----
5. REST API Development
=======================
5.1 Custom Authentication Classes
----------------------------------
The recommended best practice is to log all of the terminal (return) paths of authentication, not just the successful ones.
**REQUIRED**: Implement domain-specific authentication with logging:
.. code-block:: python
# api/authentication.py
class LoggedBasicAuthentication(authentication.BasicAuthentication):
"""Basic authentication with request logging"""
def authenticate(self, request):
if not settings.AUTH_BASIC_ENABLED:
return
ret = super().authenticate(request)
if ret:
username = ret[0].username if ret[0] else '<none>'
logger.info(
f"User {username} performed {request.method} "
f"to {request.path} through the API"
)
return ret
5.2 Custom Permission Classes
-----------------------------
**REQUIRED**: Implement comprehensive permission checking:
.. code-block:: python
# api/permissions.py
class ModelAccessPermission(permissions.BasePermission):
"""Model-based access control with hierarchy support"""
def has_permission(self, request, view):
if hasattr(view, 'parent_model'):
parent_obj = view.get_parent_object()
return check_user_access(
request.user,
view.parent_model,
'read',
parent_obj
)
return True
**Requirements**:
- Multiple authentication methods (JWT, Session, Basic)
- Custom pagination, renderers, and metadata classes
- Comprehensive API exception handling
- Resource-based URL organization
- Logging for authentication events
----
6. Security Requirements
========================
6.1 Production Security Settings
--------------------------------
**REQUIRED**: Enforce secure defaults for production:
.. code-block:: python
# settings/production.py
DEBUG = False
SECRET_KEY = None # Force explicit configuration
ALLOWED_HOSTS = [] # Must be explicitly set
# Session security
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_AGE = 1800
# CSRF protection
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
CSRF_TRUSTED_ORIGINS = []
6.2 Django SECRET_KEY loading
------------------------------
**REQUIRED**: Implement Django SECRET_KEY loading:
.. code-block:: python
# Secret key from external file
SECRET_KEY_FILE = os.environ.get('SECRET_KEY_FILE', '/etc/awx/SECRET_KEY')
if os.path.exists(SECRET_KEY_FILE):
with open(SECRET_KEY_FILE, 'rb') as f:
SECRET_KEY = f.read().strip().decode()
else:
if not DEBUG:
raise ImproperlyConfigured("SECRET_KEY must be configured in production")
For more detail, refer to the `Django documentation <https://docs.djangoproject.com/en/5.2/ref/settings/#secret-key>`_.
6.3 Proxy and Network Security
------------------------------
**REQUIRED**: Configure reverse proxy security:
.. code-block:: python
# Proxy configuration
REMOTE_HOST_HEADERS = ['REMOTE_ADDR', 'REMOTE_HOST']
PROXY_IP_ALLOWED_LIST = []
USE_X_FORWARDED_HOST = True
USE_X_FORWARDED_PORT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
**Requirements**:
- External secret file management
- Secure cookie configuration
- CSRF protection with trusted origins
- Proxy header validation
- Force HTTPS in production
----
7. Database Management
======================
7.1 Advanced Database Configuration
-----------------------------------
**REQUIRED**: Robust database connections for production:
.. code-block:: python
# Database configuration with connection tuning
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DATABASE_NAME', 'awx'),
'ATOMIC_REQUESTS': True,
'CONN_MAX_AGE': 0,
'OPTIONS': {
'keepalives': 1,
'keepalives_idle': 5,
'keepalives_interval': 5,
'keepalives_count': 5,
},
}
}
7.2 Database Version Validation
-------------------------------
**REQUIRED**: Implement database compatibility checking:
.. code-block:: python
# PostgreSQL version enforcement
def validate_database_version():
from django.db import connection
if (connection.pg_version // 10000) < 12:
raise ImproperlyConfigured(
"PostgreSQL version 12 or higher is required"
)
7.3 Migration Management
------------------------
**REQUIRED**: Structured migration organization
::
migrations/
├── 0001_initial.py
├── 0002_squashed_v300_release.py
├── 0003_squashed_v300_v303_updates.py
└── _migration_utils.py
**Requirements**:
It is best practice to not to re-write migrations. If possible, include a reverse migration, especially for data migrations to make testing easier.
----
8. Testing Standards
====================
8.1 Pytest Configuration
-------------------------
**REQUIRED**: Comprehensive test setup with optimization:
.. code-block:: ini
# pytest.ini
[pytest]
DJANGO_SETTINGS_MODULE = awx.main.tests.settings_for_test
python_files = *.py
addopts = --reuse-db --nomigrations --tb=native
markers =
ac: access control test
survey: tests related to survey feature
inventory_import: tests of code used by inventory import command
integration: integration tests requiring external services
8.2 Test Settings Module
-------------------------
**REQUIRED**: Dedicated test configuration:
.. code-block:: python
# settings/testing.py
from .defaults import *
# Fast test database
DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'
DATABASES['default']['NAME'] = ':memory:'
# Disable migrations for speed
class DisableMigrations:
def __contains__(self, item):
return True
def __getitem__(self, item):
return None
MIGRATION_MODULES = DisableMigrations()
8.3 Coverage Requirements
-------------------------
**REQUIRED**: Enforce comprehensive test coverage:
.. code-block:: python
# Coverage targets
COVERAGE_TARGETS = {
'project_overall': 75,
'library_code': 75,
'test_code': 95,
'new_patches': 100,
'type_checking': 100,
}
**Requirements**:
- Database reuse for faster execution
- Skip migrations in tests
- Custom test markers for categorization
- Dedicated test settings module
- Comprehensive warning filters
----
9. Application Configuration
=============================
9.1 Advanced AppConfig Implementation
--------------------------------------
**REQUIRED**: Custom application configuration with initialization:
.. code-block:: python
# apps.py
class MainConfig(AppConfig):
name = 'awx.main'
verbose_name = _('Main')
default_auto_field = 'django.db.models.AutoField'
def ready(self):
super().ready()
# Feature loading with environment checks
if not os.environ.get('AWX_SKIP_FEATURES', None):
self.load_credential_types()
self.load_inventory_plugins()
self.load_named_urls()
# Signal registration
self.register_signals()
def load_credential_types(self):
"""Load credential type definitions"""
pass
def register_signals(self):
"""Register Django signals"""
pass
**Requirements**:
- Custom AppConfig for complex initialization
- Feature loading in ``ready()`` method
- Environment-based feature toggling
- Plugin system integration
- Signal registration
----
10. Middleware Implementation
=============================
10.1 Custom Middleware for Enterprise Features
----------------------------------------------
**REQUIRED**: Implement domain-specific middleware:
.. code-block:: python
# middleware.py
class SettingsCacheMiddleware(MiddlewareMixin):
"""Clear settings cache on each request"""
def process_request(self, request):
from django.conf import settings
if hasattr(settings, '_awx_conf_memoizedcache'):
settings._awx_conf_memoizedcache.clear()
class TimingMiddleware(threading.local, MiddlewareMixin):
"""Request timing and performance monitoring"""
def process_request(self, request):
self.start_time = time.time()
def process_response(self, request, response):
if hasattr(self, 'start_time'):
duration = time.time() - self.start_time
response['X-Response-Time'] = f"{duration:.3f}s"
return response
**Requirements**:
- Settings cache management middleware
- Performance monitoring middleware
- Thread-local storage for request data
- Conditional middleware activation
----
11. Deployment Patterns
========================
11.1 Production-Ready ASGI/WSGI Configuration
---------------------------------------------
**REQUIRED**: Proper application server setup:
.. code-block:: python
# asgi.py
import os
import django
from channels.routing import get_default_application
from awx import prepare_env
prepare_env()
django.setup()
application = get_default_application()
# wsgi.py
import os
from django.core.wsgi import get_wsgi_application
from awx import prepare_env
prepare_env()
application = get_wsgi_application()
----
Compliance Checklist
=====================
Development Standards
---------------------
.. list-table::
:header-rows: 1
:widths: 50 10
* - Requirement
- Status
* - Modular app architecture implemented
- ☐
* - Environment-based settings configured
- ☐
* - Custom authentication and permissions
- ☐
* - Comprehensive test coverage (>75%)
- ☐
* - Security settings enforced
- ☐
* - Database optimization configured
- ☐
* - Static files properly organized
- ☐
* - Custom middleware implemented
- ☐
Production Readiness
--------------------
.. list-table::
:header-rows: 1
:widths: 50 10
* - Requirement
- Status
* - External secret management
- ☐
* - Database version validation
- ☐
* - Version deployment verification
- ☐
* - Performance monitoring
- ☐
* - Security headers configured
- ☐
* - HTTPS enforcement
- ☐
* - Proper logging setup
- ☐
* - Error handling and monitoring
- ☐
Code Quality
------------
.. list-table::
:header-rows: 1
:widths: 50 10
* - Requirement
- Status
* - Abstract base models used
- ☐
* - Mixin-based architecture
- ☐
* - Custom management commands
- ☐
* - Plugin system support
- ☐
* - Signal registration
- ☐
* - Migration organization
- ☐
* - API documentation
- ☐
* - Type hints and validation
- ☐
----
References
==========
- **Django Documentation**: https://docs.djangoproject.com/
- **Django REST Framework**: https://www.django-rest-framework.org/
- **Django Split Settings**: https://github.com/sobolevn/django-split-settings
- **AWX Source Code**: https://github.com/ansible/awx
----
| **Document Maintainer**: Development Team
| **Last Updated**: September 2025
| **Review Schedule**: Quarterly

View File

@ -15,6 +15,8 @@ Ansible AWX helps teams manage complex multi-tier deployments by adding control,
:caption: Community
contributor/index
contributor/DJANGO_REQUIREMENTS
contributor/API_REQUIREMENTS
.. toctree::
:maxdepth: 2