αžŸαŸαž…αž€αŸ’αžαžΈαžŽαŸ‚αž“αžΆαŸ†αŸ– αžšαž”αŸ€αž”αžŸαžΆαž€αž›αŸ’αž”αž„αžαž½αž“αžΆαž‘αžΈ ANSI αž“αž·αž„αžŸαŸ’αžœαŸ‚αž„αž™αž›αŸ‹αž’αŸ†αž–αžΈαž”αž‰αŸ’αž αžΆαž˜αž»αž“αž–αŸαž›αž•αž›αž·αž

αž‡αŸ†αžšαžΆαž”αžŸαž½αžšαž˜αž“αž»αžŸαŸ’αžŸαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αž“αžΆ!

αžαŸ’αž‰αž»αŸ†αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαžœαž·αžŸαŸ’αžœαž€αžš DevOps αž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž€αž€αŸ‹αžŸαžŽαŸ’αž‹αžΆαž‚αžΆαžšαŸ” Ostrovok.ru. αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡ αžαŸ’αž‰αž»αŸ†αž…αž„αŸ‹αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαž”αž‘αž–αž·αžŸαŸ„αž’αž“αŸαžšαž”αžŸαŸ‹αž™αžΎαž„αž€αŸ’αž“αž»αž„αž€αžΆαžšαžŸαžΆαž€αž›αŸ’αž”αž„αžαž½αž“αžΆαž‘αžΈ ansible αŸ”

αž“αŸ… Ostrovok.ru αž™αžΎαž„αž”αŸ’αžšαžΎ ansible αž‡αžΆαž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αŸ” αžαŸ’αž˜αžΈαŸ—αž“αŸαŸ‡αž™αžΎαž„αž”αžΆαž“αž˜αž€αžŠαž›αŸ‹αžαž˜αŸ’αžšαžΌαžœαž€αžΆαžšαžŠαžΎαž˜αŸ’αž”αžΈαžŸαžΆαž€αž›αŸ’αž”αž„αžαž½αž“αžΆαž‘αžΈ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžŠαžΌαž…αžŠαŸ‚αž›αžœαžΆαž”αžΆαž“αž”αŸ’αžšαŸ‚αž€αŸ’αž›αžΆαž™ αž˜αž·αž“αž˜αžΆαž“αž§αž”αž€αžšαžŽαŸαž…αŸ’αžšαžΎαž“αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžšαžΏαž„αž“αŸαŸ‡αž‘αŸ - αž€αžΆαžšαž–αŸαž‰αž“αž·αž™αž˜αž”αŸ†αž•αž»αž αž”αŸ’αžšαž αŸ‚αž›αž‡αžΆ Molecule framework αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž™αžΎαž„αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαž”αŸ’αžšαžΎαžœαžΆαŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžœαžΆαž”αžΆαž“αž”αŸ’αžšαŸ‚αž€αŸ’αž›αžΆαž™αžαžΆαž―αž€αžŸαžΆαžšαžšαž”αžŸαŸ‹αž‚αžΆαžαŸ‹αž“αŸ…αžŸαŸ’αž„αŸ€αž˜αž’αŸ†αž–αžΈαž”αž‰αŸ’αž αžΆαž‡αžΆαž…αŸ’αžšαžΎαž“αŸ” αž™αžΎαž„αž˜αž·αž“αž’αžΆαž…αžŸαŸ’αžœαŸ‚αž„αžšαž€αž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†αž›αž˜αŸ’αž’αž·αžαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αž‡αžΆαž—αžΆαžŸαžΆαžšαž»αžŸαŸ’αžŸαžΈαž‘αŸ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž αžΎαž™αž”αžΆαž“αž‡αžΆαž™αžΎαž„αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαžŸαžšαžŸαŸαžšαž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αŸ”

αžŸαŸαž…αž€αŸ’αžαžΈαžŽαŸ‚αž“αžΆαŸ†αŸ– αžšαž”αŸ€αž”αžŸαžΆαž€αž›αŸ’αž”αž„αžαž½αž“αžΆαž‘αžΈ ANSI αž“αž·αž„αžŸαŸ’αžœαŸ‚αž„αž™αž›αŸ‹αž’αŸ†αž–αžΈαž”αž‰αŸ’αž αžΆαž˜αž»αž“αž–αŸαž›αž•αž›αž·αž

αž˜αŸ‰αžΌαž›αŸαž‚αž»αž›

αž˜αŸ‰αžΌαž›αŸαž‚αž»αž› - αž€αŸ’αžšαž”αžαžŽαŸ’αžŒαž˜αž½αž™αžŠαžΎαž˜αŸ’αž”αžΈαž‡αž½αž™αžŸαžΆαž€αž›αŸ’αž”αž„αžαž½αž“αžΆαž‘αžΈαžŠαŸ‚αž›αž’αžΆαž…αž’αŸ’αžœαžΎαž”αžΆαž“αŸ”

αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαžŸαžΆαž˜αž‰αŸ’αž‰αŸ– αž˜αŸ‰αžΌαž›αŸαž‚αž»αž›αž”αž„αŸ’αž€αžΎαžαž§αž‘αžΆαž αžšαžŽαŸαž“αŸ…αž›αžΎαžœαŸαž‘αž·αž€αžΆαžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αž‰αŸ’αž‡αžΆαž€αŸ‹ (αž–αž–αž€ αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αž·αž˜αŸ’αž˜αž·αž αž€αž»αž„αžαžΊαž“αŸαžš αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž›αž˜αŸ’αž’αž·αž αžŸαžΌαž˜αž˜αžΎαž›αž•αŸ’αž“αŸ‚αž€ αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αž‰αŸ’αž‡αžΆ) αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžαž½αž“αžΆαž‘αžΈαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž“αŸ…αž›αžΎαžœαžΆ αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αž αž“αž·αž„αž›αž»αž”αž§αž‘αžΆαž αžšαžŽαŸαŸ” αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž”αžšαžΆαž‡αŸαž™αž›αžΎαž‡αŸ†αž αžΆαž“αž˜αž½αž™ αž˜αŸ‰αžΌαž›αŸαž‚αž»αž›αž“αžΉαž„αž‡αžΌαž“αžŠαŸ†αžŽαžΉαž„αžŠαž›αŸ‹αž’αŸ’αž“αž€αž’αŸ†αž–αžΈαžœαžΆαŸ”

αž₯αž‘αžΌαžœαž“αŸαŸ‡αž›αž˜αŸ’αž’αž·αžαž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαŸ”

αž”αž“αŸ’αžαž·αž…αž“αŸƒαž‘αŸ’αžšαžΉαžŸαŸ’αžαžΈαž˜αž½αž™

αž–αž·αž…αžΆαžšαžŽαžΆαž’αžΆαžαž»αžŸαŸ†αžαžΆαž“αŸ‹αž–αžΈαžšαž“αŸƒαž˜αŸ‰αžΌαž›αŸαž‚αž»αž›αŸ– αžŸαŸαžŽαžΆαžšαžΈαž™αŸ‰αžΌ αž“αž·αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αž‰αŸ’αž‡αžΆαŸ”

αžŸαžΆαž…αŸ‹αžšαžΏαž„

αžŸαŸ’αž‚αŸ’αžšαžΈαž”β€‹αž˜αžΆαž“β€‹αž€αžΆαžšβ€‹αž–αž·αž–αžŽαŸŒαž“αžΆβ€‹αž’αŸ†αž–αžΈβ€‹αž’αŸ’αžœαžΈ αž€αž“αŸ’αž›αŸ‚αž„β€‹αžŽαžΆ αžšαž”αŸ€αž” αž“αž·αž„β€‹αž›αŸ†αžŠαžΆαž”αŸ‹β€‹αžŽαžΆβ€‹αžŠαŸ‚αž›β€‹αž“αžΉαž„β€‹αžαŸ’αžšαžΌαžœβ€‹αž’αž“αž»αžœαžαŸ’αžαŸ” αžαž½αž“αžΆαž‘αžΈαž˜αž½αž™αž’αžΆαž…αž˜αžΆαž“αžŸαŸ’αž‚αŸ’αžšαžΈαž”αž‡αžΆαž…αŸ’αžšαžΎαž“ αž αžΎαž™αž“αžΈαž˜αž½αž™αŸ—αž‚αžΊαž‡αžΆαžαžαž“αŸ…αžαžΆαž˜αž•αŸ’αž›αžΌαžœ <role>/molecule/<scenario>αžŠαŸ‚αž›αž˜αžΆαž“αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž’αŸ†αž–αžΈαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž€αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαŸ” αžαŸ’αžšαžΌαžœαžαŸ‚αž˜αžΆαž“αžŸαŸ’αž‚αŸ’αžšαžΈαž” defaultαžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž· αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžαž½αž“αžΆαž‘αžΈαž‡αžΆαž˜αž½αž™αž˜αŸ‰αžΌαž›αŸαž‚αž»αž›αŸ” αžˆαŸ’αž˜αŸ„αŸ‡αž“αŸƒαžŸαŸ’αž‚αŸ’αžšαžΈαž”αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž‚αžΊαž’αžΆαžŸαŸ’αžšαŸαž™αž›αžΎαž’αŸ’αž“αž€αŸ”

αž›αŸ†αžŠαžΆαž”αŸ‹αž“αŸƒαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αžŸαžΆαž€αž›αŸ’αž”αž„αž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ’αž‚αŸ’αžšαžΈαž”αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸαž αŸ…αžαžΆ αž˜αŸ‰αžΆαž‘αŸ’αžšαžΈαžŸαž αžΎαž™αžαžΆαž˜αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜αžœαžΆαž‚αžΊαŸ–

(αž‡αŸ†αž αžΆαž“αžŠαŸ‚αž›αž˜αžΆαž“αžŸαŸ’αž›αžΆαž€ ?αžšαŸ†αž›αž„αžαžΆαž˜αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αž·αž“αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αžŠαŸ„αž™αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹)

  • lint - αžšαž‘αŸαŸ‡αžšαž»αž‰αŸ” αžαžΆαž˜αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎ 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-command αž“αžΈαž˜αž½αž™αŸ—αž’αžΆαž…αž˜αžΆαž“αž›αŸ†αžŠαžΆαž”αŸ‹αž“αŸƒαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αžšαž”αžŸαŸ‹αžœαžΆ αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αžšαž€αžƒαžΎαž‰αžŠαŸ„αž™αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž· molecule matrix <command>. αž§αž‘αžΆαž αžšαžŽαŸαž“αŸ…αž–αŸαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆ converge (αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸ€αžœαž—αŸ…αž›αŸαž„αž€αŸ’αžšαŸ„αž˜αž€αžΆαžšαžŸαžΆαž€αž›αŸ’αž”αž„) αžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαŸ–

$ molecule matrix converge
...
└── default         # Π½Π°Π·Π²Π°Π½ΠΈΠ΅ сцСнария
    β”œβ”€β”€ dependency  # установка зависимостСй
    β”œβ”€β”€ create      # созданиС инстанса
    β”œβ”€β”€ prepare     # прСднастройка инстанса
    └── converge    # ΠΏΡ€ΠΎΠ³ΠΎΠ½ ΠΏΠ»Π΅ΠΉΠ±ΡƒΠΊΠ°

αž›αŸ†αžŠαžΆαž”αŸ‹αž“αŸƒαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ‚αžŸαž˜αŸ’αžšαž½αž›αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αžœαžΈαž˜αž½αž™αž–αžΈαž”αž‰αŸ’αž‡αžΈαžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαžšαž½αž…αž αžΎαž™ αžœαžΆαž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαŸ†αž›αž„αŸ” αžŸαŸ’αžαžΆαž“αž—αžΆαž–αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“ αž€αŸαžŠαžΌαž…αž‡αžΆαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž“αŸƒαžœαžαŸ’αžαž» αž˜αŸ‰αžΌαž›αŸαž‚αž»αž›αž•αŸ’αž‘αž»αž€αž“αŸ…αž€αŸ’αž“αž»αž„αžαž $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 αžŠαŸ„αž™αžŸαžΆαžšαž’αž“αŸ’αžαžšαž€αž˜αŸ’αž˜αž‡αžΆαž˜αž½αž™αž˜αŸ‰αžΌαžŒαž»αž›αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαž’αžΆαž…αž€αžΎαžαž‘αžΎαž„αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž―αž€αžŸαžΆαžšαžŠαŸ‚αž›αž”αžΆαž“αžšαŸ€αž”αžšαžΆαž”αŸ‹αžαžΆαž„αž›αžΎαŸ”

αžœαžΆαž˜αžΆαž“αžαž˜αŸ’αž›αŸƒαž€αŸ’αž“αž»αž„αž€αžΆαžšαžšαŸ†αž›αŸαž…αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αž‰αŸ’αž‡αžΆαžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‘αŸαžšαžŸαž·αž‘αŸ’αž’αž· αž–αŸ’αžšαŸ„αŸ‡αž”αŸ’αžšαžŸαž·αž“αž”αžΎαžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αž„αŸ’αž€αžΎαž αž“αž·αž„αž›αž»αž”αžœαžαŸ’αžαž»αžŽαžΆαž˜αž½αž™ αž˜αžΆαž“αžαŸ‚αž€αžΆαžšαž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž“αŸƒαžœαžαŸ’αžαž»αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆ αž“αŸ…αžŸαž›αŸ‹αž‚αž½αžšαžαŸ‚αžαŸ’αžšαžΌαžœαž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆαžŠαŸ„αž™αžœαž·αžŸαŸ’αžœαž€αžšαŸ”

αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αž‰αŸ’αž‡αžΆαž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜αž‚αžΊ 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 Molecules αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž‘αžΎαž„αž–αžΈαž«αžŸαž‚αž›αŸ‹αž“αŸƒαžαž½αž“αžΆαž‘αžΈαŸ”

αžαŸ„αŸ‡β€‹αž˜αžΎαž›β€‹αžαžΆβ€‹αžαžΎβ€‹αž˜αžΆαž“β€‹αž’αŸ’αžœαžΈβ€‹αžαŸ’αž›αŸ‡β€‹αž“αŸ…β€‹αž€αŸ’αž“αž»αž„β€‹αž”αž‰αŸ’αž‡αžΈβ€‹αžˆαŸ’αž˜αŸ„αŸ‡αŸ–

> 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 αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž‡αžΆ command shell αžŠαŸ‚αž›αž”αŸ’αžšαžΎαž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈ galaxy αž“αž·αž„ gilt αž˜αž·αž“αž‚αŸ’αžšαž”αžŠαžŽαŸ’αžαž”αŸ‹αžαž˜αŸ’αžšαžΌαžœαž€αžΆαžšαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”

αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αž˜αž·αž“αžŸαŸ’αž“αžΆαž€αŸ‹αž“αŸ…αž‘αžΈαž“αŸαŸ‡αž™αžΌαžšαž‘αŸ αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αž αžΎαž™αŸ” αž―αž€αžŸαžΆαžš.

αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αž‰αŸ’αž‡αžΆ

αžˆαŸ’αž˜αŸ„αŸ‡αž’αŸ’αž“αž€αž”αžΎαž€αž”αžšαŸ” αžšαž”αžŸαŸ‹αž™αžΎαž„αž‚αžΊ docker αŸ”

αž’αŸ’αž“αžΉαž˜

αž’αž»αž„αžŸαŸ†αžšαžΆαž˜αž‚αžΊ yamllint αŸ”

αž‡αž˜αŸ’αžšαžΎαžŸαž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸαž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€αž“αŸƒαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž“αŸαŸ‡αž‚αžΊαžŸαž˜αžαŸ’αžαž—αžΆαž–αž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ yamllint αž’αžαŸαžšαž”αžšαž·αžŸαŸ’αžαžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž”αž“αŸ’αž αž¬αž”αž·αž‘ literαŸ–

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

αžœαŸαž‘αž·αž€αžΆ

αž–αž·αž–αžŽαŸŒαž“αžΆαž’αŸ†αž–αžΈαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž“αŸƒαžœαžαŸ’αžαž»αŸ”
αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈ docker αž‡αžΆαž’αŸ’αž“αž€αž”αžΎαž€αž”αžš αž˜αŸ‰αžΌαž›αŸαž‚αž»αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž˜αŸ’αžαž„αž‘αŸ€αžαž“αŸ…αž›αžΎαž•αŸ’αž“αŸ‚αž€αž“αŸαŸ‡ αž αžΎαž™αž’αžΆαžαž»αž“αžΈαž˜αž½αž™αŸ—αž“αŸƒαž”αž‰αŸ’αž‡αžΈαž˜αžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„ Dockerfile.j2 αž‡αžΆαž’αžαŸαžš item.

αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž’αŸ’αž“αž€αž”αžΎαž€αž”αžšαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž€αžΆαžš create.yml ΠΈ destroy.yml, αž•αŸ’αž“αŸ‚αž€αž˜αžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„αž–αž½αž€αžœαžΆαž‡αžΆ molecule_yml.platformsαž αžΎαž™αž€αžΆαžšαžŸαžšαžŸαŸαžšαž‘αžΎαž„αžœαž·αž‰αž›αžΎαžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆαžšαž½αž…αž αžΎαž™αž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžšαž‘αžΆαŸ†αž„αž“αŸαŸ‡αŸ”

αžŠαŸ„αž™αžŸαžΆαžš Molecule αž•αŸ’αžαž›αŸ‹αž“αžΌαžœαž€αžΆαžšαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž“αŸƒ instances αž‘αŸ… ansible modules αž“αŸ„αŸ‡αž”αž‰αŸ’αž‡αžΈαž“αŸƒαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžŠαŸ‚αž›αž’αžΆαž…αž’αŸ’αžœαžΎαž”αžΆαž“αž€αŸαž‚αž½αžšαžαŸ‚αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž€αž˜αžΎαž›αž“αŸ…αž‘αžΈαž“αŸ„αŸ‡αž•αž„αžŠαŸ‚αžšαŸ” αž§αž‘αžΆαž αžšαžŽαŸαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ docker αž˜αŸ‰αžΌαžŒαž»αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎ docker_container_module. αž˜αŸ‰αžΌαžŒαž»αž›αžŽαžΆαž˜αž½αž™αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αž‰αŸ’αž‡αžΆαž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž’αžΆαž…αžšαž€αž”αžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„ αž―αž€αžŸαžΆαžš.

αž€αŸαžŠαžΌαž…αž‡αžΆαž§αž‘αžΆαž αžšαžŽαŸαž“αŸƒαž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αž‰αŸ’αž‡αžΆαž•αŸ’αžŸαŸαž„αŸ—αž’αžΆαž…αžšαž€αž”αžΆαž“ αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαž“αŸƒαž˜αŸ‰αžΌαž›αŸαž‚αž»αž›αžαŸ’αž›αž½αž“αž―αž„.

αž‡αŸ†αž“αž½αžŸαž“αŸ…αž‘αžΈαž“αŸαŸ‡ αž€αžŽαŸ’αžαžΆαž›αŸ– ៧ αž“αŸ…αž›αžΎ Ubuntu.

αž’αŸ’αž“αž€αž•αŸ’αžαž›αŸ‹

"αž’αŸ’αž“αž€αž•αŸ’αžαž›αŸ‹αžŸαŸαžœαžΆ" αž‚αžΊαž‡αžΆαž’αž„αŸ’αž‚αž—αžΆαž–αžŠαŸ‚αž›αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž€αžšαžŽαžΈαŸ” αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž“αŸƒαž˜αŸ‰αžΌαž›αŸαž‚αž»αž› αž“αŸαŸ‡αž‚αžΊαž˜αž·αž“αž’αžΆαž…αž‘αž‘αž½αž›αž™αž€αž”αžΆαž“ αž€αžΆαžšαž‚αžΆαŸ†αž‘αŸ’αžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αžŠαž‘αŸƒαž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸ’αžšαŸ„αž„αž‘αž»αž€αž‘αŸ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž•αŸ’αž“αŸ‚αž€αž“αŸαŸ‡αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸαž αŸ…αžαžΆ αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž”αž“αŸ’αžαŸ‚αž˜αžŠαŸ‚αž›αž’αžΆαž…αž–αž„αŸ’αžšαžΈαž€αž”αžΆαž“αŸ”
αž“αŸ…αž‘αžΈαž“αŸαŸ‡αž’αŸ’αž“αž€αž’αžΆαž…αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αžšαžΏαž„αž‡αžΆαž…αŸ’αžšαžΎαž“ αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αž‚αžΌαžŸαž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž…αŸ†αžŽαž»αž…αžŸαŸ†αžαžΆαž“αŸ‹αŸ— αžαžΆαž˜αž‚αŸ†αž“αž·αžαžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ†αŸ–

  • αžŸαŸ€αžœαž—αŸ…αž›αŸαž„αŸ– αž’αŸ’αž“αž€β€‹αž’αžΆαž…β€‹αž”αž‰αŸ’αž‡αžΆαž€αŸ‹β€‹αžαžΆβ€‹αžŸαŸ€αžœαž—αŸ…β€‹αž›αŸαž„β€‹αžŽαžΆβ€‹αžŠαŸ‚αž›β€‹αž‚αž½αžšβ€‹αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž”αŸ’αžšαžΎβ€‹αž“αŸ…β€‹αžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›β€‹αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αŸ”

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

αž€αžΆαžšαž αžαŸ‹αž“αžΏαž™αž™αžΌαžšαž“αŸ…αž€αŸ’αžšαŸ„αž˜ 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

αžαž½αž“αžΆαž‘αžΈαžŠαŸαžŸαžΆαž˜αž‰αŸ’αž‰αžšαž”αžŸαŸ‹αž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžΆαž€αž›αŸ’αž”αž„αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž”αž‰αŸ’αž αžΆαŸ”
αžœαžΆαž‚αžΊαž˜αžΆαž“αžαŸ†αž›αŸƒαž…αž„αž…αžΆαŸ†αžαžΆαž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αžΆαž“αž”αž‰αŸ’αž αžΆαž€αŸ’αž“αž»αž„αž’αŸ†αž‘αž»αž„αž–αŸαž›αž€αžΆαžšαž„αžΆαžš 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 αžŠαŸ‚αž›αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αž”αž„αŸ’αž€αžΎαž“αž›αŸ’αž”αžΏαž“αž“αŸƒαž€αžΆαžšαž’αž—αž·αžœαžŒαŸ’αžαž“αŸαžŠαŸ„αž™αž€αžΆαžαŸ‹αž”αž“αŸ’αžαž™αž–αŸαž›αžœαŸαž›αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžŸαŸ€αžœαž—αŸ…αžŽαŸ‚αž“αžΆαŸ†αžŠαŸ„αž™αžŠαŸƒαŸ”

αžŸαžΌαž˜β€‹αž’αžšαž‚αž»αžŽβ€‹αž…αŸ†αž–αŸ„αŸ‡β€‹αž€αžΆαžšβ€‹αž™αž€αž…αž·αžαŸ’αžβ€‹αž‘αž»αž€αžŠαžΆαž€αŸ‹β€‹αžšαž”αžŸαŸ‹β€‹αž›αŸ„αž€αž’αŸ’αž“αž€αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž˜αžΆαž“αž”αž‘αž–αž·αžŸαŸ„αž’αž“αŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαžŸαžΆαž€αž›αŸ’αž”αž„αžαž½αž“αžΆαž‘αžΈ ansible αž αžΎαž™αžœαžΆαž˜αž·αž“αž‘αžΆαž€αŸ‹αž‘αž„αž‘αŸ…αž“αžΉαž„αž˜αŸ‰αžΌαž›αŸαž‚αž»αž›αž‘αŸ αž”αŸ’αžšαžΆαž”αŸ‹αž™αžΎαž„αž’αŸ†αž–αžΈαžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž˜αžαž·αž™αŸ„αž”αž›αŸ‹!

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹