I've created a simple task which creates a fact (new variable):
---
- name: Define internal user based on prefix
set_fact:
role_user_uid: "{{ lookup('vars', '{{ user_prefix }}_uid', default='') }}"
where user_prefix
is defined in defaults/ as user_prefix: "ansible"
.
How can I create a test which checks that user_prefix
has a specific value?
I've tried via testinfra
@pytest.fixture()
def AnsibleVars(host):
all_vars = host.ansible.get_variables()
return all_vars
def test_user_exists(host,AnsibleVars):
print(AnsibleVars)
var_prefix = AnsibleVars['user_prefix']
and via ansible provider:
- name: "test default user"
assert:
that:
user_prefix == "ansible"
but I get errors that user_prefix
is note defined.
I did enable gather_facts: yes
in verify.yml
The way I handle this is to save all vars
to a .yml
file at the end of the converge
stage, so I can then later perform pytest
tests based on the state of variables when converge
completes.
The task to do this is placed in the converge.yml
file for the scenario:
post_tasks:
- name: Dump all variables used to converge for later use.
ansible.builtin.copy:
content: |
{{ vars | to_yaml }}
dest: /tmp/ansible-vars.yml
mode: 0o600
changed_when: false
delegate_to: localhost
To access these variables during pytest
tests, do something along the lines of:
import os
import testinfra.utils.ansible_runner
import pytest
import yaml
with open('/tmp/ansible-vars.yml', 'r') as yaml_file:
ansible_vars = yaml.safe_load(yaml_file)
def get_homedir(host=None, user=None):
"""Get user's home directory path in instance."""
cmd = host.run(f'/usr/bin/getent passwd {user}')
return cmd.stdout.split(':')[5]
@pytest.fixture(params=ansible_vars.get('accounts', []))
def fixture_users(request):
return request.param
def test_bashrc_sources_aliases(host, fixture_users):
user = fixture_users
homedir = get_homedir(host=host, user=user)
f = host.file(os.path.join(homedir, '.bashrc'))
assert f.exists
assert f.user == user
assert r'. ~/.bash_aliases' in f.content_string
Not perfect, but DRY and avoids hard-coding and coupling of tasks to tests.
Don't forget to add this to the cleanup
stage:
- name: Delete variables saved from converge step.
ansible.builtin.file:
path: /tmp/ansible-vars.yml
state: absent
changed_when: false
delegate_to: localhost
If anyone has a better way to do this, chime in! :)