Как настроить тестовую разработку с помощью Molecule in Ansible

Read this article in:

Молекула Это основа тестирования, предназначенная для ролей, коллекций и плейбуков 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Для получения дополнительной информации по теме.

.

Please login to post comments: