Testing Ansible Roles with Molecule

Testing Ansible Roles with Molecule

Testing Ansible Roles with Molecule


Ton Kersten

April 21, 2018


  1. Role over, lay down Testing Roles With Molecule Ton Kersten

    Antwerp / Belgium / 2018
  2. Agenda 1 Introduction 2 Why 3 Question Time! ans-v1.25-2

  3. $ who am i --- - name: Ton Kersten creds:

    work: UNIX/Linux consultant and Trainer @ AT Computing linux: UNIX/Linux Geek (UNIX since 1986, Linux since 1992) scripting: Scripting / programming Freak cfgmgmt: Configuration Management Addict - ansible: - Ansible user and contributor since 2012 - Red Hat Certified Specialist in Ansible Automation - Ansible Ambassador since 2015 foss: Free and Open Source Software Enthusiast things: Big fan of things that just work ans-v1.25-3
  4. Why test roles Ansible playbooks and roles are production code

    Check installation of required packages Process and check needed templates Check files for contents Check running and enabled services Trigger handlers · · · ans-v1.25-4
  5. Return of investment Higher role and playbook quality Improved reliability

    ⇒ Less interruptions Ensuring consistency Improve Robustness Automatic testing ⇒ Continues Integration / Deployment · · · ans-v1.25-5
  6. Molecule Open Source (of course) Designed to test Ansible roles

    Uses Ansible to test Ansible roles Supports different OS’s / test scenarios Supports different test frameworks Supports multiple virtualization providers Setup The tools Molecule Testinfra Docker ansible-lint flake8 ans-v1.25-6 # apt-get install docker-engine # pip install ansible # pip install ansible-lint # pip install 'docker-py<3.0' # pip install molecule # pip install yamllint # pip install flake8 # pip install testinfra
  7. Get started Version 1 $ molecule init --role chrony --driver

    docker Version 2 $ molecule init role \ --role-name=chrony \ --driver-name=docker \ --verifier-name=testinfra ans-v1.25-7
  8. Configure linter molecule/default/molecule.yml (Part 1) lint: name: yamllint options: config-file:

    molecule/default/yamllint.cfg molecule/default/yamllint.cfg extends: default rules: line-length: max: 132 level: warning allow-non-breakable-words: true allow-non-breakable-inline-mappings: false truthy: disable ans-v1.25-8
  9. Configure provisioner molecule/default/molecule.yml (Part 2) # # Ansible provisioner and

    variables # provisioner: name: ansible inventory: group_vars: # Mock data for Ansible group_vars all: name: Wile E. Coyote company: ACME domain: acme.net host_vars: # Mock data for Ansible host_vars centos7: foo: bar lint: name: ansible-lint ans-v1.25-9
  10. Configure verifier molecule/default/molecule.yml (Part 3) verifier: name: testinfra options: verbose:

    False debug: False lint: name: flake8 options: ignore: "E201,E202,E203,E211,E223,E224" ans-v1.25-10 E201: whitespace after char E202: whitespace before char E203: whitespace before char E211: whitespace before text E223: tab / multiple spaces before operator E224: tab / multiple spaces after operator
  11. Configure CentOS molecule/default/molecule.yml (Part 4) - name: centos7 hostname: centos7

    image: couchbase/centos7-systemd image_version: latest privileged: True groups: - chrony - centos command: "/usr/sbin/init" # Mount cgroup volumes on Debian 9 host volumes: - "/sys/fs/cgroup:/sys/fs/cgroup:rw" ans-v1.25-11 Run /sbin/init to startup systemd
  12. Configure Ubuntu molecule/default/molecule.yml (Part 5) - name: ubuntu1604 hostname: ubuntu1604

    image: solita/ubuntu-systemd image_version: latest privileged: True groups: - chrony - ubuntu command: "/sbin/init" ans-v1.25-12 Run /sbin/init to startup systemd
  13. Create tests 1 molecule/default/tests/test_default.py import testinfra.utils.ansible_runner as ti # Get

    all hosts from the Ansible inventory # The inventory is generated from the molecule.yml file inventory = '.molecule/ansible_inventory' hosts = ti.AnsibleRunner(inventory).get_hosts('all') ans-v1.25-13 Setup framework and get all Ansible hosts
  14. Create tests 2 molecule/default/tests/test_default.py def test_services(host): try: facts = host.ansible("setup")["ansible_facts"]

    except host.ansible.AnsibleException as exc: assert exc.result['failed'] is True assert exc.result['msg'] == 'Error getting facts' osfam = facts['ansible_os_family'].lower() if osfam == 'debian': present = [ host.service('chrony') ] elif osfam == 'redhat': present = [ host.service('chronyd') ] else: raise EnvironmentError("'%s' is an unsupported OS" % osfam) ans-v1.25-14 Get all Ansible facts and check OS family
  15. Create tests 3 molecule/default/tests/test_default.py if present: for this in present:

    assert this.is_installed ans-v1.25-15 Check if all packages are installed
  16. Create tests 4 molecule/default/tests/test_default.py if present: for this in present:

    assert this.exists assert this.is_file assert this.uid == 0 assert this.gid == 0 assert this.mode == 0o644 assert this.contains("# Copyright (c) 2012-today by ACME") ans-v1.25-16 Check if files have the correct content and credentials
  17. Create tests 5 molecule/default/tests/test_default.py if present: for this in present:

    assert this.is_running assert this.is_enabled ans-v1.25-17 Check if all services are running and enabled
  18. Running tests molecule create molecule converge molecule verify Fix molecule

    login molecule destroy Correct? No Yes molecule test ans-v1.25-18
  19. Problems Fragile environment Versions of tools must match Sudden, unexpected

    breaking of test line Needs Python Docker < 3.0 Large difference between version 1 and 2 Documentation not always clear · · · ans-v1.25-19
  20. Question Time! Questions?? Contact me Ton.Kersten@ATComputing.nl http://www.atcomputing.nl https://github.com/tonk https://speakerdeck.com/tonk @TonKersten

    on Twitter TKersten on IRC Created with L A TEX Beamer Vim Poppler Tools ImageMagick Evince ans-v1.25-20