{"id":3280,"date":"2020-01-27T19:58:13","date_gmt":"2020-01-27T18:58:13","guid":{"rendered":"http:\/\/miro.borodziuk.eu\/?p=3280"},"modified":"2020-06-16T18:54:57","modified_gmt":"2020-06-16T16:54:57","slug":"ansible-variable-and-facts","status":"publish","type":"post","link":"http:\/\/miro.borodziuk.eu\/index.php\/2020\/01\/27\/ansible-variable-and-facts\/","title":{"rendered":"Ansible Variables"},"content":{"rendered":"<p>Ansible supports variables that can be used to store values that can be reused throughout files in an entire Ansible project. This can help simplify creation and maintenance of a project and reduce the incidence of errors.<br \/>\n<!--more--><\/p>\n<ul>\n<li>Places to define variables:\n<ul>\n<li><code>vars, vars_files<\/code>, and <code>vars_prompt<\/code><\/li>\n<li>Command line:\n<pre class=\"lang:sh decode:true\"># ansible-playbook play.yml -e'{\"myVar\":\"myValue\",\"anotherVar\":\"anotherValue\"}'<\/pre>\n<\/li>\n<li>Roles, blocks, and inventories<\/li>\n<\/ul>\n<\/li>\n<li>Essential variable use:\n<ul>\n<li><code>- debug: msg=\"Look! I'm using my variable ({ myVar )) !\"<\/code><\/li>\n<\/ul>\n<\/li>\n<li>A note on quotes:\n<ul>\n<li><code>name: \"({ package ))\"<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Scope of variables<\/span><br \/>\nVariables can be defined in a bewildering variety of places in an Ansible project. However, this can be simplified to three basic scope levels:<\/p>\n<ul>\n<li><em>Global scope<\/em>:\u00a0 Variables set from the command line or Ansible configuration<\/li>\n<li><em>Play scope<\/em>:\u00a0 Variables set in the play and related structures<\/li>\n<li><em>Host scope<\/em>:\u00a0 Variables set on host groups and individual hosts by the inventory, fact gathering, or registered tasks<br \/>\nIf the same variable name is defined at more than one level, the higher wins. So variables defined by the inventory are overridden by variables defined by the playbook, which are overridden by variables defined on the command line.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\"> Variables in playbooks<\/span><\/p>\n<p>When writing playbooks, administrators can use their own variables and call them in a task. For example, a variable <code>web_package<\/code> can be defined with a value of <code>httpd<\/code> and called by the <code>yum<\/code> module in order to install the <code>httpd<\/code> package.<\/p>\n<pre class=\"lang:sh decode:true\">- hosts: all\r\n  vars:\r\n    user: joe\r\n    home: \/home\/joe<\/pre>\n<p>It is also possible to define playbook variables in external files. In this case, instead of using vars, the <code>vars_files<\/code> directive may be used.<\/p>\n<pre class=\"lang:sh decode:true\">- hosts: all\r\n  vars_files:\r\n  - vars\/users.yml<\/pre>\n<p>The playbook variables are then defined in that file or those files in YAML format:<\/p>\n<pre class=\"lang:sh decode:true \">user: joe\r\nhome: \/home\/joe<\/pre>\n<p>Once variables have been declared, administrators can use the variables in tasks. Variables are referenced by placing the variable name in double curly braces.<\/p>\n<pre class=\"lang:sh decode:true\">vars:\r\n  user: joe\r\ntasks:\r\n# This line will read: Creates the user joe\r\n- name: Creates the user {{ user }}\r\n  user:\r\n  # This line will create the user named Joe\r\n    name: \"{{ user }}\"<\/pre>\n<p><strong><em>Important<\/em><\/strong><br \/>\nWhen a variable is used as the first element to start a value, quotes are mandatory. This prevents Ansible from considering the variable as starting a YAML dictionary. The following message appears if quotes are missing:<\/p>\n<pre class=\"lang:sh decode:true\">yum:\r\n  name: {{ service}}\r\n         ^ here\r\n\r\nWe could be wrong, but this one looks like it might be an issue with\r\nmissing quotes. Always quote template expression brackets when they\r\nstart a value. For instance:\r\n\r\nwith_items:\r\n- {{ foo }}\r\nShould be written as:\r\n\r\nwith_items:\r\n- \"{{ foo }}\"<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\"> Host variables and group variables<\/span><br \/>\nInventory variables that apply directly to hosts fall into two broad categories:<\/p>\n<ul>\n<li>host variables that apply to a specific host<\/li>\n<li>group variables that apply to all hosts in a host group or in a group of host groups.<\/li>\n<\/ul>\n<p>Host variables take precedence over group variables, but variables defined by a playbook take precedence over both. One way to define host variables and group variables is to do it directly in the inventory file. This is an older approach and not preferred, but may be encountered by users:<\/p>\n<p>\u2022 This is a host variable,<code> ansible_user<\/code>, being defined for the host demo.example.com.<\/p>\n<pre class=\"lang:sh decode:true \">[servers]\r\ndemo.example.com ansible_user=joe<\/pre>\n<p>\u2022 In this example, a group variable <code>user<\/code> is being defined for the group servers.<\/p>\n<pre class=\"lang:sh decode:true\">[servers]\r\ndemo1.example.com\r\ndemo2.example.com\r\n\r\n[servers:vars]\r\nuser=joe<\/pre>\n<p>\u2022 Finally, in this example a group variable <code>user<\/code> is being defined for the group servers, which happens to consist of two host groups each with two servers.<\/p>\n<pre class=\"lang:sh decode:true\">[servers1]\r\ndemo1.example.com\r\ndemo2.example.com\r\n\r\n[servers2]\r\ndemo3.example.com\r\ndemo4.example.com\r\n\r\n[servers:children]\r\nservers1\r\nservers2\r\n\r\n[servers:vars]\r\nuser=joe<\/pre>\n<p>Among the disadvantages of this approach, it makes the inventory file more difficult to work with, mixes information about hosts and variables in the same file, and uses an obsolete syntax.<\/p>\n<p><span style=\"color: #3366ff;\">Using group_vars and host_vars directories<\/span><br \/>\nThe preferred approach is to create two directories in the same working directory as the\u00a0 inventory file or directory,\u00a0 <code>group_vars<\/code> and <code>host_vars<\/code>. These directories contain files defining group variables and host variables, respectively.<\/p>\n<p><strong><em>Important<\/em><\/strong><br \/>\nThe recommended practice is to define inventory variables using<code> host_vars<\/code> and <code>group_vars<\/code> directories, and not to define them directly in the inventory file or files.<\/p>\n<p>To define group variables for the group servers, a YAML file named <code>group_vars\/servers<\/code> would be created, and then the contents of that file would set variables to values using the same syntax as a playbook:<\/p>\n<pre class=\"lang:sh decode:true \">user: joe<\/pre>\n<p>Likewise, to define host variables for a particular host, a file with a name matching the host is created in<code> host_vars<\/code> to contain the host variables.<\/p>\n<p>The following examples illustrate this approach in more detail. Consider the following scenario where there are two data centers to manage that has the following inventory file in<code> ~\/project\/inventory<\/code>:<\/p>\n<pre class=\"lang:sh decode:true \">[admin@station project]$ cat ~\/project\/inventory\r\n[datacenter1]\r\ndemo1.example.com\r\ndemo2.example.com\r\n[datacenter2]\r\ndemo3.example.com\r\ndemo4.example.com\r\n[datacenters:children]\r\ndatacenter1\r\ndatacenter2<\/pre>\n<p>\u2022 If a general value needs to be defined for all servers in both datacenters, a group variable can be set for datacenters:<\/p>\n<pre class=\"lang:sh decode:true \">[admin@station project]$ cat ~\/project\/group_vars\/datacenters\r\npackage: httpd<\/pre>\n<p>\u2022 If the value to define varies for each datacenter, a group variable can be set for each datacenter:<\/p>\n<pre class=\"lang:sh decode:true \">[admin@station project]$ cat ~\/project\/group_vars\/datacenter1\r\npackage: httpd\r\n[admin@station project]$ cat ~\/project\/group_vars\/datacenter2\r\npackage: apache<\/pre>\n<p>\u2022 If the value to be defined varies for each host in every datacenter, using host variables is recommended:<\/p>\n<pre class=\"lang:sh decode:true \">[admin@station project]$ cat ~\/project\/host_vars\/demo1.example.com\r\npackage: httpd\r\n[admin@station project]$ cat ~\/project\/host_vars\/demo2.example.com\r\npackage: apache\r\n[admin@station project]$ cat ~\/project\/host_vars\/demo3.example.com\r\npackage: mariadb-server\r\n[admin@station project]$ cat ~\/project\/host_vars\/demo4.example.com\r\npackage: mysql-server<\/pre>\n<p>The directory structure for project, if it contained all of the example files above, might look like this:<\/p>\n<pre class=\"lang:sh decode:true\">project\r\n\u251c\u2500\u2500 ansible.cfg\r\n\u251c\u2500\u2500 group_vars\r\n\u2502 \u251c\u2500\u2500 datacenters\r\n\u2502 \u251c\u2500\u2500 datacenters1\r\n\u2502 \u2514\u2500\u2500 datacenters2\r\n\u251c\u2500\u2500 host_vars\r\n\u2502 \u251c\u2500\u2500 demo1.example.com\r\n\u2502 \u251c\u2500\u2500 demo2.example.com\r\n\u2502 \u251c\u2500\u2500 demo3.example.com\r\n\u2502 \u2514\u2500\u2500 demo4.example.com\r\n\u251c\u2500\u2500 inventory\r\n\u2514\u2500\u2500 playbook.yml<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Overriding variables from the command line<\/span><br \/>\nInventory variables are overridden by variables set in a playbook, but both kinds of variables may be overridden through arguments passed to the ansible or ansible-playbook commands on the command line. This can be useful in a case where the defined value for a variable needs to be overridden for a single host for a one-off run of a playbook. For example:<\/p>\n<pre class=\"lang:sh decode:true\">[user@demo ~]$ ansible-playbook demo2.example.com main.yml -e \"package=apache\"<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Variables and arrays<\/span><br \/>\nInstead of assigning a piece of configuration data that relates to the same element (a list of packages, a list of services, a list of users, etc.) to multiple variables, administrators can use arrays. One interesting consequence of this is that an array can be browsed.<br \/>\nFor instance, consider the following snippet:<\/p>\n<pre class=\"lang:sh decode:true \">user1_first_name: Bob\r\nuser1_last_name: Jones\r\nuser1_home_dir: \/users\/bjones\r\nuser2_first_name: Anne\r\nuser2_last_name: Cook\r\nuser3_home_dir: \/users\/acook<\/pre>\n<p>This could be rewritten as an array called users:<\/p>\n<pre class=\"lang:sh decode:true\">users:\r\n  bjones:\r\n    first_name: Bob\r\n    last_name: Jones\r\n    home_dir: \/users\/bjones\r\n  acook:\r\n    first_name: Anne\r\n    last_name: Cook\r\n    home_dir: \/users\/acook<\/pre>\n<p>Users can then be accessed using the following variables:<\/p>\n<pre class=\"lang:sh decode:true \"># Returns 'Bob'\r\nusers.bjones.first_name\r\n# Returns '\/users\/acook'\r\nusers.acook.home_dir<\/pre>\n<p>Because the variable is defined as a Python dictionary, an alternative syntax is available.<\/p>\n<pre class=\"lang:sh decode:true \"># Returns 'Bob'\r\nusers['bjones']['first_name']\r\n# Returns '\/users\/acook'\r\nusers['acook']['home_dir']<\/pre>\n<p><em><strong>Important<\/strong><\/em><br \/>\nThe dot notation can cause problems if the key names are the same as names of Python methods or attributes, such as discard, copy, add, and so on. Using the brackets notation can help avoid errors. Both syntaxes are valid, but to make troubleshooting easier, it is recommended that one syntax used consistently in all files throughout any given Ansible project.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Registered variables<\/span><br \/>\nAdministrators can capture the output of a command by using the <code>register<\/code> statement. The output is saved into a variable that could be used later for either debugging purposes or in order to achieve something else, such as a particular configuration based on a command&#8217;s output. The following playbook demonstrates how to capture the output of a command for debugging purposes:<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Installs a package and prints the result\r\n  hosts: all\r\n    tasks:\r\n  - name: Install the package\r\n  yum:\r\n    name: httpd\r\n    state: installed\r\n    register: install_result\r\n    - debug: var=install_result<\/pre>\n<p>When the playbook is run, the debug module is used to dump the value of the <code>install_result<\/code> registered variable to the terminal.<\/p>\n<pre class=\"lang:sh decode:true \">[user@demo ~]$ ansible-playbook playbook.yml\r\nPLAY [Installs a package and prints the result] ****************************\r\nTASK [setup] ***************************************************************\r\nok: [demo.example.com]\r\nTASK [Install the package] *************************************************\r\nok: [demo.example.com]\r\nTASK [debug] ***************************************************************\r\nok: [demo.example.com] =&gt; {\r\n\"install_result\": {\r\n\"changed\": false,\r\n\"msg\": \"\",\r\n\"rc\": 0,\r\n\"results\": [\r\n\"httpd-2.4.6-40.el7.x86_64 providing httpd is already installed\"\r\n]\r\n}\r\n}\r\nPLAY RECAP *****************************************************************\r\ndemo.example.com : ok=3 changed=0 unreachable=0 failed=0<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Dictionary Variables<\/span><\/p>\n<pre class=\"lang:sh decode:true\">employee:\r\n  name: bob\r\n  id: 42<\/pre>\n<ul>\n<li>Yaml formatting allows for python style dictionaries to be used as variables<\/li>\n<li>There are two formats to access dictionary values:\n<ul>\n<li>employee[&#8216;name&#8217;]<\/li>\n<li>employee.name<\/li>\n<\/ul>\n<\/li>\n<li>The bracket syntax is safer as the dot notation can have collisions with python in certain circumstances<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Magic Variables and Filters<\/span><\/p>\n<ul>\n<li>Ansible defines several special variables knowns as magic variables<\/li>\n<li>You can use the variable <code>hostvars<\/code> to look at facts about other hosts in the inventory<\/li>\n<\/ul>\n<p><code>{{ hostvars['node1']['ansible_distribution'] }}<\/code><\/p>\n<ul>\n<li>There is also a groups variable that provides inventory information<\/li>\n<\/ul>\n<p><code>{{ groups['webservers'] }}<\/code><\/p>\n<ul>\n<li>Jinja2 filters can be useful in manipulating text format<\/li>\n<\/ul>\n<p><code>{{ groups['webservers']|join(' ') }}<\/code><\/p>\n<ul>\n<li>See<\/li>\n<\/ul>\n<p><a href=\"http:\/\/jinja.pocoo.org\/docs\/2.10\/templates\/#builtin-filters\">http:\/\/jinja.pocoo.org\/docs\/2.10\/templates\/#builtin-filters<\/a><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Example 1. of playboook with variables.<\/span><\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode playbooks]$ cat playbook9.yml\r\n---\r\n- hosts: localhost\r\n  vars:\r\n    inv_file: \/home\/miro\/ansible\/vars\/inv.txt\r\n  tasks:\r\n  - name: create file\r\n    file:\r\n      path: \"{{inv_file}}\"\r\n      state: touch\r\n  - name: generate inventory\r\n    lineinfile:\r\n      path: \"{{inv_file}}\"\r\n      line: \"{{ groups['labservers'] }}\"\r\n\r\n\r\n[miro@controlnode playbooks]$ ansible-playbook playbook9.yml\r\n\r\nPLAY [localhost] *****************************************************************************************************************\r\n\r\nTASK [Gathering Facts] ***********************************************************************************************************\r\nok: [localhost]\r\n\r\nTASK [create file] ***************************************************************************************************************\r\nchanged: [localhost]\r\n\r\nTASK [generate inventory] ********************************************************************************************************\r\nchanged: [localhost]\r\n\r\nPLAY RECAP ***********************************************************************************************************************\r\nlocalhost : ok=3 changed=2 unreachable=0 failed=0\r\n\r\n[miro@controlnode playbooks]$ cat ..\/vars\/inv.txt\r\n['managedhost1.example.com', 'managedhost2.example.com']\r\n<\/pre>\n<p>The playbook writes to the <code>inv.txt<\/code>\u00a0 list of host which belongs to the labservers groups.<\/p>\n<p>We can modificate playbook9 to use jinja filter:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ cat playbook9.yml\r\n---\r\n- hosts: localhost\r\n  vars:\r\n    inv_file: \/home\/miro\/ansible\/vars\/inv.txt\r\n  tasks:\r\n  - name: create file\r\n    file:\r\n      path: \"{{inv_file}}\"\r\n      state: touch\r\n  - name: generate inventory\r\n    lineinfile:\r\n      path: \"{{inv_file}}\"\r\n      line: \"{{ groups['labservers']|join(' ') }}\"<\/pre>\n<p>Now the the servers will be listed with spaces:<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode playbooks]$ rm ..\/vars\/inv.txt\r\n[miro@controlnode playbooks]$ ansible-playbook playbook9.yml\r\n\r\nPLAY [localhost] ***********************************************************************************************************************************\r\n\r\nTASK [Gathering Facts] *****************************************************************************************************************************\r\nok: [localhost]\r\n\r\nTASK [create file] *********************************************************************************************************************************\r\nchanged: [localhost]\r\n\r\nTASK [generate inventory] **************************************************************************************************************************\r\nchanged: [localhost]\r\n\r\nPLAY RECAP *****************************************************************************************************************************************\r\nlocalhost : ok=3 changed=2 unreachable=0 failed=0\r\n\r\n[miro@controlnode playbooks]$ cat ..\/vars\/inv.txt\r\nmanagedhost1.example.com managedhost2.example.com\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Example 2.<br \/>\n<\/span><\/p>\n<p>We have a file<code> users.lst<\/code> in the yaml format:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ cat users.lst\r\nstaff:\r\n- joe\r\n- john\r\n- bob\r\n- sam\r\n- mark\r\nfaculty:\r\n- matt\r\n- alex\r\n- frank\r\nother:\r\n- will\r\n- jack<\/pre>\n<p>The plabook below will read the yaml file and write the users to the list file:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ cat playbook10.yml\r\n---\r\n- hosts: localhost\r\n  vars:\r\n    userFile: \/home\/miro\/ansible\/vars\/list\r\n  tasks:\r\n  - name: create file\r\n    file:\r\n      path: \"{{ userFile }}\"\r\n      state: touch\r\n  - name: list users\r\n  lineinfile:\r\n    path: \"{{ userFile }}\"\r\n    line: \"{{ item }}\"\r\n  with_items:\r\n  - \"{{ staff }}\"\r\n  - \"{{ faculty }}\"\r\n  - \"{{ other }}\"\r\n<\/pre>\n<p>We run the playbook ant put the variables from file by adding -e parameter:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ ansible-playbook playbook10.yml -e \"@users.lst\"\r\n\r\nPLAY [localhost] ***********************************************************************************************************************************\r\n\r\nTASK [Gathering Facts] *****************************************************************************************************************************\r\nok: [localhost]\r\n\r\nTASK [create file] *********************************************************************************************************************************\r\nchanged: [localhost]\r\n\r\nTASK [list users] **********************************************************************************************************************************\r\nchanged: [localhost] =&gt; (item=joe)\r\nchanged: [localhost] =&gt; (item=john)\r\nchanged: [localhost] =&gt; (item=bob)\r\nchanged: [localhost] =&gt; (item=sam)\r\nchanged: [localhost] =&gt; (item=mark)\r\nchanged: [localhost] =&gt; (item=matt)\r\nchanged: [localhost] =&gt; (item=alex)\r\nchanged: [localhost] =&gt; (item=frank)\r\nchanged: [localhost] =&gt; (item=will)\r\nchanged: [localhost] =&gt; (item=jack)\r\n\r\nPLAY RECAP *****************************************************************************************************************************************\r\nlocalhost : ok=3 changed=2 unreachable=0 failed=0<\/pre>\n<p>After running the playbook10 the content of list file is:<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode playbooks]$ cat ..\/vars\/list\r\njoe\r\njohn\r\nbob\r\nsam\r\nmark\r\nmatt\r\nalex\r\nfrank\r\nwill\r\njack<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Example 3.<\/span><\/p>\n<p>In this example you will create a playbook that installs the Apache web server<br \/>\nand opens the ports for the service to be reachable. The playbook queries the web server to ensure it is up and running.<\/p>\n<pre class=\"lang:sh decode:true \">---\r\n- name: Install Apache and start the service\r\n  hosts: webserver\r\n  vars:\r\n    web_pkg: httpd\r\n    firewall_pkg: firewalld\r\n    web_service: httpd\r\n    firewall_service: firewalld\r\n    python_pkg: python-httplib2\r\n    rule: http\r\n  tasks:\r\n  - name: Install the required packages\r\n    yum:\r\n      name:\r\n        - \"{{ web_pkg }}\"\r\n        - \"{{ firewall_pkg }}\"\r\n        - \"{{ python_pkg }}\"\r\n      state: latest\r\n  - name: Start and enable the {{ firewall_service }} service\r\n    service:\r\n      name: \"{{ firewall_service }}\"\r\n      enabled: true\r\n      state: started\r\n  - name: Start and enable the {{ web_service }} service\r\n      service:\r\n        name: \"{{ web_service }}\"\r\n        enabled: true\r\n        state: started\r\n  - name: Create web content to be served\r\n      copy:\r\n        content: \"Example web content\"\r\n        dest: \/var\/www\/html\/index.html\r\n  - name: Open the port for {{ rule }}\r\n      firewalld:\r\n        service: \"{{ rule }}\"\r\n        permanent: true\r\n        immediate: true\r\n        state: enabled\r\n  - name: Verify the Apache service\r\n      hosts: localhost\r\n      tasks:\r\n        - name: Ensure the webserver is reachable\r\n          uri:\r\n            url: http:\/\/servera.lab.example.com\r\n            status_code: 200<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Example 4. &#8211; Scope of variables.<\/span><\/p>\n<p>Look at the inventory file. Notice that there are two host groups, webservers and dbservers, which are children of the larger host group servers. The servers host group has variables set the old way, directly in the inventory file, including one that sets package to httpd.<\/p>\n<pre class=\"lang:sh decode:true \">[webservers]\r\nservera.lab.example.com\r\n[dbservers]\r\nservera.lab.example.com\r\n[servers:children]\r\nwebservers\r\ndbservers\r\n[servers:vars]\r\nansible_user=devops\r\nansible_become=yes\r\npackage=httpd<\/pre>\n<p>Createing a new playbook, <code>playbook.yml<\/code>, for all hosts. Using the yum module, install the package specified by the package variable.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- hosts: all\r\n  tasks:\r\n  - name: Installs the \"{{ package }}\" package\r\n    yum:\r\n      name: \"{{ package }}\"\r\n      state: latest<\/pre>\n<p>Run the playbook using the ansible-playbook command. Watch the output as Ansible installs the httpd package.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ ansible-playbook playbook.yml\r\nPLAY ***********************************************************************\r\nTASK [setup] ***************************************************************\r\nok: [servera.lab.example.com]\r\nTASK [Installs the \"httpd\" package] ****************************************\r\nchanged: [servera.lab.example.com]\r\nPLAY RECAP *****************************************************************\r\nservera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0<\/pre>\n<p>Run an ad hoc command to ensure the httpd package has been successfully installed.<\/p>\n<pre class=\"lang:sh decode:true\">[student@workstation demo_variables-playbook]$ ansible servers \\\r\n&gt; -a 'yum list installed httpd'\r\nservera.lab.example.com | SUCCESS | rc=0 &gt;&gt;\r\nLoaded plugins: langpacks, search-disabled-repos\r\nInstalled Packages\r\nhttpd.x86_64 2.4.6-40.el7 @rhel_dvd<\/pre>\n<p>Create the <code>group_vars<\/code> directory and a new file <code>group_vars\/dbservers<\/code> to set<br \/>\nthe variable package to <code>mariadb-server<\/code> for the dbservers host group in the<br \/>\nrecommended way.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ cat group_vars\/dbservers\r\npackage: mariadb-server<\/pre>\n<p>Run the playbook again using the <code>ansible-playbook<\/code> command. Watch Ansible install the <code>mariadb-server<\/code> package. The package variable for the more specific host group dbservers took precedence over the one for its parent host group servers.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ ansible-playbook playbook.yml\r\nPLAY ***********************************************************************\r\nTASK [setup] ***************************************************************\r\nok: [servera.lab.example.com]\r\nTASK [Installs the \"mariadb-server\" package] *******************************\r\nchanged: [servera.lab.example.com]\r\nPLAY RECAP *****************************************************************\r\nservera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0<\/pre>\n<p>The output indicates the variable defined for the hosts group has been overridden.<\/p>\n<p>Run an ad hoc command to confirm the mariadb-server package has been successfully installed.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ ansible dbservers \\\r\n&gt; -a 'yum list installed mariadb-server'\r\nservera.lab.example.com | SUCCESS | rc=0 &gt;&gt;\r\nLoaded plugins: langpacks, search-disabled-repos\r\nInstalled Packages\r\nmariadb-server.x86_64 1:5.5.44-2.el7 @rhel_dvd<\/pre>\n<p>For servera.lab.example.com, set the variable package to screen.<br \/>\nDo this by creating a new directory, <code>host_vars<\/code>, and a file <code>host_vars\/<\/code><br \/>\n<code>servera.lab.example.com<\/code> that sets the variable in the recommended way.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ cat host_vars\/servera.lab.example.com\r\npackage: screen<\/pre>\n<p>Run the playbook again. Watch the output as Ansible installs the screen package. The host-specific value of the package variable overrides any value set by the host&#8217;s host groups.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ ansible-playbook playbook.yml\r\nPLAY ***********************************************************************\r\nTASK [setup] ***************************************************************\r\nok: [servera.lab.example.com]\r\nTASK [Installs the \"screen\" package] ***************************************\r\nchanged: [servera.lab.example.com]\r\nPLAY RECAP *****************************************************************\r\nservera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0<\/pre>\n<p>Run an ad hoc command to confirm the screen package has been successfully installed.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ ansible servera.lab.example.com \\\r\n&gt; -a 'yum list installed screen'\r\nservera.lab.example.com | SUCCESS | rc=0 &gt;&gt;\r\nLoaded plugins: langpacks, search-disabled-repos\r\nInstalled Packages\r\nscreen.x86_64 4.1.0-0.21.20120314git3c2946.el7 rhel_dvd<\/pre>\n<p>Run the ansible-playbook command again, this time using the <code>-e<\/code> option to override the package variable.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ ansible-playbook playbook.yml \\\r\n&gt; -e 'package=mutt'\r\nPLAY ***************************************************************************\r\nTASK [setup] *******************************************************************\r\nok: [servera.lab.example.com]\r\nTASK [Installs the \"mutt\" package] *********************************************\r\nchanged: [servera.lab.example.com]\r\nPLAY RECAP *********************************************************************\r\nservera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0<\/pre>\n<p>Run an ad hoc command to confirm the mutt package is installed.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo_variables-playbook]$ ansible all \\\r\n&gt; -a 'yum list installed mutt'\r\nservera.lab.example.com | SUCCESS | rc=0 &gt;&gt;\r\nLoaded plugins: langpacks, search-disabled-repos\r\nInstalled Packages\r\nmutt.x86_64 5:1.5.21-26.el7 @rhel_dvd<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ansible supports variables that can be used to store values that can be reused throughout files in an entire Ansible project. This can help simplify creation and maintenance of a project and reduce the incidence of errors.<\/p>\n","protected":false},"author":1,"featured_media":3281,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[86],"tags":[],"_links":{"self":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/3280"}],"collection":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/comments?post=3280"}],"version-history":[{"count":34,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/3280\/revisions"}],"predecessor-version":[{"id":3426,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/3280\/revisions\/3426"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media\/3281"}],"wp:attachment":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media?parent=3280"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/categories?post=3280"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/tags?post=3280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}