Configuration¶
-
class
molecule.config.
Config
¶ Config Class.
Molecule searches the current directory for
molecule.yml
files by globbing molecule/*/molecule.yml. The files are instantiated into a list of MoleculeConfig
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 instantiates Dependency, Driver, Lint, Platforms, Provisioner, Verifier, Scenario, and State references.Initialize a new config class and returns None.
- Parameters
molecule_file – A string containing the path to the Molecule file to be parsed.
args – An optional dict of options, arguments and commands from the CLI.
command_args – An optional dict of options passed to the subcommand from the CLI.
ansible_args – An optional tuple of arguments provided to the
ansible-playbook
command.
- Returns
None
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 theVERIFIER_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. Even the default as another environment variable is supported like${VARIABLE-$DEFAULT}
or${VARIABLE:-$DEFAULT}
. An empty string is returned when both variables are undefined.If a literal dollar sign is needed in a configuration, use a double dollar sign ($$).
Molecule will substitute special
MOLECULE_
environment variables defined in molecule.yml.Important
Remember, the
MOLECULE_
namespace is reserved for Molecule. Do not prefix your own variables with MOLECULE_.A file may be placed in the root of the project as .env.yml, and Molecule will read variables when rendering molecule.yml. See command usage.
Construct Interpolator.
There are following environment variables available in molecule.yml
:
Variable |
Description |
---|---|
MOLECULE_DEBUG |
If debug is turned on or off |
MOLECULE_FILE |
Path to molecule config file |
MOLECULE_ENV_FILE |
Path to molecule environment file |
MOLECULE_STATE_FILE |
? |
MOLECULE_INVENTORY_FILE |
Path to generated inventory file |
MOLECULE_EPHEMERAL_DIRECTORY |
Path to generated directory, usually
|
MOLECULE_SCENARIO_DIRECTORY |
Path to scenario directory |
MOLECULE_PROJECT_DIRECTORY |
Path to your project directory |
MOLECULE_INSTANCE_CONFIG |
? |
MOLECULE_DEPENDENCY_NAME |
Dependency type name, usually ‘galaxy’ |
MOLECULE_DRIVER_NAME |
Name of the molecule scenario driver |
MOLECULE_PROVISIONER_NAME |
Name of the provisioner tool (usually ‘ansible’) |
MOLECULE_SCENARIO_NAME |
Name of the scenario |
MOLECULE_VERIFIER_NAME |
Name of the verifier tool (usually ‘ansible’) |
MOLECULE_VERIFIER_TEST_DIRECTORY |
? |
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
¶ 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.Note
Molecule will remove any options matching ‘^[v]+$’, and pass
-vvv
to the underlyingansible-galaxy
command when executing molecule –debug.dependency: name: galaxy options: ignore-certs: True ignore-errors: True role-file: requirements.yml requirements-file: collections.yml
Use “role-file” if you have roles only. Use the “requirements-file” if you need to install collections. Note that, with Ansible Galaxy’s collections support, you can now combine the two lists into a single requirement if your file looks like this
roles: - dep.role1 - dep.role2 collections: - ns.collection - ns2.collection2
If you want to combine them, then just point your
role-file
andrequirements-file
to the same path. This is not done by default because olderrole-file
only required a list of roles, while the collections must be under thecollections:
key within the file and pointing both to the same file by default could break existing code.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
Construct AnsibleGalaxy.
Shell¶
-
class
molecule.dependency.shell.
Shell
¶ Shell
is an alternate dependency manager.It is intended to run a command in situations where Ansible Galaxy don’t suffice.
The
command
to execute is required, and is relative to Molecule’s project directory when referencing a script not in $PATH.Note
Unlike the other dependency managers,
options
are ignored and not passed to shell. Additional flags/subcommands should simply be added to the command.dependency: name: shell command: path/to/command --flag1 subcommand --flag2
The dependency manager can be disabled by setting
enabled
to False.dependency: name: shell command: path/to/command --flag1 subcommand --flag2 enabled: False
Environment variables can be passed to the dependency.
dependency: name: shell command: path/to/command --flag1 subcommand --flag2 env: FOO: bar
Construct Shell.
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 overridden 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.
Delegated¶
-
class
molecule.driver.delegated.
Delegated
¶ The class responsible for managing delegated instances.
Delegated is not the default driver used in Molecule.
Under this driver, it is the developers responsibility to implement the create and destroy playbooks.
Managed
is the default behaviour of all drivers.driver: name: delegated
However, the developer must adhere to the instance-config API. The developer’s create playbook must provide the following instance-config data, and the developer’s destroy playbook must reset the instance-config.
- address: ssh_endpoint identity_file: ssh_identity_file # mutually exclusive with password instance: instance_name port: ssh_port_as_string user: ssh_user password: ssh_password # mutually exclusive with identity_file become_method: valid_ansible_become_method # optional become_pass: password_if_required # optional - address: winrm_endpoint instance: instance_name connection: 'winrm' port: winrm_port_as_string user: winrm_user password: winrm_password winrm_transport: ntlm/credssp/kerberos winrm_cert_pem: <path to the credssp public certificate key> winrm_cert_key_pem: <path to the credssp private certificate key> winrm_server_cert_validation: validate/ignore
This article covers how to configure and use WinRM with Ansible: https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html
Molecule can also skip the provisioning/deprovisioning steps. It is the developers responsibility to manage the instances, and properly configure Molecule to connect to said instances.
driver: name: delegated options: managed: False login_cmd_template: 'docker exec -ti {instance} bash' ansible_connection_options: ansible_connection: docker platforms: - name: instance-docker
$ docker run \ -d \ --name instance-docker \ --hostname instance-docker \ -it molecule_local/ubuntu:latest sleep infinity & wait
Use Molecule with delegated instances, which are accessible over ssh.
Important
It is the developer’s responsibility to configure the ssh config file.
driver: name: delegated options: managed: False login_cmd_template: 'ssh {instance} -F /tmp/ssh-config' ansible_connection_options: ansible_connection: ssh ansible_ssh_common_args: '-F /path/to/ssh-config' platforms: - name: instance
Provide the files Molecule will preserve post
destroy
action.driver: name: delegated safe_files: - foo
And in order to use localhost as molecule’s target:
driver: name: delegated options: managed: False ansible_connection_options: ansible_connection: local
Construct Delegated.
Lint¶
Starting with v3, Molecule handles project linting by invoking and external lint commands as exemplified below.
The decision to remove the complex linting support was not easily taken as we do find it very useful. The issue was that molecule runs on scenarios and linting is usually performed at repository level.
It makes little sense to perform linting in more than one place per project. Molecule was able to use up to three linters and while it was aimed to flexible about them, it ended up creating more confusions to the users. We decided to maximize flexibility by just calling an external shell command.
lint: |
set -e
yamllint .
ansible-lint
flake8
The older format is no longer supported and you have to update the
molecule.yml
when you upgrade. If you don’t want to do any linting,
it will be enough to remove all lint related sections from the file.
# old v2 format, no longer supported
lint:
name: yamllint
enabled: true
provisioner:
lint:
name: ansible-lint
options: ...
env: ...
verifier:
lint:
name: flake8
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
Initialize a new platform class and returns None.
- Parameters
config – An instance of a Molecule config.
- Returns
None
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 create, destroy, and converge playbooks. Molecule’s
init
subcommand will provide the necessary files for convenience.Molecule will skip tasks which are tagged with either molecule-notest or notest. With the tag molecule-idempotence-notest tasks are only skipped during the idempotence action step.
Important
Reserve the create and destroy 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 prepare or converge playbooks.
It is the developers responsiblity to properly map the modules’s fact data into the instance_conf_dict fact in the create 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.Important
Options do not affect the create and destroy actions.
Note
Molecule will remove any options matching ‘^[v]+$’, and pass
-vvv
to the underlyingansible-playbook
command when executing molecule –debug.Molecule will silence log output, unless invoked with the
--debug
flag. However, this results in quite a bit of output. To enable Ansible log output, add the following to theprovisioner
section ofmolecule.yml
.provisioner: name: ansible log: True
The create/destroy playbooks for Docker and Podman are bundled with Molecule. These playbooks have a clean API from molecule.yml, and are the most commonly used. The bundled playbooks can still be overridden.
The playbook loading order is:
provisioner.playbooks.$driver_name.$action
provisioner.playbooks.$action
bundled_playbook.$driver_name.$action
provisioner: name: ansible options: vvv: True playbooks: create: create.yml converge: converge.yml destroy: destroy.yml
Share playbooks between roles.
provisioner: name: ansible playbooks: create: ../default/create.yml destroy: ../default/destroy.yml converge: converge.yml
Multiple driver playbooks. In some situations a developer may choose to test the same role against different backends. Molecule will choose driver specific create/destroy 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 (create/destroy).
provisioner: name: ansible playbooks: docker: create: create.yml destroy: destroy.yml create: create.yml destroy: destroy.yml converge: converge.yml
Important
Paths in this section are converted to absolute paths, where the relative parent is the $scenario_directory.
The side effect playbook executes actions which produce side effects 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: side_effect: side_effect.yml
Important
This feature should be considered experimental.
The prepare playbook executes actions which bring the system to a given state prior to converge. It is executed after create, and only once for the duration of the instances life.
This can be used to bring instances into a particular state, prior to testing.
provisioner: name: ansible playbooks: prepare: prepare.yml
The cleanup playbook is for cleaning up test infrastructure that may not be present on the instance that will be destroyed. The primary use-case is for “cleaning up” changes that were made outside of Molecule’s test environment. For example, remote database connections or user accounts. Intended to be used in conjunction with prepare to modify external resources when required.
The cleanup step is executed directly before every destroy step. Just like the destroy step, it will be run twice. An initial clean before converge and then a clean before the last destroy step. This means that the cleanup playbook must handle failures to cleanup resources which have not been created yet.
Add the following to the provisioner’s playbooks section to enable.
provisioner: name: ansible playbooks: cleanup: cleanup.yml
Important
This feature should be considered experimental.
Environment variables. Molecule does its best to handle common Ansible paths. The defaults are as follows.
ANSIBLE_ROLES_PATH: $ephemeral_directory/roles/:$project_directory/../:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles ANSIBLE_LIBRARY: $ephemeral_directory/modules/:$project_directory/library/:~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules ANSIBLE_FILTER_PLUGINS: $ephemeral_directory/plugins/filter/:$project_directory/filter/plugins/:~/.ansible/plugins/filter:/usr/share/ansible/plugins/modules
Environment variables can be passed to the provisioner. Variables in this section which match the names above will be appened to the above defaults, and converted to absolute paths, where the relative parent is the $scenario_directory.
Important
Paths in this section are converted to absolute paths, where the relative parent is the $scenario_directory.
provisioner: name: ansible env: FOO: bar
Modifying ansible.cfg.
provisioner: name: ansible config_options: defaults: fact_caching: jsonfile ssh_connection: scp_if_ssh: True
Important
The following keys are disallowed to prevent Molecule from improperly functioning. They can be specified through the provisioner’s env setting described above, with the exception of the privilege_escalation.
provisioner: name: ansible config_options: defaults: roles_path: /path/to/roles_path library: /path/to/library filter_plugins: /path/to/filter_plugins privilege_escalation: {}
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
Molecule automatically generates the inventory based on the hosts defined under Platforms. Using the
hosts
key allows to add extra hosts to the inventory that are not managed by Molecule.A typical use case is if you want to access some variables from another host in the inventory (using hostvars) without creating it.
Note
The content of
hosts
should follow the YAML based inventory syntax: start with theall
group and have hosts/vars/children entries.provisioner: name: ansible inventory: hosts: all: extra_host: foo: hello
Important
The extra hosts added to the inventory using this key won’t be created/destroyed by Molecule. It is the developers responsibility to target the proper hosts in the playbook. Only the hosts defined under Platforms should be targetted instead of
all
.An alternative to the above is symlinking. Molecule creates symlinks to the specified directory in the inventory directory. This allows ansible to converge utilizing its built in host/group_vars resolution. These two forms of inventory management are mutually exclusive.
Like above, it is possible to pass an additional inventory file (or even dynamic inventory script), using the
hosts
key. Ansible will automatically merge this inventory with the one generated by molecule. This can be useful if you want to define extra hosts that are not managed by Molecule.Important
Again, it is the developers responsibility to target the proper hosts in the playbook. Only the hosts defined under Platforms should be targetted instead of
all
.Note
The source directory linking is relative to the scenario’s directory.
The only valid keys are
hosts
,group_vars
andhost_vars
. Molecule’s schema validator will enforce this.provisioner: name: ansible inventory: links: hosts: ../../../inventory/hosts 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
Add arguments to ansible-playbook when running converge:
provisioner: name: ansible ansible_args: - --inventory=mygroups.yml - --limit=host1,host2
Initialize a new ansible class and returns None.
- Parameters
config – An instance of a Molecule config.
- Returns
None
Scenario¶
Molecule treats scenarios as a first-class citizens, with a top-level configuration syntax.
-
class
molecule.scenario.
Scenario
¶ A scenario allows Molecule test a role in a particular way, this is a fundamental change from Molecule v1.
A scenario is a self-contained directory containing everything necessary for testing the role in a particular way. The default scenario is named
default
, and every role should contain a default scenario.Unless mentioned explicitly, the scenario name will be the directory name hosting the files.
Any option set in this section will override the defaults.
scenario: create_sequence: - dependency - create - prepare check_sequence: - dependency - cleanup - destroy - create - prepare - converge - check - destroy converge_sequence: - dependency - create - prepare - converge destroy_sequence: - dependency - cleanup - destroy test_sequence: - dependency - lint - cleanup - destroy - syntax - create - prepare - converge - idempotence - side_effect - verify - cleanup - destroy
Initialize a new scenario class and returns None.
- Parameters
config – An instance of a Molecule config.
- Returns
None
State¶
An internal bookkeeping mechanism.
-
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.
Initialize a new state class and returns None.
- Parameters
config – An instance of a Molecule config.
- Returns
None
Verifier¶
Molecule handles role testing by invoking configurable verifiers.
Ansible¶
-
class
molecule.verifier.ansible.
Ansible
¶ Ansible is the default test verifier.
Molecule executes a playbook (verify.yml) located in the role’s scenario.directory.
verifier: name: ansible
The testing can be disabled by setting
enabled
to False.verifier: name: ansible enabled: False
Environment variables can be passed to the verifier.
verifier: name: ansible env: FOO: bar
Initialize code for all Verifier classes.
- Parameters
config – An instance of a Molecule config.
- Returns
None
Testinfra¶
-
class
molecule.verifier.testinfra.
Testinfra
¶ Testinfra is no longer the default test verifier since version 3.0.
Additional options can be passed to
testinfra
through the options dict. Any option set in this section will override the defaults.Note
Molecule will remove any options matching ‘^[v]+$’, and pass
-vvv
to the underlyingpytest
command when executingmolecule --debug
.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/
Additional tests from another file or directory relative to the scenario’s tests directory (supports regexp).
verifier: name: testinfra additional_files_or_dirs: - ../path/to/test_1.py - ../path/to/test_2.py - ../path/to/directory/*
Set up the requirements to execute
testinfra
and returns None.- Parameters
config – An instance of a Molecule config.
- Returns
None