diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index 2443e16f45..66aab8242f 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -146,6 +146,7 @@ activity_stream_registrar.connect(WorkflowJob) # prevent API filtering on certain Django-supplied sensitive fields prevent_search(User._meta.get_field('password')) + # Always, always, always defer result_stdout_text for polymorphic UnifiedJob rows # TODO: remove this defer in 3.3 when we implement https://github.com/ansible/ansible-tower/issues/5436 def defer_stdout(f): diff --git a/awx/main/signals.py b/awx/main/signals.py index 81f6e17092..77fd91a5c3 100644 --- a/awx/main/signals.py +++ b/awx/main/signals.py @@ -388,6 +388,9 @@ def activity_stream_create(sender, instance, created, **kwargs): # Skip recording any inventory source directly associated with a group. if isinstance(instance, InventorySource) and instance.deprecated_group: return + _type = type(instance) + if getattr(_type, '_deferred', False): + return object1 = camelcase_to_underscore(instance.__class__.__name__) changes = model_to_dict(instance, model_serializer_mapping) # Special case where Job survey password variables need to be hidden @@ -421,6 +424,9 @@ def activity_stream_update(sender, instance, **kwargs): changes = model_instance_diff(old, new, model_serializer_mapping) if changes is None: return + _type = type(instance) + if getattr(_type, '_deferred', False): + return object1 = camelcase_to_underscore(instance.__class__.__name__) activity_entry = ActivityStream( operation='update', @@ -445,6 +451,9 @@ def activity_stream_delete(sender, instance, **kwargs): # explicitly called with flag on in Inventory.schedule_deletion. if isinstance(instance, Inventory) and not kwargs.get('inventory_delete_flag', False): return + _type = type(instance) + if getattr(_type, '_deferred', False): + return changes = model_to_dict(instance) object1 = camelcase_to_underscore(instance.__class__.__name__) activity_entry = ActivityStream( @@ -466,6 +475,9 @@ def activity_stream_associate(sender, instance, **kwargs): else: return obj1 = instance + _type = type(instance) + if getattr(_type, '_deferred', False): + return object1=camelcase_to_underscore(obj1.__class__.__name__) obj_rel = sender.__module__ + "." + sender.__name__ @@ -476,6 +488,9 @@ def activity_stream_associate(sender, instance, **kwargs): if not obj2_actual.exists(): continue obj2_actual = obj2_actual[0] + _type = type(obj2_actual) + if getattr(_type, '_deferred', False): + return if isinstance(obj2_actual, Role) and obj2_actual.content_object is not None: obj2_actual = obj2_actual.content_object object2 = camelcase_to_underscore(obj2_actual.__class__.__name__) diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 6753fb8577..459b296d5c 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -316,7 +316,11 @@ def awx_periodic_scheduler(self): def _send_notification_templates(instance, status_str): if status_str not in ['succeeded', 'failed']: raise ValueError(_("status_str must be either succeeded or failed")) - notification_templates = instance.get_notification_templates() + try: + notification_templates = instance.get_notification_templates() + except: + logger.warn("No notification template defined for emitting notification") + notification_templates = None if notification_templates: if status_str == 'succeeded': notification_template_type = 'success'