1# 2# Copyright 2013 eNovance 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); you may 5# not use this file except in compliance with the License. You may obtain 6# a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13# License for the specific language governing permissions and limitations 14# under the License. 15 16import re 17 18 19class NotificationFilter(object): 20 21 r"""Filter notification messages 22 23 The NotificationFilter class is used to filter notifications that an 24 endpoint will received. 25 26 The notification can be filter on different fields: context, 27 publisher_id, event_type, metadata and payload. 28 29 The filter is done via a regular expression 30 31 filter_rule = NotificationFilter( 32 publisher_id='^compute.*', 33 context={'tenant_id': '^5f643cfc-664b-4c69-8000-ce2ed7b08216$', 34 'roles': 'private'}, 35 event_type='^compute\.instance\..*', 36 metadata={'timestamp': 'Aug'}, 37 payload={'state': '^active$') 38 39 """ 40 41 def __init__(self, context=None, publisher_id=None, event_type=None, 42 metadata=None, payload=None): 43 self._regex_publisher_id = None 44 self._regex_event_type = None 45 46 if publisher_id is not None: 47 self._regex_publisher_id = re.compile(publisher_id) 48 if event_type is not None: 49 self._regex_event_type = re.compile(event_type) 50 self._regexs_context = self._build_regex_dict(context) 51 self._regexs_metadata = self._build_regex_dict(metadata) 52 self._regexs_payload = self._build_regex_dict(payload) 53 54 @staticmethod 55 def _build_regex_dict(regex_list): 56 if regex_list is None: 57 return {} 58 return dict((k, re.compile(regex_list[k])) for k in regex_list) 59 60 @staticmethod 61 def _check_for_single_mismatch(data, regex): 62 if regex is None: 63 return False 64 if not isinstance(data, str): 65 return True 66 if not regex.match(data): 67 return True 68 return False 69 70 @classmethod 71 def _check_for_mismatch(cls, data, regex): 72 if isinstance(regex, dict): 73 for k in regex: 74 if k not in data: 75 return True 76 if cls._check_for_single_mismatch(data[k], regex[k]): 77 return True 78 return False 79 else: 80 return cls._check_for_single_mismatch(data, regex) 81 82 def match(self, context, publisher_id, event_type, metadata, payload): 83 if (self._check_for_mismatch(publisher_id, self._regex_publisher_id) or 84 self._check_for_mismatch(event_type, self._regex_event_type) or 85 self._check_for_mismatch(context, self._regexs_context) or 86 self._check_for_mismatch(metadata, self._regexs_metadata) or 87 self._check_for_mismatch(payload, self._regexs_payload)): 88 return False 89 return True 90