ansible/ansible — pull request #3392 by dsedivec (2013-07-01 06:06:45+00:00)
Title: Always search the standard modules, even when you add additional module paths

Prior to this commit, if you had an ansible.cfg such as

[defaults]
library = ansible-addons/library
action_plugins = ansible-addons/action_plugins
lookup_plugins = ansible-addons/lookup_plugins

Ansible would still find standard Ansible action and lookup plug-ins
(e.g. the template.py action plug-in), but it would no longer find the
standard modules (e.g. the template module). The user's custom module
path would entirely replace the standard module path. You could, of
course, add the standard module directory in your ansible.cfg as well,
but that's a pain and it also differs from how all the plug-in
configuration variables work.

This behavior with respect to modules was due to the fact that
ansible/utils/plugins.py was using PluginLoader to find modules, and
PluginLoader was not entirely suited to finding modules.

This commit refactors PluginLoader into a BaseLoader class and two
subclasses, PluginLoader and ModuleLoader. ModuleLoader now allows
the user to configure an additional directory for modules while still
searching the standard Ansible modules. In other words, the above
ansible.cfg will now work as expected.

Other significant changes:

- Renamed the "find_plugin" method to "find". The only callers
outside ansible.utils.plugins were using it on module_finder, so
they weren't finding "plugins" anyway, but modules. All of those
callers were changed to just "find".

- The has_plugin method is gone. I found no callers. \__contains\__
was being used, so it remains and its behavior is unchanged.

- All the standard *_plugins packages, such as
ansible.runner.action_plugins, will now be searched for
"categorized" plug-ins. For example, action_loader.find("bar")
would find $site_packages/ansible/runner/action_plugins/foo/bar.py
if it existed. This behavior is incidental, a side-effect of the
implementation, but it seems harmless so I left it in.

- The module-level *_CACHE variables in plugins.py are gone. They
weren't really important, since all users of this code seem to just
use the module-level instances of PluginLoader (and now
ModuleLoader), which each have their own caches.