ื”ื•ืจืื•ืช: ื›ื™ืฆื“ ืœื‘ื“ื•ืง ืชืคืงื™ื“ื™ื ืืคืฉืจื™ื™ื ื•ืœื‘ืจืจ ืขืœ ื‘ืขื™ื•ืช ืœืคื ื™ ื”ื™ื™ืฆื•ืจ

ืฉืœื•ื ืœื›ื•ืœื!

ืื ื™ ืขื•ื‘ื“ ื›ืžื”ื ื“ืก DevOps ื‘ืฉื™ืจื•ืช ื”ื–ืžื ืช ืžืœื•ื ื•ืช. Ostrovok.ru. ื‘ืžืืžืจ ื–ื”, ืื ื™ ืจื•ืฆื” ืœื“ื‘ืจ ืขืœ ื”ื ื™ืกื™ื•ืŸ ืฉืœื ื• ื‘ื‘ื“ื™ืงืช ืชืคืงื™ื“ื™ื ืืคืฉืจื™ื™ื.

ื‘- Ostrovok.ru, ืื ื• ืžืฉืชืžืฉื™ื ื‘- ansible ื›ืžื ื”ืœ ืชืฆื•ืจื”. ืœืื—ืจื•ื ื”, ื”ื’ืขื ื• ืœืฆื•ืจืš ืœื‘ื“ื•ืง ืชืคืงื™ื“ื™ื, ืื‘ืœ ื›ืคื™ ืฉื”ืชื‘ืจืจ, ืื™ืŸ ื›ืœ ื›ืš ื”ืจื‘ื” ื›ืœื™ื ืœื›ืš - ื”ืคื•ืคื•ืœืจื™ ื‘ื™ื•ืชืจ, ืื•ืœื™, ื”ื•ื ื”-Molecule framework, ืื– ื”ื—ืœื˜ื ื• ืœื”ืฉืชืžืฉ ื‘ื•. ืื‘ืœ ื”ืชื‘ืจืจ ืฉื”ืชื™ืขื•ื“ ืฉืœื• ืฉื•ืชืง ืขืœ ืžืœื›ื•ื“ื•ืช ืจื‘ื•ืช. ืœื ื”ืฆืœื—ื ื• ืœืžืฆื•ื ืžื“ืจื™ืš ืžืคื•ืจื˜ ืžืกืคื™ืง ื‘ืจื•ืกื™ืช, ืื– ื”ื—ืœื˜ื ื• ืœื›ืชื•ื‘ ืžืืžืจ ื–ื”.

ื”ื•ืจืื•ืช: ื›ื™ืฆื“ ืœื‘ื“ื•ืง ืชืคืงื™ื“ื™ื ืืคืฉืจื™ื™ื ื•ืœื‘ืจืจ ืขืœ ื‘ืขื™ื•ืช ืœืคื ื™ ื”ื™ื™ืฆื•ืจ

ืžื•ืœืงื•ืœื”

ืžื•ืœืงื•ืœื” - ืžืกื’ืจืช ืฉืชืกื™ื™ืข ื‘ื‘ื“ื™ืงืช ืชืคืงื™ื“ื™ื ืืคืฉืจื™ื™ื.

ืชื™ืื•ืจ ืคืฉื•ื˜: ื”ืžื•ืœืงื•ืœื” ื™ื•ืฆืจืช ืžื•ืคืข ื‘ืคืœื˜ืคื•ืจืžื” ืฉืฆื™ื™ื ืช (ืขื ืŸ, ืžื›ื•ื ื” ื•ื™ืจื˜ื•ืืœื™ืช, ืžื™ื›ืœ; ืœืคืจื˜ื™ื ื ื•ืกืคื™ื, ืขื™ื™ืŸ ื‘ืกืขื™ืฃ ื ื”ื’), ืžืจื™ืฅ ืืช ื”ืชืคืงื™ื“ ืฉืœืš ืขืœื™ื•, ื•ืื– ืžืคืขื™ืœ ื‘ื“ื™ืงื•ืช ื•ืžื•ื—ืง ืืช ื”ืžื•ืคืข. ื‘ืžืงืจื” ืฉืœ ื›ืฉืœ ื‘ืื—ื“ ื”ืฉืœื‘ื™ื, ื”ืžื•ืœืงื•ืœื” ืชื•ื“ื™ืข ืœืš ืขืœ ื›ืš.

ืขื›ืฉื™ื• ื‘ื™ืชืจ ืคื™ืจื•ื˜.

ืงืฆืช ืชื™ืื•ืจื™ื”

ืฉืงื•ืœ ืฉืชื™ ื™ืฉื•ื™ื•ืช ืžืคืชื— ืฉืœ ื”ืžื•ืœืงื•ืœื”: ืชืจื—ื™ืฉ ื•ื ื”ื’.

ืชึทืจื—ึดื™ืฉื

ื”ืชืกืจื™ื˜ ืžื›ื™ืœ ืชื™ืื•ืจ ืฉืœ ืžื”, ืื™ืคื”, ืื™ืš ื•ื‘ืื™ื–ื” ืจืฆืฃ ื™ื‘ื•ืฆืข. ืœืชืคืงื™ื“ ืื—ื“ ื™ื›ื•ืœื™ื ืœื”ื™ื•ืช ืžืกืคืจ ืกืงืจื™ืคื˜ื™ื, ื•ื›ืœ ืื—ื“ ืžื”ื ื”ื•ื ืกืคืจื™ื™ื” ืœืื•ืจืš ื”ื ืชื™ื‘ <role>/molecule/<scenario>, ื”ืžื›ื™ืœ ืชื™ืื•ืจื™ื ืฉืœ ื”ืคืขื•ืœื•ืช ื”ื ื“ืจืฉื•ืช ืœื‘ื“ื™ืงื”. ื™ืฉ ืœื›ืœื•ืœ ืกืงืจื™ืคื˜ default, ืฉื™ื™ื•ื•ืฆืจ ืื•ื˜ื•ืžื˜ื™ืช ืื ืืชื” ืžืืชื—ืœ ืืช ื”ืชืคืงื™ื“ ืขื ืžื•ืœืงื•ืœื”. ื”ืฉืžื•ืช ืฉืœ ื”ืชืกืจื™ื˜ื™ื ื”ื‘ืื™ื ืชืœื•ื™ื™ื ื‘ืš.

ืจืฆืฃ ืคืขื•ืœื•ืช ื”ื‘ื“ื™ืงื” ื‘ืกืงืจื™ืคื˜ ื ืงืจื ืžึทื˜ืจึดื™ืฆึธื”, ื•ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ื–ื”:

(ืฉืœื‘ื™ื ืžืกื•ืžื ื™ื ?, ื“ื™ืœื•ื’ ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ืื ืœื ืฆื•ื™ืŸ ืขืœ ื™ื“ื™ ื”ืžืฉืชืžืฉ)

  • lint - ืจื™ืฆืช linters. ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ืžืฉืžืฉื™ื yamllint ะธ flake8,
  • destroy - ืžื—ื™ืงืช ืžื•ืคืขื™ื ืžื”ื”ืฉืงื” ื”ืื—ืจื•ื ื” ืฉืœ ื”ืžื•ืœืงื•ืœื” (ืื ื™ืฉ),
  • 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. ืฆืคื• ืœืงื‘ืฆื™ื ื”ืืœื” ื”ืžื•ืœืงื•ืœื” ืชื”ื™ื” ื‘ืชื™ืงื™ื™ืช ื”ืกืงืจื™ืคื˜.

ื ื”ื’

ืžื ื”ืœ ื”ืชืงืŸ ื”ื•ื ื™ืฉื•ืช ืฉื‘ื” ื ื•ืฆืจื™ื ืžื•ืคืขื™ ื‘ื“ื™ืงื”.
ืจืฉื™ืžืช ืžื ื”ืœื™ ื”ื”ืชืงืŸ ื”ืกื˜ื ื“ืจื˜ื™ื™ื ืฉืขื‘ื•ืจื ืœืžื•ืœืงื•ืœื” ื™ืฉ ืชื‘ื ื™ื•ืช ืžื•ื›ื ื•ืช ื”ื™ื ื›ื“ืœืงืžืŸ: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

ื‘ืจื•ื‘ ื”ืžืงืจื™ื, ืชื‘ื ื™ื•ืช ื”ืŸ ืงื‘ืฆื™ื create.yml ะธ destroy.yml ื‘ืชื™ืงื™ื™ืช ื”ืกืงืจื™ืคื˜ ื”ืžืชืืจืช โ€‹โ€‹ื™ืฆื™ืจื” ื•ืžื—ื™ืงื” ืฉืœ ืžื•ืคืข, ื‘ื”ืชืืžื”.
ื™ื•ืฆืื™ ื”ื“ื•ืคืŸ ื”ื Docker ื•- Vagrant, ืฉื›ืŸ ืื™ื ื˜ืจืืงืฆื™ื•ืช ืขื ื”ืžื•ื“ื•ืœื™ื ืฉืœื”ื ื™ื›ื•ืœื•ืช ืœื”ืชืจื—ืฉ ืœืœื ื”ืงื‘ืฆื™ื ืฉื”ื•ื–ื›ืจื• ืœืขื™ืœ.

ื›ื“ืื™ ืœื”ื“ื’ื™ืฉ ืืช ืžื ื”ืœ ื”ื”ืชืงืŸ Delegated, ืฉื›ืŸ ืื ื”ื•ื ืžืฉืžืฉ ื‘ืงื‘ืฆื™ื ืœื™ืฆื™ืจื” ื•ืžื—ื™ืงื” ืฉืœ ืžื•ืคืข, ืžืชื•ืืจืช ืจืง ืขื‘ื•ื“ื” ืขื ืชืฆื•ืจืช ื”ืžื•ืคืขื™ื, ื”ืฉืืจ ืฆืจื™ืš ืœื”ื™ื•ืช ืžืชื•ืืจ ืขืœ ื™ื“ื™ ื”ืžื”ื ื“ืก.

ืžื ื”ืœ ื”ื”ืชืงืŸ ื”ืžื•ื’ื“ืจ ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ื”ื•ื Docker.

ื›ืขืช ื ืขื‘ื•ืจ ืœืชืจื’ื•ืœ ื•ื ื‘ื—ืŸ ืชื›ื•ื ื•ืช ื ื•ืกืคื•ืช ืฉื.

ืชื—ื™ืœืช ื”ืขื‘ื•ื“ื”

ื‘ืชื•ืจ "ืฉืœื•ื ืขื•ืœื", ื‘ื•ืื• ื ื‘ื“ื•ืง ืชืคืงื™ื“ ืคืฉื•ื˜ ืฉืœ ื”ืชืงื ืช nginx. ื‘ื•ื ื ื‘ื—ืจ ื‘-docer ื›ืžื ื”ืœ ื”ื”ืชืงืŸ - ืื ื™ ื—ื•ืฉื‘ ืฉืœืจื•ื‘ื›ื ื–ื” ืžื•ืชืงืŸ (ื•ื–ื›ืจื• ืฉ-docer ื”ื•ื ืžื ื”ืœ ื”ื”ืชืงืŸ ื”ืžื•ื’ื“ืจ ื›ื‘ืจื™ืจืช ืžื—ื“ืœ).

ืœื”ื›ื™ืŸ 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

ื”ืชืœื•ืช

ืกืขื™ืฃ ื–ื” ืžืชืืจ ืืช ืžืงื•ืจ ื”ืชืœื•ืช.

ืืคืฉืจื•ื™ื•ืช ืืคืฉืจื™ื•ืช: ื’ืœืงืกื™ื”, giltar, ืฆื“ืฃ.

ืžืขื˜ืคืช ื”ื™ื ืจืง ืžืขื˜ืคืช ืคืงื•ื“ื” ื”ืžืฉืžืฉืช ืœืžืงืจื” ืฉื’ืœืงืกื™ื” ื•ื’ืœืงืกื™ื” ืœื ืžื›ืกื™ื ืืช ื”ืฆืจื›ื™ื ืฉืœืš.

ืื ื™ ืœื ืืชืขื›ื‘ ื›ืืŸ ื”ืจื‘ื” ื–ืžืŸ, ื–ื” ืžืกืคื™ืง ืžืชื•ืืจ ื‘ ืชื™ืขื•ื“.

ื ื”ื’

ืฉื ื”ื ื”ื’. ืฉืœื ื• ื”ื•ื ื“ื•ืงืจ.

ืžื•ืš

ื”-linter ื”ื•ื yamllint.

ืืคืฉืจื•ื™ื•ืช ืฉื™ืžื•ืฉื™ื•ืช ื‘ื—ืœืง ื–ื” ืฉืœ ื”ืชืฆื•ืจื” ื”ืŸ ื”ื™ื›ื•ืœืช ืœืฆื™ื™ืŸ ืงื•ื‘ืฅ ืชืฆื•ืจื” ืขื‘ื•ืจ yamllint, ืžืฉืชื ื™ ืกื‘ื™ื‘ื” ืงื“ื™ืžื” ืื• ืœื”ืฉื‘ื™ืช ืืช ื”-linter:

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

ืคืœื˜ืคื•ืจืžื•ืช

ืžืชืืจ ืืช ืชืฆื•ืจืช ื”ืžื•ืคืขื™ื.
ื‘ืžืงืจื” ืฉืœ docker ื›ื ื”ื’, ื”ืžื•ืœืงื•ืœื” ืขื•ื‘ืจืช ืขืœ ืกืขื™ืฃ ื–ื”, ื•ื›ืœ ืจื›ื™ื‘ ื‘ืจืฉื™ืžื” ื–ืžื™ืŸ ื‘ Dockerfile.j2 ื‘ืชื•ืจ ืžืฉืชื ื” item.

ื‘ืžืงืจื” ืฉืœ ื ื”ื’ ืฉื“ื•ืจืฉ create.yml ะธ destroy.yml, ื”ืžื“ื•ืจ ื–ืžื™ืŸ ื‘ื”ื ื› molecule_yml.platforms, ื•ืื™ื˜ืจืฆื™ื•ืช ืขืœื™ื• ื›ื‘ืจ ืžืชื•ืืจื•ืช ื‘ืงื‘ืฆื™ื ืืœื”.

ืžื›ื™ื•ื•ืŸ ืฉื”ืžื•ืœืงื•ืœื” ืžืกืคืงืช ืฉืœื™ื˜ื” ืขืœ ืžื•ืคืขื™ื ืœืžื•ื“ื•ืœื™ื ืืคืฉืจื™ื™ื, ื™ืฉ ืœื—ืคืฉ ืฉื ื’ื ืืช ืจืฉื™ืžืช ื”ื”ื’ื“ืจื•ืช ื”ืืคืฉืจื™ื•ืช. ืขื‘ื•ืจ docker, ืœืžืฉืœ, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืžื•ื“ื•ืœ docker_container_module. ื ื™ืชืŸ ืœืžืฆื•ื ื‘ืื™ืœื• ืžื•ื“ื•ืœื™ื ืžืฉืชืžืฉื™ื ื‘ื“ืจื™ื™ื‘ืจื™ื ืื—ืจื™ื ืชื™ืขื•ื“.

ื›ืžื• ื›ืŸ ื ื™ืชืŸ ืœืžืฆื•ื ื“ื•ื’ืžืื•ืช ืœืฉื™ืžื•ืฉ ื‘ื“ืจื™ื™ื‘ืจื™ื ืฉื•ื ื™ื ื‘ื‘ื“ื™ืงื•ืช ืฉืœ ื”ืžื•ืœืงื•ืœื” ืขืฆืžื”.

ื”ื—ืœืฃ ื›ืืŸ ืกื ื˜ื•ืก: 7 ืขืœ ืื•ื‘ื•ื ื˜ื•.

ืžืกืคืง

"ืกืคืง" - ื™ืฉื•ืช ื”ืžื ื”ืœืช ืžื•ืคืขื™ื. ื‘ืžืงืจื” ืฉืœ ืžื•ืœืงื•ืœื”, ื–ื” ืืคืฉืจื™, ืชืžื™ื›ื” ื‘ืื—ืจื™ื ืœื ืžืชื•ื›ื ื ืช, ื›ืš ืฉื ื™ืชืŸ ืœืงืจื•ื ืœืกืขื™ืฃ ื–ื” ืชืฆื•ืจื” ืžื•ืจื—ื‘ืช ืžืชืื™ืžื” ืขื ืื–ื”ืจื”.
ื›ืืŸ ืืชื” ื™ื›ื•ืœ ืœืฆื™ื™ืŸ ื”ืจื‘ื” ื“ื‘ืจื™ื, ืื ื™ ืื“ื’ื™ืฉ ืืช ื”ื ืงื•ื“ื•ืช ื”ืขื™ืงืจื™ื•ืช, ืœื“ืขืชื™:

  • ืกืคืจื™ ืžืฉื—ืง: ืืชื” ื™ื›ื•ืœ ืœืฆื™ื™ืŸ ื‘ืื™ืœื• ืกืคืจื™ ืžืฉื—ืง ื™ืฉ ืœื”ืฉืชืžืฉ ื‘ืฉืœื‘ื™ื ืžืกื•ื™ืžื™ื.

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

  • ืืคืฉืจื•ื™ื•ืช: ืืคืฉืจื•ื™ื•ืช ืืคืฉืจื™ื•ืช ื•ืžืฉืชื ื™ ืกื‘ื™ื‘ื”

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

ืžืืžืช

ื”ืงืžืช ืžืกื’ืจืช ืœืžื‘ื—ื ื™ื ื•ืœื™ื™ื ื˜ืจ ืืœื™ื”. ื‘ืจื™ืจืช ื”ืžื—ื“ืœ ื”ื™ื 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.

ืžืกืงื ื”

ื›ืคื™ ืฉืืชื” ื™ื›ื•ืœ ืœืจืื•ืช, ื”ืžื•ืœืงื•ืœื” ืื™ื ื” ืžื•ืจื›ื‘ืช ื‘ืžื™ื•ื—ื“, ื•ืขืœ ื™ื“ื™ ืฉื™ืžื•ืฉ ื‘ืชื‘ื ื™ื•ืช ืžืฉืœืš, ื ื™ืชืŸ ืœืฆืžืฆื ืคืจื™ืกืช ืกืงืจื™ืคื˜ ื—ื“ืฉ ืœืขืจื™ื›ืช ืžืฉืชื ื™ื ื‘ืกืคืจื™ ื”ื”ืคืขืœื” ื•ื”ืžื—ื™ืงื” ืฉืœ ืžื•ืคืขื™ื. ื”ืžื•ืœืงื•ืœื” ืžืฉืชืœื‘ืช ื‘ืฆื•ืจื” ื—ืœืงื” ืขื ืžืขืจื›ื•ืช CI, ืžื” ืฉืžืืคืฉืจ ืœืš ืœื”ื’ื‘ื™ืจ ืืช ืžื”ื™ืจื•ืช ื”ืคื™ืชื•ื— ืขืœ ื™ื“ื™ ืฆืžืฆื•ื ื”ื–ืžืŸ ืœื‘ื“ื™ืงื” ื™ื“ื ื™ืช ืฉืœ ืกืคืจื™ ืžืฉื—ืง.

ืชื•ื“ื” ืœืš ืขืœ ืชืฉื•ืžืช ื”ืœื‘. ืื ื™ืฉ ืœืš ื ื™ืกื™ื•ืŸ ื‘ื‘ื“ื™ืงืช ืชืคืงื™ื“ื™ื ืืคืฉืจื™ื™ื, ื•ื–ื” ืœื ืงืฉื•ืจ ืœืžื•ืœืงื•ืœื”, ืกืคืจ ืœื ื• ืขืœ ื–ื” ื‘ืชื’ื•ื‘ื•ืช!

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”