From 6096f578807b11870cf3b5047def5ce637f4f92d Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Tue, 13 Nov 2018 21:12:41 -0500 Subject: [PATCH] fix cache 'update' method to be 'mapping' compatible - also simplify the update functions - fix methods and allwow backwards compat with plugins overriding 'update' --- changelogs/fragments/vm_fix.yml | 2 ++ lib/ansible/plugins/cache/__init__.py | 18 +++++++++++++----- lib/ansible/vars/manager.py | 25 ++++++++++++------------- 3 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 changelogs/fragments/vm_fix.yml diff --git a/changelogs/fragments/vm_fix.yml b/changelogs/fragments/vm_fix.yml new file mode 100644 index 0000000000..f247cce338 --- /dev/null +++ b/changelogs/fragments/vm_fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - fix issue with incorrect dict update in vars manager diff --git a/lib/ansible/plugins/cache/__init__.py b/lib/ansible/plugins/cache/__init__.py index cfb5ebce3e..2b1d51fb5a 100644 --- a/lib/ansible/plugins/cache/__init__.py +++ b/lib/ansible/plugins/cache/__init__.py @@ -289,10 +289,18 @@ class FactCache(MutableMapping): """ Flush the fact cache of all keys. """ self._plugin.flush() - def update(self, key, value): - host_cache = self._plugin.get(key) - host_cache.update(value) - self._plugin.set(key, host_cache) + def update(self, host_facts): + """ We override the normal update to ensure we always use the 'setter' method """ + for key in host_facts: + try: + host_cache = self._plugin.get(key) + if host_cache: + host_cache.update(host_facts[key]) + else: + host_cache = host_facts[key] + self._plugin.set(key, host_cache) + except KeyError: + self._plugin.set(key, host_facts[key]) class InventoryFileCacheModule(BaseFileCacheModule): @@ -311,7 +319,7 @@ class InventoryFileCacheModule(BaseFileCacheModule): def validate_cache_connection(self): try: super(InventoryFileCacheModule, self).validate_cache_connection() - except AnsibleError as e: + except AnsibleError: cache_connection_set = False else: cache_connection_set = True diff --git a/lib/ansible/vars/manager.py b/lib/ansible/vars/manager.py index 42f823beaa..439f2d8beb 100644 --- a/lib/ansible/vars/manager.py +++ b/lib/ansible/vars/manager.py @@ -622,8 +622,7 @@ class VariableManager: ''' Clears the facts for a host ''' - if hostname in self._fact_cache: - del self._fact_cache[hostname] + self._fact_cache.pop(hostname, None) def set_host_facts(self, host, facts): ''' @@ -633,13 +632,16 @@ class VariableManager: if not isinstance(facts, dict): raise AnsibleAssertionError("the type of 'facts' to set for host_facts should be a dict but is a %s" % type(facts)) - if host.name not in self._fact_cache: - self._fact_cache[host.name] = facts - else: + try: try: + # this is a cache plugin, not a dictionary + self._fact_cache.update({host.name: facts}) + except TypeError: + # this is here for backwards compatibilty for the time cache plugins were not 'dict compatible' self._fact_cache.update(host.name, facts) - except KeyError: - self._fact_cache[host.name] = facts + display.deprecated("Your configured fact cache plugin is using a deprecated form of the 'update' method", version="2.12") + except KeyError: + self._fact_cache[host.name] = facts def set_nonpersistent_facts(self, host, facts): ''' @@ -649,13 +651,10 @@ class VariableManager: if not isinstance(facts, dict): raise AnsibleAssertionError("the type of 'facts' to set for nonpersistent_facts should be a dict but is a %s" % type(facts)) - if host.name not in self._nonpersistent_fact_cache: + try: + self._nonpersistent_fact_cache[host.name].update(facts) + except KeyError: self._nonpersistent_fact_cache[host.name] = facts - else: - try: - self._nonpersistent_fact_cache[host.name].update(facts) - except KeyError: - self._nonpersistent_fact_cache[host.name] = facts def set_host_variable(self, host, varname, value): '''