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
This commit is contained in:
tengqm 2016-08-17 05:52:09 -04:00 committed by Haifeng Yan
parent fcf114294b
commit 3cdfe15897
2 changed files with 35 additions and 9 deletions

View File

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

View File

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