Përshëndetje të gjithëve!
Unë punoj si inxhinier DevOps në shërbimin e rezervimit të hoteleve . Në këtë artikull dua të tregoj për përvojën tonë në testimin e rolleve ansible.
Në Ostrovok.ru, si menaxher konfiguracionesh përdorim ansible. Së fundmi, kemi ardhur në nevojën për testimin e rolleve, por, siç rezultoi, nuk ka shumë mjete për këtë — mbase më të njohura është framerkë Molecule, prandaj vendosëm ta përdorim atë. Por ndodhi që dokumentacioni i tij injoron shumë nga pengesat. Nuk arritëm të gjejmë një udhëzues të mjaftueshëm në rusisht, prandaj vendosëm ta shkruajmë këtë artikull.

Molecule
— është një framerkë që ndihmon në testimin e rolleve ansible.
Përshkrimi i thjeshtë: Molekula krijon një instancë në platformën e specifikuar nga ju (re, virtuale, kontejner; më shumë shihni seksionin ), ekzekuton rolin tuaj mbi të, pastaj drejton testet dhe fshin instancën. Në rast se ndodhin dështime në ndonjë nga hapat, Molekula do t'ju informojë për këtë.
Tani më në detaje.
Pak teori
Le të shqyrtojmë dy entitete kryesore të Molekulës: Scenario dhe Driver.
Scenario
Scenari përmban përshkrimin e asaj që, ku, si dhe në cilën rend do të ekzekutohet. Një rol mund të ketë disa skenarë, dhe çdo skenar është një direktori në rrugën /molecule/, që përmban përshkrimet e veprimeve të nevojshme për testin. Një skenar duhet të jetë i pranishëm default, i cili do të krijohet automatikisht nëse e iniconi rolin me ndihmën e Molekulës. Emrat e skenarëve të tjerë zgjidhen sipas dëshirës suaj.
Renditja e veprimeve të testimit në skenar quhet matrix, dhe për default është ajo:
(Hapat e shënuara ?, për default do të kalohen nëse nuk përshkruhen nga përdoruesi)
lint— ekzekutimi i linters. Për default përdorenyamllintиflake8,destroy— fshirja e instancave nga ndihmesat e kaluara të Molekulës (nëse ka mbetur),dependency? — установка ansible-зависимости тестируемой роли,syntax— kontrolli i sintaksës së rolit me ndihmën eansible-playbook --syntax-check,create— krijimi i një instancës,prepare? — подготовка инстанса; например, проверка / установка python2converge— ekzekutimi i playbook-ut në testim,idempotence— ekzekutimi i përsëritur i playbook-ut për testimin e idempotencës,side_effect? — действия, не относящиеся непосредственно к роли, но нужные для тестов,verify— ekzekutimi i testeve të konfiguracionit të marrë me ndihmën etestinfra(për default) /goss/inspec,cleanup? — (в новых версиях) — грубо говоря, «очистка» внешней инфраструктуры, задетой Молекулой,destroy— fshirja e instancës.
Kjo renditje mbulon shumicën e rasteve, por, nëse është e nevojshme, mund të ndryshohet.
Çdo një nga hapat e përmendur më sipër mund të ekzekutohet veçmas duke përdorur molecule. Por është e rëndësishme të kuptoni se për çdo komandë të tillë cli mund të ekzistojë një renditje e vetme veprimesh, të cilën mund ta mēsoni duke ekzekutuar molecule matrix. Për shembull, kur ekzekutoni komandën converge (nënshkrimi 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 # parashkëputja e instancës
└── converge # nënshkrimi i playbook-utRenditja e këtyre veprimeve mund të redaktohet. Nëse diçka nga lista është kryer tashmë, ajo do të anashkalohet. Shteti aktual si dhe konfigurimi i instancave, Molekula i ruan në direktorinë $TMPDIR/molecule//.
Shtohen hapat me ? mund të bëhet duke përshkruar veprimet e dëshiruara në formatin e playbook-ut të ansible, dhe emri i skedarit mund të bëhet përkatës për hapin: prepare.yml/side_effect.yml. Molekula do t'i presë këta skedarë në dosjen e skenarit.
Driver
Drejtori është entiteti ku krijohen instancat për teste.
Lista e drejtuesve standard, për të cilët Molekula ka modele, është si më poshtë: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.
Në shumicën e rasteve, modelet janë skedarë create.yml и destroy.yml në dosjen e skenarit, të cilat përshkruajnë krijimin dhe fshirjen e instancës përkatësisht.
Përjashtime përbëjnë Docker dhe Vagrant, pasi ndërveprimi me modulet e tyre mund të ndodhi pa skedarët e përmendur më sipër.
Duhet të theksohet drejtori Delegated, pasi në rastin e përdorimit të tij, në skedarët e krijimit dhe fshirjes së instancës përshkruhet vetëm puna me konfigurimin e instancave, ndërsa resten duhet ta përshkruajë inxhinieri.
Drejtori i paracaktuar është Docker.
Tani le të kalojmë në praktikë dhe do të shqyrtojmë detajet e tjera atje.
Fillimi i punës
Si "hello world", do të testojmë një rol të thjeshtë për instalimin e nginx. Si drejtori do të zgjedhim docker – mendoj se është instaluar te shumica e juaj (dhe kujtojmë, docker është drejtori i paracaktuar).
Të përgatitim virtualenv dhe ta instalojmë në të molecule:
> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker # molekula do të instalojë ansible si varësi; docker për drejtuesinHapi tjetër është injektimi i një roli të ri.
Injeksioni i një roli të ri, ashtu si edhe i një skenari të ri, bëhet me komandën molecule init:
> molekuli init roli -r nginx
--> Po fillimin e rolit të ri nginx...
Roli u inicializua me sukses në /nginx.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars
6 drejtoritë, 1 skedarKemi një rol tipik ansible. Tani, të gjitha ndërveprimet me CLI të Molekulës bëhen nga rrënja e rolit.
Le të shohim se çfarë ndodhet në drejtorinë e rolit:
> tree molecule/default/
molecule/default/
├── Dockerfile.j2 # Shabllon Jinja për Dockerfile
├── INSTALL.rst. # Disa informacion mbi instalimin e varshmërive të skenarit
├── molecule.yml # Skedari i konfigurimit
├── playbook.yml # Playbook për nisjen e rolit
└── tests # Drejtoria me testet e fazës verify
└── test_default.py
1 drejtori, 6 skedareLe ta shqyrtojmë konfigurimin molecule/default/molecule.yml (do të zëvendësojmë vetëm imazhin e dockerit):
---
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
Kjo seksion përshkruan burimin e varshmërive.
Mundësitë janë: , , shell.
Shell është thjesht një shell komandash që përdoret kur galaxy dhe gilt nuk mbulojnë nevojat tuaja.
Nuk do të ndalem shumë këtu, ka mjaft përshkrim në .
driver
Emri i shoferit. Këtu është docker.
lint
Si linters përdoret yamllint.
Opsionet e dobishme në këtë pjesë të konfigurimit janë mundësia për të treguar skedarin e konfigurimit për yamllint, kalimin e variablave të mjedisit ose shkëputjen e linters:
lint:
name: yamllint
options:
config-file: foo/bar
env:
FOO: bar
enabled: Falseplatforms
Përshkruan konfigurimin e instancave.
Në rastin e dockerit si rol shofer, Molekula iteron përmes kësaj seksioni, dhe çdo element i listës është i disponibilizuar në Dockerfile.j2 si variabël item.
Në rastin e shoferit, ku janë të domosdoshme create.yml и destroy.yml, seksi është i aksesueshëm në ato si molecule_yml.platforms, dhe iterimet mbi të janë përshkruar tashmë në këto skedare.
Duke qenë se Molekula ofron menaxhimin e instancave për modulat ansible, lista e mundësive të konfigurimit duhet të kërkohet atje. Për dockerin, për shembull, përdoret moduli . Çfarë module përdoren në shoferët e tjerë, mund të gjendet në .
Dhe gjithashtu shembuj të përdorimit të shoferëve të ndryshëm mund të gjenden .
Le të 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ë tjerët nuk është planifikuar, prandaj kjo seksion mund të quhet me rezervë si konfigurimi i avancuar i ansible.
Këtu mund të përmend shumë gjëra, por do theksoj momentet kryesore, sipas mendimit tim:
- playbooks: mund të tregoni se cilat playbooks 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 mjedisit
provisioner:
name: ansible
options:
vvv: true
diff: true
env:
FOO: BARscenario
Emri dhe përshkrimi i sekuencave të skenarit.
Për të ndryshuar matricën e veprimeve për një komandë të caktuar, mund të shtoni çelësin <command>_sequence dhe si vlerë për të, të përcaktoni listën e nevojshme të hapave.
Të themi se duam të ndryshojmë rendin e veprimeve gjatë ekzekutimit të komandës për të ekzekutuar playbook-un: molecule converge
# изначально:
# - dependency
# - create
# - prepare
# - converge
scenario:
name: default
converge_sequence:
- create
- convergeverifier
Konfigurimi i kornizës për testet dhe lintern për të. Në mënyrë të parazgjedhur, si lintern përdoret testinfra и flake8. Opsionet e mundshme janë të ngjashme me ato të mësipërmet:
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: barKthehemi në rolin tonë. Do të editojmë skedarin tasks\/main.yml në këtë formë:
---
- name: Instaloni nginx
apt:
name: nginx
state: present
- name: Ngrini 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")
Kemi përfunduar, tani mbetet vetëm ta ekzekutojmë (nga rrënja e rolit, kujtoj):
> molecule testNjetë përgjigje e gjatë nën spoiler:
--> Po validimin e skemës /nginx/molecule/default/molecule.yml.
Validimi përfundoi me sukses.
--> Matrica e testeve
└── default
├── lint
├── shkatërro
├── varësi
├── sintaksë
├── krijo
├── përgatit
├── bashko
├── idempotencë
├── efekt_anësor
├── verifiko
└── shkatërro
--> Scenari: 'default'
--> Veprimi: 'lint'
--> Po ekzekuton Yamllint në skedarët e gjetur në /nginx/...
Lintimi përfundoi me sukses.
--> Po ekzekuton Flake8 në skedarët e gjetur në /nginx/molecule/default/tests/...
Lintimi përfundoi me sukses.
--> Po ekzekuton Ansible Lint në /nginx/molecule/default/playbook.yml...
Lintimi përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'shkatërro'
LOJA [Shkatërro] *****************************************************************
DETYRA [Shkatërro instancat e molekulës] ********************************************
ndryshuar: [localhost] => (item=None)
ndryshuar: [localhost]
DETYRA [Prit për përfundimin e fshirjes së instancave] *******************************
ok: [localhost] => (item=None)
ok: [localhost]
DETYRA [Fshi rrjetin docker] ************************************************
LOJA RECAP *********************************************************************
localhost : ok=2 ndryshuar=1 e pakapshme=0 dështoi=0
--> Scenari: 'default'
--> Veprimi: 'varësi'
Duke anashkaluar, mungon skedari i kërkesave.
--> Scenari: 'default'
--> Veprimi: 'sintaksë'
playbook: /nginx/molecule/default/playbook.yml
--> Scenari: 'default'
--> Veprimi: 'krijo'
LOJA [Krijo] ******************************************************************
DETYRA [Kyçu në një regjistër Docker] **********************************************
duke anashkaluar: [localhost] => (item=None)
DETYRA [Krijo Dockerfiles nga emrat e imazheve] *************************************
ndryshuar: [localhost] => (item=None)
ndryshuar: [localhost]
DETYRA [Zbulo imazhet lokale të Docker] ********************************************
ok: [localhost] => (item=None)
ok: [localhost]
DETYRA [Ndërto një imazh të përputhshëm me Ansible] ***************************************
ndryshuar: [localhost] => (item=None)
ndryshuar: [localhost]
DETYRA [Krijo rrjetet docker] ************************************************
DETYRA [Krijo instancat e molekulës] *********************************************
ndryshuar: [localhost] => (item=None)
ndryshuar: [localhost]
DETYRA [Prit për përfundimin e krijimit të instancave] *******************************
ndryshuar: [localhost] => (item=None)
ndryshuar: [localhost]
LOJA RECAP *********************************************************************
localhost : ok=5 ndryshuar=4 e pakapshme=0 dështoi=0
--> Scenari: 'default'
--> Veprimi: 'përgatit'
Duke anashkaluar, playbook përgatitës nuk është konfiguruar.
--> Scenari: 'default'
--> Veprimi: 'bashko'
LOJA [Bashko] ****************************************************************
DETYRA [Kumbimi i Fakteve] *********************************************************
ok: [instance]
DETYRA [nginx : Instaloni nginx] ***************************************************
ndryshuar: [instance]
DETYRA [nginx : Filloni nginx] *****************************************************
ndryshuar: [instance]
LOJA RECAP *********************************************************************
instance : ok=3 ndryshuar=2 e pakapshme=0 dështoi=0
--> Scenari: 'default'
--> Veprimi: 'idempotencë'
Idempotenca përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'efekt_anësor'
Duke anashkaluar, playbook për efekt anësor nuk është konfiguruar.
--> Scenari: 'default'
--> Veprimi: 'verifiko'
--> Po ekzekuton testet Testinfra të gjetura në /nginx/molecule/default/tests/...
============================= seanca e testit fillon ==============================
platform darwin -- Python 2.7.15, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
rootdir: /nginx/molecule/default, nëifile:
plugins: testinfra-1.16.0
mblidhe 4 artikuj
tests/test_default.py .... [100%]
========================== 4 kaloi në 27.23 sekonda ===========================
Verifikuesi përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'shkatërro'
LOJA [Shkatërro] *****************************************************************
DETYRA [Shkatërro instancat e molekulës] ********************************************
ndryshuar: [localhost] => (item=None)
ndryshuar: [localhost]
DETYRA [Prit për përfundimin e fshirjes së instancave] *******************************
ndryshuar: [localhost] => (item=None)
ndryshuar: [localhost]
DETYRA [Fshi rrjetin docker] ************************************************
LOJA RECAP *********************************************************************
localhost : ok=2 ndryshuar=2 e pakapshme=0 dështoi=0
Roli jonë e thjeshtë u testua pa probleme.
Duhet të mbani mend se nëse ndodhin probleme gjatë punës testi i molekulës, atëherë, nëse nuk keni ndryshuar rendin standard, Molekula do të fshijë instancën.
Për debugin, komandat e mëposhtme janë të dobishme:
> molecule --debug # informacion për debug. Gjatë ekzekutimit të zakonshëm, Molekula fsheh log-et.
> molecule converge # Lë 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 direktoria e rolit me komandat e mëposhtme:
# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>Në rast se ky është skenari i parë në rol, atëherë parametrin -s mund ta lini të papërdorur, pasi do të krijohet skenari default.
Përfundim
Siç e shihni, Molekula nuk është shumë e komplikuar, dhe duke përdorur shabllone të veta, mund të reduktoni implementimin e një skenari të ri në editimin e variablave në playbook-ët e krijimit dhe fshirjes së instancave. Molekula integrihet pa probleme me sistemet CI, duke lejuar përshpejtimin e zhvillimit përmes shkurtimeve të kohës së testimit manual të playbook-ëve.
Faleminderit për vëmendjen tuaj. Nëse keni përvojë në testimin e ansible-role-ve, dhe ajo nuk ka lidhje me Molekulën — na tregoni për të në komentet!
Burimi: habr.com
