Add base for notifier plugins
OSprofiler will support notifers for different collectors. So add base for plugins. In next patch we will add osprofiler oslo.messaging based notifier Change-Id: Iad14c67f1e7cdbd0f4bcc64200fecf048316e385
This commit is contained in:
parent
33fdfd7b83
commit
090e577244
0
osprofiler/_notifiers/__init__.py
Normal file
0
osprofiler/_notifiers/__init__.py
Normal file
34
osprofiler/_notifiers/base.py
Normal file
34
osprofiler/_notifiers/base.py
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright 2014 Mirantis Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from osprofiler import _utils as utils
|
||||
|
||||
|
||||
class Notifier(object):
|
||||
|
||||
def notify(self, info):
|
||||
"""This method will be called on each notifier.notify() call.
|
||||
|
||||
To add new drivers you should, create new subclass of this class and
|
||||
implement notify method.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def factory(name, *args, **kwargs):
|
||||
for driver in utils.itersubclasses(Notifier):
|
||||
if name == driver.__name__:
|
||||
return driver(*args, **kwargs).notify
|
||||
|
||||
raise TypeError("There is no driver, with name: %s" % name)
|
14
osprofiler/_notifiers/messaging.py
Normal file
14
osprofiler/_notifiers/messaging.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright 2014 Mirantis Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
@ -89,3 +89,24 @@ def signed_unpack(data, hmac_data, hmac_key):
|
||||
return json.loads(binary_decode(base64.urlsafe_b64decode(data)))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def itersubclasses(cls, _seen=None):
|
||||
"""Generator over all subclasses of a given class in depth first order."""
|
||||
|
||||
if not isinstance(cls, type):
|
||||
raise TypeError("itersubclasses must be called with "
|
||||
"new-style classes, not %.100r" % cls)
|
||||
|
||||
_seen = _seen or set()
|
||||
try:
|
||||
subs = cls.__subclasses__()
|
||||
except TypeError: # fails only when cls is type
|
||||
subs = cls.__subclasses__(cls)
|
||||
subs = cls.__subclasses__()
|
||||
for sub in subs:
|
||||
if sub not in _seen:
|
||||
_seen.add(sub)
|
||||
yield sub
|
||||
for sub in itersubclasses(sub, _seen):
|
||||
yield sub
|
||||
|
@ -13,6 +13,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from osprofiler._notifiers import base
|
||||
|
||||
|
||||
def _noop_notifier(info):
|
||||
"""Do nothing on notify()."""
|
||||
@ -45,3 +47,15 @@ def set(notifier):
|
||||
"""
|
||||
global __notifier
|
||||
__notifier = notifier
|
||||
|
||||
|
||||
def create(plugin_name, *args, **kwargs):
|
||||
"""Create notifier based on specified plugin_name
|
||||
|
||||
:param plugin_name: Name of plugin that creates notifier
|
||||
:param *args: args that will be passed to plugin init method
|
||||
:param **kwargs: kwargs that will be passed to plugin init method
|
||||
:returns: Callable notifier method
|
||||
:raise TypeError: In case of invalid name of plugin raises TypeError
|
||||
"""
|
||||
return base.Notifier.factory(plugin_name, *args, **kwargs)
|
||||
|
0
tests/notifiers/__init__.py
Normal file
0
tests/notifiers/__init__.py
Normal file
48
tests/notifiers/test_base.py
Normal file
48
tests/notifiers/test_base.py
Normal file
@ -0,0 +1,48 @@
|
||||
# Copyright 2014 Mirantis Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from osprofiler._notifiers import base
|
||||
from tests import test
|
||||
|
||||
|
||||
class NotifierBaseTestCase(test.TestCase):
|
||||
|
||||
def test_factory(self):
|
||||
|
||||
class A(base.Notifier):
|
||||
|
||||
def notify(self, a):
|
||||
return a
|
||||
|
||||
self.assertEqual(base.Notifier.factory("A")(10), 10)
|
||||
|
||||
def test_factory_with_args(self):
|
||||
|
||||
class B(base.Notifier):
|
||||
|
||||
def __init__(self, a, b=10):
|
||||
self.a = a
|
||||
self.b = b
|
||||
|
||||
def notify(self, c):
|
||||
return self.a + self.b + c
|
||||
|
||||
self.assertEqual(base.Notifier.factory("B", 5, b=7)(10), 22)
|
||||
|
||||
def test_factory_not_found(self):
|
||||
self.assertRaises(TypeError, base.Notifier.factory, "non existing")
|
||||
|
||||
def test_notify(self):
|
||||
base.Notifier().notify("")
|
@ -13,8 +13,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from osprofiler import notifier
|
||||
import mock
|
||||
|
||||
from osprofiler import notifier
|
||||
from tests import test
|
||||
|
||||
|
||||
@ -34,3 +35,17 @@ class NotifierTestCase(test.TestCase):
|
||||
|
||||
def test_get_default_notifier(self):
|
||||
self.assertEqual(notifier.get(), notifier._noop_notifier)
|
||||
|
||||
def test_notify(self):
|
||||
m = mock.MagicMock()
|
||||
notifier.set(m)
|
||||
notifier.notify(10)
|
||||
|
||||
m.assert_called_once_with(10)
|
||||
|
||||
@mock.patch("osprofiler.notifier.base.Notifier.factory")
|
||||
def test_create(self, mock_factory):
|
||||
|
||||
result = notifier.create("test", 10, b=20)
|
||||
mock_factory.assert_called_once_with("test", 10, b=20)
|
||||
self.assertEqual(mock_factory.return_value, result)
|
||||
|
@ -76,3 +76,19 @@ class UtilsTestCase(test.TestCase):
|
||||
hmac_data = utils.generate_hmac(data, hmac)
|
||||
|
||||
self.assertIsNone(utils.signed_unpack(data, hmac_data, hmac))
|
||||
|
||||
def test_itersubclasses(self):
|
||||
|
||||
class A(object):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
pass
|
||||
|
||||
class C(A):
|
||||
pass
|
||||
|
||||
class D(C):
|
||||
pass
|
||||
|
||||
self.assertEqual([B, C, D], list(utils.itersubclasses(A)))
|
||||
|
Loading…
Reference in New Issue
Block a user