Здраво на сите!
Работам како инженер DevOps во услуга за резервации на хотели. . Во оваа статија, сакам да зборувам за нашето искуство во тестирањето на соодветни улоги.
На Ostrovok.ru користиме ansible како менаџер за конфигурација. Неодамна, дојдовме до потреба да ги тестираме улогите, но како што се испостави, нема толку многу алатки за ова - најпопуларната, можеби, е рамката на Молекулата, па решивме да ја користиме. Но, се покажа дека неговата документација молчи за многу стапици. Не можевме да најдеме доволно детален прирачник на руски, па решивме да ја напишеме оваа статија.

молекула
- рамка која ќе помогне да се тестираат соодветните улоги.
Поедноставен опис: молекулата создава примерок на платформата што ја одредувате (облак, виртуелна машина, контејнер; за повеќе детали, видете го делот ), ја извршува вашата улога на неа, потоа извршува тестови и ја брише инстанцата. Во случај на неуспех на еден од чекорите, Молекулата ќе ве информира за тоа.
Сега повеќе.
Малку теорија
Размислете за два клучни ентитети на молекулата: Сценарио и Возач.
Сценарио
Сценариото содржи опис што, каде, како и во кој редослед ќе се изведува. Една улога може да има неколку скрипти и секоја е директориум по патеката <role>/molecule/<scenario>, кој содржи описи на дејствата потребни за тестот. Скриптата мора да биде вклучена default, кој автоматски ќе се креира ако ја иницијализирате улогата со молекула. Имињата на следните скрипти зависи од вас.
Редоследот на тестирање акции во скрипта се нарекува матрица, и по дифолт е:
(Чекорите се означени ?, стандардно прескокнат ако не е одредено од корисникот)
lint- трчање линтери. Стандардно се користатyamllintиflake8,destroy- бришење на примероци од последното лансирање на молекулата (ако има),dependency? — инсталирање на разбирлива зависност на тестираната улога,syntax- проверка на синтаксата на улогата користејќиansible-playbook --syntax-check,create- создавање на пример,prepare? — подготовка на инстанцата; на пример, провери/инсталирај python2converge— лансирање на книгата за игри што се тестира,idempotence- рестартирање на книгата за тестот за идемпотенција,side_effect? - дејствија кои не се директно поврзани со улогата, но неопходни за тестови,verify- извршување на тестови на добиената конфигурација користејќиtestinfra(стандардно) /goss/inspec,cleanup? - (во нови верзии) - грубо кажано, „чистење“ на надворешната инфраструктура погодена од молекулата,destroy- Бришење на пример.
Оваа низа ги опфаќа повеќето случаи, но може да се промени доколку е потребно.
Секој од горенаведените чекори може да се изврши одделно со molecule <command>. Но, треба да се разбере дека за секоја таква кли-команда може да има свој редослед на дејства, што можете да го дознаете со извршување molecule matrix <command>. На пример, кога ја извршувате командата converge (вклучувајќи ја книгата за игри што се тестира), ќе се извршат следните дејства:
$ molecule matrix converge
...
└── default # название сценария
├── dependency # установка зависимостей
├── create # создание инстанса
├── prepare # преднастройка инстанса
└── converge # прогон плейбукаРедоследот на овие дејства може да се уредува. Ако нешто од списокот е веќе направено, ќе се прескокне. Тековната состојба, како и конфигурацијата на примероците, Молекулата ја складира во директориумот $TMPDIR/molecule/<role>/<scenario>.
Додадете чекори со ? можете да ги опишете саканите дејства во формат ansible-playbook и да го направите името на датотеката според чекорот: prepare.yml/side_effect.yml. Очекувајте ги овие датотеки Молекулата ќе биде во папката скрипта.
Возачот
Возачот е ентитет каде што се креираат тест примери.
Списокот на стандардни двигатели за кои Molecule има подготвени шаблони е како што следува: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.
Во повеќето случаи, шаблоните се датотеки create.yml и destroy.yml во папката скрипта што го опишува создавањето и бришењето на пример, соодветно.
Исклучоци се Docker и Vagrant, бидејќи интеракциите со нивните модули може да се случат без гореспоменатите датотеки.
Вреди да се истакне Делегираниот двигател, бидејќи ако се користи во датотеките за креирање и бришење на пример, се опишува само работа со конфигурација на примероци, а остатокот треба да го опише инженерот.
Стандардниот драјвер е Docker.
Сега да продолжиме да вежбаме и да разгледаме дополнителни карактеристики таму.
Getting Started
Како „здрав свет“, ајде да тестираме едноставна улога за инсталација на nginx. Ајде да го избереме докерот за драјвер - мислам дека повеќето од вас го имаат инсталирано (и запомнете дека докерот е стандардниот двигател).
Подгответе virtualenv и инсталирај во него molecule:
> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker # molecule установит ansible как зависимость; docker для драйвераСледниот чекор е да се иницијализира новата улога.
Иницијализирање на нова улога, како и нова скрипта, се врши со помош на командата molecule init <params>:
> molecule init role -r nginx
--> Initializing new role nginx...
Initialized role in <path>/nginx successfully.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars
6 directories, 1 fileИспадна типична одговорна улога. Понатаму, сите интеракции со CLI молекулите се направени од коренот на улогата.
Ајде да видиме што има во директориумот за улоги:
> tree molecule/default/
molecule/default/
├── Dockerfile.j2 # Jinja-шаблон для Dockerfile
├── INSTALL.rst. # Немного информации об установке зависимостей сценария
├── molecule.yml # Файл конфигурации
├── playbook.yml # Плейбук запуска роли
└── tests # Директория с тестами стадии verify
└── test_default.py
1 directory, 6 filesАјде да ја анализираме конфигурацијата molecule/default/molecule.yml (заменете ја само докерската слика):
---
dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
platforms:
- name: instance
image: centos:7
provisioner:
name: ansible
lint:
name: ansible-lint
scenario:
name: default
verifier:
name: testinfra
lint:
name: flake8зависност
Овој дел го опишува изворот на зависностите.
Можни опции: , , школка.
Шел е само командна обвивка што се користи во случај галаксијата и позлата да не ги покриваат вашите потреби.
Нема да се задржам овде долго време, доволно е опишано во .
возачот
Името на возачот. Нашиот е докер.
лента
Линтерот е јамлинт.
Корисни опции во овој дел од конфигурацијата се способноста да се определи конфигурациска датотека за yamllint, променливи на околината за проследување или оневозможување на линтер:
lint:
name: yamllint
options:
config-file: foo/bar
env:
FOO: bar
enabled: Falseплатформи
Ја опишува конфигурацијата на примероците.
Во случај на докер како двигател, молекулата се повторува преку овој дел и секој елемент од листата е достапен во Dockerfile.j2 како променлива item.
Во случај на возач кој бара create.yml и destroy.yml, делот е достапен во нив како molecule_yml.platforms, и повторувањата над него се веќе опишани во овие датотеки.
Со оглед на тоа што Молекулата обезбедува контрола на инстанци на ансибилни модули, таму треба да се бара и списокот на можни поставки. За докер, на пример, се користи модулот . Во кои модули се користат други драјвери може да се најдат .
Како и примери за употреба на различни драјвери може да се најдат .
Заменете овде centos:7 на ubuntu.
обезбедувач
„Добавувач“ - ентитет што управува со инстанци. Во случајот со Molecule, ова е оправдано, поддршката за другите не е планирана, така што овој дел може да се нарече неиздржлива проширена конфигурација со предупредување.
Овде можете да наведете многу работи, ќе ги истакнам главните точки, според мое мислење:
- игротеки: можете да одредите кои книги за играње треба да се користат во одредени фази.
provisioner:
name: ansible
playbooks:
create: create.yml
destroy: ../default/destroy.yml
converge: playbook.yml
side_effect: side_effect.yml
cleanup: cleanup.yml- config_options:
provisioner:
name: ansible
config_options:
defaults:
fact_caching: jsonfile
ssh_connection:
scp_if_ssh: True- поврзување_опции: опции
provisioner:
name: ansible
connection_options:
ansible_ssh_common_args: "-o 'UserKnownHostsFile=/dev/null' -o 'ForwardAgent=yes'"- опции: Ansible опции и променливи на околината
provisioner:
name: ansible
options:
vvv: true
diff: true
env:
FOO: BARсценарио
Име и опис на секвенците на скрипта.
Можете да ја промените стандардната акциона матрица на која било команда со додавање на клучот <command>_sequence и како вредност за него со дефинирање на листата на чекори кои ни се потребни.
Да речеме дека сакаме да го промениме редоследот на дејства кога ја извршуваме командата за извршување на Playbook: molecule converge
# изначально:
# - dependency
# - create
# - prepare
# - converge
scenario:
name: default
converge_sequence:
- create
- convergeпотврдувач
Поставување рамка за тестови и линтер за неа. Стандардниот линтер е testinfra и flake8. Можните опции се исти како погоре:
verifier:
name: testinfra
additional_files_or_dirs:
- ../path/to/test_1.py
- ../path/to/test_2.py
- ../path/to/directory/*
options:
n: 1
enabled: False
env:
FOO: bar
lint:
name: flake8
options:
benchmark: True
enabled: False
env:
FOO: barДа се вратиме на нашата улога. Ајде да ја уредиме датотеката tasks/main.yml на овој вид:
---
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
И додадете тестови на molecule/default/tests/test_default.py
def test_nginx_is_installed(host):
nginx = host.package("nginx")
assert nginx.is_installed
def test_nginx_running_and_enabled(host):
nginx = host.service("nginx")
assert nginx.is_running
assert nginx.is_enabled
def test_nginx_config(host):
host.run("nginx -t")
Готово, останува само да се кандидира (од коренот на улогата, да ве потсетам):
> molecule testДолг издув под спојлерот:
--> Validating schema <path>/nginx/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix
└── default
├── lint
├── destroy
├── dependency
├── syntax
├── create
├── prepare
├── converge
├── idempotence
├── side_effect
├── verify
└── destroy
--> Scenario: 'default'
--> Action: 'lint'
--> Executing Yamllint on files found in <path>/nginx/...
Lint completed successfully.
--> Executing Flake8 on files found in <path>/nginx/molecule/default/tests/...
Lint completed successfully.
--> Executing Ansible Lint on <path>/nginx/molecule/default/playbook.yml...
Lint completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'
PLAY [Destroy] *****************************************************************
TASK [Destroy molecule instance(s)] ********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) deletion to complete] *******************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Delete docker network(s)] ************************************************
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
--> Scenario: 'default'
--> Action: 'syntax'
playbook: <path>/nginx/molecule/default/playbook.yml
--> Scenario: 'default'
--> Action: 'create'
PLAY [Create] ******************************************************************
TASK [Log into a Docker registry] **********************************************
skipping: [localhost] => (item=None)
TASK [Create Dockerfiles from image names] *************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Discover local Docker images] ********************************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Build an Ansible compatible image] ***************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Create docker network(s)] ************************************************
TASK [Create molecule instance(s)] *********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) creation to complete] *******************************
changed: [localhost] => (item=None)
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=5 changed=4 unreachable=0 failed=0
--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.
--> Scenario: 'default'
--> Action: 'converge'
PLAY [Converge] ****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [instance]
TASK [nginx : Install nginx] ***************************************************
changed: [instance]
TASK [nginx : Start nginx] *****************************************************
changed: [instance]
PLAY RECAP *********************************************************************
instance : ok=3 changed=2 unreachable=0 failed=0
--> Scenario: 'default'
--> Action: 'idempotence'
Idempotence completed successfully.
--> Scenario: 'default'
--> Action: 'side_effect'
Skipping, side effect playbook not configured.
--> Scenario: 'default'
--> Action: 'verify'
--> Executing Testinfra tests found in <path>/nginx/molecule/default/tests/...
============================= test session starts ==============================
platform darwin -- Python 2.7.15, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
rootdir: <path>/nginx/molecule/default, inifile:
plugins: testinfra-1.16.0
collected 4 items
tests/test_default.py .... [100%]
========================== 4 passed in 27.23 seconds ===========================
Verifier completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'
PLAY [Destroy] *****************************************************************
TASK [Destroy molecule instance(s)] ********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) deletion to complete] *******************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Delete docker network(s)] ************************************************
PLAY RECAP *********************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0
Нашата едноставна улога беше тестирана без проблеми.
Вреди да се запамети дека ако има проблеми за време на работата molecule test, тогаш ако не сте ја смениле стандардната секвенца, Молекулата ќе ја избрише инстанцата.
Следниве команди се корисни за дебагирање:
> molecule --debug <command> # debug info. При обычном запуске Молекула скрывает логи.
> molecule converge # Оставляет инстанс после прогона тестируемой роли.
> molecule login # Зайти в созданный инстанс.
> molecule --help # Полный список команд.Постоечка улога
Додавање нова скрипта на постоечка улога е од директориумот за улоги со следните команди:
# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>Во случај ова да е првото сценарио во улогата, тогаш параметарот -s може да се испушти бидејќи ќе создаде скрипта default.
Заклучок
Како што можете да видите, Молекулата не е многу сложена и со користење на ваши сопствени шаблони, распоредувањето на нова скрипта може да се сведе на уредување на променливи во книгите за создавање и бришење примери. Молекулата беспрекорно се интегрира со CI системите, што ви овозможува да ја зголемите брзината на развој со намалување на времето за рачно тестирање на книгите за играње.
Ви благодариме за вниманието. Ако имате искуство во тестирање на одговорни улоги, а не е поврзано со молекулата, кажете ни за тоа во коментарите!
Извор: www.habr.com
