From 8091b84344ccf11aed98a407830028544a4c5815 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Sat, 16 Sep 2017 09:57:52 -0400 Subject: [PATCH 1/5] Fixing up some activity stream deferreds --- awx/main/signals.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/awx/main/signals.py b/awx/main/signals.py index 81f6e17092..cf65401c0c 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 hasattr(_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 hasattr(_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 hasattr(_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 hasattr(_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 hasattr(_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__) From c07a4ff93d351a9b127f40745394c3b5b344fd71 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Sat, 16 Sep 2017 09:58:04 -0400 Subject: [PATCH 2/5] Catch any unhandled exceptions grabbing notification templates --- awx/main/tasks.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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' From ebbd42322d60865ed7b3c5eb7df871cb49be5063 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Sat, 16 Sep 2017 10:01:34 -0400 Subject: [PATCH 3/5] Fix an issue with hasattr call --- awx/main/signals.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/awx/main/signals.py b/awx/main/signals.py index cf65401c0c..998f28cc11 100644 --- a/awx/main/signals.py +++ b/awx/main/signals.py @@ -389,7 +389,7 @@ def activity_stream_create(sender, instance, created, **kwargs): if isinstance(instance, InventorySource) and instance.deprecated_group: return _type = type(instance) - if hasattr(_type, '_deferred', False): + if hasattr(_type, '_deferred'): return object1 = camelcase_to_underscore(instance.__class__.__name__) changes = model_to_dict(instance, model_serializer_mapping) @@ -425,7 +425,7 @@ def activity_stream_update(sender, instance, **kwargs): if changes is None: return _type = type(instance) - if hasattr(_type, '_deferred', False): + if hasattr(_type, '_deferred'): return object1 = camelcase_to_underscore(instance.__class__.__name__) activity_entry = ActivityStream( @@ -452,7 +452,7 @@ def activity_stream_delete(sender, instance, **kwargs): if isinstance(instance, Inventory) and not kwargs.get('inventory_delete_flag', False): return _type = type(instance) - if hasattr(_type, '_deferred', False): + if hasattr(_type, '_deferred'): return changes = model_to_dict(instance) object1 = camelcase_to_underscore(instance.__class__.__name__) @@ -476,7 +476,7 @@ def activity_stream_associate(sender, instance, **kwargs): return obj1 = instance _type = type(instance) - if hasattr(_type, '_deferred', False): + if hasattr(_type, '_deferred'): return object1=camelcase_to_underscore(obj1.__class__.__name__) obj_rel = sender.__module__ + "." + sender.__name__ @@ -489,7 +489,7 @@ def activity_stream_associate(sender, instance, **kwargs): continue obj2_actual = obj2_actual[0] _type = type(obj2_actual) - if hasattr(_type, '_deferred', False): + if hasattr(_type, '_deferred'): return if isinstance(obj2_actual, Role) and obj2_actual.content_object is not None: obj2_actual = obj2_actual.content_object From 6a4b4edea352816d2044a84cf1f8c5150031dfc2 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Sat, 16 Sep 2017 12:54:36 -0400 Subject: [PATCH 4/5] properly detect deferred ORM objects --- awx/main/signals.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/awx/main/signals.py b/awx/main/signals.py index 998f28cc11..77fd91a5c3 100644 --- a/awx/main/signals.py +++ b/awx/main/signals.py @@ -389,7 +389,7 @@ def activity_stream_create(sender, instance, created, **kwargs): if isinstance(instance, InventorySource) and instance.deprecated_group: return _type = type(instance) - if hasattr(_type, '_deferred'): + if getattr(_type, '_deferred', False): return object1 = camelcase_to_underscore(instance.__class__.__name__) changes = model_to_dict(instance, model_serializer_mapping) @@ -425,7 +425,7 @@ def activity_stream_update(sender, instance, **kwargs): if changes is None: return _type = type(instance) - if hasattr(_type, '_deferred'): + if getattr(_type, '_deferred', False): return object1 = camelcase_to_underscore(instance.__class__.__name__) activity_entry = ActivityStream( @@ -452,7 +452,7 @@ def activity_stream_delete(sender, instance, **kwargs): if isinstance(instance, Inventory) and not kwargs.get('inventory_delete_flag', False): return _type = type(instance) - if hasattr(_type, '_deferred'): + if getattr(_type, '_deferred', False): return changes = model_to_dict(instance) object1 = camelcase_to_underscore(instance.__class__.__name__) @@ -476,7 +476,7 @@ def activity_stream_associate(sender, instance, **kwargs): return obj1 = instance _type = type(instance) - if hasattr(_type, '_deferred'): + if getattr(_type, '_deferred', False): return object1=camelcase_to_underscore(obj1.__class__.__name__) obj_rel = sender.__module__ + "." + sender.__name__ @@ -489,7 +489,7 @@ def activity_stream_associate(sender, instance, **kwargs): continue obj2_actual = obj2_actual[0] _type = type(obj2_actual) - if hasattr(_type, '_deferred'): + 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 From 68b924efe5417f67d498a0522e5d320ff0feebe1 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Mon, 18 Sep 2017 09:44:39 -0400 Subject: [PATCH 5/5] flake8 fixup --- awx/main/models/__init__.py | 1 + 1 file changed, 1 insertion(+) 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):