Fix extract filter when key does not exist in container (#64959)

Fixes #64957
This commit is contained in:
Sylvain Monné 2019-12-04 13:24:52 +01:00 committed by Martin Krizek
parent 9404384985
commit 03c16096d7
4 changed files with 42 additions and 19 deletions

View file

@ -0,0 +1,3 @@
bugfixes:
- core filters - fix ``extract()`` filter when key does not exist in container
(https://github.com/ansible/ansible/issues/64957)

View file

@ -410,19 +410,18 @@ def comment(text, style='plain', **kw):
str_end)
def extract(item, container, morekeys=None):
from jinja2.runtime import Undefined
@environmentfilter
def extract(environment, item, container, morekeys=None):
if morekeys is None:
keys = [item]
elif isinstance(morekeys, list):
keys = [item] + morekeys
else:
keys = [item, morekeys]
value = container[item]
if value is not Undefined and morekeys is not None:
if not isinstance(morekeys, list):
morekeys = [morekeys]
try:
value = reduce(lambda d, k: d[k], morekeys, value)
except KeyError:
value = Undefined()
value = container
for key in keys:
value = environment.getitem(value, key)
return value

View file

@ -19,10 +19,8 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from jinja2.runtime import Undefined
from ansible.module_utils.common._collections_compat import Mapping
from ansible.template import Templar
from ansible.template import Templar, AnsibleUndefined
STATIC_VARS = [
'ansible_version',
@ -75,13 +73,13 @@ class HostVars(Mapping):
'''
host = self._find_host(host_name)
if host is None:
return Undefined(name="hostvars['%s']" % host_name)
return AnsibleUndefined(name="hostvars['%s']" % host_name)
return self._variable_manager.get_vars(host=host, include_hostvars=False)
def __getitem__(self, host_name):
data = self.raw_get(host_name)
if isinstance(data, Undefined):
if isinstance(data, AnsibleUndefined):
return data
return HostVarsVars(data, loader=self._loader)

View file

@ -116,6 +116,29 @@
# map was added to jinja2 in version 2.7
when: "{{ ( lookup('pipe', '{{ ansible_python[\"executable\"] }} -c \"import jinja2; print(jinja2.__version__)\"') is version('2.7', '>=') ) }}"
- name: Test extract filter with defaults
vars:
container:
key:
subkey: value
assert:
that:
- "'key' | extract(badcontainer) | default('a') == 'a'"
- "'key' | extract(badcontainer, 'subkey') | default('a') == 'a'"
- "('key' | extract(badcontainer)).subkey | default('a') == 'a'"
- "'badkey' | extract(container) | default('a') == 'a'"
- "'badkey' | extract(container, 'subkey') | default('a') == 'a'"
- "('badkey' | extract(container)).subsubkey | default('a') == 'a'"
- "'key' | extract(container, 'badsubkey') | default('a') == 'a'"
- "'key' | extract(container, ['badsubkey', 'subsubkey']) | default('a') == 'a'"
- "('key' | extract(container, 'badsubkey')).subsubkey | default('a') == 'a'"
- "'badkey' | extract(hostvars) | default('a') == 'a'"
- "'badkey' | extract(hostvars, 'subkey') | default('a') == 'a'"
- "('badkey' | extract(hostvars)).subsubkey | default('a') == 'a'"
- "'localhost' | extract(hostvars, 'badsubkey') | default('a') == 'a'"
- "'localhost' | extract(hostvars, ['badsubkey', 'subsubkey']) | default('a') == 'a'"
- "('localhost' | extract(hostvars, 'badsubkey')).subsubkey | default('a') == 'a'"
- name: Test json_query filter
assert:
that:
@ -239,10 +262,10 @@
assert:
that:
- "'00' | random_mac is match('^00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
- "'00:00' | random_mac is match('^00:00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
- "'00:00' | random_mac is match('^00:00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
- "'00:00:00' | random_mac is match('^00:00:00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
- "'00:00:00:00' | random_mac is match('^00:00:00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
- "'00:00:00:00:00' | random_mac is match('^00:00:00:00:00:[a-f0-9][a-f0-9]$')"
- "'00:00:00:00:00' | random_mac is match('^00:00:00:00:00:[a-f0-9][a-f0-9]$')"
- "'00:00:00' | random_mac != '00:00:00' | random_mac"
- name: Verify random_mac filter with seed