mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 01:57:35 -03:30
AAP-35227 Extend role_check.py to delete orphaned InstanceLink objects as well (#7105)
This commit is contained in:
parent
dd02d56de6
commit
a285843cf2
@ -521,7 +521,7 @@ class TestInventorySourceCredential:
|
||||
patch(url=inv_src.get_absolute_url(), data={'credential': aws_cred.pk}, expect=200, user=admin_user)
|
||||
assert list(inv_src.credentials.values_list('id', flat=True)) == [aws_cred.pk]
|
||||
|
||||
@pytest.skip(reason="Delay until AAP-53978 completed")
|
||||
@pytest.mark.skip(reason="Delay until AAP-53978 completed")
|
||||
def test_vmware_cred_create_esxi_source(self, inventory, admin_user, organization, post, get):
|
||||
"""Test that a vmware esxi source can be added with a vmware credential"""
|
||||
from awx.main.models.credential import Credential, CredentialType
|
||||
|
||||
@ -8,12 +8,16 @@ from django.db.models.fields.related_descriptors import ManyToManyDescriptor
|
||||
from awx.main.fields import ImplicitRoleField
|
||||
from awx.main.models.rbac import Role
|
||||
|
||||
from awx.main.models.ha import Instance
|
||||
from awx.main.models.ha import InstanceLink
|
||||
|
||||
|
||||
team_ct = ContentType.objects.get(app_label='main', model='team')
|
||||
|
||||
crosslinked = defaultdict(lambda: defaultdict(dict))
|
||||
crosslinked_parents = defaultdict(list)
|
||||
orphaned_roles = set()
|
||||
orphaned_instancelinks = set()
|
||||
|
||||
|
||||
def resolve(obj, path):
|
||||
@ -143,10 +147,29 @@ for r in Role.objects.exclude(role_field__startswith='system_').order_by('id'):
|
||||
crosslinked[r.content_type_id][r.object_id][f'{r.role_field}_id'] = r.id
|
||||
continue
|
||||
|
||||
sys.stderr.write('===================================\n')
|
||||
|
||||
# Find orphaned InstanceLink records which point to non-existent Instance
|
||||
# objects.
|
||||
#
|
||||
# This can only happen because the current backup/restore process doesn't
|
||||
# preserve Instance tables, but rather recreates them on restore.
|
||||
existing_instance_ids = set(Instance.objects.values_list('id', flat=True))
|
||||
for link in InstanceLink.objects.all():
|
||||
# Consider the instancelink orphaned if source or target does not exist.
|
||||
orphaned_fks = {}
|
||||
if link.source_id and link.source_id not in existing_instance_ids:
|
||||
orphaned_fks["source_id"] = link.source_id
|
||||
if link.target_id and link.target_id not in existing_instance_ids:
|
||||
orphaned_fks["target_id"] = link.target_id
|
||||
if orphaned_fks:
|
||||
sys.stderr.write(f"InstanceLink id={link.id} has orphaned foreign keys: " + ", ".join(f"{k}={v}" for k, v in orphaned_fks.items()) + "\n")
|
||||
orphaned_instancelinks.add(link.id)
|
||||
|
||||
sys.stderr.write('===================================\n')
|
||||
|
||||
|
||||
# Output a script which fixes the issues found above.
|
||||
print(
|
||||
f"""\
|
||||
from collections import Counter
|
||||
@ -155,6 +178,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from awx.main.fields import ImplicitRoleField
|
||||
from awx.main.models.rbac import Role
|
||||
from awx.main.models.ha import InstanceLink
|
||||
|
||||
|
||||
delete_counts = Counter()
|
||||
@ -188,6 +212,14 @@ for child, parents in crosslinked_parents.items():
|
||||
print(f"r.parents.remove(*Role.objects.filter(id__in={parents!r}))")
|
||||
print(f"queue.add((r.content_object.__class__, r.object_id))")
|
||||
|
||||
if orphaned_instancelinks:
|
||||
print()
|
||||
print("# Delete InstanceLink objects that are pointing to non-existent Instances.")
|
||||
print()
|
||||
for instancelink_id in orphaned_instancelinks:
|
||||
print(f"_, c = InstanceLink.objects.filter(id={instancelink_id}).delete()")
|
||||
print("delete_counts.update(c)")
|
||||
|
||||
print('\n\n')
|
||||
print('print("Objects deleted:", dict(delete_counts.most_common()))')
|
||||
print('print("Objects updated:", dict(update_counts.most_common()))')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user