mirror of
https://github.com/ZwareBear/awx.git
synced 2026-03-20 07:43:35 -05:00
disable activity stream in cleanup_jobs and test context managers
This commit is contained in:
@@ -13,12 +13,14 @@ from django.utils.timezone import now
|
|||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
from awx.main.models import (
|
from awx.main.models import (
|
||||||
Job, AdHocCommand, ProjectUpdate, InventorySource, InventoryUpdate,
|
Job, AdHocCommand, ProjectUpdate, InventoryUpdate,
|
||||||
SystemJob, WorkflowJob, Notification, Group, Host
|
SystemJob, WorkflowJob, Notification
|
||||||
)
|
)
|
||||||
from awx.main.signals import ( # noqa
|
from awx.main.signals import ( # noqa
|
||||||
emit_update_inventory_on_created_or_deleted,
|
emit_update_inventory_on_created_or_deleted,
|
||||||
emit_update_inventory_computed_fields
|
emit_update_inventory_computed_fields,
|
||||||
|
disable_activity_stream,
|
||||||
|
disable_computed_fields
|
||||||
)
|
)
|
||||||
from django.db.models.signals import post_save, post_delete, m2m_changed # noqa
|
from django.db.models.signals import post_save, post_delete, m2m_changed # noqa
|
||||||
|
|
||||||
@@ -227,28 +229,12 @@ class Command(NoArgsCommand):
|
|||||||
deleted += 1
|
deleted += 1
|
||||||
return skipped, deleted
|
return skipped, deleted
|
||||||
|
|
||||||
def disable_job_signals(self):
|
|
||||||
sigstat = []
|
|
||||||
sigstat.append(post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Host))
|
|
||||||
sigstat.append(post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Host))
|
|
||||||
sigstat.append(post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Group))
|
|
||||||
sigstat.append(post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Group))
|
|
||||||
sigstat.append(m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.hosts.through))
|
|
||||||
sigstat.append(m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.parents.through))
|
|
||||||
sigstat.append(m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Host.inventory_sources.through))
|
|
||||||
sigstat.append(m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.inventory_sources.through))
|
|
||||||
sigstat.append(post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=InventorySource))
|
|
||||||
sigstat.append(post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=InventorySource))
|
|
||||||
sigstat.append(post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Job))
|
|
||||||
sigstat.append(post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Job))
|
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def handle_noargs(self, **options):
|
def handle_noargs(self, **options):
|
||||||
self.verbosity = int(options.get('verbosity', 1))
|
self.verbosity = int(options.get('verbosity', 1))
|
||||||
self.init_logging()
|
self.init_logging()
|
||||||
self.days = int(options.get('days', 90))
|
self.days = int(options.get('days', 90))
|
||||||
self.dry_run = bool(options.get('dry_run', False))
|
self.dry_run = bool(options.get('dry_run', False))
|
||||||
self.disable_job_signals()
|
|
||||||
try:
|
try:
|
||||||
self.cutoff = now() - datetime.timedelta(days=self.days)
|
self.cutoff = now() - datetime.timedelta(days=self.days)
|
||||||
except OverflowError:
|
except OverflowError:
|
||||||
@@ -261,10 +247,11 @@ class Command(NoArgsCommand):
|
|||||||
models_to_cleanup.add(m)
|
models_to_cleanup.add(m)
|
||||||
if not models_to_cleanup:
|
if not models_to_cleanup:
|
||||||
models_to_cleanup.update(model_names)
|
models_to_cleanup.update(model_names)
|
||||||
for m in model_names:
|
with disable_activity_stream(), disable_computed_fields():
|
||||||
if m in models_to_cleanup:
|
for m in model_names:
|
||||||
skipped, deleted = getattr(self, 'cleanup_%s' % m)()
|
if m in models_to_cleanup:
|
||||||
if self.dry_run:
|
skipped, deleted = getattr(self, 'cleanup_%s' % m)()
|
||||||
self.logger.log(99, '%s: %d would be deleted, %d would be skipped.', m.replace('_', ' '), deleted, skipped)
|
if self.dry_run:
|
||||||
else:
|
self.logger.log(99, '%s: %d would be deleted, %d would be skipped.', m.replace('_', ' '), deleted, skipped)
|
||||||
self.logger.log(99, '%s: %d deleted, %d skipped.', m.replace('_', ' '), deleted, skipped)
|
else:
|
||||||
|
self.logger.log(99, '%s: %d deleted, %d skipped.', m.replace('_', ' '), deleted, skipped)
|
||||||
|
|||||||
@@ -210,18 +210,24 @@ def cleanup_detached_labels_on_deleted_parent(sender, instance, **kwargs):
|
|||||||
l.delete()
|
l.delete()
|
||||||
|
|
||||||
|
|
||||||
post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Host)
|
def connect_computed_field_signals():
|
||||||
post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Host)
|
post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Host)
|
||||||
post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Group)
|
post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Host)
|
||||||
post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Group)
|
post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Group)
|
||||||
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.hosts.through)
|
post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Group)
|
||||||
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.parents.through)
|
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.hosts.through)
|
||||||
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Host.inventory_sources.through)
|
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.parents.through)
|
||||||
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.inventory_sources.through)
|
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Host.inventory_sources.through)
|
||||||
post_save.connect(emit_update_inventory_on_created_or_deleted, sender=InventorySource)
|
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.inventory_sources.through)
|
||||||
post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=InventorySource)
|
post_save.connect(emit_update_inventory_on_created_or_deleted, sender=InventorySource)
|
||||||
post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Job)
|
post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=InventorySource)
|
||||||
post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Job)
|
post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Job)
|
||||||
|
post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Job)
|
||||||
|
|
||||||
|
|
||||||
|
connect_computed_field_signals()
|
||||||
|
|
||||||
|
|
||||||
post_save.connect(emit_job_event_detail, sender=JobEvent)
|
post_save.connect(emit_job_event_detail, sender=JobEvent)
|
||||||
post_save.connect(emit_ad_hoc_command_event_detail, sender=AdHocCommandEvent)
|
post_save.connect(emit_ad_hoc_command_event_detail, sender=AdHocCommandEvent)
|
||||||
m2m_changed.connect(rebuild_role_ancestor_list, Role.parents.through)
|
m2m_changed.connect(rebuild_role_ancestor_list, Role.parents.through)
|
||||||
@@ -340,6 +346,24 @@ def disable_activity_stream():
|
|||||||
activity_stream_enabled.enabled = previous_value
|
activity_stream_enabled.enabled = previous_value
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def disable_computed_fields():
|
||||||
|
post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Host)
|
||||||
|
post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Host)
|
||||||
|
post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Group)
|
||||||
|
post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Group)
|
||||||
|
m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.hosts.through)
|
||||||
|
m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.parents.through)
|
||||||
|
m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Host.inventory_sources.through)
|
||||||
|
m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.inventory_sources.through)
|
||||||
|
post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=InventorySource)
|
||||||
|
post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=InventorySource)
|
||||||
|
post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Job)
|
||||||
|
post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Job)
|
||||||
|
yield
|
||||||
|
connect_computed_field_signals()
|
||||||
|
|
||||||
|
|
||||||
model_serializer_mapping = {
|
model_serializer_mapping = {
|
||||||
Organization: OrganizationSerializer,
|
Organization: OrganizationSerializer,
|
||||||
Inventory: InventorySerializer,
|
Inventory: InventorySerializer,
|
||||||
|
|||||||
47
awx/main/tests/functional/models/test_context_managers.py
Normal file
47
awx/main/tests/functional/models/test_context_managers.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
# AWX context managers for testing
|
||||||
|
from awx.main.models.rbac import batch_role_ancestor_rebuilding
|
||||||
|
from awx.main.signals import (
|
||||||
|
disable_activity_stream,
|
||||||
|
disable_computed_fields,
|
||||||
|
update_inventory_computed_fields
|
||||||
|
)
|
||||||
|
|
||||||
|
# AWX models
|
||||||
|
from awx.main.models.organization import Organization
|
||||||
|
from awx.main.models import ActivityStream, Job
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_rbac_batch_rebuilding(rando, organization):
|
||||||
|
with batch_role_ancestor_rebuilding():
|
||||||
|
organization.admin_role.members.add(rando)
|
||||||
|
inventory = organization.inventories.create(name='test-inventory')
|
||||||
|
assert rando not in inventory.admin_role
|
||||||
|
assert rando in inventory.admin_role
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_disable_activity_stream():
|
||||||
|
with disable_activity_stream():
|
||||||
|
Organization.objects.create(name='test-organization')
|
||||||
|
assert ActivityStream.objects.filter(organization__isnull=False).count() == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
class TestComputedFields:
|
||||||
|
|
||||||
|
def test_computed_fields_normal_use(self, mocker, inventory):
|
||||||
|
job = Job.objects.create(name='fake-job', inventory=inventory)
|
||||||
|
with mocker.patch.object(update_inventory_computed_fields, 'delay'):
|
||||||
|
job.delete()
|
||||||
|
update_inventory_computed_fields.delay.assert_called_once_with(inventory.id, True)
|
||||||
|
|
||||||
|
def test_disable_computed_fields(self, mocker, inventory):
|
||||||
|
job = Job.objects.create(name='fake-job', inventory=inventory)
|
||||||
|
with disable_computed_fields():
|
||||||
|
with mocker.patch.object(update_inventory_computed_fields, 'delay'):
|
||||||
|
job.delete()
|
||||||
|
update_inventory_computed_fields.delay.assert_not_called()
|
||||||
|
|
||||||
@@ -42,7 +42,9 @@ from django.db import transaction # noqa
|
|||||||
from awx.main.models import * # noqa
|
from awx.main.models import * # noqa
|
||||||
from awx.main.signals import ( # noqa
|
from awx.main.signals import ( # noqa
|
||||||
emit_update_inventory_on_created_or_deleted,
|
emit_update_inventory_on_created_or_deleted,
|
||||||
emit_update_inventory_computed_fields
|
emit_update_inventory_computed_fields,
|
||||||
|
disable_activity_stream,
|
||||||
|
disable_computed_fields
|
||||||
)
|
)
|
||||||
from django.db.models.signals import post_save, post_delete, m2m_changed # noqa
|
from django.db.models.signals import post_save, post_delete, m2m_changed # noqa
|
||||||
|
|
||||||
@@ -194,32 +196,13 @@ def mock_computed_fields(self, **kwargs):
|
|||||||
PrimordialModel.save = mock_save
|
PrimordialModel.save = mock_save
|
||||||
|
|
||||||
|
|
||||||
sigstat = []
|
|
||||||
sigstat.append(post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Host))
|
|
||||||
sigstat.append(post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Host))
|
|
||||||
sigstat.append(post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Group))
|
|
||||||
sigstat.append(post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Group))
|
|
||||||
sigstat.append(m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.hosts.through))
|
|
||||||
sigstat.append(m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.parents.through))
|
|
||||||
sigstat.append(m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Host.inventory_sources.through))
|
|
||||||
sigstat.append(m2m_changed.disconnect(emit_update_inventory_computed_fields, sender=Group.inventory_sources.through))
|
|
||||||
sigstat.append(post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=InventorySource))
|
|
||||||
sigstat.append(post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=InventorySource))
|
|
||||||
sigstat.append(post_save.disconnect(emit_update_inventory_on_created_or_deleted, sender=Job))
|
|
||||||
sigstat.append(post_delete.disconnect(emit_update_inventory_on_created_or_deleted, sender=Job))
|
|
||||||
|
|
||||||
print ' status of signal disconnects '
|
|
||||||
print ' (True means successful disconnect)'
|
|
||||||
print str(sigstat)
|
|
||||||
|
|
||||||
|
|
||||||
startTime = datetime.now()
|
startTime = datetime.now()
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
with batch_role_ancestor_rebuilding():
|
with batch_role_ancestor_rebuilding(), disable_computed_fields():
|
||||||
admin, created = User.objects.get_or_create(username = 'admin', is_superuser=True)
|
admin, created = User.objects.get_or_create(username = 'admin', is_superuser=True)
|
||||||
if created:
|
if created:
|
||||||
admin.is_superuser = True
|
admin.is_superuser = True
|
||||||
|
|||||||
Reference in New Issue
Block a user