Ahojte všetci!
Pracujem ako DevOps inžinier v službe rezervácie hotelov . V tomto článku chcem rozprávať o našich skúsenostiach s testovaním ansible rolí.
Na Ostrovok.ru ako správca konfigurácií používame ansible. Nedávno sme dospeli k potrebe testovania rolí, ale, ako sa ukázalo, existuje len málo nástrojov na tento účel — najpopulárnejší je pravdepodobne framework Molecule, a preto sme sa rozhodli ho použiť. Ale ukázalo sa, že jeho dokumentácia opomína mnohé nástrahy. Nedokázali sme nájsť dostatočne podrobný návod v slovenčine, preto sme sa rozhodli napísať tento článok.

Molecule
— framework na pomoc pri testovaní ansible rolí.
Zjednodušený popis: Molekula vytvára inštanciu na platforme, ktorú ste určili (cloud, virtuálny stroj, kontajner; podrobnejšie si pozrite časť ), spustí na nej vašu rolu, potom vykoná testy a odstráni inštanciu. V prípade zlyhania v jednom z krokov vás Molekula o tom informuje.
Teraz podrobnejšie.
Trochu teórie
Preskúmame dve kľúčové entity Molekuly: Scenario a Driver.
Scenario
Scenár obsahuje popis toho, čo, kde, ako a v akom poradí sa má vykonať. Jedna rola môže mať niekoľko scenárov a každý z nich je adresárová štruktúra na ceste /molecule/, ktorá obsahuje opisy potrebných akcií na test. Určite musí existovať scenár, default, ktorý bude automaticky vytvorený, ak inicializujete rolu pomocou Molekuly. Názvy ďalších scenárov si vyberáte podľa vlastného uváženia.
Sekvencia akcií testovania v scenári sa nazýva matica, a predvolene je nasledovná:
(Kroky označené ?, sa predvolene preskočia, ak ich používateľ nenapíše)
lint— spustenie linterov. Predvolene sa používajúyamllintaflake8,destroy— odstránenie inštancií z predchádzajúceho spustenia Molekuly (ak zostali),dependency? — установка ansible-зависимости тестируемой роли,syntax— kontrola syntaktickej správnosti rolí pomocouansible-playbook --syntax-check,create— vytvorenie inštancie,prepare? — подготовка инстанса; например, проверка / установка python2converge— spustenie testovaného playbooku,idempotence— opätovné spustenie playbooku pre testovanie idempotencie,side_effect? — действия, не относящиеся непосредственно к роли, но нужные для тестов,verify— spustenie testov výslednej konfigurácie pomocoutestinfra(predvolene) /goss/inspec,cleanup? — (в новых версиях) — грубо говоря, «очистка» внешней инфраструктуры, задетой Молекулой,destroy— odstránenie inštancie.
Táto sekvencia pokrýva väčšinu prípadov, ale v prípade potreby ju môžete zmeniť.
Každý z uvedených krokov je možné spustiť samostatne pomocou molecule. Je však potrebné pochopiť, že pre každý takýto príkaz CLI môže existovať svoj vlastný postup, ktorý sa dá zistiť vykonaním molecule matrix. Napríklad pri spustení príkazu converge (spustenie testovacej playbooku) sa vykonajú nasledujúce kroky:
$ molecule matrix converge
...
└── default # názov scenára
├── dependency # inštalácia závislostí
├── create # vytvorenie inštancie
├── prepare # predpríprava inštancie
└── converge # spustenie playbookuPostup týchto krokov je možné upravovať. Pokiaľ už niečo zo zoznamu bolo vykonané, preskočí sa. Aktuálny stav, ako aj konfigurácia inštancií, Molekula uchováva v adresári $TMPDIR/molecule//.
Pridať kroky s ? je možné, ak popíšete požadované akcie vo formáte ansible-playbooku, a názov súboru prispôsobíte kroku: prepare.yml/side_effect.yml. Tieto súbory Molekula očakáva v priečinku scenára.
Driver
Ovládač je entita, kde sa vytvárajú inštancie na testy.
Zoznam štandardných ovládačov, pre ktoré má Molekula pripravené šablóny, je takýto: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.
Vo väčšine prípadov sú šablóny súbory create.yml a destroy.yml v priečinku scenára, ktoré popisujú vytvorenie a odstránenie inštancie.
Výnimkou sú Docker a Vagrant, keďže interakcia s ich modulmi môže prebiehať bez vyššie spomenutých súborov.
Stojí za zmienku ovládač Delegated, pretože v prípade jeho použitia v súboroch vytvárania a odstraňovania inštancie je popísaná iba práca s konfiguráciou inštancií, všetko ostatné musí popísať inžinier.
Predvoleným ovládačom je Docker.
Teraz prejdeme k praxi a ďalšie vlastnosti preskúmame tam.
Začiatok práce
Ako "hello world" otestujeme jednoduchú úlohu inštalácie nginx. Ako ovládač vyberieme Docker – myslím, že ho má väčšina z vás nainštalovaný (a pamätáme, že Docker je predvolené ovládanie).
Pripravíme virtualenv a nainštalujeme do neho molecule:
> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker # molecule nainštaluje ansible ako závislosť; docker pre ovládačĎalším krokom inicializujeme novú úlohu.
Inicializácia novej úlohy, rovnako ako nového scenára, sa vykonáva pomocou príkazu molecule init:
> molecule init role -r nginx
--> Inicializovanie novej úlohy nginx...
Úloha bola úspešne inicializovaná v /nginx.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars
6 adresárov, 1 súborVytvorila sa typická ansible-úloha. Ďalšie interakcie s CLI Molekuly sa vykonávajú z koreňa úlohy.
Pozrime sa, čo sa nachádza v adresári úlohy:
> tree molecule/default/
molecule/default/
├── Dockerfile.j2 # Jinja šablóna pre Dockerfile
├── INSTALL.rst. # Niekoľko informácií o inštalácii závislostí scénara
├── molecule.yml # Konfiguračný súbor
├── playbook.yml # Hlavný súbor pre spustenie úlohy
└── tests # Adresár s testami štádia overovania
└── test_default.py
1 adresár, 6 súborovRozoberieme konfiguráciu molecule/default/molecule.yml (zmeníme len docker image):
---
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: flake8dependency
Táto sekcia popisuje zdroj závislostí.
Možné voľby: , , shell.
Shell je jednoducho príkazový riadok, ktorý sa používa, ak galaxy a gilt nepokrývajú vaše potreby.
Nebudem sa tu zdržiavať, dostatočne je to popísané v .
driver
Názov ovládača. Pre nás je to docker.
lint
Na linterský účel sa používa yamllint.
Užitočné možnosti v tejto časti konfigurácie sú možnosť zadať konfiguračný súbor pre yamllint, preniesť premenné prostredia alebo vypnúť linterský nástroj:
lint:
name: yamllint
options:
config-file: foo/bar
env:
FOO: bar
enabled: Falseplatforms
Popisuje konfiguráciu inštancií.
V prípade dockeru ako ovládača Molekula prechádza touto sekciou a každý prvok zo zoznamu je dostupný v Dockerfile.j2 ako premenná item.
V prípade ovládača, kde sú potrebné create.yml a destroy.yml, sekcia je v nich dostupná ako molecule_yml.platforms, a iterácia po nej je už popísaná v týchto súboroch.
Keďže Molekula poskytuje riadenie inštancií pre ansible-moduly, zoznam možných nastavení treba hľadať tam. Pre docker sa napríklad používa modul . Aké moduly sa používajú v ostatných ovládačoch, môžete nájsť v .
A tiež príklady použitia rôznych ovládačov môžete nájsť .
Tu nahradíme centos:7 na ubuntu.
provisioner
"Poskytovateľ" je entita, ktorá spravuje inštancie. V prípade Molekuly je to ansible, podpora iných nie je plánovaná, takže túto sekciu môžeme s opatrnosťou nazvať rozšírenou konfiguráciou ansible.
Tu môžete uviesť veľa vecí, vyzdvihnem hlavné, podľa môjho názoru, body:
- playbooks: môžete uvádzať, ktoré playbooky by sa mali používať v určitých fázach.
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- connection_options: parametre
provisioner:
name: ansible
connection_options:
ansible_ssh_common_args: "-o 'UserKnownHostsFile=\/dev\/null' -o 'ForwardAgent=yes'"- options: parametre Ansible a premenné prostredia
provisioner:
name: ansible
options:
vvv: true
diff: true
env:
FOO: BARscenario
Názov a popis sekvencií scenára.
Maticu akcií predvolenej príkazu môžete zmeniť pridaním kľúča <command>_sequence a ako hodnotu pre neho zadefinovať požadovaný zoznam krokov.
Predpokladajme, že chceme zmeniť sekvenciu akcií pri spustení príkazu na vygenerovanie playbooku: molecule converge
# изначально:
# - dependency
# - create
# - prepare
# - converge
scenario:
name: default
converge_sequence:
- create
- convergeverifier
Nastavenie rámca pre testy a linter k nemu. Predvolene sa používa ako linter testinfra a flake8. Možné možnosti sú podobné ako vyššie uvedené:
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: barVráťme sa k našej úlohe. Upravíme súbor tasks\/main.yml na takýto tvar:
---
- name: Nainštalovať nginx
apt:
name: nginx
state: present
- name: Spustiť nginx
service:
name: nginx
state: started
A pridáme testy do 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")
Hotovo, zostáva len spustiť (z koreňa úlohy, pripomínam):
> molecule testDlhý výstup pod spoilerom:
--> Validácia schémy /nginx/molecule/default/molecule.yml.
Validation bola úspešne dokončená.
--> Testovacia matica
└── default
├── lint
├── destroy
├── dependency
├── syntax
├── create
├── prepare
├── converge
├── idempotence
├── side_effect
├── verify
└── destroy
--> Scenár: 'default'
--> Akcia: 'lint'
--> Spúšťam Yamllint na súboroch nájdených v /nginx/...
Lint bol úspešne dokončený.
--> Spúšťam Flake8 na súboroch nájdených v /nginx/molecule/default/tests/...
Lint bol úspešne dokončený.
--> Spúšťam Ansible Lint na /nginx/molecule/default/playbook.yml...
Lint bol úspešne dokončený.
--> Scenár: 'default'
--> Akcia: 'destroy'
HRA [Destrovanie] *****************************************************************
ÚLOHA [Destrovanie inštancie molekuly] ********************************************
zmenené: [localhost] => (item=None)
zmenené: [localhost]
ÚLOHA [Čakajte na dokončenie vymazania inštancie] *******************************
ok: [localhost] => (item=None)
ok: [localhost]
ÚLOHA [Vymazať docker siete] ************************************************
HRA RECAP *********************************************************************
localhost : ok=2 zmenené=1 nedostupné=0 neuspešné=0
--> Scenár: 'default'
--> Akcia: 'dependency'
Preskočené, chýba súbor požiadaviek.
--> Scenár: 'default'
--> Akcia: 'syntax'
playbook: /nginx/molecule/default/playbook.yml
--> Scenár: 'default'
--> Akcia: 'create'
HRA [Vytvorenie] ******************************************************************
ÚLOHA [Prihlásiť sa do Docker registry] **********************************************
preskočené: [localhost] => (item=None)
ÚLOHA [Vytvorenie Dockerfiles z názvov obrázkov] *************************************
zmenené: [localhost] => (item=None)
zmenené: [localhost]
ÚLOHA [Objaviť miestne Docker obrázky] ********************************************
ok: [localhost] => (item=None)
ok: [localhost]
ÚLOHA [Vytvoriť obraz kompatibilný s Ansible] ***************************************
zmenené: [localhost] => (item=None)
zmenené: [localhost]
ÚLOHA [Vytvoriť docker siete] ************************************************
ÚLOHA [Vytvoriť inštancie molekuly] *********************************************
zmenené: [localhost] => (item=None)
zmenené: [localhost]
ÚLOHA [Čakajte na dokončenie vytvorenia inštancie] *******************************
zmenené: [localhost] => (item=None)
zmenené: [localhost]
HRA RECAP *********************************************************************
localhost : ok=5 zmenené=4 nedostupné=0 neuspešné=0
--> Scenár: 'default'
--> Akcia: 'prepare'
Preskočené, herný plán nebol nastavený.
--> Scenár: 'default'
--> Akcia: 'converge'
HRA [Spojenie] ****************************************************************
ÚLOHA [Zber faktov] *********************************************************
ok: [instance]
ÚLOHA [nginx : Nainštalovať nginx] ***************************************************
zmenené: [instance]
ÚLOHA [nginx : Spustiť nginx] *****************************************************
zmenené: [instance]
HRA RECAP *********************************************************************
instance : ok=3 zmenené=2 nedostupné=0 neuspešné=0
--> Scenár: 'default'
--> Akcia: 'idempotence'
Idempotencia bola úspešne dokončená.
--> Scenár: 'default'
--> Akcia: 'side_effect'
Preskočené, herný plán vedľajšieho efektu nebol nastavený.
--> Scenár: 'default'
--> Akcia: 'verify'
--> Spúšťam Testinfra testy nájdené v /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: /nginx/molecule/default, inifile:
plugins: testinfra-1.16.0
collected 4 items
tests/test_default.py .... [100%]
========================== 4 prešlo v 27.23 sekundy ===========================
Verifikátor bol úspešne dokončený.
--> Scenár: 'default'
--> Akcia: 'destroy'
HRA [Destrovanie] *****************************************************************
ÚLOHA [Destrovanie inštancie molekuly] ********************************************
zmenené: [localhost] => (item=None)
zmenené: [localhost]
ÚLOHA [Čakajte na dokončenie vymazania inštancie] *******************************
zmenené: [localhost] => (item=None)
zmenené: [localhost]
ÚLOHA [Vymazať docker siete] ************************************************
HRA RECAP *********************************************************************
localhost : ok=2 zmenené=2 nedostupné=0 neuspešné=0
Naša jednoduchá úloha bola úspešne otestovaná.
Je dobré mať na pamäti, že ak sa vyskytnú problémy pri práci molecule test, ak ste nezmenili štandardnú postupnosť, Molekula odstráni inštanciu.
Pre ladenie sú užitočné nasledujúce príkazy:
> molecule --debug # informačné o ladení. Pri bežnom spustení Molekula skrýva logy.
> molecule converge # Zanechá inštanciu po spustení testovacej úlohy.
> molecule login # Prihláste sa do vytvorenej inštancie.
> molecule --help # Kompletný zoznam príkazov.Existujúca úloha
Pridanie nového scenára k existujúcej úlohe prebieha z adresára úlohy nasledujúcimi príkazmi:
# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>V prípade, že ide o prvý scenár v úlohe, parameter -s je možné vynechať, pretože sa vytvorí scenár. default.
Záver
Ako vidíte, Molekula nie je veľmi zložitá, a pri použití vlastných šablón môžete zjednodušiť nasadenie nového scenára na úpravu premenných v playbookoch pre vytváranie a odstraňovanie inštancií. Molekula sa bez problémov integruje so systémami CI, čo umožňuje zvýšiť rýchlosť vývoja skrátením času na manuálne testovanie playbookov.
Ďakujem za vašu pozornosť. Ak máte skúsenosti s testovaním ansible-úloh, ktoré nie sú spojené s Molekulou — podeľte sa o ne v komentároch!
Zdroj: habr.com
