Struzzjonijiet: kif tittestja r-rwoli Ansible u ssir taf dwar il-problemi qabel il-produzzjoni

Hello kulħadd!

Jien naħdem bħala inġinier DevOps għal servizz ta’ prenotazzjoni ta’ lukanda. Ostrovok.ru. F'dan l-artikolu nixtieq nitkellem dwar l-esperjenza tagħna fl-ittestjar tar-rwoli Ansible.

F'Ostrovok.ru nużaw ansible bħala maniġer tal-konfigurazzjoni. Riċentement wasalna għall-ħtieġa li nittestjaw ir-rwoli, iżda, kif irriżulta, m'hemmx ħafna għodod għal dan - l-aktar popolari, forsi, huwa l-qafas tal-Molecule, għalhekk iddeċidejna li nużawh. Iżda rriżulta li d-dokumentazzjoni tiegħu hija siekta dwar ħafna nases. Ma stajniex insibu gwida dettaljata biżżejjed bir-Russu, għalhekk iddeċidejna li niktbu dan l-artikolu.

Struzzjonijiet: kif tittestja r-rwoli Ansible u ssir taf dwar il-problemi qabel il-produzzjoni

Molekula

Molekula — qafas biex jgħin jittestja r-rwoli Ansible.

Deskrizzjoni simplifikata: Molecule toħloq eżempju fuq il-pjattaforma li tispeċifika (sħaba, magna virtwali, kontenitur; għal aktar dettalji, ara t-taqsima Sewwieq), imexxi r-rwol tiegħek fuqha, imbagħad iwettaq testijiet u jħassar l-istanza. Jekk ikun hemm falliment f'wieħed mill-passi, il-Molekula tinnotifikak dwarha.

Issa aktar.

Daqsxejn ta 'teorija

Ejja nikkunsidraw żewġ entitajiet ewlenin tal-Molekula: Xenarju u Sewwieq.

Xenarju

L-iskrittura fiha deskrizzjoni ta' x'se jsir, fejn, kif u f'liema sekwenza. Rwol wieħed jista 'jkollu diversi skripts, u kull wieħed huwa direttorju tul it-triq <role>/molecule/<scenario>, li jkun fih deskrizzjonijiet tal-azzjonijiet meħtieġa għat-test. Għandu jkun hemm skript default, li se tinħoloq awtomatikament jekk inizjalizza r-rwol billi tuża Molecule. L-ismijiet tal-iskripts li ġejjin huma fid-diskrezzjoni tiegħek.

Is-sekwenza tal-azzjonijiet tal-ittestjar fi skript tissejjaħ matriċi, u awtomatikament huwa bħal dan:

(Passi mmarkati ?, jinqabżu awtomatikament jekk mhux speċifikati mill-utent)

  • lint - running linters. B'mod awtomatiku yamllint и flake8,
  • destroy — it-tħassir ta' każijiet mill-aħħar tnedija ta' Molecule (jekk jibqa' hemm),
  • dependency? — l-installazzjoni tad-dipendenza anżibbli tar-rwol ittestjat,
  • syntax - verifika rwol sintassi bl-użu ansible-playbook --syntax-check,
  • create - il-ħolqien ta' eżempju,
  • prepare? — it-tħejjija tal-istanza; per eżempju verifika/installazzjoni python2
  • converge — it-tnedija tal-playbook ittestjat,
  • idempotence — erġa' ħaddem il-playbook għat-test tal-idempotenza,
  • side_effect? — azzjonijiet mhux relatati direttament mar-rwol, iżda meħtieġa għat-testijiet,
  • verify — it-twettiq tat-testijiet tal-konfigurazzjoni li tirriżulta bl-użu testinfra(default) /goss/inspec,
  • cleanup? - (f'verżjonijiet ġodda) - bejn wieħed u ieħor, "tindif" tal-infrastruttura esterna affettwata mill-Molekula,
  • destroy — tħassar istanza.

Din is-sekwenza tkopri l-biċċa l-kbira tal-każijiet, iżda tista' tiġi modifikata jekk meħtieġ.

Kull wieħed mill-passi ta 'hawn fuq jista' jitmexxa separatament bl-użu molecule <command>. Imma għandek tifhem li għal kull kmand cli bħal dan jista 'jkun hemm is-sekwenza ta' azzjonijiet tagħha stess, li tista 'ssir taf billi tmexxi molecule matrix <command>. Per eżempju, meta tmexxi l-kmand converge (tmexxi l-playbook ittestjat) se jitwettqu l-azzjonijiet li ġejjin:

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

Is-sekwenza ta' dawn l-azzjonijiet tista' tiġi editjata. Jekk xi ħaġa mil-lista tkun diġà tlestiet, din tinqabeż. L-istat attwali, kif ukoll il-konfigurazzjoni tal-istanza, huma maħżuna fid-direttorju tal-Molecule $TMPDIR/molecule/<role>/<scenario>.

Żid passi ma ? Tista' tiddeskrivi l-azzjonijiet mixtieqa fil-format tal-playbook Ansible, u tagħmel l-isem tal-fajl skont il-pass: prepare.yml/side_effect.yml. Stenna li dawn il-fajls tal-Molecule jkunu fil-folder tal-iskript.

Sewwieq

Sewwieq huwa entità fejn jinħolqu istanzi għat-testijiet.
Il-lista ta 'sewwieqa standard li għalihom Molecule għandha mudelli lesti hija: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

F'ħafna każijiet, mudelli huma fajls create.yml и destroy.yml fil-folder tal-iskrittura, li jiddeskrivu l-ħolqien u t-tħassir tal-istanza, rispettivament.
L-eċċezzjonijiet huma Docker u Vagrant, peress li l-interazzjonijiet mal-moduli tagħhom jistgħu jseħħu mingħajr il-fajls ta 'hawn fuq.

Ta 'min jenfasizza s-sewwieq Delegat, peress li jekk jintuża, ix-xogħol biss bil-konfigurazzjoni tal-istanza huwa deskritt fil-fajls tal-ħolqien u t-tħassir tal-istanza; il-bqija għandu jiġi deskritt mill-inġinier.

Is-sewwieq default huwa Docker.

Issa ejja ngħaddu għall-prattika u nikkunsidraw aktar karatteristiċi hemmhekk.

Getting Started

Bħala "hello world" aħna se nittestjaw rwol sempliċi ta 'installazzjoni nginx. Ejja nagħżlu docker bħala s-sewwieq - naħseb li ħafna minnkom għandekha installata (u ftakar li docker huwa s-sewwieq default).

Ipprepara virtualenv u tinstallah fiha molecule:

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

Il-pass li jmiss huwa li tibda rwol ġdid.
L-inizjalizzazzjoni ta 'rwol ġdid, kif ukoll skript ġdid, titwettaq bl-użu tal-kmand 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

Ir-riżultat huwa rwol tipiku ansible. Barra minn hekk, l-interazzjonijiet kollha mal-Molecules CLI huma magħmula mill-għerq tar-rwol.

Ejja naraw x'hemm fid-direttorju tar-rwoli:

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

1 directory, 6 files

Ejja nħarsu lejn il-konfigurazzjoni molecule/default/molecule.yml (se nissostitwixxu biss l-immaġni tad-docker):

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

dipendenza

Din it-taqsima tiddeskrivi s-sors tad-dipendenzi.

Għażliet possibbli: galaxie, indurat, qoxra.

Il-qoxra hija sempliċement qoxra tal-kmand biex tużah jekk il-galaxie u l-gilt ma jkoprux il-bżonnijiet tiegħek.

Mhux se noqgħod hawn għal żmien twil, huwa deskritt biżżejjed fi dokumentazzjoni.

sewwieq

Isem is-sewwieq. Għalina dan huwa docker.

bjankerija

Yamllint jintuża bħala linter.

Għażliet utli f'din il-parti tal-konfigurazzjoni huma l-abbiltà li jiġi speċifikat fajl ta 'konfigurazzjoni għal yamllint, varjabbli ambjentali 'l quddiem, jew tiddiżattiva l-linter:

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

pjattaformi

Jiddeskrivi l-konfigurazzjoni tal-istanzi.
Fil-każ ta' docker bħala sewwieq, il-Molekula ttenni fuq din it-taqsima, u kull element tal-lista huwa disponibbli f' Dockerfile.j2 bħala varjabbli item.

Fil-każ ta’ xufier li fih create.yml и destroy.yml, it-taqsima hija disponibbli fihom bħala molecule_yml.platforms, u iterazzjonijiet fuqu huma diġà deskritti f'dawn il-fajls.

Peress li Molecule tipprovdi ġestjoni tal-istanzi lill-moduli Ansible, għandek tfittex il-lista ta 'settings possibbli hemmhekk. Għal Docker, pereżempju, jintuża l-modulu docker_container_module. Liema moduli jintużaw f'sewwieqa oħra jistgħu jinstabu fihom dokumentazzjoni.

Tista' ssib ukoll eżempji ta' kif tuża diversi sewwieqa fit-testijiet tal-Molekula nnifisha.

Ejja nibdel hawn centos:7 fuq ubuntu.

provveditur

"Fornitur" hija l-entità li tmexxi l-istanzi. Fil-każ ta 'Molecule, dan huwa ansible; appoġġ għal oħrajn mhux ippjanat, għalhekk din it-taqsima tista', b'riżerva, tissejjaħ konfigurazzjoni estiża ansible.
Hemm ħafna li tista' tindika hawn, imma jien ser nenfasizza l-punti ewlenin, fl-opinjoni tiegħi:

  • kotba tal-logħob: Tista' tispeċifika liema playbooks għandhom jintużaw f'ċerti stadji.

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

  • għażliet: Parametri Ansible u varjabbli ambjentali

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

xenarju

Titolu u deskrizzjoni ta' sekwenzi ta' skript.
Tista 'tbiddel il-matriċi ta' azzjoni default ta 'kmand billi żżid iċ-ċavetta <command>_sequence u bħala valur għaliha, tiddefinixxi l-lista ta 'passi li għandna bżonn.
Ejja ngħidu li rridu nbiddlu s-sekwenza tal-azzjonijiet meta nħaddmu l-kmand tal-ġirja tal-playbook: molecule converge

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

verifikatur

It-twaqqif ta' qafas għat-testijiet u linter għalih. B'mod awtomatiku, jintuża l-linter testinfra и flake8. Għażliet possibbli huma simili għal dawn ta 'hawn fuq:

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

Ejja nerġgħu lura għar-rwol tagħna. Ejja neditjaw il-fajl tasks/main.yml għal din id-dehra:

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

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

U żid it-testijiet 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")

Lest, dak kollu li jibqa 'huwa li tiġri (mill-għerq tar-rwol, ħalluni nfakkarkom):

> molecule test

Exhaust twil taħt spoiler:

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

Ir-rwol sempliċi tagħna ttestjat mingħajr problemi.
Ta 'min jiftakar li jekk jinqalgħu problemi waqt it-tħaddim molecule test, allura jekk ma bdiltx is-sekwenza standard, Molecule se tħassar l-istanza.

Il-kmandi li ġejjin huma utli għad-debugging:

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

Rwol eżistenti

Iż-żieda ta 'kitba ġdida għal rwol eżistenti sseħħ mid-direttorju tar-rwoli bil-kmandi li ġejjin:

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

Jekk dan huwa l-ewwel skript fir-rwol, allura l-parametru -s jista' jitħalla barra peress li se tinħoloq skript default.

Konklużjoni

Kif tistgħu taraw, Molecule mhix ikkumplikata ħafna, u meta tuża l-mudelli tiegħek stess, tista 'tnaqqas l-użu ta' skript ġdid għall-editjar ta 'varjabbli fil-playbooks għall-ħolqien u t-tħassir ta' każijiet. Il-molekula tintegra bla xkiel mas-sistemi CI, li jippermettilek li żżid il-veloċità tal-iżvilupp billi tnaqqas il-ħin għall-ittestjar manwali tal-playbooks.

Grazzi tal-attenzjoni tiegħek. Jekk għandek esperjenza fl-ittestjar ta 'rwoli ansible, u mhix relatata mal-Molecule, għidilna dwarha fil-kummenti!

Sors: www.habr.com

Żid kumment