Οδηγίες: πώς να δοκιμάσετε ανεξάρτητους ρόλους και να μάθετε για προβλήματα πριν από την παραγωγή

Γεια σε όλους!

Εργάζομαι ως μηχανικός DevOps σε υπηρεσία κρατήσεων ξενοδοχείων. Ostrovok.ru. Σε αυτό το άρθρο, θέλω να μιλήσω για την εμπειρία μας στη δοκιμή ρόλων.

Στο Ostrovok.ru, χρησιμοποιούμε το ansible ως διαχειριστή διαμόρφωσης. Πρόσφατα, καταλήξαμε στην ανάγκη να δοκιμάσουμε ρόλους, αλλά όπως αποδείχθηκε, δεν υπάρχουν τόσα πολλά εργαλεία για αυτό - το πιο δημοφιλές, ίσως, είναι το πλαίσιο Molecule, οπότε αποφασίσαμε να το χρησιμοποιήσουμε. Αλλά αποδείχθηκε ότι η τεκμηρίωσή του είναι σιωπηλή για πολλές παγίδες. Δεν μπορέσαμε να βρούμε ένα αρκετά λεπτομερές εγχειρίδιο στα ρωσικά, οπότε αποφασίσαμε να γράψουμε αυτό το άρθρο.

Οδηγίες: πώς να δοκιμάσετε ανεξάρτητους ρόλους και να μάθετε για προβλήματα πριν από την παραγωγή

Μόριο

Μόριο - ένα πλαίσιο που βοηθά στη δοκιμή των δυνατών ρόλων.

Απλοποιημένη περιγραφή: Το μόριο δημιουργεί ένα στιγμιότυπο στην πλατφόρμα που καθορίζετε (σύννεφο, εικονική μηχανή, κοντέινερ, για περισσότερες λεπτομέρειες, ανατρέξτε στην ενότητα Οδηγός), εκτελεί το ρόλο σας σε αυτό, μετά εκτελεί δοκιμές και διαγράφει την παρουσία. Σε περίπτωση αποτυχίας σε ένα από τα βήματα, το Μόριο θα σας ενημερώσει σχετικά.

Τώρα περισσότερο.

Λίγο θεωρίας

Εξετάστε δύο βασικές οντότητες του μορίου: Σενάριο και Οδηγός.

σενάριο

Το σενάριο περιέχει μια περιγραφή του τι, πού, πώς και με ποια σειρά θα εκτελεστεί. Ένας ρόλος μπορεί να έχει πολλά σενάρια και το καθένα είναι ένας κατάλογος κατά μήκος της διαδρομής <role>/molecule/<scenario>, το οποίο περιέχει περιγραφές των ενεργειών που απαιτούνται για τη δοκιμή. Πρέπει να περιλαμβάνεται σενάριο default, το οποίο θα δημιουργηθεί αυτόματα εάν αρχικοποιήσετε το ρόλο με ένα Μόριο. Τα ονόματα των παρακάτω σεναρίων εξαρτάται από εσάς.

Η ακολουθία των ενεργειών δοκιμής σε ένα σενάριο ονομάζεται μήτρα, και από προεπιλογή είναι:

(Βήματα με ετικέτα ?, παραλείπεται από προεπιλογή εάν δεν έχει καθοριστεί από τον χρήστη)

  • lint - θυρίδες λειτουργίας. Από προεπιλογή χρησιμοποιούνται yamllint и flake8,
  • destroy - διαγραφή περιπτώσεων από την τελευταία εκκίνηση του Molecule (εάν υπάρχει),
  • dependency? — εγκατάσταση της αισθητής εξάρτησης του δοκιμασμένου ρόλου,
  • syntax - έλεγχος της σύνταξης του ρόλου χρησιμοποιώντας ansible-playbook --syntax-check,
  • create - δημιουργία ενός στιγμιότυπου,
  • prepare? — προετοιμασία της περίπτωσης· π.χ. έλεγχος/εγκατάσταση του python2
  • converge — εκκίνηση του βιβλίου παιχνιδιού που δοκιμάζεται,
  • idempotence - επανεκκίνηση του βιβλίου για το τεστ ανικανότητας,
  • side_effect? - ενέργειες που δεν σχετίζονται άμεσα με τον ρόλο, αλλά είναι απαραίτητες για δοκιμές,
  • verify - εκτέλεση δοκιμών της προκύπτουσας διαμόρφωσης χρησιμοποιώντας testinfra(Προκαθορισμένο) /goss/inspec,
  • cleanup? - (σε νέες εκδόσεις) - χονδρικά, "καθαρισμός" της εξωτερικής υποδομής που επηρεάζεται από το Μόριο,
  • destroy - Διαγραφή ενός στιγμιότυπου.

Αυτή η σειρά καλύπτει τις περισσότερες περιπτώσεις, αλλά μπορεί να αλλάξει εάν είναι απαραίτητο.

Κάθε ένα από τα παραπάνω βήματα μπορεί να εκτελεστεί ξεχωριστά με molecule <command>. Αλλά πρέπει να γίνει κατανοητό ότι για κάθε τέτοια εντολή cli μπορεί να υπάρχει η δική της ακολουθία ενεργειών, την οποία μπορείτε να μάθετε εκτελώντας molecule matrix <command>. Για παράδειγμα, όταν εκτελείτε την εντολή converge (τρέχοντας το βιβλίο παιχνιδιού υπό δοκιμή), θα εκτελεστούν οι ακόλουθες ενέργειες:

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

Η σειρά αυτών των ενεργειών μπορεί να τροποποιηθεί. Εάν κάτι από τη λίστα έχει ήδη γίνει, θα παραλειφθεί. Η τρέχουσα κατάσταση, καθώς και η διαμόρφωση των περιπτώσεων, το Molecule αποθηκεύει στον κατάλογο $TMPDIR/molecule/<role>/<scenario>.

Προσθήκη βημάτων με ? μπορείτε να περιγράψετε τις επιθυμητές ενέργειες στη μορφή ansible-playbook και να ορίσετε το όνομα του αρχείου σύμφωνα με το βήμα: prepare.yml/side_effect.yml. Αναμένετε αυτά τα αρχεία Το μόριο θα βρίσκεται στο φάκελο του σεναρίου.

Οδηγός

Ένα πρόγραμμα οδήγησης είναι μια οντότητα όπου δημιουργούνται περιπτώσεις δοκιμής.
Η λίστα των τυπικών προγραμμάτων οδήγησης για τα οποία το Molecule έχει έτοιμα πρότυπα είναι η εξής: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

Στις περισσότερες περιπτώσεις, τα πρότυπα είναι αρχεία create.yml и destroy.yml στο φάκελο σεναρίου που περιγράφουν τη δημιουργία και τη διαγραφή μιας παρουσίας, αντίστοιχα.
Οι εξαιρέσεις είναι το Docker και το Vagrant, καθώς οι αλληλεπιδράσεις με τις μονάδες τους μπορούν να προκύψουν χωρίς τα προαναφερθέντα αρχεία.

Αξίζει να επισημάνετε το πρόγραμμα οδήγησης Delegated, καθώς εάν χρησιμοποιείται στα αρχεία για τη δημιουργία και τη διαγραφή μιας παρουσίας, περιγράφεται μόνο η εργασία με τη ρύθμιση παραμέτρων των παρουσιών, τα υπόλοιπα πρέπει να περιγραφούν από τον μηχανικό.

Το προεπιλεγμένο πρόγραμμα οδήγησης είναι το Docker.

Τώρα ας προχωρήσουμε στην εξάσκηση και ας εξετάσουμε περαιτέρω χαρακτηριστικά εκεί.

Ξεκινώντας

Ως "γεια σας κόσμο", ας δοκιμάσουμε έναν απλό ρόλο εγκατάστασης nginx. Ας επιλέξουμε το docker ως πρόγραμμα οδήγησης - νομίζω ότι οι περισσότεροι από εσάς το έχετε εγκαταστήσει (και να θυμάστε ότι το docker είναι το προεπιλεγμένο πρόγραμμα οδήγησης).

Ας προετοιμαστούμε virtualenv και εγκαταστήστε σε αυτό molecule:

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

Το επόμενο βήμα είναι η προετοιμασία του νέου ρόλου.
Η αρχικοποίηση ενός νέου ρόλου, καθώς και ενός νέου σεναρίου, εκτελείται χρησιμοποιώντας την εντολή 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

Αποδείχθηκε ένας τυπικός ρόλος. Επιπλέον, όλες οι αλληλεπιδράσεις με τα μόρια CLI γίνονται από τη ρίζα του ρόλου.

Ας δούμε τι υπάρχει στον κατάλογο ρόλων:

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

1 directory, 6 files

Ας αναλύσουμε τη διαμόρφωση molecule/default/molecule.yml (αντικαταστήστε μόνο την εικόνα 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

εξάρτηση

Αυτή η ενότητα περιγράφει την πηγή των εξαρτήσεων.

Πιθανές επιλογές: γαλαξίας, ισχύει, κοχύλι.

Το Shell είναι απλώς ένα κέλυφος εντολών που χρησιμοποιείται σε περίπτωση που ο γαλαξίας και ο χρυσός δεν καλύπτουν τις ανάγκες σας.

Δεν θα μείνω εδώ για πολύ καιρό, περιγράφεται αρκετά τεκμηρίωση.

οδηγός

Το όνομα του οδηγού. Το δικό μας είναι λιμενεργάτης.

στουπί

Το λιντερ είναι γιαμλίντ.

Χρήσιμες επιλογές σε αυτό το τμήμα της διαμόρφωσης είναι η δυνατότητα καθορισμού ενός αρχείου διαμόρφωσης για το yamllint, μεταβλητών περιβάλλοντος προώθησης ή απενεργοποίησης του linter:

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

πλατφόρμες

Περιγράφει τη διαμόρφωση των περιπτώσεων.
Στην περίπτωση του docker ως οδηγού, το Molecule επαναλαμβάνεται σε αυτήν την ενότητα και κάθε στοιχείο της λίστας είναι διαθέσιμο σε Dockerfile.j2 ως μεταβλητή item.

Στην περίπτωση οδηγού που απαιτεί create.yml и destroy.yml, η ενότητα είναι διαθέσιμη σε αυτά ως molecule_yml.platforms, και οι επαναλήψεις πάνω από αυτό περιγράφονται ήδη σε αυτά τα αρχεία.

Δεδομένου ότι το Molecule παρέχει τον έλεγχο των παρουσιών σε ansible modules, η λίστα των πιθανών ρυθμίσεων θα πρέπει επίσης να αναζητηθεί εκεί. Για το docker, για παράδειγμα, χρησιμοποιείται η μονάδα docker_container_module. Μπορείτε να βρείτε ποιες μονάδες χρησιμοποιούνται σε άλλα προγράμματα οδήγησης τεκμηρίωση.

Μπορούν επίσης να βρεθούν παραδείγματα χρήσης διαφόρων προγραμμάτων οδήγησης στις δοκιμές του ίδιου του Μορίου.

Αντικαταστήστε εδώ σεντ:7 επί ubuntu.

προμηθευτής

"Προμηθευτής" - μια οντότητα που διαχειρίζεται παρουσίες. Στην περίπτωση του Molecule, αυτό είναι ansible, δεν έχει προγραμματιστεί υποστήριξη για άλλους, επομένως αυτή η ενότητα μπορεί να ονομαστεί ansible εκτεταμένη διαμόρφωση με μια προειδοποίηση.
Εδώ μπορείτε να προσδιορίσετε πολλά πράγματα, θα επισημάνω τα κύρια σημεία, κατά τη γνώμη μου:

  • playbooks: μπορείτε να καθορίσετε ποια βιβλία παιχνιδιού θα πρέπει να χρησιμοποιούνται σε ορισμένα στάδια.

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

  • επιλογές: Ansible επιλογές και μεταβλητές περιβάλλοντος

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

σενάριο

Όνομα και περιγραφή των σεναρίων ακολουθιών.
Μπορείτε να αλλάξετε τον προεπιλεγμένο πίνακα ενεργειών οποιασδήποτε εντολής προσθέτοντας το κλειδί <command>_sequence και ως τιμή για αυτό ορίζοντας τη λίστα των βημάτων που χρειαζόμαστε.
Ας υποθέσουμε ότι θέλουμε να αλλάξουμε τη σειρά των ενεργειών κατά την εκτέλεση της εντολής εκτέλεσης του playbook: molecule converge

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

ελεγκτής

Ρύθμιση ενός πλαισίου για δοκιμές και μιας δέσμης σε αυτό. Το προεπιλεγμένο linter είναι testinfra и flake8. Οι πιθανές επιλογές είναι οι ίδιες όπως παραπάνω:

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

Ας επιστρέψουμε στον ρόλο μας. Ας επεξεργαστούμε το αρχείο tasks/main.yml σε αυτό το είδος:

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

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

Και προσθέστε δοκιμές σε 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")

Έγινε, μένει μόνο να τρέξουμε (από τη ρίζα του ρόλου, επιτρέψτε μου να σας υπενθυμίσω):

> molecule test

Μακρά εξάτμιση κάτω από την αεροτομή:

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

Ο απλός μας ρόλος δοκιμάστηκε χωρίς προβλήματα.
Αξίζει να θυμάστε ότι εάν υπάρχουν προβλήματα κατά τη διάρκεια της εργασίας molecule test, τότε εάν δεν αλλάξατε την προεπιλεγμένη ακολουθία, το Μόριο θα διαγράψει την παρουσία.

Οι ακόλουθες εντολές είναι χρήσιμες για τον εντοπισμό σφαλμάτων:

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

Υπάρχων Ρόλος

Η προσθήκη ενός νέου σεναρίου σε έναν υπάρχοντα ρόλο είναι από τον κατάλογο ρόλων με τις παρακάτω εντολές:

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

Σε περίπτωση που αυτό είναι το πρώτο σενάριο στον ρόλο, τότε η παράμετρος -s μπορεί να παραλειφθεί καθώς θα δημιουργήσει ένα σενάριο default.

Συμπέρασμα

Όπως μπορείτε να δείτε, το Molecule δεν είναι πολύ περίπλοκο και χρησιμοποιώντας τα δικά σας πρότυπα, η ανάπτυξη ενός νέου σεναρίου μπορεί να περιοριστεί στην επεξεργασία μεταβλητών στα βιβλία δημιουργίας και διαγραφής παρουσιών. Το μόριο ενσωματώνεται απρόσκοπτα με συστήματα CI, γεγονός που σας επιτρέπει να αυξήσετε την ταχύτητα ανάπτυξης μειώνοντας τον χρόνο για χειροκίνητη δοκιμή των βιβλίων παιχνιδιού.

Σας ευχαριστώ για την προσοχή σας. Εάν έχετε εμπειρία στη δοκιμή ρόλων και δεν σχετίζεται με το Μόριο, πείτε μας για αυτό στα σχόλια!

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο