Using Ansible variables in testinfra

2024/9/30 5:38:39

Using TestInfra with Ansible backend for testing purposes. Everything goes fine except using Ansible itself while running tests

test.py

import pytest
def test_zabbix_agent_package(host):package = host.package("zabbix-agent")assert package.is_installedpackage_version = host.ansible("debug", "msg={{ zabbix_agent_version }}")["msg"](...)

where zabbix_agent_version is an Ansible variable from group_vars. It can be obtained by running this playbook

- hosts: allbecome: truetasks:- name: debugdebug: msg={{ zabbix_agent_version }}

command executing tests

pytest --connection=ansible --ansible-inventory=inventory  --hosts=$hosts -v test.py

ansible.cfg

[defaults]
timeout = 10
host_key_checking = False
library=library/
retry_files_enabled = False
roles_path=roles/
pipelining=true
ConnectTimeout=60
remote_user=deploy
private_key_file=/opt/jenkins/.ssh/deploy

the output I get is

self = <ansible>, module_name = 'debug', module_args = 'msg={{ zabbix_agent_version }}', check = True, kwargs = {}
result = {'failed': True, 'msg': "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'zabbix_agent_version' is undefined"}def __call__(self, module_name, module_args=None, check=True, **kwargs):if not self._host.backend.HAS_RUN_ANSIBLE:raise RuntimeError(("Ansible module is only available with ansible ""connection backend"))result = self._host.backend.run_ansible(module_name, module_args, check=check, **kwargs)if result.get("failed", False) is True:
>           raise AnsibleException(result)
E           AnsibleException: Unexpected error: {'failed': True,
E            'msg': u"the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'zabbix_agent_version' is undefined"}/usr/lib/python2.7/site-packages/testinfra/modules/ansible.py:70: AnsibleException

Any idea why Ansible can't see this variable when running testinfra's Ansible module while it can see it while running Ansible alone?

Answer

If zabbix_agent_version is a variable set using group_vars, then it seems as if you should be accessing it using host.ansible.get_variables() rather than running debug task. In any case, both should work. If I have, in my current directory:

test_myvar.py
group_vars/all.yml

And in group_vars/all.yml I have:

myvar: value

And in test_myvar.py I have:

def test_myvar_using_get_variables(host):all_variables = host.ansible.get_variables()assert 'myvar' in all_variablesassert all_variables['myvar'] == 'myvalue'def test_myvar_using_debug_var(host):result = host.ansible("debug", "var=myvar")assert 'myvar' in resultassert result['myvar'] == 'myvalue'def test_myvar_using_debug_msg(host):result = host.ansible("debug", "msg={{ myvar }}")assert 'msg' in resultassert result['msg'] == 'myvalue'

Then all tests pass:

$ py.test --connection=ansible --ansible-inventory=hosts -v 
test_myvar.py 
============================= test session starts ==============================
platform linux2 -- Python 2.7.13, pytest-3.2.3, py-1.4.34, pluggy-0.4.0 -- /home/lars/env/common/bin/python2
cachedir: .cache
rootdir: /home/lars/tmp/testinfra, inifile:
plugins: testinfra-1.8.1.dev2
collected 3 items                                                               test_myvar.py::test_myvar_using_get_variables[ansible://localhost] PASSED
test_myvar.py::test_myvar_using_debug_var[ansible://localhost] PASSED
test_myvar.py::test_myvar_using_debug_msg[ansible://localhost] PASSED=========================== 3 passed in 1.77 seconds ===========================

Can you confirm that the layout of our files (in particular, the location of your group_vars directory relative to the your tests) matches what I've shown here?

https://en.xdnf.cn/q/71121.html

Related Q&A

How to create a dictionary of dictionaries of dictionaries in Python

So I am taking a natural language processing class and I need to create a trigram language model to generate random text that looks "realistic" to a certain degree based off of some sample da…

How to separate Master Slave (DB read / writes) in Flask Sqlalchemy

Im trying to separate the Read and write DB operations via Flask Sqlalchemy. Im using binds to connect to the mysql databases. I would want to perform the write operation in Master and Reads from slave…

Why import class from another file will call __init__ function?

The structure of the project is:project - main.py - session.py - spider.pyThere is a class in session.py:import requestsclass Session:def __init__(self):self.session = requests.Session()print(Session c…

Flask: login session times out too soon

While editing a record, if there is a long wait of let say a few minutes (getting coffee) and then coming back to press the save (POST), I get redirected to the main page to login instead and the data …

Activate virtual environement and start jupyter notebook all in batch file

I created the following batch file: jupyter_nn.bat. Inside file I have:cd "C:\My_favorite_path" activate neuralnets jupyter notebookSo the goal is to activate conda virtual environment and s…

several contour plots in the same figures

I have several 3d functions. I would like two plot the contour plots of them in the same figure to see the difference between them. I expect to see some crossings between contours of two functions. Her…

how to detect all the rectangular boxes in the given image

I tried to detect all the rectangles in image using threshold, canny edge and applied contour detection but it was not able to detect all the rectangles. Finally, I thought of detect the same using hou…

Python Pandas Series failure datetime

I think that this has to be a failure of pandas, having a pandas Series (v.18.1 and 19 too), if I assign a date to the Series, the first time it is added as int (error), the second time it is added as …

Remove a dictionary key that has a certain value [duplicate]

This question already has answers here:Removing entries from a dictionary based on values(4 answers)Closed 10 years ago.I know dictionarys are not meant to be used this way, so there is no built in fun…

Get names of positional arguments from functions signature

Using Python 3.x, Im trying to get the name of all positional arguments from some function i.e: def foo(a, b, c=1):returnRight now Im doing this: from inspect import signature, _empty args =[x for x, p…