ProHoster > Blog > Administration > Instructions: how to test ansible roles and find out about problems before production
Instructions: how to test ansible roles and find out about problems before production
Hi all!
I work as a DevOps engineer in a hotel booking service. Ostrovok.ru. In this article, I want to talk about our experience in testing ansible roles.
At Ostrovok.ru, we use ansible as a configuration manager. Recently, we came to the need to test roles, but as it turned out, there are not so many tools for this - the most popular, perhaps, is the Molecule framework, so we decided to use it. But it turned out that his documentation is silent about many pitfalls. We could not find a sufficiently detailed manual in Russian, so we decided to write this article.
Molecule
Molecule - a framework to help test ansible roles.
Simplified description: The molecule creates an instance on the platform you specify (cloud, virtual machine, container; for more details, see the section driver), runs your role on it, then runs tests and deletes the instance. In case of failure on one of the steps, the Molecule will inform you about it.
Now the details.
Some theory
Consider two key entities of the Molecule: Scenario and Driver.
Screenwriting
The script contains a description of what, where, how and in what sequence will be performed. One role can have several scripts, and each is a directory along the path <role>/molecule/<scenario>, which contains descriptions of the actions required for the test. Script must be included default, which will be automatically created if you initialize the role with a Molecule. The names of the following scripts are up to you.
The sequence of testing actions in a script is called matrix, and by default it is:
(Steps labeled ?, skipped by default if not specified by the user)
lint - running linters. By default are used yamllint и flake8,
destroy - deleting instances from the last launch of the Molecule (if any),
dependency? — installation of the ansible dependency of the tested role,
syntax - checking the syntax of the role using ansible-playbook --syntax-check,
create - creating an instance,
prepare? — preparation of the instance; e.g. check/install python2
converge — launch of the playbook being tested,
idempotence - restarting the playbook for the idempotency test,
side_effect? - actions not directly related to the role, but necessary for tests,
verify - running tests of the resulting configuration using testinfra(default) /goss/inspec,
cleanup? - (in new versions) - roughly speaking, "cleaning" the external infrastructure affected by the Molecule,
destroy - Deleting an instance.
This sequence covers most cases, but can be changed if necessary.
Each of the above steps can be run separately with molecule <command>. But it should be understood that for each such cli-command there may be its own sequence of actions, which you can find out by executing molecule matrix <command>. For example, when running the command converge (running the playbook under test), the following actions will be performed:
$ molecule matrix converge
...
└── default # название сценария
├── dependency # установка зависимостей
├── create # создание инстанса
├── prepare # преднастройка инстанса
└── converge # прогон плейбука
The sequence of these actions can be edited. If something from the list is already done, it will be skipped. The current state, as well as the config of the instances, the Molecule stores in the directory $TMPDIR/molecule/<role>/<scenario>.
Add steps with ? you can describe the desired actions in the ansible-playbook format, and make the file name according to the step: prepare.yml/side_effect.yml. Expect these files The molecule will be in the script folder.
driver
A driver is an entity where test instances are created.
The list of standard drivers for which Molecule has templates ready is as follows: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.
In most cases, templates are files create.yml и destroy.yml in the script folder that describe the creation and deletion of an instance, respectively.
The exceptions are Docker and Vagrant, as interactions with their modules can occur without the aforementioned files.
It is worth highlighting the Delegated driver, since if it is used in the files for creating and deleting an instance, only work with the configuration of instances is described, the rest should be described by the engineer.
The default driver is Docker.
Now let's move on to practice and consider further features there.
Beginning of work
As a "hello world", let's test a simple nginx installation role. We will choose docker as the driver - I think most of you have it installed (and remember that docker is the default driver).
The next step is to initialize the new role.
Initialization of a new role, as well as a new script, is performed using the command molecule init <params>:
> molecule init role -r nginx
--> Initializing new role nginx...
Initialized role in <path>/nginx successfully.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars
6 directories, 1 file
It turned out a typical ansible-role. Further, all interactions with CLI Molecules are made from the root of the role.
Let's see what is in the role directory:
> tree molecule/default/
molecule/default/
├── Dockerfile.j2 # Jinja-шаблон для Dockerfile
├── INSTALL.rst. # Немного информации об установке зависимостей сценария
├── molecule.yml # Файл конфигурации
├── playbook.yml # Плейбук запуска роли
└── tests # Директория с тестами стадии verify
└── test_default.py
1 directory, 6 files
Let's analyze the config molecule/default/molecule.yml (replace only docker image):
Shell is just a command shell that is used in case galaxy and gilt don't cover your needs.
I will not dwell here for a long time, it is enough described in documentation.
driver
The name of the driver. Ours is docker.
ribbon
The linter is yamllint.
Useful options in this part of the config are the ability to specify a configuration file for yamllint, forward environment variables, or disable the linter:
Describes the configuration of the instances.
In the case of docker as a driver, the Molecule is iterated over this section, and each element of the list is available in Dockerfile.j2 as a variable item.
In the case of a driver that requires create.yml и destroy.yml, the section is available in them as molecule_yml.platforms, and iterations over it are already described in these files.
Since the Molecule provides control of instances to ansible modules, the list of possible settings should also be looked for there. For docker, for example, the module is used docker_container_module. Which modules are used in other drivers can be found in documentation.
As well as examples of the use of various drivers can be found in the tests of the Molecule itself.
Replace here centos:7 on ubuntu.
provisioner
"Supplier" - an entity that manages instances. In the case of Molecule, this is ansible, support for others is not planned, so this section can be called ansible extended configuration with a caveat.
Here you can specify a lot of things, I will highlight the main points, in my opinion:
playbooks: you can specify which playbooks should be used at certain stages.
Name and description of script sequences.
You can change the default action matrix of any command by adding the key <command>_sequence and as a value for it by defining the list of steps we need.
Let's say we want to change the sequence of actions when running the playbook run command: molecule converge
Our simple role was tested without problems.
It is worth remembering that if there are problems during the work molecule test, then if you didn't change the default sequence, the Molecule will delete the instance.
The following commands are useful for debugging:
> molecule --debug <command> # debug info. При обычном запуске Молекула скрывает логи.
> molecule converge # Оставляет инстанс после прогона тестируемой роли.
> molecule login # Зайти в созданный инстанс.
> molecule --help # Полный список команд.
Existing Role
Adding a new script to an existing role is from the role directory with the following commands:
# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>
In case this is the first scenario in the role, then the parameter -s can be omitted as it will create a script default.
Conclusion
As you can see, the Molecule is not very complex, and by using your own templates, deploying a new script can be reduced to editing variables in the instance creation and deletion playbooks. The molecule integrates seamlessly with CI systems, which allows you to increase the speed of development by reducing the time for manual testing of playbooks.
Thank you for your attention. If you have experience in testing ansible roles, and it is not related to the Molecule, tell us about it in the comments!