Accessing Ansible variables in molecule test, TestInfra

4.2k Views Asked by At

I picked up molecule while researching around inspec and how to use it in ansible. I found molecule very cool and adopted it. I wanted to use it in 2 ways.

1- When developing a role or playbook
2- After a particular playbook have been run on production.

On number 1: I found this very useful question/ressponse on stackoverflow and that has helped me shape my thinking.I put my variable file for the role kafka under group_vars/all as suggested in the stackoverflow post

- kafka
- - molecule
- - - default
- - - - molecule.yml
- - - - playbook.yml
- - - - ...
- - - - group_vars
- - - - - all.yml
- - - - tests
- - - - - test_default.py
- - tasks
- - - main.yml
- - ....

test_default.py

import os

import testinfra.utils.ansible_runner
import pytest


testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')


@pytest.fixture()
def AnsibleVars(host):
    all_vars = host.ansible.get_variables()
    return all_vars


def test_hosts_file(host):
    f = host.file('/etc/hosts')

    assert f.exists
    assert f.user == 'root'
    assert f.group == 'root'


def test_downloaded_binary(host, AnsibleVars):
    # arch = host.file(AnsibleVars['kafka_archive_temp'])
    result = host.ansible('debug','var=kafka_archive_temp')
    arch = host.file(result['kafka_archive_temp'])
    assert arch.exists
    assert arch.is_file

def test_installation_directory(host,AnsibleVars):
    # dir = host.file(AnsibleVars['kafka_final_path'])
    result = host.ansible('debug','var=kafka_final_path')
    dir = host.file(result['kafka_final_path'])
    assert dir.exists
    assert dir.is_directory
    assert dir.user == AnsibleVars['kafka_user_on_os']
    assert dir.group == AnsibleVars['kafka_group_on_os']


def test_user_created(host,AnsibleVars):
    user = host.user(AnsibleVars['kafka_user_on_os'])

    assert user.name == AnsibleVars['kafka_user_on_os']
    assert user.group == AnsibleVars['kafka_group_on_os']

group_vars/all.yml

kafka_version: "2.2.1"
kafka_file_name: "kafka_2.12-{{ kafka_version }}.tgz"
kafka_user_on_os: kafka
kafka_group_on_os: kafka
kafka_zookeeper_service: zookeeper
kafka_service: kafka
kafka_log_folder: /var/log/kafka
kafka_zookeeper_port: 2181
kafka_archive_temp: "/tmp/{{ kafka_file_name }}"
kafka_final_path: "/usr/local/kafka/{{ kafka_version }}"
kafka_get_binaries_details:
  - {
    dest: "{{ kafka_archive_temp }}",
    url: "http://www-us.apache.org/dist/kafka/2.2.1/kafka_2.12-2.2.1.tgz"
  }
  ....

molecule verify

molecule verify
--> Validating schema /Users/joseph/Engineering/configuration-management-ansible/roles/kafka/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    └── verify

--> Scenario: 'default'
--> Action: 'verify'
--> Executing Testinfra tests found in /Users/joseph/Engineering/configuration-management-ansible/roles/kafka/molecule/default/tests/...
============================= test session starts ==============================
platform darwin -- Python 3.7.4, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: /Users/joseph/Engineering/configuration-management-ansible/roles/kafka/molecule/default
plugins: testinfra-3.1.0
collected 8 items

tests/test_default.py ........                                             [100%]

============================== 8 passed in 18.34s  ==============================

Verifier completed successfully. However the method host.ansible.get_variables() could not resolve a variable inside another variable like : kafka_final_path: "/usr/local/kafka/{{ kafka_version }}".

I ended up using the following:

 result = host.ansible('debug','var=kafka_final_path')
 dir = host.file(result['kafka_final_path'])

to get the value of kafka_final_path.

Question 1.1: Looking at how there is a need of a little manipulation before a variable of a variable get be retrieved with all needed interpolation, I am wondering there is any better way of writing these tests?

Question 2.1: On number 2, I would like to create a different scenario for testing like for EC2 on AWS. On those playbooks, I use external variable files passed to ansible-playbook since they have higher precedence. I am wondering in that case how I would access those variables from the external vars_files in testinfra?

0

There are 0 best solutions below