Interpolating Ansible jinja in testinfra

George Shuklin
OpsOps
Published in
1 min readJul 5, 2022

One of idiosyncrasies of Ansible with pytest (testinfra) is that whilst you have access to inventory, any Jinja there will mess up you badly, as you will have a literal value with mustaches instead of expected interpolation.

Imagine an inventory:

foo:
foo1:
foobar: 42
foobar_slug: 'slug_{{ foobar }}'

Nothing fancy, right? (It become more fancy as soon as you get to {{ hostvars[groups.bar[0]].foo }})

You can use foobar_slug in Ansible playbooks without any issues. But if you ever try to use it in tests (via host.ansible.get_inventory()) it starts to fall apart. Because you get literal slug_{{ foobar }} instead of expected slug_42.

There is a neat trick. You can use debug module of ansible to evaluate any jinja expression.

This is ‘magical fixture’:

@pytest.fixture(scope="module")
def eval(host):
def inner_eval(var):
return host.ansible("debug", "var=%s" % var)[var]

return inner_eval

You get fixture eval, which allow you to safely extract value from inventory:

def test_foo(eval):
assert eval('foo_slug') == 'foo_42'

If you are not familiar with this ‘return inner…’, it’s a development pattern called ‘factory’. Instead of returning a value we return a function which can return a value.

--

--

OpsOps
OpsOps

Published in OpsOps

Tech blog on Linux, Ansible, Ceph, Openstack and operator-related programming

George Shuklin
George Shuklin

Written by George Shuklin

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux. My hobby is Rust.