提交 193a10ce 编写于 作者: C Cleber Rosa

Plugins: add mechanism to disable plugins

While the behavior of having a plugin enabled once it's installed
has suited Avocado reasonably well, there are valid use cases that
require plugins to be disabled.

While adding this mechanism, let's define what the Avocado fully
qualified name for a given plugin is.

While not an urgent feature, enabling and disabling plugins is
actually one requirement for the implementation of the Job API.  While
this change allows for disabling plugins globally, a refinement of the
same logic will allow a given Job to enable/disable some of Avocado's
functionality.
Signed-off-by: NCleber Rosa <crosa@redhat.com>
上级 13039b6f
......@@ -16,10 +16,12 @@
import sys
from stevedore import ExtensionManager
from stevedore import EnabledExtensionManager
from .settings import settings
class Dispatcher(ExtensionManager):
class Dispatcher(EnabledExtensionManager):
"""
Base dispatcher for various extension types
......@@ -28,10 +30,21 @@ class Dispatcher(ExtensionManager):
def __init__(self, namespace):
self.load_failures = []
super(Dispatcher, self).__init__(namespace=namespace,
check_func=self.enabled,
invoke_on_load=True,
on_load_failure_callback=self.store_load_failure,
propagate_map_exceptions=True)
def enabled(self, extension):
namespace_prefix = 'avocado.plugins.'
if self.namespace.startswith(namespace_prefix):
namespace = self.namespace[len(namespace_prefix):]
else:
namespace = self.namespace
disabled = settings.get_value('plugins', 'disable', key_type=list)
fqn = "%s.%s" % (namespace, extension.entry_point.name)
return fqn not in disabled
@staticmethod
def store_load_failure(manager, entrypoint, exception):
manager.load_failures.append((entrypoint, exception))
......
......@@ -81,6 +81,54 @@ to add to your setuptools based `setup.py` file something like::
Then, by running either ``$ python setup.py install`` or ``$ python setup.py
develop`` your plugin should be visible to Avocado.
Fully qualified named for a plugin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plugin registry mentioned earlier, (`setuptools`_ and its `entry
points`_) is global to a given Python installation. Avocado uses the
namespace prefix ``avocado.plugins.`` to avoid name clashes with other
software. Now, inside Avocado itself, there's no need keep using the
``avocado.plugins.`` prefix.
Take for instance, the Job Pre/Post plugins are defined on
``setup.py``::
'avocado.plugins.job.prepost': [
'jobscripts = avocado.plugins.jobscripts:JobScripts'
]
The setuptools entry point namespace is composed of the mentioned
prefix ``avocado.plugins.``, which is is then followed by the Avocado
plugin type, in this case, ``job.prepost``.
Inside avocado itself, the fully qualified name for a plugin is the
plugin type, such as ``job.prepost`` concatenated to the name used in
the entry point definition itself, in this case, ``jobscripts``.
To summarize, still using the same example, the fully qualified
Avocado plugin name is going to be ``job.prepost.jobscripts``.
Disabling a plugin
~~~~~~~~~~~~~~~~~~
Even though a plugin can be installed and registered under
`setuptools`_ `entry points`_, it can be explicitly disabled in
Avocado.
The mechanism available to do so is to add entries to the ``disable``
key under the ``plugins`` section of the Avocado configuration file.
Example::
[plugins]
disable = ['cli.hello', 'job.prepost.jobscripts']
The exact effect on Avocado when a plugin is disabled depends on the
plugin type. For instance, by disabling plugins of type ``cli.cmd``,
the command implemented by the plugin should no longer be available on
the Avocado command line application. Now, by disabling a
``job.prepost`` plugin, those won't be executed before/after the
execution of the jobs.
Wrap Up
~~~~~~~
......
......@@ -69,6 +69,9 @@ username =
password =
[plugins]
# Disable listed plugins completely. Use the fully qualified plugin
# name, as described in the Avocado documentation "Plugins" section.
disable = []
# Suppress notification about broken plugins in the app standard error.
# Add the name of each broken plugin you want to suppress the notification
# in the list. The names can be easily seen from the stderr messages. Example:
......
......@@ -865,6 +865,28 @@ class PluginsTest(AbsPluginsTest, unittest.TestCase):
(expected_rc, result))
self.assertNotIn('Disabled', output)
def test_disable_plugin(self):
os.chdir(basedir)
cmd_line = './scripts/avocado plugins'
result = process.run(cmd_line, ignore_status=True)
expected_rc = exit_codes.AVOCADO_ALL_OK
self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %d:\n%s" %
(expected_rc, result))
self.assertIn("Collect system information", result.stdout)
config_content = "[plugins]\ndisable=['cli.cmd.sysinfo',]"
config = script.TemporaryScript("disable_sysinfo_cmd.conf",
config_content)
with config:
cmd_line = './scripts/avocado --config %s plugins' % config
result = process.run(cmd_line, ignore_status=True)
expected_rc = exit_codes.AVOCADO_ALL_OK
self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %d:\n%s" %
(expected_rc, result))
self.assertNotIn("Collect system information", result.stdout)
def test_Namespace_object_has_no_attribute(self):
os.chdir(basedir)
cmd_line = './scripts/avocado plugins'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册