From c03bdbfad081ad61862e0aa1f971bddb39e9b124 Mon Sep 17 00:00:00 2001 From: Thomas Quinot Date: Mon, 24 Oct 2016 13:05:56 -0500 Subject: [PATCH] Filter out internal magic and connection variables from facts returns Fixes #15925 (cherry picked from commit 236c923c25c053b0ff912f328e87da2dd26cbf69) --- lib/ansible/plugins/__init__.py | 5 +++++ lib/ansible/plugins/action/__init__.py | 27 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/ansible/plugins/__init__.py b/lib/ansible/plugins/__init__.py index e8558fef0a4..89f2cf0de85 100644 --- a/lib/ansible/plugins/__init__.py +++ b/lib/ansible/plugins/__init__.py @@ -353,6 +353,7 @@ class PluginLoader: def all(self, *args, **kwargs): ''' instantiates all plugins with the same arguments ''' + path_only = kwargs.pop('path_only', False) class_only = kwargs.pop('class_only', False) all_matches = [] @@ -364,6 +365,10 @@ class PluginLoader: if '__init__' in name: continue + if path_only: + yield path + continue + if path not in self._module_cache: self._module_cache[path] = self._load_module_source(name, path) diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index 2d1653bcaee..78feace55f3 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -35,6 +35,7 @@ from ansible.compat.six import binary_type, text_type, iteritems, with_metaclass from ansible import constants as C from ansible.errors import AnsibleError, AnsibleConnectionFailure from ansible.executor.module_common import modify_module +from ansible.playbook.play_context import MAGIC_VARIABLE_MAPPING from ansible.release import __version__ from ansible.parsing.utils.jsonify import jsonify from ansible.utils.unicode import to_bytes, to_unicode @@ -686,6 +687,32 @@ class ActionBase(with_metaclass(ABCMeta, object)): try: data = json.loads(self._filter_non_json_lines(res.get('stdout', u''))) data['_ansible_parsed'] = True + if 'ansible_facts' in data and isinstance(data['ansible_facts'], dict): + remove_keys = set() + fact_keys = set(data['ansible_facts'].keys()) + # first we add all of our magic variable names to the set of + # keys we want to remove from facts + for magic_var in MAGIC_VARIABLE_MAPPING: + remove_keys.update(fact_keys.intersection(MAGIC_VARIABLE_MAPPING[magic_var])) + # next we remove any connection plugin specific vars + for conn_path in self._shared_loader_obj.connection_loader.all(path_only=True): + try: + conn_name = os.path.splitext(os.path.basename(conn_path))[0] + re_key = re.compile('^ansible_%s_' % conn_name) + for fact_key in fact_keys: + if re_key.match(fact_key): + remove_keys.add(fact_key) + except AttributeError: + pass + # finally, we search for interpreter keys to remove + re_interp = re.compile('^ansible_.*_interpreter$') + for fact_key in fact_keys: + if re_interp.match(fact_key): + remove_keys.add(fact_key) + # then we remove them (except for ssh host keys) + for r_key in remove_keys: + if not r_key.startswith('ansible_ssh_host_key_'): + del data['ansible_facts'][r_key] except ValueError: # not valid json, lets try to capture error data = dict(failed=True, _ansible_parsed=False)