Utasítások: hogyan lehet tesztelni a lehetséges szerepeket és tájékozódni a problémákról a gyártás előtt

Hello!

DevOps mérnökként dolgozom egy szállodafoglalási szolgáltatásnál. Ostrovok.ru. 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.

Utasítások: hogyan lehet tesztelni a lehetséges szerepeket és tájékozódni a problémákról a gyártás előtt

Molekula

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 Vezető), 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álatosak yamllint и 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ével ansible-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-t
  • converge — 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ével testinfra(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 file

Kiderü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 files

Elemezzü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: flake8

függőség

Ez a rész a függőségek forrását írja le.

Lehetséges lehetőségek: Galaxy, alkalmazandó, 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 dokumentáció.

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: False

platformok

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 docker_container_module. A más illesztőprogramokban használt modulokat itt találja dokumentáció.

Valamint példák találhatók a különféle illesztőprogramok használatára maga a Molekula tesztjeiben.

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

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'"

  • lehetőségek: Lehetséges opciók és környezeti változók

provisioner:
  name: ansible  
  options:
    vvv: true
    diff: true
  env:
    FOO: BAR

forgató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
    - converge

hitelesí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: bar

Té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 test

Hosszú 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

Hozzászólás