DEV Community

koh-sh
koh-sh

Posted on • Originally published at koh-sh.hatenablog.com

Using Testinfra with Ansible

Testinfra which tests infrastructure works really well with Ansible.
I posted about Testinfra previously so please check if you like.

Sharing Inventory

Testinfra can refer to Inventories of Ansible.
So you don't have to re-define hosts information for Ansible and tests too.

https://testinfra.readthedocs.io/en/latest/backends.html#ansible

$ py.test --hosts='ansible://all' # tests all inventory hosts
$ py.test --hosts='ansible://host1,ansible://host2'
$ py.test --hosts='ansible://web*'
$ py.test --force-ansible --hosts='ansible://all'
$ py.test --hosts='ansible://host?force_ansible=True'
Enter fullscreen mode Exit fullscreen mode

If the inventory file is not specified with ansible.cfg, you can specify with --ansible-inventory=ANSIBLE_INVENTORY in command lines.

Executing modules of Ansible

You can execute modules of Ansible while testing.

https://testinfra.readthedocs.io/en/latest/modules.html#ansible

[koh@kohs-MBP] ~/vag_test
% ipython
Python 3.7.3 (default, May  1 2019, 16:07:48)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import testinfra

In [2]: host = testinfra.get_host("ansible://Vag1")

In [3]: host.ansible("command", "echo foo", check=False)
Out[3]:
{'ansible_facts': {'discovered_interpreter_python': '/usr/bin/python'},
 'changed': True,
 'cmd': ['echo', 'foo'],
 'delta': '0:00:00.004734',
 'end': '2019-10-05 15:07:42.251008',
 'rc': 0,
 'start': '2019-10-05 15:07:42.246274',
 'stderr': '',
 'stderr_lines': [],
 'stdout': 'foo',
 'stdout_lines': ['foo']}

In [4]:
Enter fullscreen mode Exit fullscreen mode

This is an example of executing command module of Ansible with Testinfra.

As a result of executing a module, you can get like changed, rc or stdout same as Ansible.

setup module would fit well with testing.

[koh@kohs-MBP] ~/vag_test
% cat test_ansible.py
def test_dns(host):
    nameservers = host.ansible("setup")["ansible_facts"]["ansible_dns"]["nameservers"]
    assert '10.1.1.1' in nameservers
[koh@kohs-MBP] ~/vag_test
% 
[koh@kohs-MBP] ~/vag_test
% py.test -v test_ansible.py --hosts='ansible://Vag1'
======================================== test session starts ========================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.9.0 -- /Users/koh/.pyenv/versions/3.7.3/bin/python3.7
cachedir: .pytest_cache
rootdir: /Users/koh/vag_test, inifile: pytest.ini
plugins: xonsh-0.8.12, testinfra-3.0.5
collected 1 item

test_ansible.py::test_dns[ansible://Vag1] FAILED                                              [100%]

============================================= FAILURES ==============================================
_____________________________________ test_dns[ansible://Vag1] ______________________________________

host = <testinfra.host.Host object at 0x10e9be748>

    def test_dns(host):
        nameservers = host.ansible("setup")["ansible_facts"]["ansible_dns"]["nameservers"]
>       assert '10.1.1.1' in nameservers
E       AssertionError: assert '10.1.1.1' in ['10.0.2.3']

test_ansible.py:3: AssertionError
===================================== 1 failed in 2.17 seconds ======================================
zsh: exit 1     py.test -v test_ansible.py --hosts='ansible://Vag1'
[koh@kohs-MBP] ~/vag_test
%
Enter fullscreen mode Exit fullscreen mode

This is an example of checking nameserver of resolv.conf with setup module.

Refering Variable

You can refer to variables of Ansible.
host_vars, group_vars and magic variables like inventory_hostname can be referred from Testinfra.
Variables defined with include_vars in Playbooks cannot be referred.

[koh@kohs-MBP] ~/vag_test
% ipython
Python 3.7.3 (default, May  1 2019, 16:07:48)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import testinfra

In [2]: host = testinfra.get_host("ansible://Vag1")

In [3]: host.ansible.get_variables()
Out[3]:
{'aaa': 'bbb',
 'foo': 'bar',
 'hoge': 'fuga',
 'inventory_hostname': 'Vag1',
 'group_names': ['Vag'],
 'groups': {'Vag': ['Vag1', 'Vag2', 'Vag3'], 'all': ['Vag1', 'Vag2', 'Vag3']}}

In [4]:
Enter fullscreen mode Exit fullscreen mode

Conclusion

As currently, Molecule use Testinfra as the default test tool, Testinfra works really well with Ansible.
Testinfra can be used with Docker or Kubernetes too, so I would keep trying them out.

Discussion (0)