diff --git a/awx/api/generics.py b/awx/api/generics.py index a660b2acba..3c1321300c 100644 --- a/awx/api/generics.py +++ b/awx/api/generics.py @@ -7,7 +7,6 @@ import logging import time # Django -from django.http import Http404 from django.conf import settings from django.db import connection from django.shortcuts import get_object_or_404 @@ -415,9 +414,7 @@ class SubListCreateAttachDetachAPIView(SubListCreateAPIView): raise PermissionDenied() if parent_key: - # sub object has a ForeignKey to the parent, so we can't remove it - # from the set, only mark it as inactive. - sub.mark_inactive() + sub.delete() else: relationship.remove(sub) @@ -457,17 +454,9 @@ class RetrieveDestroyAPIView(RetrieveAPIView, generics.RetrieveDestroyAPIView): def destroy(self, request, *args, **kwargs): # somewhat lame that delete has to call it's own permissions check obj = self.get_object() - # FIXME: Why isn't the active check being caught earlier by RBAC? - if not getattr(obj, 'active', True): - raise Http404() - if not getattr(obj, 'is_active', True): - raise Http404() if not request.user.can_access(self.model, 'delete', obj): raise PermissionDenied() - if hasattr(obj, 'mark_inactive'): - obj.mark_inactive() - else: - raise NotImplementedError('destroy() not implemented yet for %s' % obj) + obj.delete() return Response(status=status.HTTP_204_NO_CONTENT) class RetrieveUpdateDestroyAPIView(RetrieveUpdateAPIView, RetrieveDestroyAPIView): diff --git a/awx/api/views.py b/awx/api/views.py index 4883342003..7d54f9dd56 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -1093,8 +1093,6 @@ class UserDetail(RetrieveUpdateDestroyAPIView): can_delete = request.user.can_access(User, 'delete', obj) if not can_delete: raise PermissionDenied('Cannot delete user') - for own_credential in Credential.objects.filter(user=obj): - own_credential.mark_inactive() return super(UserDetail, self).destroy(request, *args, **kwargs) class UserAccessList(ResourceAccessList): @@ -1400,7 +1398,7 @@ class GroupChildrenList(SubListCreateAttachDetachAPIView): if sub_id is not None: return super(GroupChildrenList, self).unattach(request, *args, **kwargs) parent = self.get_parent_object() - parent.mark_inactive() + parent.delete() return Response(status=status.HTTP_204_NO_CONTENT) def _unattach(self, request, *args, **kwargs): # FIXME: Disabled for now for UI support. @@ -1424,7 +1422,7 @@ class GroupChildrenList(SubListCreateAttachDetachAPIView): raise PermissionDenied() if sub.parents.filter(active=True).exclude(pk=parent.pk).count() == 0: - sub.mark_inactive() + sub.delete() else: relationship.remove(sub) @@ -1526,15 +1524,9 @@ class GroupDetail(RetrieveUpdateDestroyAPIView): def destroy(self, request, *args, **kwargs): obj = self.get_object() - # FIXME: Why isn't the active check being caught earlier by RBAC? - if not getattr(obj, 'active', True): - raise Http404() - if not getattr(obj, 'is_active', True): - raise Http404() if not request.user.can_access(self.model, 'delete', obj): raise PermissionDenied() - if hasattr(obj, 'mark_inactive'): - obj.mark_inactive_recursive() + obj.delete_recursive() return Response(status=status.HTTP_204_NO_CONTENT) class GroupAccessList(ResourceAccessList): diff --git a/awx/main/management/commands/inventory_import.py b/awx/main/management/commands/inventory_import.py index 187a04af7e..76898af111 100644 --- a/awx/main/management/commands/inventory_import.py +++ b/awx/main/management/commands/inventory_import.py @@ -53,13 +53,13 @@ class MemObject(object): ''' Common code shared between in-memory groups and hosts. ''' - + def __init__(self, name, source_dir): assert name, 'no name' assert source_dir, 'no source dir' self.name = name self.source_dir = source_dir - + def load_vars(self, base_path): all_vars = {} files_found = 0 @@ -107,7 +107,7 @@ class MemGroup(MemObject): group_vars = os.path.join(source_dir, 'group_vars', self.name) self.variables = self.load_vars(group_vars) logger.debug('Loaded group: %s', self.name) - + def child_group_by_name(self, name, loader): if name == 'all': return @@ -266,7 +266,7 @@ class BaseLoader(object): logger.debug('Filtering group %s', name) return None if name not in self.all_group.all_groups: - group = MemGroup(name, self.source_dir) + group = MemGroup(name, self.source_dir) if not child: all_group.add_child_group(group) self.all_group.all_groups[name] = group @@ -315,7 +315,7 @@ class IniLoader(BaseLoader): for t in tokens[1:]: k,v = t.split('=', 1) host.variables[k] = v - group.add_host(host) + group.add_host(host) elif input_mode == 'children': group.child_group_by_name(line, self) elif input_mode == 'vars': @@ -328,7 +328,7 @@ class IniLoader(BaseLoader): # from API documentation: # # if called with --list, inventory outputs like so: -# +# # { # "databases" : { # "hosts" : [ "host1.example.com", "host2.example.com" ], @@ -581,7 +581,7 @@ class Command(NoArgsCommand): def _get_instance_id(self, from_dict, default=''): ''' Retrieve the instance ID from the given dict of host variables. - + The instance ID variable may be specified as 'foo.bar', in which case the lookup will traverse into nested dicts, equivalent to: @@ -765,7 +765,7 @@ class Command(NoArgsCommand): del_pks = all_del_pks[offset:(offset + self._batch_size)] for host in hosts_qs.filter(pk__in=del_pks): host_name = host.name - host.mark_inactive() + host.delete() self.logger.info('Deleted host "%s"', host_name) if settings.SQL_DEBUG: self.logger.warning('host deletions took %d queries for %d hosts', @@ -799,7 +799,8 @@ class Command(NoArgsCommand): del_pks = all_del_pks[offset:(offset + self._batch_size)] for group in groups_qs.filter(pk__in=del_pks): group_name = group.name - group.mark_inactive(recompute=False) + with ignore_inventory_computed_fields(): + group.delete() self.logger.info('Group "%s" deleted', group_name) if settings.SQL_DEBUG: self.logger.warning('group deletions took %d queries for %d groups', @@ -1297,7 +1298,7 @@ class Command(NoArgsCommand): except CommandError as e: self.mark_license_failure(save=True) raise e - + if self.inventory_source.group: inv_name = 'group "%s"' % (self.inventory_source.group.name) else: @@ -1336,7 +1337,7 @@ class Command(NoArgsCommand): self.inventory_update.result_traceback = tb self.inventory_update.status = status self.inventory_update.save(update_fields=['status', 'result_traceback']) - + if exc and isinstance(exc, CommandError): sys.exit(1) elif exc: diff --git a/awx/main/models/base.py b/awx/main/models/base.py index 677e48e92d..a25dd1d154 100644 --- a/awx/main/models/base.py +++ b/awx/main/models/base.py @@ -203,15 +203,6 @@ class PasswordFieldsModel(BaseModel): def _password_field_allows_ask(self, field): return False # Override in subclasses if needed. - def mark_inactive(self, save=True): - ''' - When marking a password model inactive we'll clear sensitive fields - ''' - for sensitive_field in self.PASSWORD_FIELDS: - setattr(self, sensitive_field, "") - self.save() - super(PasswordFieldsModel, self).mark_inactive(save=save) - def save(self, *args, **kwargs): new_instance = not bool(self.pk) # If update_fields has been specified, add our field names to it, diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 32175b19d9..44f1a404f6 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -26,7 +26,7 @@ from awx.main.models.jobs import Job from awx.main.models.unified_jobs import * # noqa from awx.main.models.mixins import ResourceMixin from awx.main.models.notifications import Notifier -from awx.main.utils import ignore_inventory_computed_fields, _inventory_updates +from awx.main.utils import _inventory_updates from awx.main.conf import tower_settings __all__ = ['Inventory', 'Host', 'Group', 'InventorySource', 'InventoryUpdate', 'CustomInventoryScript'] @@ -120,18 +120,6 @@ class Inventory(CommonModel, ResourceMixin): def get_absolute_url(self): return reverse('api:inventory_detail', args=(self.pk,)) - def mark_inactive(self, save=True): - ''' - When marking inventory inactive, also mark hosts and groups inactive. - ''' - with ignore_inventory_computed_fields(): - for host in self.hosts.filter(active=True): - host.mark_inactive() - for group in self.groups.filter(active=True): - group.mark_inactive(recompute=False) - for inventory_source in self.inventory_sources.filter(active=True): - inventory_source.mark_inactive() - super(Inventory, self).mark_inactive(save=save) variables_dict = VarsDictProperty('variables') @@ -412,15 +400,6 @@ class Host(CommonModelNameNotUnique, ResourceMixin): def get_absolute_url(self): return reverse('api:host_detail', args=(self.pk,)) - def mark_inactive(self, save=True, from_inventory_import=False, skip_active_check=False): - ''' - When marking hosts inactive, remove all associations to related - inventory sources. - ''' - super(Host, self).mark_inactive(save=save, skip_active_check=skip_active_check) - if not from_inventory_import: - self.inventory_sources.clear() - def update_computed_fields(self, update_inventory=True, update_groups=True): ''' Update model fields that are computed from database relationships. @@ -575,11 +554,11 @@ class Group(CommonModelNameNotUnique, ResourceMixin): return reverse('api:group_detail', args=(self.pk,)) @transaction.atomic - def mark_inactive_recursive(self): - from awx.main.tasks import bulk_inventory_element_delete + def delete_recursive(self): from awx.main.utils import ignore_inventory_computed_fields from awx.main.signals import disable_activity_stream + def mark_actual(): all_group_hosts = Group.hosts.through.objects.select_related("host", "group").filter(group__inventory=self.inventory) group_hosts = {'groups': {}, 'hosts': {}} @@ -629,38 +608,13 @@ class Group(CommonModelNameNotUnique, ResourceMixin): for direct_child in group_children[group]: linked_children.append((group, direct_child)) marked_groups.append(group) - Group.objects.filter(id__in=marked_groups).update(active=False) - Host.objects.filter(id__in=marked_hosts).update(active=False) - Group.parents.through.objects.filter(to_group__id__in=marked_groups) - Group.hosts.through.objects.filter(group__id__in=marked_groups) - Group.inventory_sources.through.objects.filter(group__id__in=marked_groups).delete() - bulk_inventory_element_delete.delay(self.inventory.id, groups=marked_groups, hosts=marked_hosts) + Group.objects.filter(id__in=marked_groups).delete() + Host.objects.filter(id__in=marked_hosts).delete() + update_inventory_computed_fields.delay(self.inventory.id) with ignore_inventory_computed_fields(): with disable_activity_stream(): mark_actual() - def mark_inactive(self, save=True, recompute=True, from_inventory_import=False, skip_active_check=False): - ''' - When marking groups inactive, remove all associations to related - groups/hosts/inventory_sources. - ''' - def mark_actual(): - super(Group, self).mark_inactive(save=save, skip_active_check=skip_active_check) - self.inventory_source.mark_inactive(save=save) - self.inventory_sources.clear() - self.parents.clear() - self.children.clear() - self.hosts.clear() - i = self.inventory - - if from_inventory_import: - super(Group, self).mark_inactive(save=save, skip_active_check=skip_active_check) - elif recompute: - with ignore_inventory_computed_fields(): - mark_actual() - i.update_computed_fields() - else: - mark_actual() def update_computed_fields(self): ''' diff --git a/awx/main/models/organization.py b/awx/main/models/organization.py index 1362b23f37..d83c68832e 100644 --- a/awx/main/models/organization.py +++ b/awx/main/models/organization.py @@ -79,11 +79,6 @@ class Organization(CommonModel, NotificationFieldsModel, ResourceMixin): def __unicode__(self): return self.name - def mark_inactive(self, save=True): - for script in self.custom_inventory_scripts.all(): - script.organization = None - script.save() - super(Organization, self).mark_inactive(save=save) class Team(CommonModelNameNotUnique, ResourceMixin): @@ -135,14 +130,6 @@ class Team(CommonModelNameNotUnique, ResourceMixin): def get_absolute_url(self): return reverse('api:team_detail', args=(self.pk,)) - def mark_inactive(self, save=True): - ''' - When marking a team inactive we'll wipe out its credentials also - ''' - for cred in self.credentials.all(): - cred.mark_inactive() - super(Team, self).mark_inactive(save=save) - class Permission(CommonModelNameNotUnique): ''' @@ -351,22 +338,6 @@ class AuthToken(BaseModel): return self.key -# Add mark_inactive method to User model. -def user_mark_inactive(user, save=True): - '''Use instead of delete to rename and mark users inactive.''' - if user.is_active: - # Set timestamp to datetime.isoformat() but without the time zone - # offset to stay withint the 30 character username limit. - dtnow = tz_now() - deleted_ts = dtnow.strftime('%Y-%m-%dT%H:%M:%S.%f') - user.username = '_d_%s' % deleted_ts - user.is_active = False - if save: - user.save() - -User.add_to_class('mark_inactive', user_mark_inactive) - - # Add get_absolute_url method to User model if not present. if not hasattr(User, 'get_absolute_url'): def user_get_absolute_url(user): diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 3750ccf41e..5b9949dbe9 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -210,17 +210,6 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, Notificatio self.next_job_run = related_schedules[0].next_run self.save(update_fields=['next_schedule', 'next_job_run']) - def mark_inactive(self, save=True): - ''' - When marking a unified job template inactive, also mark its schedules - inactive. - ''' - for schedule in self.schedules.filter(active=True): - schedule.mark_inactive() - schedule.enabled = False - schedule.save() - super(UnifiedJobTemplate, self).mark_inactive(save=save) - def save(self, *args, **kwargs): # If update_fields has been specified, add our field names to it, # if it hasn't been specified, then we're just doing a normal save. diff --git a/awx/main/signals.py b/awx/main/signals.py index 797296ef13..dbccf61dd6 100644 --- a/awx/main/signals.py +++ b/awx/main/signals.py @@ -265,7 +265,7 @@ def migrate_children_from_inactive_group_to_parent_groups(sender, **kwargs): if inventory_source_pk: try: inventory_source = InventorySource.objects.get(pk=inventory_source_pk, active=True) - inventory_source.mark_inactive() + inventory_source.delete() except InventorySource.DoesNotExist: pass inventory_pk = getattr(instance, '_saved_inventory_pk', None) diff --git a/awx/main/tasks.py b/awx/main/tasks.py index b8bb60905b..49589a6e3b 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -110,17 +110,6 @@ def run_administrative_checks(self): tower_admin_emails, fail_silently=True) -@task() -def bulk_inventory_element_delete(inventory, hosts=[], groups=[]): - from awx.main.signals import disable_activity_stream - with ignore_inventory_computed_fields(): - with disable_activity_stream(): - for group in groups: - Group.objects.get(id=group).mark_inactive(skip_active_check=True) - for host in hosts: - Host.objects.get(id=host).mark_inactive(skip_active_check=True) - update_inventory_computed_fields(inventory) - @task(bind=True) def tower_periodic_scheduler(self): def get_last_run(): diff --git a/awx/main/tests/old/ad_hoc.py b/awx/main/tests/old/ad_hoc.py index 52e22faf21..95b8130664 100644 --- a/awx/main/tests/old/ad_hoc.py +++ b/awx/main/tests/old/ad_hoc.py @@ -637,8 +637,8 @@ class AdHocCommandApiTest(BaseAdHocCommandTest): # Verify that the credential and inventory are null when they have # been deleted, can delete an ad hoc command without inventory or # credential. - self.credential.mark_inactive() - self.inventory.mark_inactive() + self.credential.delete() + self.inventory.delete() with self.current_user('admin'): response = self.get(url, expect=200) self.assertEqual(response['credential'], None) @@ -758,7 +758,7 @@ class AdHocCommandApiTest(BaseAdHocCommandTest): tower_settings.AD_HOC_COMMANDS = ad_hoc_commands # Try to relaunch after the inventory has been marked inactive. - self.inventory.mark_inactive() + self.inventory.delete() with self.current_user('admin'): response = self.get(url, expect=200) self.assertEqual(response['passwords_needed_to_start'], []) diff --git a/awx/main/tests/old/commands/age_deleted.py b/awx/main/tests/old/commands/age_deleted.py deleted file mode 100644 index ec5591d28e..0000000000 --- a/awx/main/tests/old/commands/age_deleted.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2015 Ansible, Inc. -# All Rights Reserved - -# AWX -from awx.main.tests.base import BaseTest -from command_base import BaseCommandMixin - -__all__ = ['AgeDeletedCommandFunctionalTest'] - -class AgeDeletedCommandFunctionalTest(BaseCommandMixin, BaseTest): - def setUp(self): - super(AgeDeletedCommandFunctionalTest, self).setUp() - self.create_test_license_file() - self.setup_instances() - self.setup_users() - self.organization = self.make_organization(self.super_django_user) - self.credential = self.make_credential() - self.credential2 = self.make_credential() - self.credential.mark_inactive(True) - self.credential2.mark_inactive(True) - self.credential_active = self.make_credential() - self.super_django_user.mark_inactive(True) - - def test_default(self): - result, stdout, stderr = self.run_command('age_deleted') - self.assertEqual(stdout, 'Aged %d items\n' % 3) - - def test_type(self): - result, stdout, stderr = self.run_command('age_deleted', type='Credential') - self.assertEqual(stdout, 'Aged %d items\n' % 2) - - def test_id_type(self): - result, stdout, stderr = self.run_command('age_deleted', type='Credential', id=self.credential.pk) - self.assertEqual(stdout, 'Aged %d items\n' % 1) diff --git a/awx/main/tests/old/commands/commands_monolithic.py b/awx/main/tests/old/commands/commands_monolithic.py index c658f6411c..c3de826259 100644 --- a/awx/main/tests/old/commands/commands_monolithic.py +++ b/awx/main/tests/old/commands/commands_monolithic.py @@ -15,7 +15,6 @@ import unittest2 as unittest # Django from django.conf import settings -from django.contrib.auth.models import User from django.core.management import call_command from django.core.management.base import CommandError from django.utils.timezone import now @@ -232,126 +231,6 @@ class DumpDataTest(BaseCommandMixin, BaseTest): self.assertEqual(result, None) json.loads(stdout) -class CleanupDeletedTest(BaseCommandMixin, BaseTest): - ''' - Test cases for cleanup_deleted management command. - ''' - - def setUp(self): - self.start_redis() - super(CleanupDeletedTest, self).setUp() - self.create_test_inventories() - - def tearDown(self): - super(CleanupDeletedTest, self).tearDown() - self.stop_redis() - - def get_model_counts(self): - def get_models(m): - if not m._meta.abstract: - yield m - for sub in m.__subclasses__(): - for subm in get_models(sub): - yield subm - counts = {} - for model in get_models(PrimordialModel): - active = model.objects.filter(active=True).count() - inactive = model.objects.filter(active=False).count() - counts[model] = (active, inactive) - return counts - - def test_cleanup_our_models(self): - # Test with nothing to be deleted. - counts_before = self.get_model_counts() - self.assertFalse(sum(x[1] for x in counts_before.values())) - result, stdout, stderr = self.run_command('cleanup_deleted') - self.assertEqual(result, None) - counts_after = self.get_model_counts() - self.assertEqual(counts_before, counts_after) - # "Delete" some hosts. - for host in Host.objects.all(): - host.mark_inactive() - # With no parameters, "days" defaults to 90, which won't cleanup any of - # the hosts we just removed. - counts_before = self.get_model_counts() - self.assertTrue(sum(x[1] for x in counts_before.values())) - result, stdout, stderr = self.run_command('cleanup_deleted') - self.assertEqual(result, None) - counts_after = self.get_model_counts() - self.assertEqual(counts_before, counts_after) - # Even with days=1, the hosts will remain. - counts_before = self.get_model_counts() - self.assertTrue(sum(x[1] for x in counts_before.values())) - result, stdout, stderr = self.run_command('cleanup_deleted', days=1) - self.assertEqual(result, None) - counts_after = self.get_model_counts() - self.assertEqual(counts_before, counts_after) - # With days=0, the hosts will be deleted. - counts_before = self.get_model_counts() - self.assertTrue(sum(x[1] for x in counts_before.values())) - result, stdout, stderr = self.run_command('cleanup_deleted', days=0) - self.assertEqual(result, None) - counts_after = self.get_model_counts() - self.assertNotEqual(counts_before, counts_after) - self.assertFalse(sum(x[1] for x in counts_after.values())) - return # Don't test how long it takes (for now). - - # Create lots of hosts already marked as deleted. - t = time.time() - dtnow = now() - for x in xrange(1000): - hostname = "_deleted_%s_host-%d" % (dtnow.isoformat(), x) - host = self.inventories[0].hosts.create(name=hostname, active=False) - create_elapsed = time.time() - t - - # Time how long it takes to cleanup deleted items, should be no more - # then the time taken to create them. - counts_before = self.get_model_counts() - self.assertTrue(sum(x[1] for x in counts_before.values())) - t = time.time() - result, stdout, stderr = self.run_command('cleanup_deleted', days=0) - cleanup_elapsed = time.time() - t - self.assertEqual(result, None) - counts_after = self.get_model_counts() - self.assertNotEqual(counts_before, counts_after) - self.assertFalse(sum(x[1] for x in counts_after.values())) - self.assertTrue(cleanup_elapsed < create_elapsed, - 'create took %0.3fs, cleanup took %0.3fs, expected < %0.3fs' % (create_elapsed, cleanup_elapsed, create_elapsed)) - - def get_user_counts(self): - active = User.objects.filter(is_active=True).count() - inactive = User.objects.filter(is_active=False).count() - return active, inactive - - def test_cleanup_user_model(self): - # Test with nothing to be deleted. - counts_before = self.get_user_counts() - self.assertFalse(counts_before[1]) - result, stdout, stderr = self.run_command('cleanup_deleted') - self.assertEqual(result, None) - counts_after = self.get_user_counts() - self.assertEqual(counts_before, counts_after) - # "Delete some users". - for user in User.objects.all(): - user.mark_inactive() - self.assertTrue(len(user.username) <= 30, - 'len(%r) == %d' % (user.username, len(user.username))) - # With days=1, no users will be deleted. - counts_before = self.get_user_counts() - self.assertTrue(counts_before[1]) - result, stdout, stderr = self.run_command('cleanup_deleted', days=1) - self.assertEqual(result, None) - counts_after = self.get_user_counts() - self.assertEqual(counts_before, counts_after) - # With days=0, inactive users will be deleted. - counts_before = self.get_user_counts() - self.assertTrue(counts_before[1]) - result, stdout, stderr = self.run_command('cleanup_deleted', days=0) - self.assertEqual(result, None) - counts_after = self.get_user_counts() - self.assertNotEqual(counts_before, counts_after) - self.assertFalse(counts_after[1]) - @override_settings(CELERY_ALWAYS_EAGER=True, CELERY_EAGER_PROPAGATES_EXCEPTIONS=True, ANSIBLE_TRANSPORT='local') diff --git a/awx/main/tests/old/inventory.py b/awx/main/tests/old/inventory.py index a3f3b63794..a47807e62b 100644 --- a/awx/main/tests/old/inventory.py +++ b/awx/main/tests/old/inventory.py @@ -423,7 +423,7 @@ class InventoryTest(BaseTest): del_children_url = reverse('api:group_children_list', args=(del_group.pk,)) nondel_url = reverse('api:group_detail', args=(Group.objects.get(name='nondel').pk,)) - del_group.mark_inactive() + del_group.delete() nondel_detail = self.get(nondel_url, expect=200, auth=self.get_normal_credentials()) self.post(del_children_url, data=nondel_detail, expect=403, auth=self.get_normal_credentials()) @@ -944,13 +944,10 @@ class InventoryTest(BaseTest): # Mark group C inactive. Its child groups and hosts should now also be # attached to group A. Group D hosts should be unchanged. Group C # should also no longer have any group or host relationships. - g_c.mark_inactive() + g_c.delete() self.assertTrue(g_d in g_a.children.all()) self.assertTrue(h_c in g_a.hosts.all()) self.assertFalse(h_d in g_a.hosts.all()) - self.assertFalse(g_c.parents.all()) - self.assertFalse(g_c.children.all()) - self.assertFalse(g_c.hosts.all()) def test_safe_delete_recursion(self): # First hierarchy @@ -989,11 +986,9 @@ class InventoryTest(BaseTest): self.assertTrue(other_sub_group in sub_group.children.all()) # Now recursively remove its parent and the reference from subgroup should remain - other_top_group.mark_inactive_recursive() - other_top_group = Group.objects.get(pk=other_top_group.pk) + other_top_group.delete_recursive() self.assertTrue(s2 in sub_group.all_hosts.all()) self.assertTrue(other_sub_group in sub_group.children.all()) - self.assertFalse(other_top_group.active) def test_group_parents_and_children(self): # Test for various levels of group parent/child relations, with hosts, @@ -1173,7 +1168,7 @@ class InventoryTest(BaseTest): # Delete recently added hosts and verify the count drops. hostnames4 = list('defg') for host in Host.objects.filter(name__in=hostnames4): - host.mark_inactive() + host.delete() with self.current_user(self.super_django_user): response = self.get(url) for n, d in enumerate(reversed(response['hosts'])): diff --git a/awx/main/tests/old/jobs/job_launch.py b/awx/main/tests/old/jobs/job_launch.py index 0beb3a9546..5cd9f9e7e0 100644 --- a/awx/main/tests/old/jobs/job_launch.py +++ b/awx/main/tests/old/jobs/job_launch.py @@ -96,7 +96,7 @@ class JobTemplateLaunchTest(BaseJobTestMixin, django.test.TransactionTestCase): def test_credential_explicit(self): # Explicit, credential with self.current_user(self.user_sue): - self.cred_sue.mark_inactive() + self.cred_sue.delete() response = self.post(self.launch_url, {'credential': self.cred_doug.pk}, expect=202) j = Job.objects.get(pk=response['job']) self.assertEqual(j.status, 'new') @@ -105,7 +105,7 @@ class JobTemplateLaunchTest(BaseJobTestMixin, django.test.TransactionTestCase): def test_credential_explicit_via_credential_id(self): # Explicit, credential with self.current_user(self.user_sue): - self.cred_sue.mark_inactive() + self.cred_sue.delete() response = self.post(self.launch_url, {'credential_id': self.cred_doug.pk}, expect=202) j = Job.objects.get(pk=response['job']) self.assertEqual(j.status, 'new') @@ -131,15 +131,16 @@ class JobTemplateLaunchTest(BaseJobTestMixin, django.test.TransactionTestCase): # Can't launch a job template without a credential defined (or if we # pass an invalid/inactive credential value). with self.current_user(self.user_sue): - self.cred_sue.mark_inactive() + self.cred_sue.delete() self.post(self.launch_url, {}, expect=400) self.post(self.launch_url, {'credential': 0}, expect=400) self.post(self.launch_url, {'credential_id': 0}, expect=400) self.post(self.launch_url, {'credential': 'one'}, expect=400) self.post(self.launch_url, {'credential_id': 'one'}, expect=400) - self.cred_doug.mark_inactive() - self.post(self.launch_url, {'credential': self.cred_doug.pk}, expect=400) - self.post(self.launch_url, {'credential_id': self.cred_doug.pk}, expect=400) + doug_pk = self.cred_doug.pk + self.cred_doug.delete() + self.post(self.launch_url, {'credential': cred_doug_pk}, expect=400) + self.post(self.launch_url, {'credential_id': cred_doug_pk}, expect=400) def test_explicit_unowned_cred(self): # Explicitly specify a credential that we don't have access to @@ -174,7 +175,7 @@ class JobTemplateLaunchTest(BaseJobTestMixin, django.test.TransactionTestCase): def test_deleted_credential_fail(self): # Job Templates with deleted credentials cannot be launched. - self.cred_sue.mark_inactive() + self.cred_sue.delete() with self.current_user(self.user_sue): self.post(self.launch_url, {}, expect=400) @@ -202,7 +203,7 @@ class JobTemplateLaunchPasswordsTest(BaseJobTestMixin, django.test.TransactionTe passwords_required = ['ssh_password', 'become_password', 'ssh_key_unlock'] # Job Templates with deleted credentials cannot be launched. with self.current_user(self.user_sue): - self.cred_sue_ask.mark_inactive() + self.cred_sue_ask.delete() response = self.post(self.launch_url, {'credential_id': self.cred_sue_ask_many.pk}, expect=400) for p in passwords_required: self.assertIn(p, response['passwords_needed_to_start']) diff --git a/awx/main/tests/old/projects.py b/awx/main/tests/old/projects.py index 9834356860..416ad41327 100644 --- a/awx/main/tests/old/projects.py +++ b/awx/main/tests/old/projects.py @@ -169,7 +169,7 @@ class ProjectsTest(BaseTransactionTest): local_path = project.local_path response = self.get(url, expect=200, auth=self.get_super_credentials()) self.assertTrue(local_path not in response['project_local_paths']) - project.mark_inactive() + project.delete() response = self.get(url, expect=200, auth=self.get_super_credentials()) self.assertTrue(local_path in response['project_local_paths']) diff --git a/awx/main/tests/old/scripts.py b/awx/main/tests/old/scripts.py index 1b5295d0bd..735d0f0197 100644 --- a/awx/main/tests/old/scripts.py +++ b/awx/main/tests/old/scripts.py @@ -88,7 +88,8 @@ class InventoryScriptTest(BaseScriptTest): inventory=inventory, variables=variables) if x in (3, 7): - host.mark_inactive() + host.delete() + continue hosts.append(host) # add localhost just to make sure it's thrown into all (Ansible github bug) @@ -106,7 +107,8 @@ class InventoryScriptTest(BaseScriptTest): inventory=inventory, variables=variables) if x == 2: - group.mark_inactive() + group.delete() + continue groups.append(group) group.hosts.add(hosts[x]) group.hosts.add(hosts[x + 5]) @@ -320,9 +322,9 @@ class InventoryScriptTest(BaseScriptTest): def test_with_deleted_inventory(self): inventory = self.inventories[0] - inventory.mark_inactive() - self.assertFalse(inventory.active) - os.environ['INVENTORY_ID'] = str(inventory.pk) + pk = inventory.pk + inventory.delete() + os.environ['INVENTORY_ID'] = str(pk) rc, stdout, stderr = self.run_inventory_script(list=True) self.assertNotEqual(rc, 0, stderr) self.assertEqual(json.loads(stdout), {'failed': True}) diff --git a/awx/main/tests/old/tasks.py b/awx/main/tests/old/tasks.py index a57202a958..30f58353c2 100644 --- a/awx/main/tests/old/tasks.py +++ b/awx/main/tests/old/tasks.py @@ -592,26 +592,8 @@ class RunJobTest(BaseJobExecutionTest): new_group.children.remove(self.group) new_group = Group.objects.get(pk=new_group.pk) self.assertFalse(new_group.has_active_failures) - # Mark host inactive (should clear flag on parent group and inventory) - self.host.mark_inactive() - self.group = Group.objects.get(pk=self.group.pk) - self.assertFalse(self.group.has_active_failures) - self.inventory = Inventory.objects.get(pk=self.inventory.pk) - self.assertFalse(self.inventory.has_active_failures) - # Un-mark host as inactive (need to force update of flag on group and - # inventory) - host = self.host - host.name = '_'.join(host.name.split('_')[3:]) or 'undeleted host' - host.active = True - host.save() - host.update_computed_fields() - self.group = Group.objects.get(pk=self.group.pk) - self.assertTrue(self.group.has_active_failures) - self.inventory = Inventory.objects.get(pk=self.inventory.pk) - self.assertTrue(self.inventory.has_active_failures) - # Delete host. (should clear flag) + # Delete host (should clear flag on parent group and inventory) self.host.delete() - self.host = None self.group = Group.objects.get(pk=self.group.pk) self.assertFalse(self.group.has_active_failures) self.inventory = Inventory.objects.get(pk=self.inventory.pk) @@ -619,30 +601,7 @@ class RunJobTest(BaseJobExecutionTest): def test_update_has_active_failures_when_job_removed(self): job = self.test_run_job_that_fails() - # Mark job as inactive (should clear flags). - job.mark_inactive() - self.host = Host.objects.get(pk=self.host.pk) - self.assertFalse(self.host.has_active_failures) - self.group = Group.objects.get(pk=self.group.pk) - self.assertFalse(self.group.has_active_failures) - self.inventory = Inventory.objects.get(pk=self.inventory.pk) - self.assertFalse(self.inventory.has_active_failures) - # Un-mark job as inactive (need to force update of flag) - job.active = True - job.save() - # Need to manually update last_job on host... - host = Host.objects.get(pk=self.host.pk) - host.last_job = job - host.last_job_host_summary = JobHostSummary.objects.get(job=job, host=host) - host.save() - self.inventory.update_computed_fields() - self.host = Host.objects.get(pk=self.host.pk) - self.assertTrue(self.host.has_active_failures) - self.group = Group.objects.get(pk=self.group.pk) - self.assertTrue(self.group.has_active_failures) - self.inventory = Inventory.objects.get(pk=self.inventory.pk) - self.assertTrue(self.inventory.has_active_failures) - # Delete job entirely. + # Delete (should clear flags). job.delete() self.host = Host.objects.get(pk=self.host.pk) self.assertFalse(self.host.has_active_failures) @@ -662,8 +621,8 @@ class RunJobTest(BaseJobExecutionTest): self.host = Host.objects.get(pk=self.host.pk) self.assertEqual(self.host.last_job, job1) self.assertEqual(self.host.last_job_host_summary.job, job1) - # Mark job1 inactive (should update host.last_job to None). - job1.mark_inactive() + # Delete job1 (should update host.last_job to None). + job1.delete() self.host = Host.objects.get(pk=self.host.pk) self.assertEqual(self.host.last_job, None) self.assertEqual(self.host.last_job_host_summary, None) diff --git a/awx/main/tests/old/users.py b/awx/main/tests/old/users.py index 2fa89402f9..75377037da 100644 --- a/awx/main/tests/old/users.py +++ b/awx/main/tests/old/users.py @@ -196,7 +196,7 @@ class UsersTest(BaseTest): self.post(url, expect=201, data=new_user2, auth=self.get_normal_credentials()) self.post(url, expect=400, data=new_user2, auth=self.get_normal_credentials()) # Normal user cannot add users after his org is marked inactive. - self.organizations[0].mark_inactive() + self.organizations[0].delete() new_user3 = dict(username='blippy3') self.post(url, expect=403, data=new_user3, auth=self.get_normal_credentials()) @@ -316,7 +316,7 @@ class UsersTest(BaseTest): remote_addr=remote_addr) # Token auth should be denied if the user is inactive. - self.normal_django_user.mark_inactive() + self.normal_django_user.delete() response = self.get(user_me_url, expect=401, auth=auth_token2, remote_addr=remote_addr) self.assertEqual(response['detail'], 'User inactive or deleted') @@ -422,7 +422,7 @@ class UsersTest(BaseTest): # Normal user can no longer see all users after the organization he # admins is marked inactive, nor can he see any other users that were # in that org, so he only sees himself. - self.organizations[0].mark_inactive() + self.organizations[0].delete() data3 = self.get(url, expect=200, auth=self.get_normal_credentials()) self.assertEquals(data3['count'], 1)