From 173586b8718b88780f400234bcc81bc64257e889 Mon Sep 17 00:00:00 2001 From: Serge van Ginderachter Date: Mon, 12 Aug 2013 22:17:53 +0200 Subject: [PATCH] Ensure plugin_loader.all() only loads one instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit by ensuring all basedirs, plugin paths and extra paths are handled as absolute paths and are checked to not add any doubles. This fixes the corner case where e.g. the user has an additional plugin path configured to a dir relative to his playbooks or inventory location, which also matches the _plugin subdir relative to one of the basedirs in the play. For most plugins this doesn't show as an obvious issue except for callback_plugins, which might fire more than once. Other plugins (inventory and template plugins) might unnecessarily be ran twice. e.g. ansible.cfg has callback_plugins = ./plays/callback_plugins and plays/ contains a playbook file: . ├── ansible.cfg ├── inventory └── plays ├── callback_plugins │   └── timestamp.py └── site.yml modified: lib/ansible/utils/plugins.py --- lib/ansible/utils/plugins.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/ansible/utils/plugins.py b/lib/ansible/utils/plugins.py index 8d1ef493c3..4bf5854dd6 100644 --- a/lib/ansible/utils/plugins.py +++ b/lib/ansible/utils/plugins.py @@ -29,6 +29,8 @@ PLUGIN_PATH_CACHE = {} _basedirs = [] def push_basedir(basedir): + # avoid pushing the same absolute dir more than once + basedir = os.path.abspath(basedir) if basedir not in _basedirs: _basedirs.insert(0, basedir) @@ -97,7 +99,7 @@ class PluginLoader(object): ret = [] ret += self._extra_dirs for basedir in _basedirs: - fullpath = os.path.join(basedir, self.subdir) + fullpath = os.path.abspath(os.path.join(basedir, self.subdir)) if os.path.isdir(fullpath): files = glob.glob("%s/*" % fullpath) for file in files: @@ -109,12 +111,13 @@ class PluginLoader(object): # look in any configured plugin paths, allow one level deep for subcategories configured_paths = self.config.split(os.pathsep) for path in configured_paths: - path = os.path.expanduser(path) + path = os.path.abspath(os.path.expanduser(path)) contents = glob.glob("%s/*" % path) for c in contents: - if os.path.isdir(c): + if os.path.isdir(c) and c not in ret: ret.append(c) - ret.append(path) + if path not in ret: + ret.append(path) # look for any plugins installed in the package subtree ret.extend(self._get_package_paths()) @@ -128,6 +131,7 @@ class PluginLoader(object): ''' Adds an additional directory to the search path ''' self._paths = None + directory = os.path.abspath(directory) if directory is not None: if with_subdir: