mirror of
https://github.com/ansible/awx.git
synced 2026-03-08 05:01:09 -02:30
* Make the JT name uniqueness enforced at the database level * Forgot demo project fixture * New approach, done by adding a new field * Update for linters and failures * Fix logical error in migration test * Revert some test changes based on review comment * Do not rename first template, add test * Avoid name-too-long rename errors * Insert migration into place * Move existing files with git * Bump migrations of existing * Update migration test * Awkward bump * Fix migration file link * update test reference again
This commit is contained in:
50
awx/main/migrations/0200_template_name_constraint.py
Normal file
50
awx/main/migrations/0200_template_name_constraint.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# Generated by Django 4.2.20 on 2025-04-22 15:54
|
||||
|
||||
import logging
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
from awx.main.migrations._db_constraints import _rename_duplicates
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def rename_jts(apps, schema_editor):
|
||||
cls = apps.get_model('main', 'JobTemplate')
|
||||
_rename_duplicates(cls)
|
||||
|
||||
|
||||
def rename_projects(apps, schema_editor):
|
||||
cls = apps.get_model('main', 'Project')
|
||||
_rename_duplicates(cls)
|
||||
|
||||
|
||||
def change_inventory_source_org_unique(apps, schema_editor):
|
||||
cls = apps.get_model('main', 'InventorySource')
|
||||
r = cls.objects.update(org_unique=False)
|
||||
logger.info(f'Set database constraint rule for {r} inventory source objects')
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0199_inventorygroupvariableswithhistory_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_jts, migrations.RunPython.noop),
|
||||
migrations.RunPython(rename_projects, migrations.RunPython.noop),
|
||||
migrations.AddField(
|
||||
model_name='unifiedjobtemplate',
|
||||
name='org_unique',
|
||||
field=models.BooleanField(blank=True, default=True, editable=False, help_text='Used internally to selectively enforce database constraint on name'),
|
||||
),
|
||||
migrations.RunPython(change_inventory_source_org_unique, migrations.RunPython.noop),
|
||||
migrations.AddConstraint(
|
||||
model_name='unifiedjobtemplate',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('org_unique', True)), fields=('polymorphic_ctype', 'name', 'organization'), name='ujt_hard_name_constraint'
|
||||
),
|
||||
),
|
||||
]
|
||||
25
awx/main/migrations/_db_constraints.py
Normal file
25
awx/main/migrations/_db_constraints.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import logging
|
||||
|
||||
from django.db.models import Count
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _rename_duplicates(cls):
|
||||
field = cls._meta.get_field('name')
|
||||
max_len = field.max_length
|
||||
for organization_id in cls.objects.order_by().values_list('organization_id', flat=True).distinct():
|
||||
duplicate_data = cls.objects.values('name').filter(organization_id=organization_id).annotate(count=Count('name')).order_by().filter(count__gt=1)
|
||||
for data in duplicate_data:
|
||||
name = data['name']
|
||||
for idx, ujt in enumerate(cls.objects.filter(name=name, organization_id=organization_id).order_by('created')):
|
||||
if idx > 0:
|
||||
suffix = f'_dup{idx}'
|
||||
max_chars = max_len - len(suffix)
|
||||
if len(ujt.name) >= max_chars:
|
||||
ujt.name = ujt.name[:max_chars] + suffix
|
||||
else:
|
||||
ujt.name = ujt.name + suffix
|
||||
logger.info(f'Renaming duplicate {cls._meta.model_name} to `{ujt.name}` because of duplicate name entry')
|
||||
ujt.save(update_fields=['name'])
|
||||
Reference in New Issue
Block a user