Spec-Zone.ru › Ansible

Разработка модулей сетевых ресурсов

  • Общие сведения о модулях сетевых ресурсов и ресурсов безопасности
  • Разработка модулей сетевых ресурсов и ресурсов безопасности

    • Общие сведения о модели и конструкторе модулей ресурсов
    • Доступ к конструктору модулей ресурсов
    • Создание модели
    • Создание каркаса коллекции на основе модели ресурса
  • Примеры

    • Структура каталогов коллекции
    • Структура каталогов роли
    • Использование коллекции
    • Использование роли
  • Структура и рабочий процесс модуля ресурсов
  • Запуск ansible-test sanity и tox для модулей ресурсов
  • Тестирование модулей ресурсов

    • Интеграционные тесты модулей ресурсов
    • Требования к модульным тестам
  • Пример: модульное тестирование модулей сетевых ресурсов Ansible

    • Использование объектов-заглушек для модульного тестирования модулей сетевых ресурсов Ansible
    • Имитация данных устройства

Общие сведения о модулях сетевых ресурсов и ресурсов безопасности

Сетевые устройства и устройства безопасности разделяют конфигурацию на разделы (например, интерфейсы, VLAN и т. д.), применяемые к сетевым службам или службам безопасности. Модули ресурсов Ansible используют эту особенность, позволяя пользователям настраивать подразделы или ресурсы в конфигурации устройства. Модули ресурсов обеспечивают единообразную работу с различными сетевыми устройствами и устройствами безопасности. Например, модуль сетевых ресурсов может обновлять только конфигурацию определенной части сетевых интерфейсов, VLAN, ACL и т. д. сетевого устройства. Модуль ресурсов выполняет следующие действия:

  1. Получает часть конфигурации (сбор фактов), например конфигурацию интерфейсов.
  2. Преобразует полученную конфигурацию в пары «ключ-значение».
  3. Помещает эти пары «ключ-значение» во внутренний независимый структурированный формат данных.

После нормализации данных конфигурации пользователь может обновить и изменить их, а затем использовать модуль ресурсов, чтобы отправить данные конфигурации обратно на устройство. В результате конфигурация обновляется в полном цикле без необходимости вручную анализировать и обрабатывать данные или управлять моделью данных.

Модуль ресурсов имеет два ключа верхнего уровня — config и state:

  • config определяет модель данных конфигурации ресурса в виде пар «ключ-значение». Тип параметра config может быть dict или list of dict в зависимости от управляемого ресурса. Если на устройстве имеется одна глобальная конфигурация, это должен быть тип dict (например, глобальная конфигурация LLDP). Если на устройстве имеется несколько экземпляров конфигурации, тип должен быть list, а каждый элемент списка должен иметь тип dict (например, конфигурация интерфейсов).
  • state определяет действие, которое модуль ресурсов выполняет на конечном устройстве.

Параметр state нового модуля ресурсов должен поддерживать следующие значения (если они поддерживаются устройствами):

merged

Ansible объединяет конфигурацию устройства с конфигурацией, указанной в задаче.

replaced

Ansible заменяет подраздел конфигурации устройства подразделом конфигурации, указанным в задаче.

overridden

Ansible переопределяет конфигурацию ресурса на устройстве конфигурацией, указанной в задаче. Будьте осторожны при использовании этого состояния: вы можете потерять доступ к устройству (например, переопределив конфигурацию интерфейса управления).

deleted

Ansible удаляет подраздел конфигурации устройства и восстанавливает настройки по умолчанию.

gathered

Ansible отображает сведения о ресурсе, собранные с сетевого устройства и доступные в результате по ключу gathered.

rendered

Ansible преобразует конфигурацию, указанную в задаче, в собственный формат устройства (например, Cisco IOS CLI). Ansible возвращает преобразованную конфигурацию в результате по ключу rendered. Обратите внимание, что в этом состоянии связь с сетевым устройством не устанавливается, поэтому его можно использовать автономно.

parsed

Ansible анализирует конфигурацию из параметра running_configuration и преобразует её в структурированные данные Ansible, которые помещаются в результат по ключу parsed. Обратите внимание, что конфигурация сетевого устройства не собирается, поэтому это состояние можно использовать автономно.

Модули в поддерживаемых Ansible коллекциях должны поддерживать эти значения состояния. Если вы разрабатываете модуль, в котором для состояния предусмотрены только «present» и «absent», его можно отправить в коллекцию сообщества.

Примечание

Состояния rendered, gathered и parsed не вносят никаких изменений на устройстве.

Разработка модулей сетевых ресурсов и ресурсов безопасности

Команда разработки Ansible следит за единообразием проектирования модулей и шаблонов кода в поддерживаемых Ansible коллекциях для разных ресурсов и платформ. Это обеспечивает независимый от поставщика подход и высокое качество кода. Для разработки модуля ресурсов мы рекомендуем использовать конструктор модулей ресурсов.

Общий процесс разработки модуля ресурсов:

  1. Создайте модель ресурса и отправьте её на проверку в виде PR в репозиторий моделей модулей ресурсов.
  2. Скачайте последнюю версию конструктора модулей ресурсов.
  3. Запустите resource module builder, чтобы создать каркас коллекции на основе утверждённой модели ресурса.
  4. Напишите код для реализации модуля ресурсов.
  5. Разработайте интеграционные и модульные тесты для проверки модуля ресурсов.
  6. Создайте PR в соответствующую коллекцию, в которую нужно добавить новый модуль ресурсов. Сведения о выборе подходящей коллекции для модуля см. в разделе Участие в разработке поддерживаемых Ansible коллекций.

Общие сведения о модели и конструкторе модулей ресурсов

Конструктор модулей ресурсов — это Ansible Playbook, помогающий разработчикам создавать каркас модуля ресурсов Ansible и поддерживать его. В качестве единого источника достоверных данных для модуля используется модель. Эта модель представляет собой файл yaml, используемый для раздела DOCUMENTATION модуля и спецификации аргументов.

Конструктор модулей ресурсов предоставляет следующие возможности:

  • Использует заданную модель для создания структуры каталогов модуля ресурсов и начальных файлов классов.
  • Создаёт каркас роли Ansible или коллекции.
  • При последующих запусках конструктора модулей ресурсов заменяются только спецификация аргументов модуля и файл, содержащий строку документации модуля.
  • Позволяет хранить сложные примеры в одном каталоге с моделью.
  • Сохраняет модель в качестве единого источника достоверных данных для модуля и позволяет использовать конструктор модулей ресурсов для обновления исходных файлов по мере необходимости.
  • Создаёт работающие примеры модулей как для <network_os>_<resource>, так и для <network_os>_facts.

Доступ к конструктору модулей ресурсов

Чтобы получить доступ к конструктору модулей ресурсов:

  1. Клонируйте репозиторий GitHub:
git clone https://github.com/ansible-network/resource_module_builder.git
  1. Установите необходимые компоненты:
pip install -r requirements.txt

Создание модели

Для нового ресурса необходимо создать модель. Модель является единым источником достоверных данных как для спецификации аргументов, так и для строки документации, обеспечивая их синхронизацию. После утверждения модели можно использовать конструктор модулей ресурсов для создания на её основе трёх элементов:

  • Каркаса нового модуля
  • Спецификации аргументов нового модуля
  • Строки документации нового модуля

При последующих изменениях функциональности сначала обновите модель, а затем используйте конструктор модулей ресурсов для обновления спецификации аргументов и строки документации модуля.

Например, в конструкторе моделей ресурсов есть пример myos_interfaces.yml в каталоге models, показанный ниже:

---
GENERATOR_VERSION: '1.0'

NETWORK_OS: myos
RESOURCE: interfaces
COPYRIGHT: Copyright 2019 Red Hat
LICENSE: gpl-3.0.txt

DOCUMENTATION: |
  module: myos_interfaces
  version_added: 1.0.0
  short_description: 'Manages <xxxx> attributes of <network_os> <resource>'
  description: 'Manages <xxxx> attributes of <network_os> <resource>.'
  author: Ansible Network Engineer
  notes:
    - 'Tested against <network_os> <version>'
  options:
    config:
      description: The provided configuration
      type: list
      elements: dict
      suboptions:
        name:
          type: str
          description: The name of the <resource>
        some_string:
          type: str
          description:
          - The some_string_01
          choices:
          - choice_a
          - choice_b
          - choice_c
          default: choice_a
        some_bool:
          description:
          - The some_bool.
          type: bool
        some_int:
          description:
          - The some_int.
          type: int
          version_added: '1.1.0'
        some_dict:
          type: dict
          description:
          - The some_dict.
          suboptions:
            property_01:
              description:
              - The property_01
              type: str
    state:
      description:
      - The state of the configuration after module completion.
      type: str
      choices:
      - merged
      - replaced
      - overridden
      - deleted
      default: merged
EXAMPLES:
  - deleted_example_01.txt
  - merged_example_01.txt
  - overridden_example_01.txt
  - replaced_example_01.txt

Обратите внимание: следует добавить примеры для каждого состояния, поддерживаемого ресурсом. Эти примеры также включены в образец модели конструктора модулей ресурсов.

Отправьте эту модель на проверку в виде PR в репозиторий моделей модулей ресурсов. Там же можно найти другие примеры моделей.

Создание каркаса коллекции на основе модели ресурса

Чтобы с помощью конструктора модулей ресурсов создать каркас коллекции на основе утверждённой модели ресурса:

ansible-playbook -e rm_dest=<destination for modules and module utils> \
                 -e structure=collection \
                 -e collection_org=<collection_org> \
                 -e collection_name=<collection_name> \
                 -e model=<model> \
                 site.yml

Параметры:

  • rm_dest: каталог, в котором конструктор модулей ресурсов размещает файлы и каталоги модуля ресурсов и модулей facts.
  • structure: тип структуры каталогов (роль или коллекция)

    • role: создать структуру каталогов роли.
    • collection: создать структуру каталогов коллекции.
  • collection_org: организация коллекции; обязательный параметр, если указан structure=collection.
  • collection_name: имя коллекции; обязательный параметр, если указан structure=collection.
  • model: путь к файлу модели.

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

ansible-playbook -e rm_dest=<destination for modules and module utils> \
                 -e structure=role \
                 -e model=<model> \
                 site.yml

Примеры

Структура каталогов коллекции

В этом примере показана структура каталогов для следующих параметров:

  • network_os: myos
  • resource: interfaces
ansible-playbook -e rm_dest=~/github/rm_example \
                 -e structure=collection \
                 -e collection_org=cidrblock \
                 -e collection_name=my_collection \
                 -e model=models/myos/interfaces/myos_interfaces.yml \
                 site.yml
├── docs
├── LICENSE.txt
├── playbooks
├── plugins
|   ├── action
|   ├── filter
|   ├── inventory
|   ├── modules
|   |   ├── __init__.py
|   |   ├── myos_facts.py
|   |   └──  myos_interfaces.py
|   └──  module_utils
|       ├── __init__.py
|       └──  network
|           ├── __init__.py
|           └──  myos
|               ├── argspec
|               |   ├── facts
|               |   |   ├── facts.py
|               |   |   └──  __init__.py
|               |   ├── __init__.py
|               |   └──  interfaces
|               |       ├── __init__.py
|               |       └──  interfaces.py
|               ├── config
|               |   ├── __init__.py
|               |   └──  interfaces
|               |       ├── __init__.py
|               |       └──  interfaces.py
|               ├── facts
|               |   ├── facts.py
|               |   ├── __init__.py
|               |   └──  interfaces
|               |       ├── __init__.py
|               |       └──  interfaces.py
|               ├── __init__.py
|               └──  utils
|                   ├── __init__.py
|                   └──  utils.py
├── README.md
└──  roles

Структура каталогов роли

В этом примере показана структура каталогов роли для следующих параметров:

  • network_os: myos
  • resource: interfaces
ansible-playbook -e rm_dest=~/github/rm_example/roles/my_role \
                 -e structure=role \
                 -e model=models/myos/interfaces/myos_interfaces.yml \
                 site.yml
roles
└── my_role
    ├── library
    │   ├── __init__.py
    │   ├── myos_facts.py
    │   └── myos_interfaces.py
    ├── LICENSE.txt
    ├── module_utils
    │   ├── __init__.py
    │   └── network
    │       ├── __init__.py
    │       └── myos
    │           ├── argspec
    │           │   ├── facts
    │           │   │   ├── facts.py
    │           │   │   └── __init__.py
    │           │   ├── __init__.py
    │           │   └── interfaces
    │           │       ├── __init__.py
    │           │       └── interfaces.py
    │           ├── config
    │           │   ├── __init__.py
    │           │   └── interfaces
    │           │       ├── __init__.py
    │           │       └── interfaces.py
    │           ├── facts
    │           │   ├── facts.py
    │           │   ├── __init__.py
    │           │   └── interfaces
    │           │       ├── __init__.py
    │           │       └── interfaces.py
    │           ├── __init__.py
    │           └── utils
    │               ├── __init__.py
    │               └── utils.py
    └── README.md

Использование коллекции

В этом примере показано, как использовать созданную коллекцию в плейбуке:

---
- hosts: myos101
  gather_facts: False
  tasks:
  - cidrblock.my_collection.myos_interfaces:
    register: result
  - debug:
      var: result
  - cidrblock.my_collection.myos_facts:
  - debug:
      var: ansible_network_resources

Использование роли

В этом примере показано, как использовать созданную роль в плейбуке:

- hosts: myos101
  gather_facts: False
  roles:
  - my_role

- hosts: myos101
  gather_facts: False
  tasks:
  - myos_interfaces:
    register: result
  - debug:
      var: result
  - myos_facts:
  - debug:
      var: ansible_network_resources

Структура и рабочий процесс модуля ресурсов

Структура модуля ресурсов включает следующие компоненты:

Модуль
  • library/<ansible_network_os>_<resource>.py.
  • Импортирует пакет ресурсов module_utils и вызывает API execute_module:
def main():
    result = <resource_package>(module).execute_module()
Спецификация аргументов модуля
  • module_utils/<ansible_network_os>/argspec/<resource>/.
  • Спецификация аргументов ресурса.
Факты
  • module_utils/<ansible_network_os>/facts/<resource>/.
  • Заполнение фактов для ресурса.
  • Запись в module_utils/<ansible_network_os>/facts/facts.py для API get_facts, обеспечивающая синхронизацию модуля <ansible_network_os>_facts и собранных фактов для модуля ресурсов по каждому подмножеству.
  • Запись подмножества ресурса в список FACTS_RESOURCE_SUBSETS в module_utils/<ansible_network_os>/facts/facts.py, необходимая для сбора фактов.
Пакет модуля в module_utils
  • module_utils/<ansible_network_os>/<config>/<resource>/.
  • Реализация API execute_module, который загружает конфигурацию на устройство и формирует результат с ключами changed, commands, before и after.
  • Вызов API get_facts, возвращающего факты конфигурации <resource> или различия, если устройство поддерживает вычисление различий на своей стороне.
  • Сравнение собранных фактов и заданных пар «ключ-значение», если вычисление различий не поддерживается.
  • Формирование итоговой конфигурации.
Утилиты
  • module_utils/<ansible_network_os>/utils.
  • Утилиты для платформы <ansible_network_os>.

Запуск ansible-test sanity и tox для модулей ресурсов

Перед отправкой PR в поддерживаемую Ansible коллекцию запустите ansible-test sanity и tox -elinters из корневого каталога коллекции. CI запускает оба теста, и при их сбое проверка завершится с ошибкой. Подробные сведения о ansible-test sanity см. в разделе Тестирование Ansible.

Чтобы установить необходимые пакеты:

  1. Убедитесь, что настроена корректная среда разработки Ansible. Подробные сведения см. в разделе Подготовка среды для разработки модулей Ansible.
  2. Запустите pip install -r requirements.txt из корневого каталога коллекции.

При запуске tox -elinters выполняются следующие действия:

  • Считывается tox.ini из корневого каталога коллекции и устанавливаются необходимые зависимости (например, black и flake8).
  • Эти инструменты запускаются с предварительно настроенными параметрами (например, ограничением длины строк и исключениями).
  • black запускается в режиме проверки, чтобы показать, какие файлы будут отформатированы, не выполняя форматирование.

Тестирование модулей ресурсов

Тесты используют роль, созданную конструктором модулей ресурсов. После внесения изменений в конструктор модулей ресурсов необходимо заново создать роль, а затем при необходимости изменить и запустить тесты. Чтобы создать роль после внесения изменений:

rm -rf rmb_tests/roles/my_role
ansible-playbook -e rm_dest=./rmb_tests/roles/my_role \
                 -e structure=role \
                 -e model=models/myos/interfaces/myos_interfaces.yml \
                 site.yml

Интеграционные тесты модулей ресурсов

Общие требования к интеграционным тестам новых модулей ресурсов:

  1. Напишите тестовый случай для каждого состояния.
  2. Напишите дополнительные тестовые случаи, проверяющие поведение модуля при передаче пустого значения config.yaml.
  3. Добавьте тест полного цикла. Он включает операцию merge, за которой следует gather_facts, обновление merge с дополнительной конфигурацией, а затем возврат к исходной конфигурации с использованием ранее собранных фактов и параметра state, установленного в overridden.
  4. По возможности утверждения должны проверять состояние до и после dicts относительно жёстко заданного эталона.

Для выполнения интеграционных тестов в CI мы используем Zuul.

  • Чтобы просмотреть отчёт, нажмите Details в комментарии CI к PR.
  • Чтобы просмотреть отчёт об ошибках, нажмите ansible/check и выберите тест, завершившийся с ошибкой.
  • Чтобы просмотреть журналы во время выполнения теста, найдите номер своего PR на доске состояния Zuul.
  • Чтобы локально устранить сбой статического теста, запустите tox -e black в корневом каталоге коллекции.

Чтобы просмотреть журналы запуска Ansible и отладить сбои тестов:

  1. Нажмите на задание, завершившееся с ошибкой, чтобы открыть сводку, а затем нажмите Logs, чтобы просмотреть журнал.
  2. Нажмите console и прокрутите страницу вниз до теста, завершившегося с ошибкой.
  3. Нажмите > рядом с тестом, завершившимся с ошибкой, чтобы просмотреть полные сведения.

Структура интеграционных тестов

Каждый тестовый случай обычно должен следовать такому шаблону:

  • настройка —> тест —> проверка —> повторный тест (для проверки идемпотентности) —> проверка —> очистка (если требуется) -> завершение. Это позволяет избежать громоздких плейбуков тестов, которые сложно отлаживать.
  • Добавьте имя каждой задаче, которая не является проверкой. Именовать можно и проверки, но имя для каждой задачи упрощает поиск проблемной задачи при сбое теста.
  • Файлы с тестовыми случаями должны иметь расширение .yaml

Реализация

Для платформ, поддерживающих connection: local и connection: network_cli, следуйте приведённым ниже рекомендациям:

  • Назовите каталоги targets/ в соответствии с именем модуля.
  • Файл main.yaml должен содержать только ссылку на транспорт.

В следующем примере рассматриваются интеграционные тесты модуля vyos.vyos.vyos_l3_interfaces в коллекции vyos.vyos:

test/integration/targets/vyos_l3_interfaces/tasks/main.yaml

---
- import_tasks: cli.yaml
  tags:
    - cli

test/integration/targets/vyos_l3_interfaces/tasks/cli.yaml

---
- name: collect all cli test cases
  find:
    paths: "{{ role_path }}/tests/cli"
    patterns: "{{ testcase }}.yaml"
  register: test_cases
  delegate_to: localhost

- name: set test_items
  set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"

- name: run test cases (connection=network_cli)
  include_tasks:
     file: "{{ test_case_to_run }}"
  vars:
     ansible_connection: network_cli
  with_items: "{{ test_items }}"
  loop_control:
    loop_var: test_case_to_run

- name: run test case (connection=local)
  include_tasks:
     file: "{{ test_case_to_run }}"
  vars:
     ansible_connection: local
     ansible_become: false
  with_first_found: "{{ test_items }}"
  loop_control:
    loop_var: test_case_to_run

test/integration/targets/vyos_l3_interfaces/tests/cli/overridden.yaml

---
- debug: null
  msg: START vyos_l3_interfaces merged integration tests on connection={{ ansible_connection }}

- import_tasks: _remove_config.yaml

- block:
  - import_tasks: _populate.yaml
  - name: Overrides all device configuration with provided configuration
    register: result
    vyos.vyos.vyos_l3_interfaces:
      config:
        - name: eth0
          ipv4:
            - address: dhcp
        - name: eth1
          ipv4:
            - address: 192.0.2.15/24
      state: overridden
  - name: Assert that before dicts were correctly generated
    assert:
      that:
        - populate | symmetric_difference(result['before']) | length == 0
  - name: Assert that correct commands were generated
    assert:
      that:
        - >-
          overridden['commands']
          | symmetric_difference(result['commands'])
          | length
          == 0
  - name: Assert that after dicts were correctly generated
    assert:
      that:
        - overridden['after'] | symmetric_difference(result['after']) | length == 0
  - name: Override device configuration with provided configuration (IDEMPOTENT)
    register: result
    vyos.vyos.vyos_l3_interfaces:
      config:
        - name: eth0
          ipv4:
            - address: dhcp
        - name: eth1
          ipv4:
            - address: 192.0.2.15/24
      state: overridden
  - name: Assert that the previous task was idempotent
    assert:
      that:
        - result is not changed
  - name: Assert that before dicts were correctly generated
    assert:
      that:
        - overridden['after'] | symmetric_difference(result['before']) | length == 0
  always:
  - import_tasks: _remove_config.yaml

Обнаружение тестовых ресурсов во время выполнения

Тесты должны обнаруживать ресурсы (например, интерфейсы) во время выполнения, а не содержать их жёстко заданные значения. Это позволяет запускать тесты в различных системах.

Например:

- name: Collect interface list
  connection: ansible.netcommon.network_cli
  register: intout
  cisco.nxos.nxos_command:
    commands:
      - show interface brief | json

- set_fact:
    intdataraw: "{{ intout.stdout_lines[0]['TABLE_interface']['ROW_interface'] }}"

- set_fact:
    nxos_int1: '{{ intdataraw[1].interface }}'

- set_fact:
    nxos_int2: '{{ intdataraw[2].interface }}'

- set_fact:
    nxos_int3: '{{ intdataraw[3].interface }}'

Полный пример теста см. по адресу https://github.com/ansible-collections/cisco.nxos/blob/main/tests/integration/targets/prepare_nxos_tests/tasks/main.yml.

Запуск сетевых интеграционных тестов

Ansible использует Zuul для запуска набора интеграционных тестов при каждом PR, включая новые тесты, добавленные в этом PR. Чтобы находить и устранять проблемы в сетевых модулях, запустите сетевые интеграционные тесты локально до отправки PR.

Сначала создайте файл инвентаризации, содержащий адреса тестовых машин. Группа инвентаризации должна соответствовать имени платформы (например, eos, ios):

cd test/integration
cp inventory.network.template inventory.networking
${EDITOR:-vi} inventory.networking
# Add in machines for the platform(s) you wish to test

Для запуска этих сетевых интеграционных тестов используйте ansible-test network-integration --inventory </path/to/inventory> <tests_to_run>:

ansible-test network-integration  --inventory ~/myinventory -vvv vyos_facts
ansible-test network-integration  --inventory ~/myinventory -vvv vyos_.*

Чтобы запустить все сетевые тесты для определённой платформы:

ansible-test network-integration --inventory  /path/to-collection-module/test/integration/inventory.networking vyos_.*

В этом примере будут запущены тесты для всех модулей vyos. Обратите внимание: vyos_.* — это регулярное выражение, а не шаблон оболочки bash. Если вы изменяете этот пример, включите ..

Чтобы запустить интеграционные тесты для определённого модуля:

ansible-test network-integration --inventory  /path/to-collection-module/test/integration/inventory.networking vyos_l3_interfaces

Чтобы запустить один тестовый случай для определённого модуля:

# Only run vyos_l3_interfaces/tests/cli/gathered.yaml
ansible-test network-integration --inventory  /path/to-collection-module/test/integration/inventory.networking vyos_l3_interfaces --testcase gathered

Чтобы запустить интеграционные тесты для определённого транспорта:

 # Only run nxapi test
ansible-test network-integration --inventory  /path/to-collection-module/test/integration/inventory.networking  --tags="nxapi" nxos_.*

# Skip any cli tests
 ansible-test network-integration --inventory  /path/to-collection-module/test/integration/inventory.networking  --skip-tags="cli" nxos_.*

О том, как это реализовано в тестах, см. файл test/integration/targets/nxos_bgp/tasks/main.yaml.

Дополнительные параметры:

ansible-test network-integration --help

Если вам нужна дополнительная помощь или вы хотите оставить отзыв, обратитесь к сообществу. Подробности см. в руководстве по общению с сообществом Ansible.

Требования к модульным тестам

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

  1. Напишите тестовые случаи для всех состояний и всех возможных сочетаний значений конфигурации.
  2. Напишите тестовые случаи для проверки условий ошибок (негативных сценариев).
  3. Проверяйте значения ключей changed и commands в каждом тестовом случае.

Мы запускаем все модульные тесты в наборе тестов Zuul с последней версией Python, поддерживаемой нашей конфигурацией CI.

Для просмотра отчётов и журналов модульных тестов Zuul используйте ту же процедуру, что и для интеграционных тестов.

Общие сведения о модульном тестировании см. в разделе модульное тестирование модулей.

Пример: модульное тестирование модулей сетевых ресурсов Ansible

В этом разделе на примере рассматривается разработка модульных тестов для модулей ресурсов Ansible.

Общие сведения о модульных тестах Ansible для модулей см. в разделах Модульные тесты и Модульное тестирование модулей Ansible. Сначала прочитайте эти страницы, чтобы разобраться в модульных тестах, а также понять, зачем и когда их следует использовать.

Использование объектов-заглушек для модульного тестирования модулей сетевых ресурсов Ansible

Объекты-заглушки могут быть очень полезны при создании модульных тестов для особых или сложных случаев, но они также могут усложнить код и сделать его трудным для понимания. Хороший пример применения заглушек — имитация API. Пакет Python mock входит в состав Ansible (используйте import units.compat.mock).

Подключение к устройству и его вывод можно имитировать следующим образом:

self.mock_get_config = patch( "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config"
)
self.get_config = self.mock_get_config.start()

self.mock_load_config = patch(
"ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config"
)
self.load_config = self.mock_load_config.start()

self.mock_get_resource_connection_config = patch(
"ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection"
)
self.get_resource_connection_config = (self.mock_get_resource_connection_config.start())

self.mock_get_resource_connection_facts = patch(
"ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection"
)
self.get_resource_connection_facts = (self.mock_get_resource_connection_facts.start())

self.mock_edit_config = patch(
"ansible_collections.arista.eos.plugins.module_utils.network.eos.providers.providers.CliProvider.edit_config"
)
self.edit_config = self.mock_edit_config.start()

self.mock_execute_show_command = patch(
"ansible_collections.arista.eos.plugins.module_utils.network.eos.facts.l2_interfaces.l2_interfaces.L2_interfacesFacts.get_device_data"
)
self.execute_show_command = self.mock_execute_show_command.start()

Теперь файл facts модуля содержит новый метод get_device_data. Вызовите здесь get_device_data, чтобы имитировать вывод устройства.

Имитация данных устройства

Чтобы имитировать получение результатов с устройств или предоставить другие сложные структуры данных из внешних библиотек, можно использовать fixtures для чтения предварительно созданных данных. Текстовые файлы с такими данными хранятся в test/units/modules/network/PLATFORM/fixtures/. Например, см. файл eos_l2_interfaces.cfg.

Загрузите данные с помощью метода load_fixture и задайте их в качестве возвращаемого значения метода get_device_data в файле facts:

def load_fixtures(self, commands=None, transport='cli'):
    def load_from_file(*args, **kwargs):
        return load_fixture('eos_l2_interfaces_config.cfg')
    self.execute_show_command.side_effect = load_from_file

Практический пример см. в файле модульного теста test_eos_l2_interfaces.

См. также

Модульные тесты

Подробное руководство по разработке модульных тестов для модулей Ansible

Тестирование Ansible и коллекций

Запуск тестов локально, в том числе сбор и создание отчётов о покрытии

Разработка модулей

Начало работы над модулем

© 2012–2018 Michael DeHaan
© 2018–2025 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/projects/ansible/latest/network/dev_guide/developing_resource_modules_network.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API