With testinfra, I'm using
get_variables()
method from testinfra.modules.ansible.Ansible but it seems that testinfra cannot evaluate my Ansible variable.
Let's describe my poc.
~/tmp/ansible-testinfra
├── inventories
│ ├── group_vars
│ │ └── all.yml
│ └── inventory.ini
└── test_simple.py
I defined 2 variables :
# inventories/group_vars/all.yml
---
one: "value one"
two: "{{ one }} and value two"
and my inventory.ini
is a simple localhost :
# inventories/inventory
[all]
localhost
I created a very simple test like this :
# test_simple.py
import pprint
def test_print_variables(host):
pprint.pprint(host.ansible.get_variables())
def test_variables(host):
my_vars = host.ansible.get_variables()
assert my_vars['two'] == 'value one and value two'
When I run pytest, here is my sdtout :
~/tmp/ansible-testinfra$ pytest --hosts "ansible://all?ansible_inventory=inventories/inventory.ini" -s --tb=no
============================================================================ test session starts ============================================================================
platform linux -- Python 3.6.9, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
rootdir: /home/olhoa/tmp/ansible-testinfra
plugins: testinfra-6.1.0
collected 2 items
test_simple.py {'group_names': ['ungrouped'],
'groups': {'all': ['localhost'], 'ungrouped': ['localhost']},
'inventory_hostname': 'localhost',
'one': 'value one',
'two': '{{ one }} and value two'}
.F
========================================================================== short test summary info ==========================================================================
FAILED test_simple.py::test_variables[ansible://localhost] - AssertionError: assert '{{ one }} and value two' == 'value one and value two'
As you can see, variable one
is not interpreted when used in variable two
.
So, is this possible to do this and how ?
Thank you for your feedback ! :)
You're testing the inventory. The result is correct
shell> ansible-inventory -i inventory.ini --graph --vars
@all:
|--@ungrouped:
| |--localhost
| | |--{one = value one}
| | |--{two = {{ one }} and value two}
|--{one = value one}
|--{two = {{ one }} and value two}
Quoting from Glossary:
Lazy Evaluation: In general, Ansible evaluates any variables in playbook content at the last possible second, which means that if you define a data structure that data structure itself can define variable values within it, and everything “just works” as you would expect. This also means variable strings can include other variables inside of those strings.
To evaluate the variables in playbook content write one, e.g.
shell> cat playbook
- hosts: localhost
tasks:
- debug:
var: one
- debug:
var: two
gives
shell> ansible-playbook playbook.yml -i inventory.ini
...
TASK [debug] ************************************************************
ok: [localhost] =>
one: value one
TASK [debug] ************************************************************
ok: [localhost] =>
two: value one and value two
As a side note, see Understanding variable precedence. In Ansible, the variable precedence is rather complex, e.g.
shell> ansible-playbook playbook.yml -i inventory.ini -e one=X
...
TASK [debug] ************************************************************
ok: [localhost] =>
one: X
TASK [debug] ************************************************************
ok: [localhost] =>
two: X and value two