Configuration

Config

class molecule.config.Config

Molecule searches the current directory for molecule.yml files by globbing molecule/*/molecule.yml. The files are instantiated into a list of Molecule Config objects, and each Molecule subcommand operates on this list.

The directory in which the molecule.yml resides is the Scenario’s directory. Molecule performs most functions within this directory.

The Config object has instantiated Dependency, Driver, Lint, Platforms, Provisioner, Verifier, Scenario, and State references.

Variable Substitution

class molecule.interpolation.Interpolator

Configuration options may contain environment variables. For example, suppose the shell contains VERIFIER_NAME=testinfra and the following molecule.yml is supplied.

verifier:
  - name: ${VERIFIER_NAME}

Molecule will substitute $VERIFIER_NAME with the value of the VERIFIER_NAME environment variable.

Warning

If an environment variable is not set, Molecule substitutes with an empty string.

Both $VARIABLE and ${VARIABLE} syntax are supported. Extended shell-style features, such as ${VARIABLE-default} and ${VARIABLE:-default} are also supported.

If a literal dollar sign is needed in a configuration, use a double dollar sign ($$).

Dependency

Testing roles may rely upon additional dependencies. Molecule handles managing these dependencies by invoking configurable dependency managers.

Ansible Galaxy

class molecule.dependency.ansible_galaxy.AnsibleGalaxy

Ansible Galaxy is the default dependency manager.

Additional options can be passed to ansible-galaxy install through the options dict. Any option set in this section will override the defaults.

dependency:
  name: galaxy
  options:
    ignore-certs: True
    ignore-errors: True

The dependency manager can be disabled by setting enabled to False.

dependency:
  name: galaxy
  enabled: False

Environment variables can be passed to the dependency.

dependency:
  name: galaxy
  env:
    FOO: bar

Gilt

class molecule.dependency.gilt.Gilt

Gilt is an alternate dependency manager.

Additional options can be passed to gilt overlay through the options dict. Any option set in this section will override the defaults.

dependency:
  name: gilt
  options:
    debug: True

The dependency manager can be disabled by setting enabled to False.

dependency:
  name: gilt
  enabled: False

Environment variables can be passed to the dependency.

dependency:
  name: gilt
  env:
    FOO: bar

Driver

Molecule uses Ansible to manage instances to operate on. Molecule supports any provider Ansible supports. This work is offloaded to the provisioner.

The driver’s name is specified in molecule.yml, and can be overriden on the command line. Molecule will remember the last successful driver used, and continue to use the driver for all subsequent subcommands, or until the instances are destroyed by Molecule.

Important

The verifier must support the Ansible provider for proper Molecule integration.

The driver’s python package requires installation.

Docker

class molecule.driver.dockr.Dockr

The class responsible for managing Docker containers. Docker is the default driver used in Molecule.

driver:
  name: docker
$ sudo pip install docker-py

Provide the files Molecule will preserve upon each subcommand execution.

driver:
  name: ec2
  safe_files:
    - foo
    - .molecule/bar

EC2

class molecule.driver.ec2.Ec2

The class responsible for managing EC2 instances. EC2 is not the default driver used in Molecule.

driver:
  name: ec2
$ sudo pip install boto

Change the options passed to the ssh client.

driver:
  name: ec2
  ssh_connection_options:
    -o ControlPath=~/.ansible/cp/%r@%h-%p

Important

Molecule does not merge lists, when overriding the developer must provide all options.

Provide the files Molecule will preserve upon each subcommand execution.

driver:
  name: ec2
  safe_files:
    - foo
    - .molecule/bar

GCE

class molecule.driver.gce.Gce

The class responsible for managing GCE instances. GCE is not the default driver used in Molecule.

GCE is somewhat different than other cloud providers. There is not an Ansible module for managing ssh keys. This driver assumes the developer has deployed project wide ssh key.

driver:
  name: gce
$ sudo pip install apache-libcloud

Change the options passed to the ssh client.

driver:
  name: gce
  ssh_connection_options:
    -o ControlPath=~/.ansible/cp/%r@%h-%p

Important

Molecule does not merge lists, when overriding the developer must provide all options.

Provide the files Molecule will preserve upon each subcommand execution.

driver:
  name: gce
  safe_files:
    - foo
    - .molecule/bar

LXC

class molecule.driver.lxc.Lxc

The class responsible for managing LXC containers. LXC is not the default driver used in Molecule.

driver:
  name: lxc
$ sudo pip install lxc-python2

Provide the files Molecule will preserve upon each subcommand execution.

driver:
  name: ec2
  safe_files:
    - foo
    - .molecule/bar

LXD

class molecule.driver.lxd.Lxd

The class responsible for managing LXD containers. LXD is not the default driver used in Molecule.

driver:
  name: lxd

Provide the files Molecule will preserve upon each subcommand execution.

driver:
  name: ec2
  safe_files:
    - foo
    - .molecule/bar

Openstack

class molecule.driver.openstack.Openstack

The class responsible for managing OpenStack instances. OpenStack is not the default driver used in Molecule.

driver:
  name: openstack
$ sudo pip install shade

Change the options passed to the ssh client.

driver:
  name: openstack
  ssh_connection_options:
    -o ControlPath=~/.ansible/cp/%r@%h-%p

Important

Molecule does not merge lists, when overriding the developer must provide all options.

Provide the files Molecule will preserve upon each subcommand execution.

driver:
  name: ec2
  safe_files:
    - foo
    - .molecule/bar

Static

class molecule.driver.static.Static

The class responsible for managing static instances. Static is not the default driver used in Molecule.

Under this driver, Molecule skips the provisioning/deprovisioning steps. It is the developers responsibility to manage the instances, and properly configure Molecule to connect to said instances.

driver:
  name: static

Use Molecule with statically managed Docker instances.

$ docker run \
    -d \
    --name static-instance-docker \
    --hostname static-instance-docker \
    -it molecule_local/ubuntu:latest sleep infinity & wait
driver:
  name: static
  options:
    login_cmd_template: 'docker exec -ti {instance} bash'
    ansible_connection_options:
      connection: docker
platforms:
  - name: static-instance-docker

Use Molecule with statically managed instances, which are accessible over ssh.

Important

It is the developers responsibility to configure the ssh config file.

driver:
  name: static
  options:
    login_cmd_template: 'ssh {instance} -F /tmp/ssh-config'
    ansible_connection_options:
      connection: ssh
      ansible_ssh_common_args -F /path/to/ssh-config
platforms:
  - name: static-instance-vagrant

Important

Molecule automatically appends the scenario name to the instances it is testing. It doesn’t seem useful to converge each scenario against the same static host.

Provide the files Molecule will preserve upon each subcommand execution.

driver:
  name: ec2
  safe_files:
    - foo
    - .molecule/bar

Vagrant

class molecule.driver.vagrant.Vagrant

The class responsible for managing Vagrant instances. Vagrant is not the default driver used in Molecule.

Important

This driver is alpha quality software. Do not perform any additonal tasks inside the setup playbook. Molecule does not know about the Vagrant instances’ configuration until the converge playbook is executed.

The setup playbook boots instances, then the instance data is written to disk. The instance data is then added to Molecule’s Ansible inventory on the next execution of molecule.command.create, which happens to be the converge playbook.

This is an area needing improvement. Gluing togher Ansible playbook return data and molecule is clunky. Moving the playbook execution from sh to python is less than ideal, since the playbook’s return data needs handled by an internal callback plugin.

Operating this far inside Ansible’s internals doesn’t feel right. Nor does orchestrating Ansible’s CLI with Molecule. Ansible is throwing pieces over the wall, which Molecule is picking up and reconstructing.

driver:
  name: vagrant
$ sudo pip install python-vagrant

Change the options passed to the ssh client.

driver:
  name: vagrant
  ssh_connection_options:
    -o ControlPath=~/.ansible/cp/%r@%h-%p

Important

Molecule does not merge lists, when overriding the developer must provide all options.

Provide the files Molecule will preserve upon each subcommand execution.

driver:
  name: ec2
  safe_files:
    - foo
    - .molecule/bar

Molecule Vagrant Module

Molecule manages Vagrant via an internal Ansible module. The following belongs in the appropriate create or destroy playbooks, and uses the default provider.

Supported Providers:

  • VirtualBox (default)
  • VMware (vmware_fusion, vmware_workstation and vmware_desktop)
  • Parallels

Create instances.

- hosts: localhost
  connection: local
  tasks:
    - name: Create instances
      molecule_vagrant:
        instance_name: "{{ item }}"
        platform_box: ubuntu/trusty64
        state: up
      with_items:
        - instance-1
        - instance-2

Destroy instances.

- hosts: localhost
  connection: local
  tasks:
    - name: Destroy instances
      molecule_vagrant:
        instance_name: "{{ item }}"
        platform_box: ubuntu/trusty64
        state: destroy
      with_items:
        - instance-1
        - instance-2

Create instances with interfaces.

- hosts: localhost
  connection: local
  tasks:
    - name: Create instance with interfaces
      molecule_vagrant:
        instance_name: instance-1
        instance_interfaces:
          - auto_config: true
            network_name: private_network
            type: dhcp
          - auto_config: false
            network_name: private_network
            type: dhcp
          - auto_config: true
            ip: 192.168.11.3
            network_name: private_network
            type: static
        platform_box: ubuntu/trusty64
        state: destroy

Create instances with additional provider options.

- hosts: localhost
  connection: local
  tasks:
    - name: Create instances
      molecule_vagrant:
        instance_name: "{{ item }}"
        platform_box: ubuntu/trusty64
        provider_name: virtualbox
        provider_memory: 1024
        provider_cpus: 4
        provider_raw_config_args:
          - "customize ['modifyvm', :id, '--cpuexecutioncap', '50']"
        provider_options:
          gui: true
        state: up
      with_items:
        - instance-1
        - instance-2

Create instances with additional instance options.

- hosts: localhost
  connection: local
  tasks:
    - name: Create instances
      molecule_vagrant:
        instance_name: "{{ item }}"
        platform_box: ubuntu/trusty64
        instance_raw_config_args:
          - "vm.network 'forwarded_port', guest: 80, host: 8080"
        state: up
      with_items:
        - instance-1
        - instance-2

Lint

Molecule handles project linting by invoking configurable linters.

Yaml Lint

class molecule.lint.yamllint.Yamllint

Yamllint is the default projet linter.

Yamllint is a linter for YAML files. In addition to checking for syntax validity, also checks for key repetition, and cosmetic problems such as lines length, trailing spaces, and indentation.

Additional options can be passed to yamllint through the options dict. Any option set in this section will override the defaults.

lint:
  name: yamllint
  options:
    config-file: foo/bar

The project linting can be disabled by setting enabled to False.

lint:
  name: yamllint
  enabled: False

Environment variables can be passed to lint.

lint:
  name: yamllint
  env:
    FOO: bar

Platforms

class molecule.platforms.Platforms

Platforms define the instances to be tested, and the groups to which the instances belong.

platforms:
  - name: instance-1

Multiple instances can be provided.

platforms:
  - name: instance-1
  - name: instance-2

Mapping instances to groups. These groups will be used by the Provisioner for orchestration purposes.

platforms:
  - name: instance-1
    groups:
      - group1
      - group2

Children allow the creation of groups of groups.

platforms:
  - name: instance-1
    groups:
      - group1
      - group2
    children:
      - child_group1

Provisioner

Molecule handles provisioning and converging the role.

Ansible

class molecule.provisioner.ansible.Ansible

Ansible is the default provisioner. No other provisioner will be supported.

Molecule’s provisioner manages the instances lifecycle. However, the user must provide the setup, teardown, and converge playbooks. Molecule’s init subcommand will provide the necessary files for convenience.

Important

Reserve the setup and teardown playbooks for provisioning. Do not attempt to gather facts or perform operations on the provisioned nodes inside these playbooks. Due to the gymnastics necessary to sync state between Ansible and Molecule, it is best to perform these tasks in the converge playbook.

It is the developers responsiblity to properly map the modules’s fact data into the instance_conf_dict fact in the setup playbook. This allows Molecule to properly configure Ansible inventory.

Additional options can be passed to ansible-playbook through the options dict. Any option set in this section will override the defaults.

provisioner:
  name: ansible
  options:
    vvv: True
  playbooks:
    setup: create.yml
    converge: playbook.yml
    teardown: destroy.yml

Share playbooks between roles.

provisioner:
  name: ansible
  playbooks:
    setup: ../default/create.yml
    teardown: ../default/destroy.yml
    converge: playbook.yml

Multiple driver playbooks. In some situations a developer may choose to test the same role against different backends. Molecule will choose driver specific setup/teardown playbooks, if the determined driver has a key in the playbooks section of the provisioner’s dict.

Important

If the determined driver has a key in the playbooks dict, Molecule will use this dict to resolve all provisioning playbooks (setup/teardown).

provisioner:
  name: ansible
  playbooks:
    docker:
      setup: create.yml
      teardown: destroy.yml
    setup: create.yml
    teardown: destroy.yml
    converge: playbook.yml

The destruct playbook executes actions which are destructive to the instances(s). Intended to test HA failover scenarios or the like. It is not enabled by default. Add the following to the provisioner’s playbooks section to enable.

provisioner:
  name: ansible
  playbooks:
    destruct: destruct.yml

Important

This is feature should be considered experimental.

Environment variables can be passed to the provisioner.

provisioner:
  name: ansible
  env:
    FOO: bar

Modifying ansible.cfg.

provisioner:
  name: ansible
  config_options:
    defaults:
      fact_caching: jsonfile
    ssh_connection:
      scp_if_ssh: True

Roles which require host/groups to have certain variables set. Molecule uses the same variables defined in a playbook syntax as Ansible.

provisioner:
  name: ansible
  inventory:
    group_vars:
      foo1:
        foo: bar
      foo2:
        foo: bar
        baz:
          qux: zzyzx
    host_vars:
      foo1-01:
        foo: bar

An alternative to the above is symlinking. Molecule creates symlinks to the specified directory in the inventory directory. This allows ansible to converge utilzing its built in host/group_vars resolution. These two forms of inventory management are mutually exclusive.

Note

The source directory linking is relative to the scenario’s ephemeral directory (molecule/$scenario_name/.molecule/).

The only valid keys are group_vars and host_vars. Molecule’s schema validator will enforce this.

provisioner:
  name: ansible
  inventory:
    links:
      group_vars: ../../../inventory/group_vars/
      host_vars: ../../../inventory/host_vars/

Override connection options:

provisioner:
  name: ansible
  connection_options:
    ansible_ssh_user: foo
    ansible_ssh_common_args: -o IdentitiesOnly=no

Lint

Molecule handles provisioner linting by invoking configurable linters.

class molecule.provisioner.lint.ansible_lint.AnsibleLint

Ansible Lint is the default role linter.

Ansible Lint checks playbooks for practices, and behaviour that could potentially be improved.

Additional options can be passed to ansible-lint through the options dict. Any option set in this section will override the defaults.

provisioner:
  name: ansible
  lint:
    name: ansible-lint
    options:
      excludes:
        - path/exclude1
        - path/exclude2
      force-color: True

The role linting can be disabled by setting enabled to False.

provisioner:
  name: ansible
  lint:
    name: ansible-lint
    enabled: False

Environment variables can be passed to lint.

provisioner:
  name: ansible
  lint:
    name: ansible-lint
    env:
      FOO: bar

Scenario

Molecule treats scenarios as a first-class citizens, with a top-level configuration syntax.

class molecule.scenario.Scenario

Scenarios allow Molecule test a role in various ways. Scenarios are a fundamental change from Molecule v1.

Molecule will search the molecule/ directory for directories representing scenarios. These scenario directories contain everything necessary for managing the instances, and converging/testing the role.

Any option set in this section will override the defaults.

scenario:
  name: default
  converge_sequence:
    - create
    - converge
  test_sequence:
    - destroy
    - create
    - converge
    - lint
    - verify
    - destroy

A good source of examples are the scenario functional tests.

Important

The scenario name cannot be configured through molecule.yml. It is determined by the directory name of the scenario. It provided so that the config is symmetrical. It may be removed in the future, if this becomes a source of confusion.

State

class molecule.state.State

A class which manages the state file. Intended to be used as a singleton throughout a given Molecule config. The initial state is serialized to disk if the file does not exist, otherwise is deserialized from the existing state file. Changes made to the object are immediately serialized.

State is not a top level option in Molecule’s config. It’s purpose is for bookkeeping, and each Config object has a reference to a State object.

Note

Currently, it’s use is significantly smaller than it was in v1 of Molecule.

Verifier

Molecule handles role testing by invoking configurable verifiers.

Goss

class molecule.verifier.goss.Goss

Goss is not the default test runner.

Goss is a YAML based serverspec-like tool for validating a server’s configuration. Goss is not the default verifier used in Molecule.

Molecule executes a playbook (test_default.yml) located in the role’s scenario.directory. This playbook will copy YAML files to the instances, and execute Goss using a community written Goss Ansible module bundled with Molecule.

Additional options can be passed to goss validate by modifying the test playbook.

The testing can be disabled by setting enabled to False.

verifier:
  name: goss
  enabled: False

Important

Due to the nature of this verifier. Molecule does not perform options handling the same way Testinfra does.

Lint

The Goss verifier does not utilize a linter.

Testinfra

class molecule.verifier.testinfra.Testinfra

Testinfra is the default test runner.

Additional options can be passed to testinfra through the options dict. Any option set in this section will override the defaults.

verifier:
  name: testinfra
  options:
    n: 1

The testing can be disabled by setting enabled to False.

verifier:
  name: testinfra
  enabled: False

Environment variables can be passed to the verifier.

verifier:
  name: testinfra
  env:
    FOO: bar

Change path to the test directory.

verifier:
  name: testinfra
  directory: /foo/bar/

Lint

Molecule handles test linting by invoking configurable linters.

class molecule.verifier.lint.flake8.Flake8

Flake8 is the default verifier linter.

Flake8 is a linter for python files.

Additional options can be passed to flake8 through the options dict. Any option set in this section will override the defaults.

provisioner:
  name: ansible
  lint:
    name: flake8
    options:
      benchmark: True

The role linting can be disabled by setting enabled to False.

provisioner:
  name: ansible
  lint:
    name: flake8
    enabled: False

Environment variables can be passed to lint.

provisioner:
  name: ansible
  lint:
    name: flake8
    env:
      FOO: bar