【问题标题】:Using Ansible variables in testinfra在 testinfra 中使用 Ansible 变量
【发布时间】:2017-10-17 14:17:16
【问题描述】:

使用带有 Ansible 后端的 TestInfra 进行测试。一切都很好,除了在运行测试时使用 Ansible 本身

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"]
    (...)

其中 zabbix_agent_version 是来自 group_vars 的 Ansible 变量。运行此playbook即可获得

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

命令执行测试

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

我得到的输出是

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

知道为什么 Ansible 在运行 testinfra 的 Ansible 模块时看不到这个变量,而在单独运行 Ansible 时可以看到它吗?

【问题讨论】:

  • Ansible 版本 2.2.1.0 Python 版本 2.7.5 Testinfra 版本 1.6.4 Pytest 版本 3.1.3
  • 当您手动运行 Ansible 时,zabbix_agent_version 在哪里定义?这是来自远程主机上的自定义事实,还是设置在本地变量文件中?
  • zabbix_agent_version 在 group_vars 中定义。当运行一个检查这个事实的剧本时(调试:msg={{ zabbix_agent_version }}),它可以通过 Ansible 获得。

标签: python testing ansible pytest testinfra


【解决方案1】:

如果zabbix_agent_version 是使用group_vars 设置的变量,那么您似乎应该使用host.ansible.get_variables() 访问它,而不是运行debug 任务。无论如何,两者都应该工作。如果有,在我的当前目录中:

test_myvar.py
group_vars/
  all.yml

group_vars/all.yml 我有:

myvar: value

test_myvar.py 我有:

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'

那么所有测试都通过了:

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

您能否确认我们的文件布局(特别是您的 group_vars 目录相对于您的测试的位置)与我在此处显示的内容相符?

【讨论】:

  • 是的,我的布局与您提供的布局相同。在进行进一步测试时很奇怪,当我尝试获取 Ansible 内置的一些事实(如 ansible_ssh_host)时,testinfra 可以毫无问题地找到它,但是当我尝试由我的 group_vars 设置的东西时它找不到虽然在运行 debug Ansible 时可以看到它。
【解决方案2】:

我几天来一直在寻找这个问题的答案。这就是最终对我有用的方法。本质上,您是在使用 testinfra 的 Ansible 模块来访问 Ansible 的 include_vars 函数。

import pytest

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

然后在我的测试中,我将该函数作为参数包含在内:

def test_something(host, AnsibleVars):

此解决方案部分来自https://github.com/metacloud/molecule/issues/151

我遇到了一个有趣的问题,我试图从我的主要剧本中包含变量,并且在包含 playbook.yml 文件时收到“必须存储为字典/哈希”错误。将变量分离到 group_vars/all/vars.yml 文件中解决了该错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2015-12-18
    • 2017-08-30
    相关资源
    最近更新 更多