{"id":5936,"date":"2022-08-18T10:41:44","date_gmt":"2022-08-18T10:41:44","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=5936"},"modified":"2023-08-14T04:04:44","modified_gmt":"2023-08-14T04:04:44","slug":"anatomy-of-ansible-play-defined","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/anatomy-of-ansible-play-defined\/","title":{"rendered":"Ansible Tutorial: Anatomy of Ansible playbook defined!"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"538\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-350-1024x538.png\" alt=\"\" class=\"wp-image-38194\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-350-1024x538.png 1024w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-350-300x158.png 300w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-350-768x403.png 768w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-350.png 1441w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A Play performs one or more Tasks against one or more Managed Nodes.<\/li>\n\n\n\n<li>Each playbook is composed of one or more &#8216;plays&#8217; in a list.<\/li>\n\n\n\n<li>A play map a group of hosts to some well defined roles, represented by tasks.<\/li>\n\n\n\n<li>Plays run in the order specified: top to bottom.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"898\" height=\"589\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-351.png\" alt=\"\" class=\"wp-image-38196\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-351.png 898w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-351-300x197.png 300w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-351-768x504.png 768w\" sizes=\"auto, (max-width: 898px) 100vw, 898px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1021\" height=\"661\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-353.png\" alt=\"\" class=\"wp-image-38201\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-353.png 1021w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-353-300x194.png 300w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/08\/image-353-768x497.png 768w\" sizes=\"auto, (max-width: 1021px) 100vw, 1021px\" \/><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">Example\n\n---\n- name: Start the Play          <span class=\"hljs-comment\"># describes WHAT we are doing<\/span>\n- hosts: all <span class=\"hljs-comment\"># one or more group or host patterns<\/span>\n  order: sorted <span class=\"hljs-comment\"># Host order: value can be 'inventory' ie as is in the inventory file, reverse_inventory, sorted (alpha), reverse_sorted, shuffle (random)<\/span>\n  remote_user: yourname <span class=\"hljs-comment\"># or root This property was called user before Ansible 1.4<\/span>\n  become: yes <span class=\"hljs-comment\"># optional<\/span>\n  become_user: postgres <span class=\"hljs-comment\"># optional<\/span>\n  gather_facts: <span class=\"hljs-keyword\">False<\/span>\n  order: inventory <span class=\"hljs-comment\"># Default<\/span>\n  connection: local <span class=\"hljs-keyword\">or<\/span> network_cli\n  serial: <span class=\"hljs-number\">1<\/span> <span class=\"hljs-keyword\">OR<\/span> <span class=\"hljs-number\">30<\/span>%\n  max_fail_percentage\n  strategy: free\n  any_errors_fatal: <span class=\"hljs-keyword\">True<\/span>\n\nwhere:\n\n--- separates play<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>host <\/strong>defines the target machines: one or more groups or host patterns, separated by colons that should match hosts in the inventory. all is a group that means all hosts in the inventory file.<\/p>\n\n\n\n<p><strong>remote_user<\/strong>, <strong>become <\/strong>and <strong>become_user <\/strong>are connection variable<br>     remote_user defines the default logging remote user (The remote user can also be defined for a task)<\/p>\n\n\n\n<p>gather_facts defines if fact must be gathered<\/p>\n\n\n\n<p>become and become_user defines user escalation mechanism<\/p>\n\n\n\n<p>gather_facts defines if fact must be gatheredgather_facts defines if fact must be gathered<\/p>\n\n\n\n<p><strong>order <\/strong>&#8211; Control the order in which hosts are run. The default is to follow the order supplied by the inventory. Possible values for order are:<br><\/p>\n\n\n\n<p><strong>inventory<\/strong>: The default. The order is \u2018as provided\u2019 by the inventory<br> <\/p>\n\n\n\n<p><strong>reverse_inventory<\/strong>: As the name implies, this reverses the order \u2018as provided\u2019 by the inventory<br> <strong>sorted<\/strong>: Hosts are alphabetically sorted by name<br> <strong>reverse_sorted<\/strong>: Hosts are sorted by name in reverse alphabetical order<br> <strong>shuffle<\/strong>: Hosts are randomly ordered each run.<\/p>\n\n\n\n<p><strong>max_fail_percentage <\/strong>&#8211; max_fail_percentage can be used to abort the run after a given percentage of hosts has failed.<\/p>\n\n\n\n<p><strong>strategy <\/strong>&#8211; A strategy ships with Ansible &#8211; free &#8211; which allows each host to run until the end of the play as fast as it can.<\/p>\n\n\n\n<p><strong>serial <\/strong>&#8211; You can define how many hosts Ansible should manage at a single time by using the serial keyword. The serial directive can \u2018batch\u2019 this behaviour to a subset of the hosts, which then run to completion of the play before the next \u2018batch\u2019 starts. The serial keyword can also be specified as a percentage, which will be applied to the total number of hosts in a play, in order to determine the number of hosts per pass:<\/p>\n\n\n\n<p><strong>any_errors_fatal <\/strong>&#8211; With the \u2018\u2019any_errors_fatal\u2019\u2019 option, any failure on any host in a multi-host play will be treated as fatal and Ansible will exit immediately without waiting for the other hosts.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">Lets understand each piece, let\u2019s look at the overall construction of a Play.\n\n---\n- name: Start the Play          <span class=\"hljs-comment\"># describes WHAT we are doing<\/span>\n  hosts: application            <span class=\"hljs-comment\"># describes WHERE we are doing it (e.g. against all application hosts)<\/span>\n  become: <span class=\"hljs-keyword\">false<\/span>                 <span class=\"hljs-comment\"># describes HOW we are doing it (with priviledge escalation, by gather facts, serial batches, etc)<\/span>\n  gather_facts: <span class=\"hljs-keyword\">true<\/span>\n  serial: <span class=\"hljs-number\">10<\/span>\n\n  vars:\n    app_path: \/opt\/app\n\n  environment:\n    PATH: \/my\/folder:\n\n  pre_tasks:\n\n  roles:\n\n  tasks:\n\n  post_tasks:\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Playbook  &#8211; A Playbook is a file containing one or more Plays.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">--\n- name: Start the first Play    <span class=\"hljs-comment\"># describes WHAT we are doing<\/span>\n  hosts: application            <span class=\"hljs-comment\"># describes WHERE we are doing it; what target hosts<\/span>\n  become: <span class=\"hljs-keyword\">false<\/span>                 <span class=\"hljs-comment\"># describes HOW we are doing it (with priviledge escalation, by gather facts, serial batches, etc)<\/span>\n  gather_facts: <span class=\"hljs-keyword\">true<\/span>\n  serial: <span class=\"hljs-number\">10<\/span>\n\n  <span class=\"hljs-comment\"># vars, environment, pre_tasks, roles, tasks, post_tasks, etc.<\/span>\n\n- name: Start the second Play\n  hosts: webservers\n  become: <span class=\"hljs-keyword\">true<\/span>\n  gather_facts: <span class=\"hljs-keyword\">false<\/span>\n  serial: <span class=\"hljs-number\">5<\/span>\n\n  <span class=\"hljs-comment\"># vars, environment, pre_tasks, roles, tasks, post_tasks, etc.<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Role<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">role-foobar\/\n\u251c\u2500\u2500 defaults\n\u2502   \u2514\u2500\u2500 main.yml\n\u251c\u2500\u2500 vars\n\u2502   \u2514\u2500\u2500 main.yml\n\u251c\u2500\u2500 files\n|   \u2514\u2500\u2500 foobar.txt\n\u251c\u2500\u2500 handlers\n\u2502   \u2514\u2500\u2500 main.yml\n\u251c\u2500\u2500 meta\n\u2502   \u2514\u2500\u2500 main.yml\n\u251c\u2500\u2500 tasks\n\u2502   \u2514\u2500\u2500 main.yml\n\u2514\u2500\u2500 templates\n    \u2514\u2500\u2500 foobar.conf.j2<\/code><\/span><\/pre>\n\n<div class=\"epyt-gallery\" data-currpage=\"1\" id=\"epyt_gallery_89490\"><iframe loading=\"lazy\"  id=\"_ytid_70662\"  width=\"760\" height=\"427\"  data-origwidth=\"760\" data-origheight=\"427\" src=\"https:\/\/www.youtube.com\/embed\/?enablejsapi=1&#038;autoplay=0&#038;cc_load_policy=0&#038;cc_lang_pref=&#038;iv_load_policy=1&#038;loop=0&#038;rel=1&#038;fs=1&#038;playsinline=0&#038;autohide=2&#038;theme=dark&#038;color=red&#038;controls=1&#038;disablekb=0&#038;\" class=\"__youtube_prefs__  no-lazyload\" title=\"YouTube player\"  data-epytgalleryid=\"epyt_gallery_89490\"  allow=\"fullscreen; accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen data-no-lazy=\"1\" data-skipgform_ajax_framebjll=\"\"><\/iframe><div class=\"epyt-gallery-list\"><div>Sorry, there was a YouTube error.<\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>host defines the target machines: one or more groups or host patterns, separated by colons that should match hosts in the inventory. all is a group that means all hosts&#8230; <\/p>\n","protected":false},"author":1,"featured_media":5984,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[5038],"tags":[639,5196,5040],"class_list":["post-5936","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ansible","tag-ansible","tag-play","tag-playbook"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/5936","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=5936"}],"version-history":[{"count":9,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/5936\/revisions"}],"predecessor-version":[{"id":38203,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/5936\/revisions\/38203"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/5984"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=5936"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=5936"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=5936"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}