Added a section wrt. hybrid plugins and provide an example for lookup plugins

This commit is contained in:
Dag Wieers 2016-02-25 16:37:48 +01:00
parent 064cdec6ff
commit c1d90e3f2d

View file

@ -254,6 +254,130 @@ Connection plugins
* connection plugins
Hybrid plugins
==============
In specific cases you may want a plugin that supports both ansible-1.9.x *and*
ansible-2.0. Much like porting plugins from v1 to v2, you need to understand
how plugins work in each version and support both requirements. It may mean
playing tricks on Ansible.
Since the ansible-2.0 plugin system is more advanced, it is easier to adapt
your plugin to provide similar pieces (subclasses, methods) for ansible-1.9.x
as ansible-2.0 expects. This way your code will look a lot cleaner.
You may find the following tips useful:
* Check whether the ansible-2.0 class(es) are available and if they are missing
(ansible-1.9.x) mimic them with the needed methods (e.g. `__init__`)
* When ansible-2.0 python modules are imported, and they fail (ansible-1.9.x),
catch the `ImportError` exception and perform the equivalent imports for
ansible-1.9.x. With possible translations (e.g. importing specific methods).
* Use the existence of these methods as a qualifier to what version of Ansible
you are running. So rather than using version checks, you can do capability
checks instead. (See examples below)
* Document for each if-then-else case for which specific version each block is
needed. This will help others to understand how they have to adapt their
plugins, but it will also help you to remove the older ansible-1.9.x support
when it is deprecated.
* When doing plugin development, it is very useful to have the `warning()`
method during development, but it is also important to emit warnings for
deadends (cases that you expect should never be triggered) or corner cases
(e.g. cases where you expect misconfigurations).
Lookup plugins
--------------
As a simple example we are going to make a hybrid `fileglob` lookup plugin.
The `fileglob` lookup plugin is pretty simple to understand::
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import glob
try:
# ansible-2.0
from ansible.plugins.lookup import LookupBase
except ImportError:
# ansible-1.9.x
class LookupBase(object):
def __init__(self, basedir=None, runner=None, **kwargs):
self.runner = runner
self.basedir = self.runner.basedir
def get_basedir(self, variables):
return self.basedir
try:
# ansible-1.9.x
from ansible.utils import (listify_lookup_plugin_terms, path_dwim, warning)
except ImportError:
# ansible-2.0
from __main__ import display
warning = display.warning
class LookupModule(LookupBase):
# For ansible-1.9.x, we added inject=None as valid arguments
def run(self, terms, inject=None, variables=None, **kwargs):
# ansible-2.0, but we made this work for ansible-1.9.x too !
basedir = self.get_basedir(variables)
# ansible-1.9.x
if 'listify_lookup_plugin_terms' in globals():
terms = listify_lookup_plugin_terms(terms, basedir, inject)
ret = []
for term in terms:
term_file = os.path.basename(term)
# For ansible-1.9.x, we imported path_dwim() from ansible.utils
if 'path_dwim' in globals():
# ansible-1.9.x
dwimmed_path = path_dwim(basedir, os.path.dirname(term))
else:
# ansible-2.0
dwimmed_path = self._loader.path_dwim_relative(basedir, 'files', os.path.dirname(term))
globbed = glob.glob(os.path.join(dwimmed_path, term_file))
ret.extend(g for g in globbed if os.path.isfile(g))
return ret
Note that in the above example we did not use the `warning()` method as we
had no direct use for it in the final version. However we left this code in
so people can use this part during development/porting/use.
Connection plugins
------------------
* connection plugins
Action plugins
--------------
* action plugins
Callback plugins
----------------
* callback plugins
Connection plugins
------------------
* connection plugins
Porting custom scripts
======================