mirror of
https://github.com/ansible/awx.git
synced 2026-01-09 15:02:07 -03:30
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:
parent
f3fd9945d6
commit
0d9483b54c
1305
docs/docsite/rst/contributor/API_REQUIREMENTS.rst
Normal file
1305
docs/docsite/rst/contributor/API_REQUIREMENTS.rst
Normal file
File diff suppressed because it is too large
Load Diff
725
docs/docsite/rst/contributor/DJANGO_REQUIREMENTS.rst
Normal file
725
docs/docsite/rst/contributor/DJANGO_REQUIREMENTS.rst
Normal 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
|
||||||
@ -15,6 +15,8 @@ Ansible AWX helps teams manage complex multi-tier deployments by adding control,
|
|||||||
:caption: Community
|
:caption: Community
|
||||||
|
|
||||||
contributor/index
|
contributor/index
|
||||||
|
contributor/DJANGO_REQUIREMENTS
|
||||||
|
contributor/API_REQUIREMENTS
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user