From 515a990dce650497718a428ab25e0c9ff984855c Mon Sep 17 00:00:00 2001 From: Jamie Lennox Date: Mon, 27 Jun 2016 10:27:20 +1000 Subject: [PATCH] Extract a common notifier pattern Create a notifier pattern that abstracts the message notification. This should make it easier to test. Change-Id: Ifbe3be434c304f1d3d4d570d645937a72c3503c8 --- keystonemiddleware/audit/__init__.py | 64 +++------------ keystonemiddleware/audit/_notifier.py | 77 +++++++++++++++++++ .../tests/unit/audit/test_audit_middleware.py | 7 +- 3 files changed, 92 insertions(+), 56 deletions(-) create mode 100644 keystonemiddleware/audit/_notifier.py diff --git a/keystonemiddleware/audit/__init__.py b/keystonemiddleware/audit/__init__.py index 8a64a923..05dc4f11 100644 --- a/keystonemiddleware/audit/__init__.py +++ b/keystonemiddleware/audit/__init__.py @@ -22,16 +22,9 @@ provides. import copy import functools import logging -import os.path -import sys from oslo_config import cfg from oslo_context import context as oslo_context -try: - import oslo_messaging - messaging = True -except ImportError: - messaging = False from pycadf import cadftaxonomy as taxonomy from pycadf import cadftype from pycadf import credential @@ -47,7 +40,8 @@ import webob.dec from keystonemiddleware._common import config from keystonemiddleware.audit import _api -from keystonemiddleware.i18n import _LE, _LI +from keystonemiddleware.audit import _notifier +from keystonemiddleware.i18n import _LE _LOG = None @@ -107,21 +101,6 @@ class AuditMiddleware(object): http://docs.openstack.org/developer/keystonemiddleware/audit.html """ - @staticmethod - def _get_aliases(proj): - aliases = {} - if proj: - # Aliases to support backward compatibility - aliases = { - '%s.openstack.common.rpc.impl_kombu' % proj: 'rabbit', - '%s.openstack.common.rpc.impl_qpid' % proj: 'qpid', - '%s.openstack.common.rpc.impl_zmq' % proj: 'zmq', - '%s.rpc.impl_kombu' % proj: 'rabbit', - '%s.rpc.impl_qpid' % proj: 'qpid', - '%s.rpc.impl_zmq' % proj: 'zmq', - } - return aliases - def __init__(self, app, **conf): self._application = app self._conf = config.Config('audit', @@ -135,32 +114,7 @@ class AuditMiddleware(object): conf.get('ignore_req_list', '').split(',')] self._cadf_audit = _api.OpenStackAuditApi(conf.get('audit_map_file'), _LOG) - - project = self._conf.project or taxonomy.UNKNOWN - transport_aliases = self._get_aliases(project) - if messaging: - transport = oslo_messaging.get_transport( - cfg.CONF, - url=self._conf.get('transport_url'), - aliases=transport_aliases) - self._notifier = oslo_messaging.Notifier( - transport, - os.path.basename(sys.argv[0]), - driver=self._conf.get('driver'), - topics=self._conf.get('topics')) - - def _emit_audit(self, context, event_type, payload): - """Emit audit notification. - - if oslo.messaging enabled, send notification. if not, log event. - """ - if messaging: - self._notifier.info(context, event_type, payload) - else: - _LOG.info(_LI('Event type: %(event_type)s, Context: %(context)s, ' - 'Payload: %(payload)s'), {'context': context, - 'event_type': event_type, - 'payload': payload}) + self._notifier = _notifier.create_notifier(self._conf, _LOG) def _create_event(self, req): correlation_id = identifier.generate_uuid() @@ -194,10 +148,9 @@ class AuditMiddleware(object): @_log_and_ignore_error def _process_request(self, request): - event = self._create_event(request) - - self._emit_audit(request.context, 'audit.http.request', - event.as_dict()) + self._notifier.notify(request.context, + 'audit.http.request', + self._create_event(request).as_dict()) @_log_and_ignore_error def _process_response(self, request, response=None): @@ -223,8 +176,9 @@ class AuditMiddleware(object): reporter=resource.Resource(id='target'), reporterTime=timestamp.get_utc_now())) - self._emit_audit(request.context, 'audit.http.response', - event.as_dict()) + self._notifier.notify(request.context, + 'audit.http.response', + event.as_dict()) @webob.dec.wsgify def __call__(self, req): diff --git a/keystonemiddleware/audit/_notifier.py b/keystonemiddleware/audit/_notifier.py new file mode 100644 index 00000000..83898d41 --- /dev/null +++ b/keystonemiddleware/audit/_notifier.py @@ -0,0 +1,77 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import os +import sys + +try: + import oslo_messaging +except ImportError: + oslo_messaging = None + +from pycadf import cadftaxonomy as taxonomy + +from keystonemiddleware.i18n import _LI + + +class _LogNotifier(object): + + def __init__(self, log): + self._log = log + + def notify(self, context, event_type, payload): + self._log.info(_LI('Event type: %(event_type)s, Context: %(context)s, ' + 'Payload: %(payload)s'), {'context': context, + 'event_type': event_type, + 'payload': payload}) + + +class _MessagingNotifier(object): + + def __init__(self, notifier): + self._notifier = notifier + + def notify(self, context, event_type, payload): + self._notifier.info(context, event_type, payload) + + +def create_notifier(conf, log): + if oslo_messaging: + proj = conf.project or taxonomy.UNKNOWN + + if proj: + # Aliases to support backward compatibility + aliases = { + '%s.openstack.common.rpc.impl_kombu' % proj: 'rabbit', + '%s.openstack.common.rpc.impl_qpid' % proj: 'qpid', + '%s.openstack.common.rpc.impl_zmq' % proj: 'zmq', + '%s.rpc.impl_kombu' % proj: 'rabbit', + '%s.rpc.impl_qpid' % proj: 'qpid', + '%s.rpc.impl_zmq' % proj: 'zmq', + } + else: + aliases = {} + + transport = oslo_messaging.get_transport(conf.oslo_conf_obj, + url=conf.get('transport_url'), + aliases=aliases) + + notifier = oslo_messaging.Notifier( + transport, + os.path.basename(sys.argv[0]), + driver=conf.get('driver'), + topics=conf.get('topics')) + + return _MessagingNotifier(notifier) + + else: + return _LogNotifier(log) diff --git a/keystonemiddleware/tests/unit/audit/test_audit_middleware.py b/keystonemiddleware/tests/unit/audit/test_audit_middleware.py index acdb7fd5..f9295061 100644 --- a/keystonemiddleware/tests/unit/audit/test_audit_middleware.py +++ b/keystonemiddleware/tests/unit/audit/test_audit_middleware.py @@ -198,8 +198,13 @@ class AuditMiddlewareTest(BaseAuditMiddlewareTest): def test_api_request_no_messaging(self): req = webob.Request.blank('/foo/bar', environ=self.get_environ_header('GET')) - with mock.patch('keystonemiddleware.audit.messaging', None): + with mock.patch('keystonemiddleware.audit._notifier.oslo_messaging', + None): with mock.patch('keystonemiddleware.audit._LOG.info') as log: + self.middleware = audit.AuditMiddleware( + FakeApp(), + audit_map_file=self.audit_map) + self.middleware(req) # Check first notification with only 'request' call_args = log.call_args_list[0][0]