Active flag removal: switched from using mark_inactive to delete calls

This commit is contained in:
Akita Noek 2016-03-10 13:58:00 -05:00
parent 1e7c71edfb
commit ba833d683e
18 changed files with 55 additions and 377 deletions

View File

@ -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):

View File

@ -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):

View File

@ -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:

View File

@ -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,

View File

@ -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):
'''

View File

@ -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):

View File

@ -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.

View File

@ -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)

View File

@ -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():

View File

@ -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'], [])

View File

@ -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)

View File

@ -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')

View File

@ -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'])):

View File

@ -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'])

View File

@ -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'])

View File

@ -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})

View File

@ -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)

View File

@ -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)