Përshëndetje të gjithëve!
Punoj si inxhinier DevOps në një shërbim rezervimi hotelesh . Në këtë artikull, dua të flas për përvojën tonë në testimin e rolëve ansible.
Në Ostrovok.ru, si menaxher konfiguracionesh, ne përdorim ansible. Së fundmi, arritëm në nevojën për të testuar rolët, por, siç rezultoi, nuk ka shumë mjete për këtë — framework-u më i njohur ndoshta është Molecule, prandaj vendosëm ta përdorim atë. Por rezultoi se dokumentacioni i tij përmban shumë mungesa. Nuk arritëm të gjenim një udhëzues të mjaftueshëm në rusisht, kështu që vendosëm të shkruajmë këtë artikull.

Molecule
— është një framework për ndihmë në testimin e rolëve ansible.
Përshkrimi i thjeshtuar: Molekula krijon një instancë në platformën që keni caktuar (re, virtuale, konteiner; më shumë informacion në seksionin ), ekzekuton rolin tuaj mbi të, më pas nis testet dhe fshin instancën. Në rast një dështimi në një nga hapat, Molekula do t'ju njoftojë për këtë.
Tani më me detaje.
Pak teori
Le të shqyrtojmë dy entitete kryesore të Molekulës: Scenario dhe Driver.
Scenario
Skema përmban një përshkrim të asaj që, ku, si dhe në cilën rend do të realizohet. Një rol mund të ketë disa skenarë, dhe çdo skenar është një direktori sipas rrugës /molecule/, e cila përmban përshkrime të veprimeve të nevojshme për test. Domosdoshmërisht duhet të jetë i pranishëm një skenar default, i cili do të krijohet automatikisht nëse e inicializoni rolin me Molekulën. Emrat e skenarëve të tjerë zgjedhën sipas dëshirës tuaj.
Renditja e veprimeve të testit në skenar quhet matrix, dhe sipas parashikimit është si më poshtë:
(Hapat e shënuar ?, sipas parashikimit anashkalohen nëse nuk përshkruhen nga përdoruesi)
lint— ekzekutimi i linteve. Sipërfaqësisht përdorenyamllintdheflake8,destroy— fshirja e instancave nga rinisja e mëparshme të Molekulës (nëse ka mbetur ndonjë)dependency? — установка ansible-зависимости тестируемой роли,syntax— kontrolli i sintaksës së rolit me ndihmën eansible-playbook --syntax-check,krijo— krijimi i një instance,prepare? — подготовка инстанса; например, проверка / установка python2converge— ekzekutimi i playbook-ut të testuar,idempotence— ekzekutimi i përsëritur i playbook-ut për testimin e idempotencës,side_effect? — действия, не относящиеся непосредственно к роли, но нужные для тестов,verify— ekzekutimi i testeve të konfiguracionit të rezultuar me ndihmën etestinfra(sipas parashikimit) /goss/inspec,cleanup? — (в новых версиях) — грубо говоря, «очистка» внешней инфраструктуры, задетой Молекулой,destroy— fshirja e instancës.
Ky sekvencë mbulon shumicën e rasteve, por, nëse është e nevojshme, mund të ndryshohet.
Çdo hap të mësipërm mund të ekzekutohet veçmas me anë të molecule. Por është e rëndësishme të kuptohet se për çdo komandë të tillë cli mund të ekzistojë një sekvencë veprimesh, të cilën mund ta zbuloni duke ekzekutuar molecule matrix. Për shembull, kur ekzekutohet komanda converge (ekzekutimi i playbook-ut të testuar) do të kryhen veprimet e mëposhtme:
$ molecule matrix converge
...
└── default # emri i skenarit
├── dependency # instalimi i varësive
├── create # krijimi i instancës
├── prepare # përgatitja e instancës
└── converge # ekzekutimi i playbook-utSekuenca e këtyre veprimeve mund të redaktohet. Nëse diçka nga lista tashmë është kryer, do të kalojë. Gjendja aktuale, si dhe konfigurimi i instancave, Molecule i ruan në direktorinë $TMPDIR/molecule//.
Hapat me ? mund të shtohen, duke përshkruar veprimet e dëshiruara në formatin e playbook-ut të ansible, dhe emri i skedarit të bëhet përkatësisht hapit: prepare.yml/side_effect.yml. Molecule do të presë këto skedarë në dosjen e skenarit.
Driver
Drejtori është një entitet, ku krijohen instancat për testime.
Lista e drejtuesve standard për të cilët Molecula ka përgatitur shabllone është si më poshtë: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.
Në shumicën e rasteve, shabllonet janë skedarë create.yml dhe destroy.yml në dosjen e skenarit, të cilat përshkruajnë krijimin dhe fshirjen e instancave përkatësisht.
Përjashtim përbëjnë Docker dhe Vagrant, pasi ndërveprimi me modulet e tyre mund të ndodhë pa skedarët e përmendur më sipër.
Vlen të theksohet drejtuesi Delegated, pasi në rastin e përdorimit të tij në skedarin e krijimit dhe fshirjes së instancës, përshkruhet vetëm puna me konfigurimin e instanceve, pjesa tjetër duhet të përshkruhet nga inxhinieri.
Drejtuesi default është Docker.
Tani le të kalojmë në praktikë dhe të shqyrtojmë veçoritë e mëtejshme atje.
Fillimi i punës
Si 'hello world', do të testojmë një rol të thjeshtë për instalimin e nginx. Si drejtues do të zgjedhim docker – besoj se është instaluar tek shumica prej jush (dhe kujtojmë se docker është drejtuesi default).
Të përgatisim virtualenv dhe ta instalojmë në të molecule:
> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker # molecule do të instalojë ansible si varësi; docker për drejtuesinHapi tjetër është të inicializojmë një rol të ri.
Inicimi i një roli të re, ashtu si edhe një skenari të ri, bëhet përmes komandës molecule init:
> molecule init role -r nginx
--> Po inicializohet roli i ri nginx...
Inicimi i rolit në /nginx u bë me sukses.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars
6 direktorë, 1 skedarKemi marrë një rol tipik ansible. Më tej, të gjitha ndërveprimet me CLI të Molekulës bëhen nga rrënja e rolit.
Le të shohim çfarë ndodhet në direktorinë e rolit:
> tree molecule/default/
molecule/default/
├── Dockerfile.j2 # Shablloni Jinja për Dockerfile
├── INSTALL.rst. # Pak informacion mbi instalimin e varësive të skenarit
├── molecule.yml # File konfigurimi
├── playbook.yml # Playbook që aktivizon rolin
└── tests # Direktorinë me testet e stagës verify
└── test_default.py
1 direktor, 6 skedareTë shqyrtojmë konfigurimin molecule/default/molecule.yml (do ta zëvendosim vetëm imazhin docker):
---
dependencë:
emri: galaxy
driver:
emri: docker
lint:
emri: yamllint
platforms:
- emri: instance
imazh: centos:7
provisioner:
emri: ansible
lint:
emri: ansible-lint
scenario:
emri: default
verifier:
emri: testinfra
lint:
emri: flake8dependency
Ky seksion përshkruan burimin e varësive.
Opsionet e mundshme: , , shell.
Shell është thjesht një shell komandash që përdoret në rast se galaxy dhe gilt nuk mbulojnë nevojat tuaja.
Nuk do të qëndroj këtu gjatë, është mjaft e përshkruar në .
driver
Emri i driver-it. Ne këtë e kemi docker.
lint
Si linte, përdoret yamllint.
Mundësi të dobishme në këtë pjesë të konfigurimit janë mundësia për të treguar skedarin e konfigurimit për yamllint, për të kaluar variablat mjedisorë ose për të çaktivizuar lintern:
lint:
name: yamllint
options:
config-file: foo/bar
env:
FOO: bar
enabled: Falseplatformat
Përshkruan konfigurimin e instancave.
Në rastin e docker-it si driver, Molecule iteron përmes kësaj seksioni, dhe çdo element i listës është i disponueshëm në Dockerfile.j2 si variabël item.
Në rastin e driver-it ku janë të domosdoshme create.yml dhe destroy.yml, seksioni është i disponueshëm në to si molecule_yml.platforms, dhe iterimet për të përshkruhen tashmë në këto skedarë.
Pasi Molecule ofron menaxhimin e instancave për modulët ansible, lista e mundshme e konfigurimeve duhet të kërkohet aty. Për docker-in, për shembull, përdoret moduli . Cilat module përdoren në driver-at e tjerë, mund të gjenden në .
Gjithashtu, shembuj të përdorimit të driver-eve të ndryshme mund të gjenden .
Do ta zëvendësojmë këtu centos:7 në ubuntu.
provisioner
«Furnizuesi» është një entitet që menaxhon instancat. Në rastin e Molekulës, kjo është ansible, mbështetje për të tjera nuk është e planifikuar, prandaj ky seksion mund të quhet me kusht konfigurim i zgjeruar i ansible.
Këtu mund të specifikoni shumë gjëra, por do të theksoj momentet kryesore, sipas mendimit tim:
- playbooks: mund të specifikoni se cilat playbook duhet të përdoren në faza të caktuara.
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: parametrat
provisioner:
name: ansible
connection_options:
ansible_ssh_common_args: "-o 'UserKnownHostsFile=/dev/null' -o 'ForwardAgent=yes'"- options: parametrat e Ansible dhe variablat e ambientit
provisioner:
name: ansible
options:
vvv: true
diff: true
env:
FOO: BARscenario
Emri dhe përshkrimi i sekuencave të skenarit.
Mund të ndryshoni matricën e veprimeve të paracaktuar të ndonjë komande, duke shtuar kyçin <command>_sequence dhe si vlerë për të përcaktoni listën e hapave që na nevojitet.
Supozoni se dëshirojmë të ndryshojmë sekuencën e veprimit gjatë ekzekutimit të komandës për të ekzekutuar playbook: molecule converge
# изначально:
# - dependency
# - create
# - prepare
# - converge
scenario:
name: default
converge_sequence:
- create
- convergeverifikuesi
Konfigurimi i kornizës për testet dhe linters që i përket. Siç është e parazgjedhur, përdoret për lintern testinfra dhe flake8. Opsionet e mundshme janë të ngjashme me ato të përmendura më lart:
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: barTë kthehemi te roli ynë. Të redaktojmë skedarin tasks/main.yml në këtë formë:
---
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
Dhe do të shtojmë testet në 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")
Gati, mbetet vetëm të ekzekutojmë (nga rrënja e rolit, kujtoj):
> molecule testNjë dalje e gjatë nën spoiler:
--> Duke validimin e skemës /nginx/molecule/default/molecule.yml.
Validimi u përfundua me sukses.
--> Matricha e testit
└── default
├── lint
├── shkathtëso
├── varësia
├── sintaksë
├── krijo
├── përgatit
├── bashko
├── idempotencë
├── efekt_anësor
├── verifiko
└── shkathtëso
--> Scenari: 'default'
--> Veprimi: 'lint'
--> Duke ekzekutuar Yamllint në skedarët e gjetur në /nginx/...
Lintimi përfundoi me sukses.
--> Duke ekzekutuar Flake8 në skedarët e gjetur në /nginx/molecule/default/tests/...
Lintimi përfundoi me sukses.
--> Duke ekzekutuar Ansible Lint në /nginx/molecule/default/playbook.yml...
Lintimi përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'shkathtëso'
LOJA [Shkathtësia] *****************************************************************
DETYRA [Shkathtëso instancat e molekulës] ********************************************
u ndryshua: [localhost] => (item=None)
u ndryshua: [localhost]
DETYRA [Prisni që fshirja e instancave të përfundojë] *******************************
ok: [localhost] => (item=None)
ok: [localhost]
DETYRA [Fshirja e rrjeteve docker] ************************************************
RISHIKIM I LOJES *********************************************************************
localhost : ok=2 u ndryshua=1 e paarritshme=0 dështuar=0
--> Scenari: 'default'
--> Veprimi: 'varësia'
Duke e anashkaluar, mungon skedari i kërkesave.
--> Scenari: 'default'
--> Veprimi: 'sintaksë'
libri: /nginx/molecule/default/playbook.yml
--> Scenari: 'default'
--> Veprimi: 'krijo'
LOJA [Krijo] ******************************************************************
DETYRA [Hyni në një regjistrim Docker] **********************************************
duke e anashkaluar: [localhost] => (item=None)
DETYRA [Krijoni Dockerfile nga emrat e figurave] *************************************
u ndryshua: [localhost] => (item=None)
u ndryshua: [localhost]
DETYRA [Zbulo imazhet e Docker në nivel lokal] ********************************************
ok: [localhost] => (item=None)
ok: [localhost]
DETYRA [Ndërto një figurë të përputhshme me Ansible] ***************************************
u ndryshua: [localhost] => (item=None)
u ndryshua: [localhost]
DETYRA [Krijoni rrjetet docker] ************************************************
DETYRA [Krijoni instancat e molekulës] *********************************************
u ndryshua: [localhost] => (item=None)
u ndryshua: [localhost]
DETYRA [Prisni që krijimi i instancave të përfundojë] *******************************
u ndryshua: [localhost] => (item=None)
u ndryshua: [localhost]
RISHIKIM I LOJES *********************************************************************
localhost : ok=5 u ndryshua=4 e paarritshme=0 dështuar=0
--> Scenari: 'default'
--> Veprimi: 'përgatit'
Duke e anashkaluar, libri përgatitës nuk është i konfiguruar.
--> Scenari: 'default'
--> Veprimi: 'bashko'
LOJA [Bashko] ****************************************************************
DETYRA [Grumbullimi i Fakteve] *********************************************************
ok: [instance]
DETYRA [nginx : Instaloni nginx] ***************************************************
u ndryshua: [instance]
DETYRA [nginx : Filloni nginx] *****************************************************
u ndryshua: [instance]
RISHIKIM I LOJES *********************************************************************
instance : ok=3 u ndryshua=2 e paarritshme=0 dështuar=0
--> Scenari: 'default'
--> Veprimi: 'idempotencë'
Idempotenca përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'efekt_anësor'
Duke e anashkaluar, libri i efektit anësor nuk është i konfiguruar.
--> Scenari: 'default'
--> Veprimi: 'verifiko'
--> Duke ekzekutuar testet Testinfra të gjetura në /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
mbled 4 items
tests/test_default.py .... [100%]
========================== 4 kaluan në 27.23 sekonda ===========================
Verifikuesi përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'shkathtëso'
LOJA [Shkathtësia] *****************************************************************
DETYRA [Shkathtëso instancat e molekulës] ********************************************
u ndryshua: [localhost] => (item=None)
u ndryshua: [localhost]
DETYRA [Prisni që fshirja e instancave të përfundojë] *******************************
u ndryshua: [localhost] => (item=None)
u ndryshua: [localhost]
DETYRA [Fshirja e rrjeteve docker] ************************************************
RISHIKIM I LOJES *********************************************************************
localhost : ok=2 u ndryshua=2 e paarritshme=0 dështuar=0
Roli ynë e thjeshtë u testua pa probleme.
Është e rëndësishme të mbani mend se nëse hasni probleme gjatë punës testi i molekulës, nëse nuk keni ndryshuar renditjen standarde, Molekula do të fshijë instancën.
Për debagimin, komandat e mëposhtme janë të dobishme:
> molecule --debug # informacion për debagim. Në kohën e funksionimit normal, Molekula fsheh logët.
> molecule converge # Mbush instancën pas ekzekutimit të rolit të testuar.
> molecule login # Hyni në instancën e krijuar.
> molecule --help # Lista e plotë e komandave.Roli ekzistues
Shtimi i një skenari të ri në rolin ekzistues ndodh nga direktoriumi i rolit me komandat e mëposhtme:
# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>Nëse ky është skenari i parë në rol, parametri -s mund të lihet jashtë, pasi do të krijohet një skenar default.
Përfundimi
Siç e shihni, Molekula nuk është shumë e komplikuar, dhe duke përdorur template të veta, mund të reduktoni shpërndarjen e një skenari të ri në modifikimin e variablave në playbook-et e krijimit dhe fshirjes së instancave. Molekula integrohet pa vështirësi me sistemet CI, duke lejuar rritjen e shpejtësisë së zhvillimit përmes reduktimit të kohës për testimin manual të playbook-eve.
Faleminderit për vëmendjen tuaj. Nëse keni përvojë në testimin e rolleve ansible, dhe ajo nuk është e lidhur me Molekulën — tregoni për të në komentet!
Burimi: habr.com
