# Molecule
## Введение
**Molecule** - инструмент, направленный на облегчение написания и тестирования Ansible ролей и плейбуков. Позволяет выполнять тесты одновременно на различных комбинациях операционных систем и виртуальных сред с использованием разных инструментов тестирования.
## Версирование и установка
Текущая главная версия - **Molecule v3**. В нашем отделе используется **v3.5.2**.
Molecule представляет собой модуль Python, поэтому установку можно производить с помощью PIP. Дополнительные модули указываются в квадратных скобках: ```molecule[lint,docker,vagrant]```.
Например, установка на систему с docker, vagrant и virtualbox производится следующей командой:
```bash
python3 -m pip install molecule==3.5.2 molecule[lint,vagrant,docker] docker python-vagrant
```
## Терминология
**Prerun** - последовательность действий, выполняемая для нахождения и установки модулей, ролей и коллекций, используемые Ansible в проекте.
**Scenario** - описывает все возможные последовательности (sequence) команд (command), которые можно выполнять в рамках текущего проекта. Например, создание виртуальной среды по умолчанию состоит из трех действий: разрешение зависимостей, создание среды и ее подготовка.
## Molecule Workflow
В общем виде архитектуру Molecule можно представить в следующем виде:

В более конкретном виде выполнение последовательности описывается следующей схемой:

Та же схема, но с расшифрованными командами:

В зависимости от последовательности некоторые команды могут отсутствовать. Например, создание виртуальной среды состоит из следующих этапов:

---
Узнать, какие команды будут выполняться в конкретной последовательности, можно с помощью команды ``` molecule matrix command```. Например, в случае create получаем вывод:
```
$ molecule matrix create
INFO Test matrix
---
default:
- dependency
- create
- prepare
```
## Включение Molecule в процесс разработки
Molecule использует Ansible Galaxy для генерации общепринятой структуры роли. Чтобы создать новую роль, нужно выполнить команду:
```
molecule init role role-name
```
После выполнения в корне текущей директории появится следующая структура:
```
$ tree role-name
role-name/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── molecule
│ └── default
│ ├── converge.yml
│ ├── create.yml
│ ├── destroy.yml
│ ├── INSTALL.rst
│ ├── molecule.yml
│ └── verify.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
```
Как видно, структура роли идентична той, которая используется в Ansible Galaxy, за исключением директории *molecule*, в которой хранятся все сценарии.
Если же требуется инициализировать Molecule в существующей роли, то нужно выполнить следующую команду в корне этой роли:
```bash
molecule init scenario -r role-name
```
### Описание компонентов Molecule
Стандартный сценарий после инициализации роли имеет название *default*. В нем находятся конфигурационные файлы, основным среди которых является *molecule.yml*. Он содержит описание следующих компонентов Molecule:
- *Dependency* - разрешает зависимости роли. По умолчанию используется Ansible Galaxy.
- *Driver* - параметры используемого драйвера, отвечающего за создание и удаление виртуальных сред тестирования, что описывается соответственно в файлах *create.yml* и *destroy.yml*. По умолчанию используется Delegated Driver, который перекладывает всю ответственность по составлению этих файлов на разработчика.
- *Lint* - набор команд, проверяющие соответствие содержания файлов проекта набору общепринятых правил. По умолчанию используется Yamllint.
- *Platforms* - описание виртуальных сред, которые будут задействованы в процессе тестирования.
- *Provisioner* - запускает роль/плейбук в виртуальной среде в соответствии с описанием в файле *converge.yml*. Поддерживается только Ansible.
- *Scenario* - задает порядок выполнения команд в последовательностях.
- *Verifier* - управляет запуском тестов в виртуальной среде, описанных в файле *verify.yml*. По умолчанию используется Ansible.
Пример файла *molecule.yml*:
```yaml
---
dependency:
name: galaxy
enabled: false
options:
role-file: requirements.yml
driver:
name: vagrant
provider:
name: virtualbox
lint: |
set -e
yamllint .
ansible-lint
flake8
platforms:
- name: centos7
box: "centos/7"
box_url: "https://prod-nexus.scartel.dc/repository/infrastructure/vagrant/centos7_1.1.json"
cpus: 2
memory: 1024
instance_raw_config_args:
- "vm.box_download_insecure = true"
- "vm.network 'private_network', ip: '192.168.30.21'"
provider_raw_config_args:
- "customize ['createhd', '--filename', 'centos7-d1.vdi', '--size', 2 * 1024]"
- "customize ['storageattach', :id, '--storagectl', 'IDE', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', 'centos7-d1.vdi']"
- name: centos8
box: "centos/8"
box_url: "https://prod-nexus.scartel.dc/repository/infrastructure/vagrant/centos8_1.1.json"
cpus: 2
memory: 1024
instance_raw_config_args:
- "vm.box_download_insecure = true"
- "vm.network 'private_network', ip: '192.168.30.22'"
provider_raw_config_args:
- "customize ['createhd', '--filename', 'centos8-d1.vdi', '--size', 2 * 1024]"
- "customize ['storageattach', :id, '--storagectl', 'IDE', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', 'centos8-d1.vdi']"
provisioner:
name: ansible
playbooks:
converge: converge.yml
verify: verify.yml
scenario:
create_sequence:
- create
converge_sequence:
- create
- converge
destroy_sequence:
- destroy
test_sequence:
- lint
- destroy
- syntax
- create
- converge
- verify
- destroy
verifier:
name: ansible
```
### Директива provisioner
Чтобы подключить к molecule директории с переменными групп и хостов и файл inventory, нужно добавить следующий раздел:
```yaml
inventory:
links:
hosts: "../../../inventory/hosts"
group_vars: "../../../inventory/group_vars/"
host_vars: "../../../inventory/host_vars/"
```
Аргументы при запуске сценария с помощью *ansible-playbook* указываются в разделе:
```yaml
ansible_args:
- --inventory=mygroups.yml
- --limit=host1,host2
```
### Файл *converge.yml*
Данный файл является полноценным сценарием, поэтому в нем можно указать также роли, расположенные в родительской директории текущей роли, чтобы они выполнялись с помощью команды *mol converge*.
## Полезные команды
Информацию о виртуальной среде, описанных в конфигурационном файле Molecule, можно получить из вывода команды ```molecule list```:
```
$ molecule list
INFO Running default > list
╷ ╷ ╷ ╷ ╷
Instance Name │ Driver Name │ Provisioner Name │ Scenario Name │ Created │ Converged
╶───────────────┼─────────────┼──────────────────┼───────────────┼─────────┼───────────╴
centos7 │ vagrant │ ansible │ default │ true │ true
centos8 │ vagrant │ ansible │ default │ true │ false
```
---
Команда ```molecule login --host instance_name``` позволяет подключиться к работающей системе в виртуальной среде посредством SSH. Поддерживает сокращения. Например, если в выводе ```molecule list``` всего один экземпляр с именем *centos7*, то подключиться к нему можно выполнив ```molecule login -h c```.
---
Получить список установленных и поддерживаемых Molecule драйверов можно выполнением команды ```molecule drivers```:
```
$ molecule drivers
╶───────────────────────────────────────────────────────────────────────────────────────
delegated
docker
vagrant
```
---
Команда ```molecule reset``` очищает временные файлы, созданные в процессе выполнения prerun и хранящиеся в *$HOME/.cache/molecule/<projectname>*.
---
Команда ```molecule check``` предназначена для получения результата выполнения роли или плейбука без фактического применения изменений (Dry Run). Она является эквивалентной в Ansible команде ```ansible-playbook playbook.yml --check```.