Extract a common notifier pattern
Create a notifier pattern that abstracts the message notification. This should make it easier to test. Change-Id: Ifbe3be434c304f1d3d4d570d645937a72c3503c8
This commit is contained in:
parent
aa2cde7f9f
commit
515a990dce
@ -22,16 +22,9 @@ provides.
|
|||||||
import copy
|
import copy
|
||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
import os.path
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_context import context as oslo_context
|
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 cadftaxonomy as taxonomy
|
||||||
from pycadf import cadftype
|
from pycadf import cadftype
|
||||||
from pycadf import credential
|
from pycadf import credential
|
||||||
@ -47,7 +40,8 @@ import webob.dec
|
|||||||
|
|
||||||
from keystonemiddleware._common import config
|
from keystonemiddleware._common import config
|
||||||
from keystonemiddleware.audit import _api
|
from keystonemiddleware.audit import _api
|
||||||
from keystonemiddleware.i18n import _LE, _LI
|
from keystonemiddleware.audit import _notifier
|
||||||
|
from keystonemiddleware.i18n import _LE
|
||||||
|
|
||||||
|
|
||||||
_LOG = None
|
_LOG = None
|
||||||
@ -107,21 +101,6 @@ class AuditMiddleware(object):
|
|||||||
http://docs.openstack.org/developer/keystonemiddleware/audit.html
|
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):
|
def __init__(self, app, **conf):
|
||||||
self._application = app
|
self._application = app
|
||||||
self._conf = config.Config('audit',
|
self._conf = config.Config('audit',
|
||||||
@ -135,32 +114,7 @@ class AuditMiddleware(object):
|
|||||||
conf.get('ignore_req_list', '').split(',')]
|
conf.get('ignore_req_list', '').split(',')]
|
||||||
self._cadf_audit = _api.OpenStackAuditApi(conf.get('audit_map_file'),
|
self._cadf_audit = _api.OpenStackAuditApi(conf.get('audit_map_file'),
|
||||||
_LOG)
|
_LOG)
|
||||||
|
self._notifier = _notifier.create_notifier(self._conf, _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})
|
|
||||||
|
|
||||||
def _create_event(self, req):
|
def _create_event(self, req):
|
||||||
correlation_id = identifier.generate_uuid()
|
correlation_id = identifier.generate_uuid()
|
||||||
@ -194,10 +148,9 @@ class AuditMiddleware(object):
|
|||||||
|
|
||||||
@_log_and_ignore_error
|
@_log_and_ignore_error
|
||||||
def _process_request(self, request):
|
def _process_request(self, request):
|
||||||
event = self._create_event(request)
|
self._notifier.notify(request.context,
|
||||||
|
'audit.http.request',
|
||||||
self._emit_audit(request.context, 'audit.http.request',
|
self._create_event(request).as_dict())
|
||||||
event.as_dict())
|
|
||||||
|
|
||||||
@_log_and_ignore_error
|
@_log_and_ignore_error
|
||||||
def _process_response(self, request, response=None):
|
def _process_response(self, request, response=None):
|
||||||
@ -223,7 +176,8 @@ class AuditMiddleware(object):
|
|||||||
reporter=resource.Resource(id='target'),
|
reporter=resource.Resource(id='target'),
|
||||||
reporterTime=timestamp.get_utc_now()))
|
reporterTime=timestamp.get_utc_now()))
|
||||||
|
|
||||||
self._emit_audit(request.context, 'audit.http.response',
|
self._notifier.notify(request.context,
|
||||||
|
'audit.http.response',
|
||||||
event.as_dict())
|
event.as_dict())
|
||||||
|
|
||||||
@webob.dec.wsgify
|
@webob.dec.wsgify
|
||||||
|
77
keystonemiddleware/audit/_notifier.py
Normal file
77
keystonemiddleware/audit/_notifier.py
Normal file
@ -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)
|
@ -198,8 +198,13 @@ class AuditMiddlewareTest(BaseAuditMiddlewareTest):
|
|||||||
def test_api_request_no_messaging(self):
|
def test_api_request_no_messaging(self):
|
||||||
req = webob.Request.blank('/foo/bar',
|
req = webob.Request.blank('/foo/bar',
|
||||||
environ=self.get_environ_header('GET'))
|
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:
|
with mock.patch('keystonemiddleware.audit._LOG.info') as log:
|
||||||
|
self.middleware = audit.AuditMiddleware(
|
||||||
|
FakeApp(),
|
||||||
|
audit_map_file=self.audit_map)
|
||||||
|
|
||||||
self.middleware(req)
|
self.middleware(req)
|
||||||
# Check first notification with only 'request'
|
# Check first notification with only 'request'
|
||||||
call_args = log.call_args_list[0][0]
|
call_args = log.call_args_list[0][0]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user