2017-10-17 4 views
1

Utilisation de TestInfra avec un backend Ansible à des fins de test. Tout va bien, sauf en utilisant Ansible lui-même pendant les testsUtilisation de variables Ansible dans testinfra

de test.py

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

où zabbix_agent_version est une variable Ansible de group_vars. Il peut être obtenu en exécutant cette PlayBook

- hosts: all 
    become: true 
    tasks: 
    - name: debug 
    debug: msg={{ zabbix_agent_version }} 
commande

l'exécution des 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 

la sortie que je reçois est

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 

Toute idée pourquoi Ansible ne peut pas voir cette variable quand Exécuter le module Ansible de testinfra alors qu'il peut le voir en cours d'exécution Ansible seul?

+0

Ansible Version 2.2.1.0 Python version 2.7.5 Testinfra Version 1.6.4 Version 3.1.3 Pytest – FRC

+0

Où est 'zabbix_agent_version' défini lorsque vous êtes en cours d'exécution Ansible manuellement?Est-ce que cela provient d'un fait personnalisé sur l'hôte distant, ou est-ce que ceci est défini dans un fichier de variable local? – larsks

+0

zabbix_agent_version est définie dans group_vars. lors de l'exécution d'un playbook qui vérifie ce fait (debug: msg = {{zabbix_agent_version}}) il peut être obtenu par Ansible. – FRC

Répondre

1

Si zabbix_agent_version est un ensemble variable en utilisant group_vars, il semble que vous devriez y accéder en utilisant host.ansible.get_variables() plutôt que d'exécuter debug tâche. En tout cas, les deux devraient fonctionner. Si je, dans mon répertoire courant:

test_myvar.py 
group_vars/ 
    all.yml 

Et group_vars/all.yml je:

myvar: value 

Et test_myvar.py je:

def test_myvar_using_get_variables(host): 
    all_variables = host.ansible.get_variables() 
    assert 'myvar' in all_variables 
    assert all_variables['myvar'] == 'myvalue' 


def test_myvar_using_debug_var(host): 
    result = host.ansible("debug", "var=myvar") 
    assert 'myvar' in result 
    assert result['myvar'] == 'myvalue' 


def test_myvar_using_debug_msg(host): 
    result = host.ansible("debug", "msg={{ myvar }}") 
    assert 'msg' in result 
    assert result['msg'] == 'myvalue' 

Puis tous les tests passent:

$ 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 =========================== 

Pouvez-vous confirmer que la disposition de nos fichiers (en particulier, l'emplacement de votre répertoire group_vars par rapport à vos tests) correspond à ce que j'ai montré ici?

+0

Oui, j'ai la même disposition que celle que vous avez présentée. En faisant d'autres tests, il est étrange que lorsque j'essaie d'obtenir des faits intégrés à Ansible (comme ansible_ssh_host) testinfra puisse le trouver sans problème, mais quand j'essaye quelque chose qui est en train d'être mis en place par mon groupe_vars, il ne trouve pas bien que lors de l'exécution de déboguer Ansible peut le voir. – FRC

0

J'ai chassé une réponse à cela pendant des jours. Voici ce qui a finalement fonctionné pour moi. Essentiellement, vous utilisez le module Ansible de testinfra pour accéder à la fonction include_vars d'Ansible.

import pytest 

@pytest.fixture() 
def AnsibleVars(host): 
ansible_vars = host.ansible(
    "include_vars", "file=./group_vars/all/vars.yml") 
return ansible_vars["ansible_facts"] 

Puis dans mes tests, j'inclus la fonction en tant que paramètre:

def test_something(host, AnsibleVars): 

Cette solution a été partiellement de https://github.com/metacloud/molecule/issues/151

J'ai eu une question intéressante où je tentais d'inclure la Les variables de mon playbook principal et moi recevions une erreur de "doit être stocké comme un dictionnaire/hash" en incluant le fichier playbook.yml. Séparer les variables dans le fichier group_vars/all/vars.yml a résolu cette erreur.