[Перевод] Проверка ролей Ansible через делегированный драйвер Molecule

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

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

Этот пост основан на моем опыте разработки простой роли Ansible от 0 до galaxy и фокусирует внимание на использовании делегированного драйвера, интегрированного с Google Cloud Platform. В качестве отправной точки я взял следующие полезные ссылки для своего проекта:

Делегированный драйвер: что говорит документация Molecule?

Одна из причин, которая заставила меня написать это руководство, — это заявление в официальной документации Molecule:

Разработчик должен придерживаться instance-config API. Пособие по созданию разработчика должно содержать следующие данные instance-config, а руководство по уничтожению разработчика должно сбрасывать instance-config.

Возникает вопрос: что такое instance-config и какие данные должен предоставить разработчик?

Instance-config — это факт Ansible, хранящийся в файле YAML в кэше Molecule ( $HOME/.cache/molecule/<role-name>/<scenario-name>/instance_config.yml), который имеет следующую структуру:

- address: 10.10.15.17
 identity_file: /home/fabio/.ssh/id_rsa # mutually exclusive with
                                        # password
 instance: millennium_falcon
 port: 22
 user: hansolo
# password: ssh_password # mutually exclusive with identity_file
 become_method: sudo # optional
# become_pass: password_if_required # optional

Для тех, кому нужно иметь дело с узлами Windows, документация также предоставляет эквивалентную структуру для WinRM.

Файл create.yml

После того, как мы прояснили, что такое instance-config, мы можем переходить к следующему шагу. К счастью, Molecule также помогает нам сделать дополнительный шаг вперед, предоставляя файлы шаблонов сценариев с помощью команды molecule init, например:

molecule init scenario -driver-name=delegated

который создает следующую структуру каталогов:

.
├── INSTALL.rst
├── converge.yml
├── create.yml
├── destroy.yml
├── molecule.yml
└── verify.yml

  • molecule.yml — это файл конфигурации Molecule, который определяет переменные, устанавливает фазовую последовательность и конфигурацию для каждой из них.
  • create.yml — код Ansible для создания экземпляров на облачной платформе и хранения данных в instance-config.
  • destroy.yml код Ansible для уничтожения экземпляров на облачной платформе и удаления их из instance-config
  • converge.yml исполнение роли
  • verify.yml набор проверочных тестов
  • INSTALL.rst инструкции по установке необходимых зависимостей для запуска тестов Molecule

Теперь давайте сосредоточимся на файле create.yml, созданном Molecule:

---
- name: Create
 hosts: localhost
 connection: local
 gather_facts: false
 no_log: "{{ molecule_no_log }}"
 tasks:

 # Developer must implement.
 # Developer must map instance config.
 # Mandatory configuration for Molecule to function.

 — name: Populate instance config dict
 set_fact:
 instance_conf_dict: {
 'instance': "{{ }}",
 'address': "{{ }}",
 'user': "{{ }}",
 'port': "{{ }}",
 'identity_file': "{{ }}", }
 with_items: "{{ server.results }}"
 register: instance_config_dict
 when: server.changed | bool

 — name: Convert instance config dict to a list
 set_fact:
 instance_conf: {{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
 when: server.changed | bool

 — name: Dump instance config
 copy:
 content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
 dest: "{{ molecule_instance_config }}"
 when: server.changed | bool

Три задачи: заполнение, преобразование и дамп, создание в конце файла instance-config.yml. Прокомментированный раздел является заполнителем для кода Ansible, который должен создавать облачные ресурсы и возвращать массив серверов (содержащий детали экземпляра) в качестве зарегистрированной переменной или факта. Следующий фрагмент кода, взятый из этой проблемы с github, предоставляет пример того, что указано выше для контекста VMWare:

…
 7     - name: Create molecule instance(s)
 8      vmware_guest:
 9        hostname: "{{ molecule_yml.driver.hostname }}"
10        esxi_hostname: "{{ molecule_yml.driver.esxi_hostname }}"
11        username: "{{ molecule_yml.driver.username }}"
12        password: "{{ molecule_yml.driver.password }}"
13        datacenter: "{{ molecule_yml.driver.datacenter }}"
14        validate_certs: "{{ molecule_yml.driver.validate_certs }}"
15        resource_pool: "{{ molecule_yml.driver.resource_pool }}"
16         folder: "{{ molecule_yml.driver.folder }}"
17         name: "{{ item.name }}"
18         template: "{{ item.template }}"
19         hardware:
20           memory_mb: "{{ item.memory | default(omit) }}"
21           num_cpus: "{{ item.cpu | default(omit) }}"
22         wait_for_ip_address: "yes"
23         state: poweredon
24       register: server
25       with_items: "{{ molecule_yml.platforms }}"
26     
27     - name: Populate instance config dict
28       set_fact:
29         instance_conf_dict: {
30           'instance': "{{ item.instance.hw_name }}",
31           'address': "{{ item.instance.ipv4 }}",
32           'user': "vagrant",
33           'port': "22",
34           'identity_file': 'identity_file': "{{
                     molecule_yml.driver.ssh_identity_file }}"
35         }
36       with_items: "{{ server.results }}"
37       register: instance_config_dict
38       when: server is changed
…

Код вызывает модуль vmware_guest (строки 7–23) для создания виртуальной машины на сервере VMWare. Это делается для каждого элемента массива платформ, определенного в файле molecule.yml (строка 25). Как видите, переменные, определенные в файле molecule.yml, доступны через факт molecule_yml.

Значения, возвращаемые каждым вызовом vmware_guest, регистрируются как элементы массива сервера (строка 24), который, в свою очередь, используется для заполнения конфигурации экземпляра (instance-config) (строки 27 и далее). Обратите внимание, что обновление факта конфигурации экземпляра пропускается, если переменная сервера не изменяется.

Работа с Google Cloud Platform (GCP)

Теперь, когда я разъяснил, что и как должен делать разработчик при работе с делегированным драйвером, я собираюсь поделиться работой, проделанной для моей роли docker-secured Ansible. Для этой роли я решил использовать GCP в качестве облачного сервера для делегированного драйвера. Ansible предоставляет семейство модулей GCP для работы с таким облачным провайдером, и я надеюсь, что вы легко сможете адаптировать мой код, если вам нужно сменить семейство модулей и облачного провайдера.

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

  • python 2.7
  • ansible 2.9.6
  • molecule 3.0.2
  • ansible-lint 4.2.0
  • yamllint 1.20.0
  • flake8 3.7.9 (mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 2.7.17 на Linux

где yamllint, ansible-lint и flake8 — инструменты для проверки кода, которые включены в фазы молекулы.

Роль docker-secured

Роль для тестирования устанавливает докер на узел, предоставляет API-интерфейсы докеров и защищает их с помощью ssl. Процедура, которой я следовал, описана в этих двух ссылках из документации Docker:

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

Вы можете посмотреть мой проект, клонировав репозиторий GitHub:

git clone https://github.com/fabiomarinetti/fmarinetti.docker-secured.git

Предварительные шаги для GCP

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

Для этой роли я создал проект ansible-272015 и службу учетной записи service, ее ключ хранится в файле secret.json.

Файл molecule.yml

В этом разделе я покажу и прокомментирую соответствующий раздел моего файла molecule.yml.

Проект, тип аутентификации и секретный ключ вставляются в файл molecule.yml в разделе driver. Кроме того, я также добавил в тот же раздел все другие параметры, которые остаются постоянными на этапах создания и уничтожения, например, регион и зона GCP, пользователь ssh и файл идентификатора, а также параметры сети, поскольку предполагается, что виртуальные машины находятся в той же сети, в которой создан ad-hoc на время теста. Ко всем этим значениям можно получить доступ из сценария через molecule_yml (например, molecule_yml.driver.region для доступа к региону).

20 driver:
21   name: delegated
22   gcp_service_account_key: ${GOOGLE_APPLICATION_CREDENTIALS}
23   gcp_project_id: ansible-272015
24   region: us-east1
25   zone: us-east1-c
26   ssh_user: ${SSH_USER}
27   ssh_pub_key_file: "${SSH_ID_FILE}.pub"
28   ssh_key_file: "${SSH_ID_FILE}"
29   network_name: ansible-network
30   subnet_name: ansible-subnet
31   firewall_name: ansible-firewall
32   ip_cidr_range: 172.16.0.0/28

Раздел платформы в файле molecule.yml содержит массив, содержащий параметры (имя, изображение, тип, размер…) для экземпляров, которые я хочу проверить. Мое тестовое покрытие включает CentOS 7, Ubuntu Xenial 16.04 и Ubuntu Bionic 18.04. Эти машины сгруппированы по типу ОС (например, CentOS или Ubuntu), чтобы использовать группы инвентаря при выполнении Ansible.

41 platforms:
42   - name: "ds-centos7-${TRAVIS_BUILD_ID}"
43     image_family: projects/centos-cloud/global/images/family
                     /centos-7
44     machine_type: n1-standard-1
45     size_gb: 200
46     groups:
47       - centos
48   - name: "ds-ubuntu-bionic-${TRAVIS_BUILD_ID}"
49     image_family: projects/ubuntu-os-cloud/global/images/family
                     /ubuntu-1804-lts
50     machine_type: n1-standard-1
51     size_gb: 200
52     groups:
53       - ubuntu
54   - name:  "ds-ubuntu-xenial-${TRAVIS_BUILD_ID}"
55     image_family: projects/ubuntu-os-cloud/global/images/family
                     /ubuntu-1604-lts
56     machine_type: n1-standard-1
57     size_gb: 200
58     groups:
59       - ubuntu

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

Фаза создания и файл create.yml

Как уже говорилось ранее, create.yml — это сценарий, который управляет этапом создания. Здесь я широко использовал модули семейства gcp для управления ресурсами облачного провайдера (GCP). Модули GCP нуждаются в каком-то фиксированном параметре, таком как идентификатор проекта, тип аутентификации и путь к секретному ключу, и, чтобы избежать повторения этих значений в коде при каждом вызове модуля, я установил их как module_defaults для всего семейства gcp.

 7   module_defaults:
 8     group/gcp:
 9       project: "{{ molecule_yml.driver.gcp_project_id }}"
10       auth_kind: serviceaccount
11       service_account_file: "{{ 
              molecule_yml.driver.gcp_service_account_key }}"

В отличие от того, что мы видели ранее в случае VMWare, создание экземпляра в GCP — это не просто вопрос использования одного модуля, а процесс, состоящий из нескольких шагов: создание загрузочного диска, назначение IP-адреса и создание самого экземпляра. Это означает, что для цикла по платформам мне нужно было поместить задачи создания в отдельный файл и включить его в цикл:

16 — name: create instances
17   include_tasks: tasks/create_instance.yml
18   loop: "{{ molecule_yml.platforms }}"

Файл create_instance.yml содержит задачи по резервированию IP-адреса, созданию загрузочного диска и созданию экземпляра. То, как я вызвал связанные модули, довольно стандартно и их можно менять, если вы хотите переключиться на другого облачного провайдера, поэтому я не буду их обсуждать дальше, а лишь хочу сказать несколько слов о том, как возвращать данные экземпляра для подачи задач заполнения instance-config.

7 - name: initialize instance facts
 8   set_fact:
 9     instance_created:
10       instances: []
11   when: instance_created is not defined
... create the instance and return instance variable ...
56 - name: update instance facts
57   set_fact:
58     instance_created:
59       changed: instance.changed | bool
60       instances: "{{ instance_created.instances + [ instance ]}}"

Затем после цикла платформы для заполнения isntance-config используется факт instance_create:

20     - name: Populate instance config dict
21       set_fact:
22         instance_conf_dict: {
23           'instance': "{{ item.name }}",
24           'address': "{{
               item.networkInterfaces[0].accessConfigs[0].natIP }}",
25           'user': "{{ molecule_yml.driver.ssh_user }}",
26           'port': "22",
27           'identity_file': "{{ molecule_yml.driver.ssh_key_file
               }}", }
28       with_items: "{{ instance_created.instances }}"
29       register: instance_config_dict
30       when: instance_created.changed

Здесь эта задача выполняется, только если один из экземпляров был изменен, как это произошло в случае VMWare, когда было указано предложение servers is changed

Наконец, я протестировал этап создания, введя команду:

molecule create --scenario-name=gcp

Убедившись, что результаты созданы правильно, я перешел к конвейеру и выполнил / протестировал фазы:

  • lint, которая выполняет проверку кода
  • prepare, которая подготавливает экземпляр для применения роли. В данном случае это просто обновление исходных кодов пакетов для группы ubuntu.
  • converge, которая просто применяет роль
  • idempotence, которая применяет роль во второй раз для обеспечения ее идемпотентности
  • verify, которая подтверждает, что результаты применения роли соответствуют ожиданиям
molecule <phase> --scenario-name=gcp

В этом случае, учитывая простоту роли и ограниченные требования, мне не пришлось так сильно менять Молекулу, генерируемую при инициализации сценария.

На последнем шаге я написал destroy.yml для удаления созданных ресурсов из проекта (а также моего счета ). Код для уничтожения ресурсов следует той же философии, что и тот, который их создает. Очевидно, проверка проводилась путем выдачи:

molecule destroy --scenario-name=gcp

Как только все этапы были правильными и не выдали ошибок, я мог протестировать весь процесс с помощью команды:

molecule test --scenario-test=gcp

Выводы

В этом посте я объяснил, как использовать делегированный драйвер Molecule, и показал, как я реализовал его с помощью GCP. Этот же код легко адаптировать к другому облачному провайдеру: AWS, Azure, Digital Ocean… и я надеюсь, что вы наверняка получите выгоду от использования Molecule. Пожалуйста, оставьте отзыв.

Let’s block ads! (Why?)

Read More

Recent Posts

Apple возобновила переговоры с OpenAI и Google для интеграции ИИ в iPhone

Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…

4 дня ago

Российская «дочка» Google подготовила 23 иска к крупнейшим игрокам рекламного рынка

Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…

4 дня ago

Google завершил обновление основного алгоритма March 2024 Core Update

Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…

4 дня ago

Нейросети будут писать тексты объявления за продавцов на Авито

У частных продавцов на Авито появилась возможность составлять текст объявлений с помощью нейросети. Новый функционал доступен в категории «Обувь, одежда,…

4 дня ago

Объявлены победители международной премии Workspace Digital Awards-2024

24 апреля 2024 года в Москве состоялась церемония вручения наград международного конкурса Workspace Digital Awards. В этом году участниками стали…

5 дней ago

Яндекс проведет гик-фестиваль Young Con

27 июня Яндекс проведет гик-фестиваль Young Con для студентов и молодых специалистов, которые интересуются технологиями и хотят работать в IT.…

5 дней ago