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 re
import six
class NotificationFilter(object): class NotificationFilter(object):
@ -31,7 +33,7 @@ class NotificationFilter(object):
filter_rule = NotificationFilter( filter_rule = NotificationFilter(
publisher_id='^compute.*', publisher_id='^compute.*',
context={'tenant_id': '^5f643cfc-664b-4c69-8000-ce2ed7b08216$', context={'tenant_id': '^5f643cfc-664b-4c69-8000-ce2ed7b08216$',
'roles='private'}, 'roles': 'private'},
event_type='^compute\.instance\..*', event_type='^compute\.instance\..*',
metadata={'timestamp': 'Aug'}, metadata={'timestamp': 'Aug'},
payload={'state': '^active$') payload={'state': '^active$')
@ -58,15 +60,27 @@ class NotificationFilter(object):
return dict((k, re.compile(regex_list[k])) for k in regex_list) return dict((k, re.compile(regex_list[k])) for k in regex_list)
@staticmethod @staticmethod
def _check_for_mismatch(data, regex): def _check_for_single_mismatch(data, regex):
if isinstance(regex, dict): if regex is None:
for k in regex: return False
if (k not in data or not regex[k].match(data[k])): if not isinstance(data, six.string_types):
return True return True
elif regex is not None and not regex.match(data): if not regex.match(data):
return True return True
return False 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): def match(self, context, publisher_id, event_type, metadata, payload):
if (self._check_for_mismatch(publisher_id, self._regex_publisher_id) or if (self._check_for_mismatch(publisher_id, self._regex_publisher_id) or
self._check_for_mismatch(event_type, self._regex_event_type) 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', event_type='instance.create.start',
context={}, context={},
match=False)), 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', ('context_match',
dict(filter_rule=dict(context={'user': '^adm'}), dict(filter_rule=dict(context={'user': '^adm'}),
publisher_id='compute01.manager', publisher_id='compute01.manager',
@ -206,6 +213,12 @@ class TestDispatcherFilter(test_utils.BaseTestCase):
event_type='instance.create.start', event_type='instance.create.start',
context={}, context={},
match=False)), 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', ('mix_match',
dict(filter_rule=dict(event_type='^instance\.create', dict(filter_rule=dict(event_type='^instance\.create',
publisher_id='^compute', publisher_id='^compute',
@ -214,7 +227,6 @@ class TestDispatcherFilter(test_utils.BaseTestCase):
event_type='instance.create.start', event_type='instance.create.start',
context={'user': 'admin'}, context={'user': 'admin'},
match=True)), match=True)),
] ]
def test_filters(self): def test_filters(self):
@ -224,7 +236,7 @@ class TestDispatcherFilter(test_utils.BaseTestCase):
dispatcher = notify_dispatcher.NotificationDispatcher( dispatcher = notify_dispatcher.NotificationDispatcher(
[endpoint], serializer=None) [endpoint], serializer=None)
message = {'payload': {'state': 'active'}, message = {'payload': {'state': 'active', 'virtual_size': None},
'priority': 'info', 'priority': 'info',
'publisher_id': self.publisher_id, 'publisher_id': self.publisher_id,
'event_type': self.event_type, 'event_type': self.event_type,