Molecule notes

not a tutorial, more of a tricks session

Based on molecule v3.0.2

Why to test?

  • code needs to be maintained
  • avoid production outages
  • assert change risks

Manual testing does not pay well!

Terminology

  • driver (provider) - inventory management backend
  • scenario - basically a functional test
  • command
    • usually a playbook and optional
    • can be embedded
  • sequence - a list of commands
  • verifier - tools use to validate success run

What can Molecule test

  • roles
  • playbooks
  • anything you can run

Molecule provisions virtualized test hosts, run commands on them and assert the success.

What Molecule cannot do

☕️

Installing

pip3 install 'molecule[docker]' molecule-azure
# most drivers are now plugins and with their own packages
# docker driver is part of core

Getting more information

$ molecule --version
molecule 3.0.3.dev41+gbe117525
   ansible==2.9.6 python==3.7

$ molecule drivers
name
---------
azure  # <-- this is here because we installed molecule-azure
delegated
docker
podman

Command line help

molecule-help

Molecule driver (provider)

  • A driver is used to manage test hosts:
    • create (so ansible can manage them)
    • destroy (dealocate them)
  • Core drivers:
    • delegated – aka “DIY”
    • docker
    • podman
  • Plugins: azure, ec2, gce, openstack, vagrant, lxd, libvirt*, …

Which driver to use

  • Containers (docker/podman) unless you need systemd
  • Delegated tests already existing inventory
  • If you need real VMs use either:
    • Any cloud provider
    • Vagrant which can run locally and make use of virtualbox or libvirt

Molecule verifiers

Tools used to assert success of your test

  • ansible: default verifier
  • testinfra: a pytest plugin useful recommended for advanced use-cases
  • goss: 3rd party plugin

Molecule commands and sequences

  • command ~= a playbook (often embeded)
  • a sequence is a list of commands to be run, :
    • create
    • check
    • converge
    • destroy
    • test - most complete one!

Molecule test sequence

Default test sequence includes:

$ molecule matrix test
--> Test matrix

└── default  # <-- this is the name of the scenario
    ├── dependency
    ├── lint
    ├── cleanup
    ├── destroy
    ├── syntax
    ├── create
    ├── prepare  # bring host to testable status
    ├── converge  # <-- only one required
    ├── idempotence
    ├── side_effect
    ├── verify  # asserts best location
    ├── cleanup
    └── destroy

Each scenario has a persistent state

  • create and destroy affect the created state
  • converge and cleanup affect the converged state
  • disable auto-destroy by adding --destroy=never

A minimalist scenario layout

$ tree  # from inside a role directory
├── README.md
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── molecule
│   └── default  # scenario name
│       ├── converge.yml  # should contain at least "include_role: foo"
│       ├── molecule.yml  # <-- required
│       └── verify.yml
├── tasks
│   └── main.yml
└── vars
    └── main.yml

Using config file to avoid repetition

  • config file defines only default values for molecule.yml files
  • config file can be stored at repository level or user:
    • ~/.config/molecule/config.yml - user level
    • {REPO}/.config/molecule/config.yml - repo level (recommended)
  • any key defined in molecule.yml will override values from config.yml

Practical config example:

# .config/molecule/config.ym
driver:
  name: delegated  # <-- now default driver will be delegated
lint: ansible-lint -v
# molecule.yml
driver:
  name: docker
# what is effectively loaded
driver:
  name: docker
lint: ansible-lint -v

Hint: Use config.yml to follow DRY principle

🤗

That’s it! Any Questions?