From 3cdfe158978fb7c66b27c187687b8b4241c40775 Mon Sep 17 00:00:00 2001 From: tengqm Date: Wed, 17 Aug 2016 05:52:09 -0400 Subject: [PATCH] Fix notify filter when data item is None When data[k] is None during match check, we are getting annoying TypeError exceptions like: "TypeError: expected string or buffer". This patch adds a check that data[k] is something the regex can do matching. Change-Id: I75c8f602a59a90aeb5a6973f2e9e25708194ad78 --- oslo_messaging/notify/filter.py | 28 ++++++++++++++----- .../tests/notify/test_dispatcher.py | 16 +++++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/oslo_messaging/notify/filter.py b/oslo_messaging/notify/filter.py index b23fac40d..f6d609806 100644 --- a/oslo_messaging/notify/filter.py +++ b/oslo_messaging/notify/filter.py @@ -15,6 +15,8 @@ import re +import six + class NotificationFilter(object): @@ -31,7 +33,7 @@ class NotificationFilter(object): filter_rule = NotificationFilter( publisher_id='^compute.*', context={'tenant_id': '^5f643cfc-664b-4c69-8000-ce2ed7b08216$', - 'roles='private'}, + 'roles': 'private'}, event_type='^compute\.instance\..*', metadata={'timestamp': 'Aug'}, payload={'state': '^active$') @@ -58,15 +60,27 @@ class NotificationFilter(object): return dict((k, re.compile(regex_list[k])) for k in regex_list) @staticmethod - def _check_for_mismatch(data, regex): - if isinstance(regex, dict): - for k in regex: - if (k not in data or not regex[k].match(data[k])): - return True - elif regex is not None and not regex.match(data): + def _check_for_single_mismatch(data, regex): + if regex is None: + return False + if not isinstance(data, six.string_types): + return True + if not regex.match(data): return True return False + @classmethod + def _check_for_mismatch(cls, data, regex): + if isinstance(regex, dict): + for k in regex: + if k not in data: + return True + if cls._check_for_single_mismatch(data[k], regex[k]): + return True + return False + else: + return cls._check_for_single_mismatch(data, regex) + def match(self, context, publisher_id, event_type, metadata, payload): if (self._check_for_mismatch(publisher_id, self._regex_publisher_id) or self._check_for_mismatch(event_type, self._regex_event_type) or diff --git a/oslo_messaging/tests/notify/test_dispatcher.py b/oslo_messaging/tests/notify/test_dispatcher.py index 18744fabf..9780cd388 100644 --- a/oslo_messaging/tests/notify/test_dispatcher.py +++ b/oslo_messaging/tests/notify/test_dispatcher.py @@ -163,6 +163,13 @@ class TestDispatcherFilter(test_utils.BaseTestCase): event_type='instance.create.start', context={}, match=False)), + # this is only for simulation + ('event_type_not_string', + dict(filter_rule=dict(event_type='^instance\.delete'), + publisher_id='compute01.manager', + event_type=['instance.swim', 'instance.fly'], + context={}, + match=False)), ('context_match', dict(filter_rule=dict(context={'user': '^adm'}), publisher_id='compute01.manager', @@ -206,6 +213,12 @@ class TestDispatcherFilter(test_utils.BaseTestCase): event_type='instance.create.start', context={}, match=False)), + ('payload_value_none', + dict(filter_rule=dict(payload={'virtual_size': '2048'}), + publisher_id='compute01.manager', + event_type='instance.create.start', + context={}, + match=False)), ('mix_match', dict(filter_rule=dict(event_type='^instance\.create', publisher_id='^compute', @@ -214,7 +227,6 @@ class TestDispatcherFilter(test_utils.BaseTestCase): event_type='instance.create.start', context={'user': 'admin'}, match=True)), - ] def test_filters(self): @@ -224,7 +236,7 @@ class TestDispatcherFilter(test_utils.BaseTestCase): dispatcher = notify_dispatcher.NotificationDispatcher( [endpoint], serializer=None) - message = {'payload': {'state': 'active'}, + message = {'payload': {'state': 'active', 'virtual_size': None}, 'priority': 'info', 'publisher_id': self.publisher_id, 'event_type': self.event_type,