Instrukcioj: kiel testi ansibajn rolojn kaj ekscii pri problemoj antaŭ produktado

Saluton ĉiuj!

Mi laboras kiel DevOps-inĝeniero en hotela rezerva servo. Ostrovok.ru. En ĉi tiu artikolo, mi volas paroli pri nia sperto pri testado de ansible roloj.

Ĉe Ostrovok.ru, ni uzas ansible kiel agordan administranton. Lastatempe ni venis al la bezono testi rolojn, sed kiel montriĝis, ne ekzistas tiom da iloj por ĉi tio - la plej populara, eble, estas la Molecule-kadro, do ni decidis uzi ĝin. Sed montriĝis, ke lia dokumentado silentas pri multaj faŭltoj. Ni ne povis trovi sufiĉe detalan manlibron en la rusa, do ni decidis skribi ĉi tiun artikolon.

Instrukcioj: kiel testi ansibajn rolojn kaj ekscii pri problemoj antaŭ produktado

Molekulo

Molekulo - kadro por helpi testi ansibajn rolojn.

Simpligita priskribo: La molekulo kreas ekzemplon sur la platformo, kiun vi specifas (nubo, virtuala maŝino, ujo; por pliaj detaloj, vidu la sekcion). ŝoforo), prizorgas vian rolon sur ĝi, poste faras testojn kaj forigas la petskribon. En kazo de malsukceso en unu el la ŝtupoj, la Molekulo informos vin pri tio.

Nun pli.

Iom teorio

Konsideru du ĉefajn estaĵojn de la Molekulo: Scenaro kaj Ŝoforo.

scenaro

La skripto enhavas priskribon de kio, kie, kiel kaj en kiu sinsekvo estos farita. Unu rolo povas havi plurajn skriptojn, kaj ĉiu estas dosierujo laŭ la vojo <role>/molecule/<scenario>, kiu enhavas priskribojn de la agoj necesaj por la testo. Skripto devas esti inkluzivita default, kiu aŭtomate kreiĝos se vi pravigos la rolon per Molekulo. La nomoj de la sekvaj skriptoj dependas de vi.

La sekvenco de testaj agoj en skripto nomiĝas Matrico, kaj defaŭlte ĝi estas:

(Paŝoj etikeditaj ?, preterlasita defaŭlte se ne specifita de la uzanto)

  • lint - kurante linters. Defaŭlte estas uzataj yamllint и flake8,
  • destroy - forigi okazojn de la lasta lanĉo de la Molekulo (se ekzistas),
  • dependency? — instalado de la ansible dependeco de la testita rolo,
  • syntax - kontroli la sintakson de la rolo uzante ansible-playbook --syntax-check,
  • create - kreante ekzemplon,
  • prepare? — preparado de la petskribo; ekz. kontroli/instali python2
  • converge — lanĉo de la testata ludlibro,
  • idempotence - rekomencante la ludlibron por la provo de idempotenco,
  • side_effect? - agoj ne rekte rilataj al la rolo, sed necesaj por testoj,
  • verify - ruli testojn de la rezulta agordo uzante testinfra(defaŭlte)/goss/inspec,
  • cleanup? - (en novaj versioj) - proksimume, "purigante" la eksteran infrastrukturon trafitan de la Molekulo,
  • destroy - Forigo de kazo.

Ĉi tiu sekvenco kovras la plej multajn kazojn, sed povas esti ŝanĝita se necese.

Ĉiu el la supraj paŝoj povas esti rulita aparte kun molecule <command>. Sed oni devas kompreni, ke por ĉiu tia kli-komando povas ekzisti sia propra sinsekvo de agoj, kiujn vi povas ekscii per ekzekuto. molecule matrix <command>. Ekzemple, kiam oni rulas la komandon converge (prizorgante la ludlibron sub testo), la sekvaj agoj estos faritaj:

$ molecule matrix converge
...
└── default         # название сценария
    ├── dependency  # установка зависимостей
    ├── create      # создание инстанса
    ├── prepare     # преднастройка инстанса
    └── converge    # прогон плейбука

La sekvenco de ĉi tiuj agoj povas esti redaktita. Se io el la listo jam estas farita, ĝi estos preterlasita. La aktuala stato, same kiel la agordo de la petskriboj, la Molekulo stokas en la dosierujo $TMPDIR/molecule/<role>/<scenario>.

Aldonu paŝojn kun ? vi povas priskribi la deziratajn agojn en la formato ansible-playbook, kaj fari la dosiernomon laŭ la paŝo: prepare.yml/side_effect.yml. Atendu ĉi tiujn dosierojn La molekulo estos en la skriptdosierujo.

ŝoforo

Ŝoforo estas ento kie testaj petskriboj estas kreitaj.
La listo de normaj ŝoforoj por kiuj Molecule havas ŝablonojn pretajn estas jena: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

Plejofte, ŝablonoj estas dosieroj create.yml и destroy.yml en la skriptdosierujo, kiu priskribas la kreadon kaj forigon de kazo, respektive.
La esceptoj estas Docker kaj Vagrant, ĉar interagoj kun iliaj moduloj povas okazi sen la menciitaj dosieroj.

Indas reliefigi la Delegitan pelilon, ĉar se ĝi estas uzata en la dosieroj por krei kaj forigi petskribon, nur laboro kun la agordo de petskriboj estas priskribita, la resto devus esti priskribita de la inĝeniero.

La defaŭlta ŝoforo estas Docker.

Nun ni plu praktiku kaj konsideru pliajn funkciojn tie.

Kiel ekuzi

Kiel "saluton mondo", ni provu simplan instalrolon de nginx. Ni elektos docker kiel la pelilon - mi pensas, ke la plimulto el vi havas ĝin instalita (kaj memoru, ke docker estas la defaŭlta pelilo).

Preparu virtualenv kaj instalu en ĝi molecule:

> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker  # molecule установит ansible как зависимость; docker для драйвера

La sekva paŝo estas pravalorigi la novan rolon.
Iniciatigo de nova rolo, same kiel nova skripto, estas farita per la komando 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

Ĝi rezultis tipa ansible-rolo. Plue, ĉiuj interagoj kun CLI-Molekuloj estas faritaj de la radiko de la rolo.

Ni vidu kio estas en la rola dosierujo:

> tree molecule/default/
molecule/default/
├── Dockerfile.j2  # Jinja-шаблон для Dockerfile
├── INSTALL.rst.   # Немного информации об установке зависимостей сценария
├── molecule.yml   # Файл конфигурации
├── playbook.yml   # Плейбук запуска роли
└── tests          # Директория с тестами стадии verify
    └── test_default.py

1 directory, 6 files

Ni analizu la agordon molecule/default/molecule.yml (anstataŭigu nur docker-bildon):

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

dependeco

Ĉi tiu sekcio priskribas la fonton de dependecoj.

Eblaj ebloj: galaksio, aplikiĝas, ŝelo.

Ŝelo estas nur komanda ŝelo, kiu estas uzata se galaksio kaj origita ne kovras viajn bezonojn.

Mi ne loĝos ĉi tie dum longa tempo, ĝi estas sufiĉe priskribita en dokumentado.

ŝoforo

La nomo de la ŝoforo. Nia estas docker.

tolaĵo

La linter estas yamllint.

Utilaj opcioj en ĉi tiu parto de la agordo estas la kapablo specifi agordan dosieron por yamllint, antaŭenigi mediovariablojn aŭ malŝalti la linter:

lint:
  name: yamllint
  options:
    config-file: foo/bar
  env:
    FOO: bar
  enabled: False

platformoj

Priskribas la agordon de la petskriboj.
En la kazo de docker kiel ŝoforo, la Molekulo estas ripetata super ĉi tiu sekcio, kaj ĉiu elemento de la listo estas havebla en Dockerfile.j2 kiel variablo item.

En la kazo de ŝoforo kiu postulas create.yml и destroy.yml, la sekcio disponeblas en ili kiel molecule_yml.platforms, kaj ripetoj super ĝi jam estas priskribitaj en ĉi tiuj dosieroj.

Ĉar la Molekulo disponigas kontrolon de okazoj al ansibaj moduloj, la listo de eblaj agordoj ankaŭ devus esti serĉita tie. Por docker, ekzemple, la modulo estas uzata docker_container_module. En kiuj moduloj estas uzataj en aliaj ŝoforoj troviĝas dokumentado.

Same kiel ekzemploj de la uzo de diversaj ŝoforoj troveblas en la provoj de la Molekulo mem.

Anstataŭigu ĉi tie centos:7 sur ubuntu.

provizanto

"Provizanto" - ento kiu administras petskribojn. En la kazo de Molecule, ĉi tio estas ansible, subteno por aliaj ne estas planita, do ĉi tiu sekcio povas esti nomita ansible etendita agordo kun averto.
Ĉi tie vi povas specifi multajn aferojn, mi reliefigos la ĉefajn punktojn, laŭ mi:

  • ludlibroj: vi povas specifi kiuj ludlibroj estu uzataj en certaj stadioj.

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

  • opcioj: Ansible opcioj kaj mediaj variabloj

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

scenaro

Nomo kaj priskribo de skriptosekvencoj.
Vi povas ŝanĝi la defaŭltan agan matricon de iu ajn komando aldonante la ŝlosilon <command>_sequence kaj kiel valoron por ĝi difinante la liston de paŝoj, kiujn ni bezonas.
Ni diru, ke ni volas ŝanĝi la sekvencon de agoj dum rulado de la ludlibro prizorga komando: molecule converge

# изначально:
# - dependency
# - create
# - prepare
# - converge
scenario:
  name: default
  converge_sequence:
    - create
    - converge

kontrolilo

Starigante kadron por testoj kaj linter al ĝi. La defaŭlta linter estas testinfra и flake8. La eblaj opcioj estas la samaj kiel supre:

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

Ni revenu al nia rolo. Ni redaktu la dosieron tasks/main.yml al ĉi tiu speco:

---
- name: Install nginx
  apt:
    name: nginx
    state: present

- name: Start nginx
  service:
    name: nginx
    state: started

Kaj aldonu testojn al 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")

Farite, restas nur kuri (de la radiko de la rolo, mi memorigu vin):

> molecule test

Longa ellasilo sub la alerono:

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

Nia simpla rolo estis provita senprobleme.
Indas memori, ke se estas problemoj dum la laboro molecule test, tiam se vi ne ŝanĝis la defaŭltan sekvencon, la Molekulo forigos la kazon.

La sekvaj komandoj estas utilaj por sencimigi:

> molecule --debug <command> # debug info. При обычном запуске Молекула скрывает логи.
> molecule converge          # Оставляет инстанс после прогона тестируемой роли.
> molecule login             # Зайти в созданный инстанс.
> molecule --help            # Полный список команд.

Ekzistanta Rolo

Aldoni novan skripton al ekzistanta rolo estas el la rola dosierujo kun la jenaj komandoj:

# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>

Se ĉi tio estas la unua scenaro en la rolo, tiam la parametro -s povas esti preterlasita ĉar ĝi kreos skripton default.

konkludo

Kiel vi povas vidi, la Molekulo ne estas tre kompleksa, kaj uzante viajn proprajn ŝablonojn, deploji novan skripton povas reduktiĝi al redaktado de variabloj en la ludlibroj pri kreado kaj forigo de petskriboj. La molekulo integriĝas perfekte kun CI-sistemoj, kio ebligas al vi pliigi la rapidecon de evoluo reduktante la tempon por manlibrotestado de ludlibroj.

Dankon pro via atento. Se vi havas sperton pri testado de ansibaj roloj, kaj ĝi ne rilatas al la Molekulo, diru al ni pri ĝi en la komentoj!

fonto: www.habr.com

Aldoni komenton