Hello!
DevOps mérnökként dolgozom egy szállodafoglalási szolgáltatásnál. . Ebben a cikkben az alkalmazható szerepek tesztelésével kapcsolatos tapasztalatainkról szeretnék beszélni.
Az Ostrovok.ru oldalon az ansible-t használjuk konfigurációkezelőként. Nemrég jutottunk el a szerepek tesztelésének szükségességéhez, de mint kiderült, erre nincs olyan sok eszköz - a legnépszerűbb talán a Molecule keretrendszer, ezért úgy döntöttünk, hogy használjuk. De kiderült, hogy dokumentációja sok buktatóról hallgat. Nem találtunk kellően részletes orosz nyelvű kézikönyvet, ezért úgy döntöttünk, hogy megírjuk ezt a cikket.

Molekula
- keretrendszer, amely segít tesztelni a lehetséges szerepeket.
Egyszerűsített leírás: A molekula egy példányt hoz létre az Ön által megadott platformon (felhő, virtuális gép, tároló; további részletekért lásd a részt ), futtatja rajta a szerepkörét, majd teszteket futtat, és törli a példányt. Az egyik lépés meghibásodása esetén a Molekula értesíti Önt.
Most még több.
Egy kis elmélet
Tekintsük a molekula két kulcsfontosságú entitását: a forgatókönyvet és az illesztőprogramot.
Forgatókönyv
A forgatókönyv leírást tartalmaz arról, hogy mit, hol, hogyan és milyen sorrendben fognak végrehajtani. Egy szerepkör több szkriptet is tartalmazhat, és mindegyik egy könyvtár az elérési út mentén <role>/molecule/<scenario>, amely a teszthez szükséges műveletek leírását tartalmazza. Szkriptet kell mellékelni default, amely automatikusan létrejön, ha inicializálja a szerepet egy molekulával. A következő szkriptek nevét Ön döntheti el.
A szkriptben lévő tesztelési műveletek sorozatát hívják mátrix, és alapértelmezés szerint ez:
(Felcímkézett lépések ?, alapértelmezés szerint kihagyva, ha a felhasználó nem adta meg)
lint- futó szálak. Alapértelmezés szerint használatosakyamllintиflake8,destroy- példányok törlése a molekula utolsó indításából (ha van ilyen),dependency? — a tesztelt szerepkör lehetséges függőségének telepítése,syntax- a szerepkör szintaxisának ellenőrzése segítségévelansible-playbook --syntax-check,create- példány létrehozása,prepare? — a példány előkészítése; például ellenőrizze/telepítse a python2-tconverge— a tesztelés alatt álló játékkönyv elindítása,idempotence- az idempotencia teszt játékkönyvének újraindítása,side_effect? - a szerepkörhöz közvetlenül nem kapcsolódó, de a tesztekhez szükséges tevékenységek,verify- a kapott konfiguráció tesztjeinek futtatása segítségéveltestinfra(alapértelmezett) /goss/inspec,cleanup? - (új verziókban) - durván szólva a Molekula által érintett külső infrastruktúra "megtisztítása",destroy- Példány törlése.
Ez a sorrend a legtöbb esetet lefedi, de szükség esetén módosítható.
A fenti lépések mindegyike külön-külön is végrehajtható molecule <command>. De meg kell érteni, hogy minden ilyen klip-parancsnak megvan a saját műveletsorozata, amelyet végrehajtásával megtudhat molecule matrix <command>. Például a parancs futtatásakor converge (a tesztkönyv futtatása alatt), a következő műveleteket hajtják végre:
$ molecule matrix converge
...
└── default # название сценария
├── dependency # установка зависимостей
├── create # создание инстанса
├── prepare # преднастройка инстанса
└── converge # прогон плейбукаA műveletek sorrendje szerkeszthető. Ha valami a listából már elkészült, az kimarad. Az aktuális állapotot, valamint a példányok konfigurációját a Molecule a könyvtárban tárolja $TMPDIR/molecule/<role>/<scenario>.
Adjon hozzá lépéseket a következővel: ? leírhatja a kívánt műveleteket ansible-playbook formátumban, és megadhatja a fájl nevét a lépés szerint: prepare.yml/side_effect.yml. Várja ezeket a fájlokat A molekula a script mappában lesz.
Vezető
Az illesztőprogram egy olyan entitás, ahol tesztpéldányok jönnek létre.
Azon szabványos illesztőprogramok listája, amelyekhez a Molecule kész sablonokkal rendelkezik, a következő: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, delegált.
A legtöbb esetben a sablonok fájlok create.yml и destroy.yml abban a script mappában, amely leírja egy példány létrehozását, illetve törlését.
Ez alól kivétel a Docker és a Vagrant, mivel a moduljaikkal való interakció a fent említett fájlok nélkül is megtörténhet.
Érdemes kiemelni a Delegated drivert, hiszen ha a fájlokban egy példány létrehozására és törlésére használjuk, akkor csak a példányok konfigurációjával való munka van leírva, a többit a mérnöknek kell leírnia.
Az alapértelmezett illesztőprogram a Docker.
Most folytassuk a gyakorlatot, és vegyük figyelembe a további funkciókat.
Az első lépések
"Hello world"-ként teszteljünk egy egyszerű nginx-telepítési szerepet. Válasszuk a dockert illesztőprogramnak – szerintem a legtöbben telepítették (és ne feledje, hogy a docker az alapértelmezett illesztőprogram).
Készít virtualenv és telepítse bele molecule:
> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker # molecule установит ansible как зависимость; docker для драйвераA következő lépés az új szerepkör inicializálása.
Egy új szerepkör, valamint egy új szkript inicializálása a paranccsal történik 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 fileKiderült egy tipikus lehetséges-szerep. Ezenkívül a CLI-molekulákkal való összes interakció a szerep gyökeréből származik.
Lássuk, mi van a szerepkönyvtárban:
> tree molecule/default/
molecule/default/
├── Dockerfile.j2 # Jinja-шаблон для Dockerfile
├── INSTALL.rst. # Немного информации об установке зависимостей сценария
├── molecule.yml # Файл конфигурации
├── playbook.yml # Плейбук запуска роли
└── tests # Директория с тестами стадии verify
└── test_default.py
1 directory, 6 filesElemezzük a konfigurációt molecule/default/molecule.yml (csak a docker kép cseréje):
---
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: flake8függőség
Ez a rész a függőségek forrását írja le.
Lehetséges lehetőségek: , , héj.
A Shell csak egy parancshéj, amelyet arra az esetre használnak, ha a galaxy és a gilt nem fedezi az Ön igényeit.
Nem fogok itt sokáig időzni, elég leírva .
gépkocsivezető
A sofőr neve. A miénk a dokkoló.
szösz
A linter yamllint.
A konfiguráció ezen részében található hasznos opciók a yamllint konfigurációs fájl megadása, a környezeti változók továbbítása vagy a linter letiltása:
lint:
name: yamllint
options:
config-file: foo/bar
env:
FOO: bar
enabled: Falseplatformok
Leírja a példányok konfigurációját.
A docker mint meghajtó esetében a molekula ismétlődik ezen a szakaszon, és a lista minden eleme elérhető Dockerfile.j2 mint változó item.
Olyan járművezető esetén, amely megköveteli create.yml и destroy.yml, a rész elérhető bennük mint molecule_yml.platforms, és a rajta végrehajtott iterációk már le vannak írva ezekben a fájlokban.
Mivel a Molecule a lehetséges modulok példányainak vezérlését biztosítja, a lehetséges beállítások listáját is ott kell keresni. Docker esetében például a modult használják . A más illesztőprogramokban használt modulokat itt találja .
Valamint példák találhatók a különféle illesztőprogramok használatára .
Cserélje ide centos:7 on ubuntu.
gondozó
„Beszállító” – példányokat kezelő entitás. A Molecule esetében ez lehetséges, mások támogatását nem tervezik, így ezt a részt egy kitétellel lehetséges kiterjesztett konfigurációnak nevezhetjük.
Itt sok mindent meg lehet adni, a főbb pontokat kiemelem véleményem szerint:
- játékkönyvek: megadhatja, hogy bizonyos szakaszokban mely játékkönyveket kell használni.
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- kapcsolati_beállítások: lehetőségek
provisioner:
name: ansible
connection_options:
ansible_ssh_common_args: "-o 'UserKnownHostsFile=/dev/null' -o 'ForwardAgent=yes'"- lehetőségek: Lehetséges opciók és környezeti változók
provisioner:
name: ansible
options:
vvv: true
diff: true
env:
FOO: BARforgatókönyv
A szkriptsorozatok neve és leírása.
Bármely parancs alapértelmezett műveletmátrixát megváltoztathatja a kulcs hozzáadásával <command>_sequence értékként pedig a szükséges lépések listájának meghatározásával.
Tegyük fel, hogy meg akarjuk változtatni a műveletek sorrendjét a playbook run parancs futtatásakor: molecule converge
# изначально:
# - dependency
# - create
# - prepare
# - converge
scenario:
name: default
converge_sequence:
- create
- convergehitelesítő
Keretrendszer felállítása a tesztekhez és egy linter hozzá. Az alapértelmezett linter a testinfra и flake8. A lehetséges opciók megegyeznek a fentiekkel:
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érjünk vissza a szerepünkhöz. Szerkesszük a fájlt tasks/main.yml ehhez a fajtához:
---
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
És adjunk hozzá teszteket 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")
Kész, már csak futni kell (a szerep gyökerétől, hadd emlékeztesselek):
> molecule testHosszú kipufogó a légterelő alatt:
--> 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
Egyszerű szerepünket probléma nélkül teszteltük.
Érdemes megjegyezni, hogy ha problémák merülnek fel a munka során molecule test, akkor ha nem változtatta meg az alapértelmezett sorrendet, a Molekula törli a példányt.
A következő parancsok hasznosak a hibakereséshez:
> molecule --debug <command> # debug info. При обычном запуске Молекула скрывает логи.
> molecule converge # Оставляет инстанс после прогона тестируемой роли.
> molecule login # Зайти в созданный инстанс.
> molecule --help # Полный список команд.Meglévő szerep
Új szkript hozzáadása egy meglévő szerepkörhöz a szerepkönyvtárból a következő parancsokkal:
# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>Ha ez az első forgatókönyv a szerepkörben, akkor a paraméter -s elhagyható, mivel ez scriptet hoz létre default.
Következtetés
Amint látható, a Molecule nem túl bonyolult, és saját sablonok használatával egy új szkript telepítése a példánylétrehozási és -törlési füzetekben lévő változók szerkesztésére redukálható. A molekula zökkenőmentesen integrálódik a CI rendszerekkel, ami lehetővé teszi a fejlesztés sebességének növelését azáltal, hogy csökkenti a játékkönyvek kézi teszteléséhez szükséges időt.
Köszönöm a figyelmet. Ha van tapasztalatod a lehetséges szerepek tesztelésében, és ez nem kapcsolódik a Molekulához, írd meg nekünk kommentben!
Forrás: will.com
