How to do Ansible role test with Molecule in KVM

sky_joker@Ansible x VMware
3 min readJan 26, 2021

--

In this article, I will explain to do Ansible role test with the molecule in KVM.
In the molecule, the driver exists for the libvirt, but that the playbook was blank for a test instance creating and destroying.

So, we need to use the delegated driver if you want to do the test in KVM.

Advance preparation

You need to meet the requirements of the following.

  • KVM installed
  • Template VM created(This time, use Linux)

Molecule installation

Install the molecule.

pip install molecule

Molecule scenario generation

Execute a scenario initialization after moving to a role you want to do the test.
This time, I use prepared the example role as a sample.

cd example/
molecule init scenario
ls molecule/default/
converge.yml create.yml destroy.yml INSTALL.rst molecule.yml verify.yml

Please check to exist the default scenario and the molecule files.

destroy.yml changing

The destroy.yml destroys a test instance.
The test instance destroys using the virt module.
An error occurs if the test instance doesn’t exist, so it will ignore to be set true to the ignore_errors.
Finally, delete an image file for the test instance.

---
- name: Destroy
hosts: localhost
connection: local
gather_facts: false
no_log: "{{ molecule_no_log }}"
tasks:
- name: Shutdown the instance
virt:
name: "{{ item.name }}"
command: shutdown
state: shutdown
loop: "{{ molecule_yml.platforms }}"
ignore_errors: true
- name: Destroy the instance
virt:
name: "{{ item.name }}"
command: destroy
state: destroyed
loop: "{{ molecule_yml.platforms }}"
ignore_errors: true
- name: Undefine the instance
virt:
name: "{{ item.name }}"
command: undefine
loop: "{{ molecule_yml.platforms }}"
ignore_errors: true
- name: Delete image file of the instance
file:
path: "{{ item.image_file_path }}"
state: absent
loop: "{{ molecule_yml.platforms }}"

create.yml changing

The create.yml creates a test instance.
First, clone the test instance from the template VM.
After that, start the test instance and waiting until to get IP Address.
The instance network needs to config NAT.

---
- name: Create
hosts: localhost
connection: local
gather_facts: false
no_log: "{{ molecule_no_log }}"
tasks:
- name: Create a new instance for molecule test
command: |
virt-clone --original {{ item.image }} \
--name {{ item.name }} \
--file {{ item.image_file_path }} \
--check \
path_exists=off
changed_when: true
register: server
loop: "{{ molecule_yml.platforms }}"
- name: Start the instance
virt:
name: "{{ item.name }}"
command: start
state: running
loop: "{{ molecule_yml.platforms }}"
when: server is changed
- name: Wait if until assigned IP Address to the instance
command: "virsh domifaddr {{ item.name }}"
retries: 60
delay: 5
until: check_ip_address_result.stdout | regex_search('ipv4')
register: check_ip_address_result
changed_when: false
loop: "{{ molecule_yml.platforms }}"
when: server is changed
- name: Set _instance_info variable that is using when a connection to the instance
set_fact:
_instance_info: >-
{{ _instance_info | default([])
+ [data]
}}
vars:
data:
name: >-
{{ item.item.name }}
instance_ip_addr: >-
{{ item.stdout_lines
| map('regex_search','(?:[0-9]{1,3}\.){3}[0-9]{1,3}')
| select('string')
| list
| first
}}
loop: "{{ check_ip_address_result.results }}"
when: server is changed
- name: Wait if until a connection is to be possible for the SSH port of the instance
wait_for:
host: "{{ item.instance_ip_addr }}"
port: 22
state: started
loop: "{{ _instance_info }}"
when: server is changed
- name: Populate instance config dict
set_fact:
instance_conf_dict:
instance: "{{ instance_info.name }}"
address: "{{ instance_info.instance_ip_addr }}"
user: "{{ molecule_yml.driver.vm_username }}"
password: "{{ molecule_yml.driver.vm_password | default(omit) }}"
port: 22
identity_file: "{{ instance_info.ssh_key_path | default(omit) }}"
loop: "{{ _instance_info }}"
loop_control:
loop_var: instance_info
register: instance_config_dict
when: server is changed
- name: Convert instance config dict to a list.
set_fact:
instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
when: server is changed
- name: Dump instance config
copy:
content: "{{ instance_conf | to_json | from_json | to_yaml }}"
dest: "{{ molecule_instance_config }}"
mode: 0644
when: server is changed

molecule.yml changing

The molecule.yml is a configuration of the molecule.
The driver uses the delegated.
Please change other config based on your environment.

---
dependency:
name: galaxy
driver:
name: delegated
vm_username: root # is OS user of the test instance
vm_password: secret # is OS user password of the test instance
platforms:
- name: instance # is the test instance name
image: centos7.0 # is the template VM name to use in clone
image_file_path: /var/lib/libvirt/images/testvm2.img # is an image file saving path of the test instance
provisioner:
name: ansible
verifier:
name: ansible

Test execution

Execute the molecule test command.

molecule test

The role test is executed in the test instance after the creation of it.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

sky_joker@Ansible x VMware
sky_joker@Ansible x VMware

No responses yet

Write a response