Молекула Это основа тестирования, предназначенная для ролей, коллекций и плейбуков Ansible. В экосистеме Ansible обеспечивает структурированный рабочий процесс для разработки и проверки инфраструктуры в качестве кода.
С более широкой точки зрения Молекула поощряет Развитие инфраструктуры на основе испытаний (TDD)Вместо того, чтобы развертывать роли непосредственно в производстве и надеяться, что они работают, разработчики могут проверять их локально или в трубопроводах CI с Molecule. Он поддерживает различные стратегии тестирования, подкладку, идемпотентность и экосистему плагинов.
Будучи немного сложным в настройке, Molecule позволяет разработчику формализмы правильного мышления (TM). TDD позволяет разработчику проверить готовый шаг и пометить его как завершенный. TDD позволяет мыслить по частям: вместо того, чтобы быть перегруженным большой задачей, разработчик может реализовать и проверить небольшие части реализуемой функциональности - и с такими постепенными изменениями весь проект может быть завершен.
* * * * * * *
Молекула претерпела серьезные изменения между некоторыми релизами, и некоторые документы в Интернете оказались неверными. Эта статья работает с Molecule версии 25. Здесь я просто настраиваю минимальный каркас, чтобы запустить простой тест на одной машине для удаления. Читатель может взять его оттуда, настраивая эшафот под свои специфические потребности.
Допустим, у нас есть приемлемый проект со следующей структурой папки:
wco_ansible/
inventory/
ants.yml
do.yml
playbooks/
setup_mongo.yml
setup_ubuntu.yml
requirements.yml
roles/
ror/
files/
root/
_screenrc
meta/
main.yml
molecule/
...
requirements.yml
tasks/
packaged_app.yml
templates/
etc/
mongo.conf
vars/
packaged_app_1.ymlМы проверим конкретную задачу в этой роли. рогаВо-первых, давайте разберем структуру wco ansible/roles/ror/molecule Вот так:
wco_ansible/roles/ror/molecule/
README.txt
default/
converge.yml
create.yml
destroy.yml
molecule.yml
verify.yml
И содержимое файлов:
## requirements.yml
collections:
- name: community.docker
version: ">=3.10.4"
- name: community.general.
## converge.yml
- name: Fail if molecule group is missing
hosts: localhost
tasks:
- name: Print some info
ansible.builtin.debug:
msg: "{{ groups }}"
- name: Assert group existence
ansible.builtin.assert:
that: "'molecule' in groups"
fail_msg: |
molecule group was not found inside inventory groups: {{ groups }}
- name: Converge
hosts: molecule
# We disable gather facts because it would fail due to our container not
# having python installed. This will not prevent use from running 'raw'
# commands. Most molecule users are expected to use containers that already
# have python installed in order to avoid notable delays installing it.
# gather_facts: false
tasks:
- name: Check uname
ansible.builtin.raw: uname -a
register: result
changed_when: false
- name: Print some info
ansible.builtin.assert:
that: result.stdout is ansible.builtin.search("^Linux")
- name: "+++ +++ Check Python version is >= 3.8"
command: python3 --version
register: py_ver
changed_when: false
- name: "+++ +++ Assert correct Python version"
assert:
that:
- py_ver.stdout is match("Python 3\\.[189].*|Python [4-9].*")Важно следующее. В частности, добавление контейнера в molevule inventory имеет значение.
## create.yml
- name: Create
hosts: localhost
gather_facts: false
vars:
molecule_inventory:
all:
hosts: {}
# molecule: {}
tasks:
- name: Create a container
community.docker.docker_container:
name: "{{ item.name }}"
image: "{{ item.image }}"
state: started
command: sleep 1d
log_driver: json-file
register: result
loop: "{{ molecule_yml.platforms }}"
- name: Print some info
ansible.builtin.debug:
msg: "{{ result.results }}"
- name: Fail if container is not running
when: >
item.container.State.ExitCode != 0 or
not item.container.State.Running
ansible.builtin.include_tasks:
file: tasks/create-fail.yml
loop: "{{ result.results }}"
loop_control:
label: "{{ item.container.Name }}"
- name: Add container to molecule_inventory
vars:
inventory_partial_yaml: |
all:
children:
molecule:
hosts:
"{{ item.name }}":
ansible_connection: {{ item.ansible_connection }}
ansible_user: {{ item.ansible_user }}
ansible_host: {{ item.ansible_host }}
ansible_port: {{ item.ansible_port }}
ansible_ssh_common_args: {{ item.ansible_ssh_common_args }}
ansible_ssh_private_key_file: {{ item.ansible_ssh_private_key_file }}
ansible.builtin.set_fact:
molecule_inventory: >
{{ molecule_inventory | combine(inventory_partial_yaml | from_yaml, recursive=true) }}
loop: "{{ molecule_yml.platforms }}"
loop_control:
label: "{{ item.name }}"
- name: Dump molecule_inventory
ansible.builtin.copy:
content: |
{{ molecule_inventory | to_yaml }}
dest: "{{ molecule_ephemeral_directory }}/inventory/molecule_inventory.yml"
mode: "0600"
- name: Force inventory refresh
ansible.builtin.meta: refresh_inventory
- name: Fail if molecule group is missing
ansible.builtin.assert:
that: "'molecule' in groups"
fail_msg: |
molecule group was not found inside inventory groups: {{ groups }}
run_once: true # noqa: run-once[task]
# we want to avoid errors like "Failed to create temporary directory"
- name: Validate that inventory was refreshed
hosts: molecule
gather_facts: false
tasks:
- name: Check uname
ansible.builtin.raw: uname -a
register: result
changed_when: false
- name: Display uname info
ansible.builtin.debug:
msg: "{{ result.stdout }}".
## destroy.yml
- name: Destroy molecule containers
hosts: molecule
gather_facts: false
tasks:
- name: Stop and remove container
delegate_to: localhost
community.docker.docker_container:
name: "{{ inventory_hostname }}"
state: absent
auto_remove: true
- name: Remove dynamic molecule inventory
hosts: localhost
gather_facts: false
tasks:
- name: Remove dynamic inventory file
ansible.builtin.file:
path: "{{ molecule_ephemeral_directory }}/inventory/molecule_inventory.yml"
state: absentВ следующем файле вы хотите иметь оба платформы и поставщик Ключи. Для меня эти же данные... Ведущий, порт и другие аргументы в поставщик Они определенно важны. Платформы могут быть необязательными, но я использую их в create.yml Так что пока они должны остаться. Следует отметить, что структура платформы Вероятно, можно упростить:
## molecule.yml
dependency:
name: galaxy
options:
requirements-file: requirements.yml
# driver:
# name: ssh
platforms:
- name: do-ubuntu24-3
ansible_connection: ssh
ansible_user: root
ansible_host: "x.x.x.x"
ansible_port: 22
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
ansible_ssh_private_key_file: ~/.ssh/your-key
groups:
- molecule
image: piousbox/ubuntu-sshd:0.0.0 ## not used, but presence is required
provisioner:
name: ansible
inventory:
host_vars:
do-ubuntu24-3:
ansible_connection: ssh
ansible_host: x.x.x.x
ansible_port: 22
ansible_user: root
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
ansible_ssh_private_key_file: ~/.ssh/your-keyТеперь комментарий на шшш vs докер Водитель. Я использую оба. Поскольку я веду докер с ансиблом, часто мне нужен докер внутри докера или что-то подобное, и в конце концов мне легче раскрутить виртуальную машину в другом месте и провести там тестирование через ssh. С другой стороны, в разработке ноутбука определенно используется много докеров, поэтому драйвер докера для молекул ценен и полезен. У меня есть свой собственный образ, который позволяет систематизировать и ssh. Вы можете прочитать статью на Как настроить изображение Docker с помощью Systemd и SSHDДля получения дополнительной информации по теме.
.