mirror of
https://github.com/ansible/awx.git
synced 2026-06-29 02:18:01 -02:30
Upgrade to Django 5.2 LTS (#16185)
Upgrade to Django 5.2 LTS with compatibility fixes across fields, migrations, dispatch config, tests, and dev deps. Dependencies: - Upgrade django to 5.2.8 and relax requirements.in to >=5.2,<5.3. - Bump django-debug-toolbar to >=6.0 for compatibility. Backend: - awx/conf/fields.py: switch URL TLD regex to use DomainNameValidator.ul in custom URLField. - awx/main/management/commands/gather_analytics.py: use datetime.timezone.utc for naïve datetime handling. - awx/main/dispatch/config.py: add mock_publish option; avoid DB access for test runs, set default max_workers, and support a noop broker. Migrations (SQLite/Postgres compatibility): - Add awx/main/migrations/_sqlite_helper.py with db-aware AlterIndexTogether/RenameIndex wrappers; consume in 0144_event_partitions.py and 0184_django_indexes.py. - Update 0187_hop_nodes.py to use CheckConstraint(condition=...). - Add 0205_alter_instance_peers_alter_job_hosts_and_more.py adjusting through_fields/relations on instance.peers, job.hosts, and role.ancestors. - _dab_rbac.py: iterate roles with chunk_size=1000 for migration performance. Tests: Include hcp_terraform in default credential types in test_credential.py. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Alan Rominger <arominge@redhat.com>
This commit is contained in:
@@ -237,7 +237,7 @@ class Migration(migrations.Migration):
|
||||
db_index=False, editable=False, on_delete=models.deletion.DO_NOTHING, related_name='system_job_events', to='main.SystemJob'
|
||||
),
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
dbawaremigrations.AlterIndexTogether(
|
||||
name='adhoccommandevent',
|
||||
index_together={
|
||||
('ad_hoc_command', 'job_created', 'event'),
|
||||
@@ -245,11 +245,11 @@ class Migration(migrations.Migration):
|
||||
('ad_hoc_command', 'job_created', 'uuid'),
|
||||
},
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
dbawaremigrations.AlterIndexTogether(
|
||||
name='inventoryupdateevent',
|
||||
index_together={('inventory_update', 'job_created', 'counter'), ('inventory_update', 'job_created', 'uuid')},
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
dbawaremigrations.AlterIndexTogether(
|
||||
name='jobevent',
|
||||
index_together={
|
||||
('job', 'job_created', 'counter'),
|
||||
@@ -258,7 +258,7 @@ class Migration(migrations.Migration):
|
||||
('job', 'job_created', 'parent_uuid'),
|
||||
},
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
dbawaremigrations.AlterIndexTogether(
|
||||
name='projectupdateevent',
|
||||
index_together={
|
||||
('project_update', 'job_created', 'uuid'),
|
||||
@@ -266,7 +266,7 @@ class Migration(migrations.Migration):
|
||||
('project_update', 'job_created', 'counter'),
|
||||
},
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
dbawaremigrations.AlterIndexTogether(
|
||||
name='systemjobevent',
|
||||
index_together={('system_job', 'job_created', 'uuid'), ('system_job', 'job_created', 'counter')},
|
||||
),
|
||||
|
||||
@@ -6,6 +6,8 @@ from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
from ._sqlite_helper import dbawaremigrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
@@ -15,92 +17,92 @@ class Migration(migrations.Migration):
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='adhoccommandevent',
|
||||
new_name='main_adhocc_ad_hoc__1e4d24_idx',
|
||||
old_fields=('ad_hoc_command', 'job_created', 'uuid'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='adhoccommandevent',
|
||||
new_name='main_adhocc_ad_hoc__e72142_idx',
|
||||
old_fields=('ad_hoc_command', 'job_created', 'event'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='adhoccommandevent',
|
||||
new_name='main_adhocc_ad_hoc__a57777_idx',
|
||||
old_fields=('ad_hoc_command', 'job_created', 'counter'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='inventoryupdateevent',
|
||||
new_name='main_invent_invento_f72b21_idx',
|
||||
old_fields=('inventory_update', 'job_created', 'uuid'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='inventoryupdateevent',
|
||||
new_name='main_invent_invento_364dcb_idx',
|
||||
old_fields=('inventory_update', 'job_created', 'counter'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='jobevent',
|
||||
new_name='main_jobeve_job_id_40a56d_idx',
|
||||
old_fields=('job', 'job_created', 'parent_uuid'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='jobevent',
|
||||
new_name='main_jobeve_job_id_3c4a4a_idx',
|
||||
old_fields=('job', 'job_created', 'uuid'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='jobevent',
|
||||
new_name='main_jobeve_job_id_51c382_idx',
|
||||
old_fields=('job', 'job_created', 'counter'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='jobevent',
|
||||
new_name='main_jobeve_job_id_0ddc6b_idx',
|
||||
old_fields=('job', 'job_created', 'event'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='projectupdateevent',
|
||||
new_name='main_projec_project_449bbd_idx',
|
||||
old_fields=('project_update', 'job_created', 'uuid'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='projectupdateevent',
|
||||
new_name='main_projec_project_69559a_idx',
|
||||
old_fields=('project_update', 'job_created', 'counter'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='projectupdateevent',
|
||||
new_name='main_projec_project_c44b7c_idx',
|
||||
old_fields=('project_update', 'job_created', 'event'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='role',
|
||||
new_name='main_rbac_r_content_979bdd_idx',
|
||||
old_fields=('content_type', 'object_id'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='roleancestorentry',
|
||||
new_name='main_rbac_r_ancesto_b44606_idx',
|
||||
old_fields=('ancestor', 'content_type_id', 'role_field'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='roleancestorentry',
|
||||
new_name='main_rbac_r_ancesto_22b9f0_idx',
|
||||
old_fields=('ancestor', 'content_type_id', 'object_id'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='roleancestorentry',
|
||||
new_name='main_rbac_r_ancesto_c87b87_idx',
|
||||
old_fields=('ancestor', 'descendent'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='systemjobevent',
|
||||
new_name='main_system_system__e39825_idx',
|
||||
old_fields=('system_job', 'job_created', 'uuid'),
|
||||
),
|
||||
migrations.RenameIndex(
|
||||
dbawaremigrations.RenameIndex(
|
||||
model_name='systemjobevent',
|
||||
new_name='main_system_system__73537a_idx',
|
||||
old_fields=('system_job', 'job_created', 'counter'),
|
||||
|
||||
@@ -69,7 +69,7 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='instancelink',
|
||||
constraint=models.CheckConstraint(check=models.Q(('source', models.F('target')), _negated=True), name='source_and_target_can_not_be_equal'),
|
||||
constraint=models.CheckConstraint(condition=models.Q(('source', models.F('target')), _negated=True), name='source_and_target_can_not_be_equal'),
|
||||
),
|
||||
migrations.RunPython(automatically_peer_from_control_plane),
|
||||
]
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Generated by Django 5.2.8 on 2025-11-20 18:39
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0204_squashed_deletions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='instance',
|
||||
name='peers',
|
||||
field=models.ManyToManyField(
|
||||
related_name='peers_from', through='main.InstanceLink', through_fields=('source', 'target'), to='main.receptoraddress'
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='job',
|
||||
name='hosts',
|
||||
field=models.ManyToManyField(editable=False, related_name='jobs', through='main.JobHostSummary', through_fields=('job', 'host'), to='main.host'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='role',
|
||||
name='ancestors',
|
||||
field=models.ManyToManyField(
|
||||
related_name='descendents', through='main.RoleAncestorEntry', through_fields=('descendent', 'ancestor'), to='main.role'
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -194,7 +194,7 @@ def migrate_to_new_rbac(apps, schema_editor):
|
||||
# NOTE: this import is expected to break at some point, and then just move the data here
|
||||
from awx.main.models.rbac import role_descriptions
|
||||
|
||||
for role in Role.objects.prefetch_related('members', 'parents').iterator():
|
||||
for role in Role.objects.prefetch_related('members', 'parents').iterator(chunk_size=1000):
|
||||
if role.singleton_name:
|
||||
continue # only bothering to migrate object roles
|
||||
|
||||
|
||||
@@ -1,6 +1,78 @@
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class AlterIndexTogether(migrations.AlterIndexTogether):
|
||||
"""
|
||||
Database-aware AlterIndexTogether that handles SQLite's missing indexes gracefully.
|
||||
|
||||
In Django 5.2+, SQLite table rewrites (triggered by AlterField operations)
|
||||
can drop multi-column indexes. For SQLite, this catches the ValueError and
|
||||
ignores it when the index doesn't exist. For PostgreSQL, uses standard behavior.
|
||||
"""
|
||||
|
||||
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||
if not schema_editor.connection.vendor.startswith('postgres'):
|
||||
# SQLite-specific handling: ignore missing indexes from table rewrites
|
||||
try:
|
||||
super().database_forwards(app_label, schema_editor, from_state, to_state)
|
||||
except ValueError as exc:
|
||||
if "Found wrong number (0) of constraints" in str(exc) or "Found wrong number (0) of indexes" in str(exc):
|
||||
return
|
||||
raise
|
||||
else:
|
||||
# PostgreSQL: standard behavior
|
||||
super().database_forwards(app_label, schema_editor, from_state, to_state)
|
||||
|
||||
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||
if not schema_editor.connection.vendor.startswith('postgres'):
|
||||
# SQLite-specific handling: ignore missing indexes from table rewrites
|
||||
try:
|
||||
super().database_backwards(app_label, schema_editor, from_state, to_state)
|
||||
except ValueError as exc:
|
||||
if "Found wrong number (0) of constraints" in str(exc) or "Found wrong number (0) of indexes" in str(exc):
|
||||
return
|
||||
raise
|
||||
else:
|
||||
# PostgreSQL: standard behavior
|
||||
super().database_backwards(app_label, schema_editor, from_state, to_state)
|
||||
|
||||
|
||||
class RenameIndex(migrations.RenameIndex):
|
||||
"""
|
||||
Database-aware RenameIndex that handles SQLite's missing indexes gracefully.
|
||||
|
||||
In Django 5.2+, SQLite table rewrites (triggered by AlterField operations)
|
||||
can drop multi-column indexes. For SQLite, this catches the ValueError and
|
||||
ignores it when the index doesn't exist. For PostgreSQL, uses standard behavior.
|
||||
"""
|
||||
|
||||
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||
if not schema_editor.connection.vendor.startswith('postgres'):
|
||||
# SQLite-specific handling: ignore missing indexes from table rewrites
|
||||
try:
|
||||
super().database_forwards(app_label, schema_editor, from_state, to_state)
|
||||
except ValueError as exc:
|
||||
if "Found wrong number (0) of constraints" in str(exc) or "wrong number (0) of indexes" in str(exc):
|
||||
return
|
||||
raise
|
||||
else:
|
||||
# PostgreSQL: standard behavior
|
||||
super().database_forwards(app_label, schema_editor, from_state, to_state)
|
||||
|
||||
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||
if not schema_editor.connection.vendor.startswith('postgres'):
|
||||
# SQLite-specific handling: ignore missing indexes from table rewrites
|
||||
try:
|
||||
super().database_backwards(app_label, schema_editor, from_state, to_state)
|
||||
except ValueError as exc:
|
||||
if "Found wrong number (0) of constraints" in str(exc) or "wrong number (0) of indexes" in str(exc):
|
||||
return
|
||||
raise
|
||||
else:
|
||||
# PostgreSQL: standard behavior
|
||||
super().database_backwards(app_label, schema_editor, from_state, to_state)
|
||||
|
||||
|
||||
class RunSQL(migrations.operations.special.RunSQL):
|
||||
"""
|
||||
Bit of a hack here. Django actually wants this decision made in the router
|
||||
@@ -56,6 +128,8 @@ class RunPython(migrations.operations.special.RunPython):
|
||||
class _sqlitemigrations:
|
||||
RunPython = RunPython
|
||||
RunSQL = RunSQL
|
||||
AlterIndexTogether = AlterIndexTogether
|
||||
RenameIndex = RenameIndex
|
||||
|
||||
|
||||
dbawaremigrations = _sqlitemigrations()
|
||||
|
||||
Reference in New Issue
Block a user