The goal of this project is to test your ansible system automation. Its goal is basically to test ansible roles, but role_unit’s own tests are an example of an other usage that can be made.
Role_unit is based on bash_unit, a bash unit-testing framework. The first provides the second a controlled environment for reproductible testing over multiple environments.
After a long time using only bash and standard Unix commands (like sed, grep, tr…), jq has been added as a pre-requisite. It is not a strong constraint and is used to manipulate docker and podman json outputs.
None of the following are really required to use role_unit. It only depends on your use-case.
-
docker, podman or podman-compose installed and configured to test using containers
-
nocloud if you want to test using nocloud virtual machines
-
ansible to test ansible roles
There is no installation process. Valid way to use role_unit is to clone repository somewhere and link role_init to a place where it will be in your PATH environment variable.
To create a new ansible role tested with role_unit, place yourself in the directory where you want the role and run role_init:
cd /my/ansible/dir/roles role_init my_role
This will create an empty role with the testing tools in the tests directory. A default tests file is created. To run the tests, you will have to specify the distribution by setting the RU_ENV_IMAGE variable (see below). Standard use is the following:
cd my_role RU_ENV_IMAGE=debian9 tests/bash_unit tests/tests_my_role
Full exemple of a role creation using role_init:
/tmp role_init app /tmp cd app /tmp/app RU_ENV_IMAGE=debian9 tests/bash_unit tests/tests_app Running tests in tests/tests_app starting container ru_role_unit_00 applying ansible playbook Running test_that_succeeds... SUCCESS ✓ Running test_that_succeeds_in_failure... SUCCESS ✓ stopping container ru_role_unit_00 /tmp/app RU_BACKEND=nocloud RU_ENV_IMAGE=debian9 tests/bash_unit tests/tests_app Running tests in tests/tests_app applying ansible playbook Running test_that_succeeds... SUCCESS ✓ Running test_that_succeeds_in_failure... SUCCESS ✓ stopping machines
The tests directory is a standard ansible structure : if you place a group_vars directory it will be used.
You have a list of functions you can call in your test file, described below.
In the standard usage, role_unit executes the following sequence:
-
containers creation
-
application of automation to the container(s)
-
execution of tests through bash_unit
-
containers destruction
if you set RU_DEBUG environment variable to 1, the sequence will be:
-
search for an existing debug environment
-
containers creation if none found
-
application of automation to the container(s)
-
execution of tests through bash_unit
containers are then not removed and instructions are given to enter the container to do actual debugging and dispose of the environment when debugging is done.
if tests are run without debug, any existing debug environment matching test file and backend will be destroyed.
here is a list of functions available in the test file as a complement of bash_unit to manipulate the test environment. For some examples see the tests_tuto file.
Initiates testing environment, i.e. creates containers or virtual machines depending on configuration.
Initiates ansible inventory and playbook necessary to test your ansible role.
Note that if your testing directory contains a requirements.yml file, ansible-galaxy will be used to fetch the roles in the roles directory. It is then up to you to use that role (rewrite playbook, include tasks in your role…).
Runs the specified command on all of the servers or just on the one specified. N is the number of the server you want to run the command on.
If you specify -d option, this will launch command in a detached mode. There may be evolution in the future about that but for now those options must be sepcified in this order only.
Similar to ru_run but will retry cmd every second until timeout T is expired or command returns a 0 exit code (whatever comes first). Return code will be the exit code of the last run of the command.
This comes handy for instance if you start a service on the server and you want to wait until the service is effectively operational.
Returns the specified ansible fact for all of the servers or just on the one specified. N is the number of the server you want to get the fact from.
Filters facts with the given expression and return the matching part of the facts in json format.
For instance, running
will return a similar parsable output :ru_fact_filter anisble_default_ipv4
192.168.13.53 | SUCCESS => { "ansible_facts": { "ansible_default_ipv4": { "address": "192.168.13.53", "alias": "ens3", "broadcast": "192.168.13.255", "gateway": "192.168.13.1", "interface": "ens3", "macaddress": "00:50:56:7a:3e:d9", "mtu": 1500, "netmask": "255.255.255.0", "network": "192.168.13.0", "type": "ether" } }, "changed": false }
Calling ru_group will rearange inventory by creating a new inventory group containing servers which indexes are past as argument.
This function comes with two others:
-
ru_groups will list all existing groups in inventory
-
ru_group_servers will list all servers in a group passed as argument
Those functions return either a single server name from index, or the list.
Returns the list of indexes to address the server through functions like ru_server or ru_run.
There is only one mandatory environment variable, which is RU_ENV_IMAGE. It defines the linux flavor you will run your tests against. Default configuration pulls docker images from role_unit containers repository (registry.gitlab.com/role_unit/role_unit_containers). Actually, you can choose among :
-
debian 11 (bullseye)
-
debian 10 (buster)
-
debian 9 (stretch)
-
ubuntu 22.04
-
ubuntu 20.04
-
ubuntu 18.04
-
centos 8
-
archlinux
This list is completed by some additional containers. For instance the '_cached' containers where package manager has a cache buitin to install package whithout extra steps (cache is being cleaned in standard container to reduce image size). Full list of those containers can be found in the container registry of role_unit_containers repository.
role_unit behaviour can be changed using environment variables:
-
RU_ENV_NAME defines the testing environment name. It is the name of the role you will test.
-
RU_BACKEND defines the the backend you are using. Can be docker, podman, podman-compose or nocloud, defaults to docker.
-
RU_ENV_DOCKER_REPO defines the docker repository to pull images from.
-
RU_ENV_IMAGE defines the system image used to create test environment.
-
RU_COUNT sets the number of containers or virtual machines
-
RU_DEBUG when set to 1, will make role_unit not to stop containers after the run, so you can enter them to check things.
-
RU_NOTMPFS defines wheter /tmp and /run are mounted as tmpfs. As a default they are, but there may be cases where, for instance, you want /tmp not to be mounted /noexec.
Following variable, only available with docker backend:
-
RU_FIXED_NAMES if set to 1, will have containers names based on RU_ENV_NAME instead of UUIDs. This will break the hability to run tests in a conccurent way, but is needed when container names must be predictable.
other role_unit variables may be used, but only to read values. Overwriting them may produce unexpected behaviours:
-
ru_inventory is an absolute path to the inventory that will be used by ru_run_frontend
-
ru_playbook is an absolute path to the playbook that will be used by ru_run_frontend
-
ru_dir is the temporary working directory for the tests. You will for instance find the group_vars in it.
For example of the usage you can made of these variables, have a look at the tests_tuto file in your tests directory.
Role unit functions are prefixed by ru_. Role_unit environment variables for configuration are prefixed by RU_. Internal variables are prefixed with ru_. We keep it that way to minimize impact on tested environment.