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.
  • You should use include_role instead of import_role when utilizing roles from this project.

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.

Flexible Metadata Format for default provisioner(s)

You can find information for FMF here, and for supported FMF attributes here.

Initialize a new metadata tree

To add desired parameters for default provisioners first of all make sure that your /tests directory has initialized metadata tree. Directory .fmf must be present. If it is not, run next command:

fmf init

Usage

Make sure fmf is initialized as described above. Put in /tests a file with name provision.fmf:

---

standard-inventory-qcow2:
  qemu:
    m: 3G
    net_nic:
      model: e1000
    drive:
    - size: 11000000000
      path: /home/vader
    - size: 2000000000
    usb_drive:
    - path: /tmp
    - size: 2000000000
      path: /tmp

standard-inventory-docker:
  dumb_option: dumb_parameter

Supported parameters

standard-inventory-qcow2

  • qemu.m - RAM size in megabytes. Optionally, a suffix of M or G.
  • qemu.net_nic.model - Use qemu-system-x86_64 -net nic,model=help for a list of available devices.
  • drive - has to contain dict of additional drive(s)
  • drive.size - allows to specify additional drive with size in bytes (default size: 2G)
  • drive.path - allows to specify additional drive with custom directory path to its backing file Filename for image will be auto-generated. (default path: /tmp)
  • usb_drive - has to contain dict of additional usb drive(s)
  • usb_drive.size - allows to specify additional usb drive with size in bytes (default size: 1G)
  • usb_drive.path - allows to specify additional usb drive with custom directory path to its backing file Filename for image will be auto-generated. (default path: /tmp)

You can open a RFE ticket to extend supported parameters according to https://qemu.weilnetz.de/doc/qemu-doc.html

LOCK_ON_FILE for standard-inventory-qcow2

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
  vars:
    # 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
  tasks:
  - name: create lock file to synchronize on the VM
    tempfile:
      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
    environment:
      LOCK_ON_FILE: "{{ tmp_lock_file.path }}"
  - name: prepare inventory data for add_host
    set_fact:
      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 %}"