Standard Test Interface Roles

This repository contains the shared Ansible roles for the Ansible based Standard Test Interface as described at InvokingTests

Style suggestions, conceptual approaches

  • Ansible YAML is not imperative. It does not focuse on describing how a program operates. It's a declarative syntax, "statement of fact". It's far easier to stick any needed logic into scripts, and keep playbooks very matter-of-fact, or declarations-of-state.
  • Do all the subject creation by script, before the main testing-related play(s) run.
  • Host creation and management logic is kept in inventory and out of playbooks. Playbooks need only declare desired idempotent-state from one task to the next.
  • No Ansible inventory population during playbook runs. Banning that will cut down on the number of failure-modes quite a bit.
  • There is some caution against using role-dependencies.

Standard Inventory scripts

The inventory scripts are about taking the subjects produced by a CI system and transforming them into something testable. That includes launching a QCow2 image into a virtual machine, or installing an RPM.

Tests are not required to use these scripts but they provide useful, usable defaults for this task.


This inventory script launches a virtual machine via qemu. The VM image should be specified via command line or an environment variable TEST_SUBJECTS.

By default, the virtual machine is killed when the process (your shell) it invoked the script, is gone. This behavior may not be desirable when invoking the inventory script from an Ansible playbook (since Ansible spawns a long hierarchy of processes). For that purpose you can use environment variable LOCK_ON_FILE: the VM will be killed once the file specified by this variable is missing. Let's look at an example:

- hosts: localhost
    # path to the VM image to use
    vm_image: "./Fedora-Cloud-Base-27-1.6.x86_64.qcow2"
    # inventory name of the VM
    vm_name: "awesome-vm"
    # which python interpreter should be used by ansible (e.g. Fedora doesn't have /usr/bin/python)
    vm_python_interpreter: "/usr/bin/python3"
    # path to the script which will provision the VM
    vm_provisioning_script: /usr/share/ansible/inventory/standard-inventory-qcow2
  - name: create lock file to synchronize on the VM
      prefix: inventory-cloud
      suffix: .lock
      state: file
    register: tmp_lock_file
  - name: provision the VM
    command: "{{ vm_provisioning_script }} {{ vm_image }}"
    register: vm_provision_data
      LOCK_ON_FILE: "{{ tmp_lock_file.path }}"
  - name: prepare inventory data for add_host
      inventory_data: '{{ (vm_provision_data.stdout | from_json)._meta.hostvars[vm_image] }}'
  - add_host:
      name: "{{ vm_name }}"
      ansible_ssh_common_args: "{{ inventory_data.ansible_ssh_common_args }}"
      ansible_host: "{{ inventory_data.ansible_host }}"
      ansible_ssh_pass: "{{ inventory_data.ansible_ssh_pass }}"
      ansible_port: "{{ inventory_data.ansible_port }}"
      ansible_ssh_private_key_file: "{{ inventory_data.ansible_ssh_private_key_file }}"
      ansible_user: "{{ inventory_data.ansible_user }}"
      ansible_python_interpreter: "{% if vm_python_interpreter != '' %}{{ vm_python_interpreter }}{% else %}/usr/bin/python2{% endif %}"