{"id":3441,"date":"2020-01-30T14:51:40","date_gmt":"2020-01-30T13:51:40","guid":{"rendered":"http:\/\/miro.borodziuk.eu\/?p=3441"},"modified":"2020-04-28T19:35:57","modified_gmt":"2020-04-28T17:35:57","slug":"ansible-managing-inclusions","status":"publish","type":"post","link":"http:\/\/miro.borodziuk.eu\/index.php\/2020\/01\/30\/ansible-managing-inclusions\/","title":{"rendered":"Ansible managing inclusions"},"content":{"rendered":"<p>When working with complex or long playbooks, administrators can use separate files to divide tasks and lists of variables into smaller pieces for easier management. There are multiple ways to include task files and variables in a playbook.<\/p>\n<p><!--more--><\/p>\n<p>\u2022 Tasks can be included in a playbook from an external file by using the <code>include<\/code> directive.<\/p>\n<pre class=\"lang:sh decode:true\">tasks:\r\n- name: Include tasks to install the database server\r\n  include: tasks\/db_server.yml<\/pre>\n<p>\u2022 The <code>include_vars<\/code> module can include variables defined in either JSON or YAML files, overriding host variables and playbook variables already defined.<\/p>\n<pre class=\"lang:sh decode:true\">tasks:\r\n- name: Include the variables from a YAML or JSON file\r\n  include_vars: vars\/variables.yml<\/pre>\n<p>Using multiple, external files for tasks and variables is a convenient way to build the main playbook in a modular way, and facilitates reuse of Ansible elements across multiple playbooks.<\/p>\n<p><span style=\"color: #3366ff;\"> Including tasks<\/span><\/p>\n<p>The include directive allows administrators to have a task file inserted at a particular point in a playbook. A task file is simply a file that contains a flat list of tasks ( <code>environment.yml<\/code>):<\/p>\n<pre class=\"lang:sh decode:true\">- name: Installs the {{ package }} package\r\n  yum:\r\n    name: \"{{ package }}\"\r\n    state: latest\r\n- name: Starts the {{ service }} service\r\n    service:\r\n      name: \"{{ service }}\"\r\n      state: \"{{ state }}\"<\/pre>\n<p>An <code>include<\/code> directive with variables could be used in a playbook, like this:<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Install, start, and enable services\r\n  hosts: all\r\n  tasks:\r\n  - name: Includes the tasks file and defines the variables\r\n    include: environment.yml\r\n    vars:\r\n      package: mariadb-server\r\n      service: mariadb\r\n      state: started\r\n      register: output\r\n - name: Debugs the included tasks\r\n   debug:\r\n     var: output<\/pre>\n<p><em><strong> Important<\/strong><\/em><br \/>\nTasks included in a playbook are evaluated based on their order in the playbook. For example, a playbook may have a task to start a service provided by a software package, and a second task included from an external file that installs that software package. The external task must be included in the playbook before the task to start the package&#8217;s service is declared in the playbook.<\/p>\n<p>For complex projects, <strong>roles<\/strong> provide a powerful way to organize included task files and playbooks.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Including variables<\/span><br \/>\nJust as tasks can be included in playbooks, variables can be externally defined and included in playbooks. There are many ways in which this can be done. Some of the ways to set variables include:<br \/>\n\u2022 Inventory variables defined in the inventory file or in external files in <code>host_vars<\/code> and <code>group_vars<\/code> directories<br \/>\n\u2022 Facts and <code>registered<\/code> variables<br \/>\n\u2022 Playbook variables defined in the playbook file with vars or in an external file through<code> vars_files<\/code><\/p>\n<p>The following YAML file, <code>variables.yml<\/code>, contains two variables<br \/>\nthat define the packages to install:<\/p>\n<pre class=\"lang:sh decode:true\">---\r\npackages:\r\n  web_package: httpd\r\n  db_package: mariadb-server<\/pre>\n<p>To import these two variables in a playbook, the <code>include_vars<\/code> module can be used:<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Install web application packages\r\n  hosts: all\r\n  tasks:\r\n  - name: Includes the tasks file and defines the variables\r\n      include_vars: variables.yml\r\n  - name: Debugs the variables imported\r\n      debug:\r\n        msg: &gt;\r\n          \"{{ packages['web_package'] }} and {{ packages.db_package }} have been imported\"<\/pre>\n<p><em><strong> Important<\/strong><\/em><br \/>\nWhen deciding where to define variables, try to keep things simple.<br \/>\nIn most cases, it is not necessary to use include_vars, host_vars and<br \/>\ngroup_vars files, playbook vars_files directives, inlined variables in playbook and inventory files, and command-line overrides all at the same time. In fact, that much complexity could make it hard to easily maintain your Ansible project.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Example 1.<\/span><\/p>\n<p>Define the <code>paths.yml<\/code> variables file and create a dictionary that sets some system paths. Specify the fileserver base path\u00a0 with the\u00a0<code> ansible_fqdn<\/code> variable and dbpath base path\u00a0 with the <code>ansible_fqdn<\/code> variable.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\npaths:\r\n  fileserver: \/home\/student\/srv\/filer\/{{ ansible_fqdn }}\r\n  dbpath: \/home\/student\/srv\/database\/{{ ansible_fqdn }}\r\n<\/pre>\n<p>Create the fileservers.yml playbook and include the paths.yml variables file. The fileserver will be created using the variable defined previously in the paths.yml variables file.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Configure fileservers\r\n  hosts: fileservers\r\n  tasks:\r\n   - name: Imports the variables file\r\n     include_vars: paths.yml\r\n   - name: Creates the remote directory\r\n     file:\r\n       path: \"{{ paths.fileserver }}\"\r\n       state: directory\r\n       mode: 0755\r\n       register: result\r\n   - name: Debugs the results\r\n     debug:\r\n       var: result<\/pre>\n<p>Run the fileservers.yml playbook and examine the output.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo-vars-inclusions]$ ansible-playbook fileservers.yml\r\nPLAY [Configure fileservers] ***********************************************\r\nTASK [setup] ***************************************************************\r\nChapter\u00a04.\u00a0Managing Variables and Inclusions\r\n144 DO407-A2.0-en-1-20160804\r\nok: [servera.lab.example.com]\r\nTASK [Imports the variables file] ******************************************\r\nok: [servera.lab.example.com]\r\nTASK [Creates the remote directory] ****************************************\r\nchanged: [servera.lab.example.com]\r\nTASK [Debugs the results] **************************************************\r\nok: [servera.lab.example.com] =&gt; {\r\n\"result\": {\r\n\"changed\": true,\r\n\"gid\": 0,\r\n\"group\": \"root\",\r\n\"mode\": \"0755\",\r\n\"owner\": \"root\",\r\n\"path\": \"\/home\/student\/srv\/filer\/servera.lab.example.com\",\r\n\"secontext\": \"unconfined_u:object_r:user_home_t:s0\",\r\n\"size\": 6,\r\n\"state\": \"directory\",\r\n\"uid\": 0\r\n}\r\n}\r\nPLAY RECAP *****************************************************************\r\nservera.lab.example.com : ok=4 changed=1 unreachable=0 failed=0<\/pre>\n<p>The output shows the directory structure that has been created by Ansible, which matches the path that has been set by the paths.fileserver variable.<\/p>\n<p>Create the <code>dbservers.yml<\/code> playbook. Include the variable file and use the <code>paths.dbpath<\/code> variable to create the directory structure.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Configure DB Servers\r\n  hosts: dbservers\r\n  tasks:\r\n  - name: Imports the variables file\r\n    include_vars: paths.yml\r\n  - name: Creates the remote directory\r\n    file:\r\n      path: \"{{ paths.dbpath }}\"\r\n      state: directory\r\n      mode: 0755\r\n      register: result\r\n  - name: Debugs the results\r\n    debug:\r\n      var: result<\/pre>\n<p>Run the <code>dbservers.yml<\/code> playbook and examine the output.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo-vars-inclusions]$ ansible-playbook dbservers.yml\r\nPLAY [Configure DB Servers] ************************************************\r\nTASK [setup] ***************************************************************\r\nok: [servera.lab.example.com]\r\nTASK [Imports the variables file] ******************************************\r\nIncluding variables\r\nDO407-A2.0-en-1-20160804 145\r\nok: [servera.lab.example.com]\r\nTASK [Creates the remote directory] ****************************************\r\nchanged: [servera.lab.example.com]\r\nTASK [Debugs the results] **************************************************\r\nok: [servera.lab.example.com] =&gt; {\r\n\"result\": {\r\n\"changed\": true,\r\n\"gid\": 0,\r\n\"group\": \"root\",\r\n\"mode\": \"0755\",\r\n\"owner\": \"root\",\r\n\"path\": \"\/home\/student\/srv\/database\/servera.lab.example.com\",\r\n\"secontext\": \"unconfined_u:object_r:user_home_t:s0\",\r\n\"size\": 6,\r\n\"state\": \"directory\",\r\n\"uid\": 0\r\n}\r\n}\r\nPLAY RECAP *****************************************************************\r\nservera.lab.example.com : ok=4 changed=1 unreachable=0 failed=0<\/pre>\n<p>Create another variable file, <code>package.yml<\/code>, and define the name of the package to install.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\npackages:\r\n  web_pkg: httpd<\/pre>\n<p>Create a task file, called <code>install_package.yml<\/code>, and create a basic task that installs a package.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Installs {{ packages.web_pkg }}\r\n  yum:\r\n    name: \"{{ packages.web_pkg }}\"\r\n    state: latest<\/pre>\n<p>Create the <code>playbook.yml<\/code> playbook. Define it for the hosts in the fileservers group. Include both variable files as well as the task file.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Install fileserver packages\r\n  hosts: fileservers\r\n  tasks:\r\n  - name: Includes the variable\r\n      include_vars: package.yml\r\n  - name: Installs the package\r\n      include: install_package.yml<\/pre>\n<p>Run the playbook and watch the output.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo-vars-inclusions]$ ansible-playbook playbook.yml\r\nPLAY [Install fileserver packages] *****************************************\r\nChapter\u00a04.\u00a0Managing Variables and Inclusions\r\n146 DO407-A2.0-en-1-20160804\r\nTASK [setup] ***************************************************************\r\nok: [servera.lab.example.com]\r\nTASK [Includes the variable] ***********************************************\r\nok: [servera.lab.example.com]\r\nTASK [Installs the package] ************************************************\r\nincluded: \/home\/student\/demo-vars-inclusions\/install_package.yml\r\nfor servera.lab.example.com\r\nTASK [Installs httpd] ******************************************************\r\nchanged: [servera.lab.example.com]\r\nPLAY RECAP *****************************************************************\r\nservera.lab.example.com : ok=4 changed=1 unreachable=0 failed=0<\/pre>\n<p>Note the httpd package has been installed from a task, whereas the name of the package to install is defined in the variables file.<\/p>\n<p>Update the <code>playbook.yml<\/code> playbook to override the name of the package to install. Append a vars block to the include statement and define a dictionary to override the name of the package to install.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Install fileserver packages\r\n  hosts: fileservers\r\n  tasks:\r\n  - name: Includes the variable\r\n      include_vars: package.yml\r\n  - name: Installs the package\r\n      include: install_package.yml\r\n  vars:\r\n    packages:\r\n      web_pkg: tomcat<\/pre>\n<p>Run the playbook and watch the output as Ansible installs the tomcat package.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation demo-vars-inclusions]$ ansible-playbook playbook.yml\r\nPLAY [Install fileserver packages] *****************************************\r\nTASK [setup] ***************************************************************\r\nok: [servera.lab.example.com]\r\nTASK [Includes the variable] ***********************************************\r\nok: [servera.lab.example.com]\r\nTASK [Installs the package] ************************************************\r\nincluded: \/home\/student\/demo-vars-inclusions\/install_package.yml\r\nfor servera.lab.example.com\r\nTASK [Installs tomcat] *****************************************************\r\nchanged: [servera.lab.example.com]\r\nPLAY RECAP *****************************************************************\r\nservera.lab.example.com : ok=4 changed=1 unreachable=0 failed=0<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Example 2.<\/span><\/p>\n<p>In the vars directory, create the <code>variables.yml<\/code> variables file. The file defines the <code>firewall_pkg<\/code> variable in YAML format. The file should read as follows:<\/p>\n<pre class=\"lang:sh decode:true \">---\r\nfirewall_pkg: firewalld<\/pre>\n<p>In the tasks directory, create the <code>environment.yml<\/code> task file. Define the two tasks that install and start the web server; use the package variable for the package name, service for the service name, and svc_state for the service state.<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Install the {{ package }} package\r\n  yum:\r\n    name: \"{{ package }}\"\r\n    state: latest\r\n- name: Start the {{ service }} service\r\n  service:\r\n    name: \"{{ service }}\"\r\n    state: \"{{ svc_state }}\"<\/pre>\n<p>Create and edit the main playbook, named playbook.yml. The playbook imports the tasks as well as the variables; and it installs the firewalld service and configures it.\u00a0 Start by adding the webserver host group. Define a rule variable with a value of http.<\/p>\n<p>Define the first task, which uses the<code> include_vars<\/code> module to import extra variables in the playbook. The variables are used by other tasks in the playbook. Include the <code>variables.yml<\/code> variable file created previously.<\/p>\n<p>Define the second task which uses the include module to include the base<br \/>\n<code>environment.yml<\/code> playbook. Because the three defined variables are used in the base playbook, but are not defined, include a vars block. Set three variables in the vars section: <code>package<\/code> set as httpd, <code>service<\/code> set as httpd, and <code>svc_state<\/code> set as started.<\/p>\n<p>Create three more tasks: one that installs the firewalld package, one that starts the firewalld service, and one that adds a rule for the HTTP service. Use the variables that were defined previously.<\/p>\n<p>Create a task that installs the <em>firewalld<\/em> package using the<code> firewall_pkg<\/code> variable. Create a task that starts the firewalld service. Create a task that adds a firewall rule for the HTTP service using the rule variable.<\/p>\n<p>Finally, add a task that creates the<code> index.html<\/code> file for the web server using the copy module. Create the file with the Ansible <code>ansible_fqdn fact<\/code>, which returns the fully qualified domain name. Also include a time stamp in the file using an Ansible fact.<\/p>\n<p>The main <code>playbook.yml<\/code> playbook appear as follows:<\/p>\n<pre class=\"lang:sh decode:true \">---\r\n- hosts: webserver\r\n  vars:\r\n    rule: http\r\n  tasks:\r\n  - name: Include the variables from the YAML file\r\n      include_vars: vars\/variables.yml\r\n  - name: Include the environment file and set the variables\r\n      include: tasks\/environment.yml\r\n  vars:\r\n    package: httpd\r\n    service: httpd\r\n    svc_state: started\r\n  - name: Install the firewall\r\n    yum:\r\n      name: \"{{ firewall_pkg }}\"\r\n      state: latest\r\n  - name: Start the firewall\r\n    service:\r\n      name: firewalld\r\n      state: started\r\n      enabled: true\r\n  - name: Open the port for {{ rule }}\r\n    firewalld:\r\n      service: \"{{ rule }}\"\r\n      immediate: true\r\n      permanent: true\r\n      state: enabled\r\n  - name: Create index.html\r\n    copy:\r\n      content: \"{{ ansible_fqdn }} has been customized using Ansible on the{{ ansible_date_time.date }}\\n\"\r\n      dest: \/var\/www\/html\/index.html<\/pre>\n<p>Run the playbook using the ansible-playbook command. Watch the output as Ansible starts by including the environment.yml playbook and running its tasks, then keeps executing the tasks defined in the main playbook.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation dev-vars-inclusions]$ ansible-playbook playbook.yml\r\nPLAY ***********************************************************************\r\nTASK [setup] ***************************************************************\r\nok: [servera.lab.example.com]\r\nTASK [Include the variables from the YAML file] ****************************\r\nok: [servera.lab.example.com]\r\nTASK [Include the environment file and set the variables] ******************\r\nincluded: \/home\/student\/dev-vars-inclusions\/tasks\/environment.yml for\r\nservera.lab.example.com\r\nTASK [Install and start the web server] ************************************\r\nchanged: [servera.lab.example.com]\r\nTASK [Start the service] ***************************************************\r\nchanged: [servera.lab.example.com]\r\nTASK [Install the firewall] ************************************************\r\nchanged: [servera.lab.example.com]\r\nTASK [Start the firewall] **************************************************\r\nchanged: [servera.lab.example.com]\r\nTASK [Open the port for http] **********************************************\r\nchanged: [servera.lab.example.com]\r\nTASK [Create index.html] ***************************************************\r\nchanged: [servera.lab.example.com]\r\nPLAY RECAP *****************************************************************\r\nservera.lab.example.com : ok=9 changed=4 unreachable=0 failed=0<\/pre>\n<p>Use curl to ensure the web server is reachable from workstation. Because the<br \/>\n<code>index.html<\/code> has been created, the output should appear as follows:<\/p>\n<pre class=\"lang:sh decode:true\">[student@workstation dev-vars-inclusions]$ curl http:\/\/servera.lab.example.com\r\nservera.lab.example.com has been customized using Ansible on the 2016-03-31<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Example 2.<\/span><\/p>\n<p>Create a facts file in INI format called custom.fact. Create a section called <code>packages<\/code> and define two facts: one called <code>db_package<\/code>, with a value of <code>mariadb-server<\/code>, and one called <code>web_package<\/code>, with a value of <code>httpd<\/code>. Create a section called services with two facts: one called <code>db_service<\/code>, with a value of <code>mariadb<\/code>, and one called <code>web_service<\/code>, with a value of <code>httpd<\/code>.<br \/>\nDefine a playbook, called setup_facts.yml, that will install the facts on serverb.<\/p>\n<p>Create the fact file <code>custom.fact<\/code>. The file should appear as follows:<\/p>\n<pre class=\"lang:sh decode:true\">[packages]\r\ndb_package = mariadb-server\r\nweb_package = httpd\r\n\r\n[services]\r\ndb_service = mariadb\r\nweb_service = httpd<\/pre>\n<p>From the project directory, create the<code> setup_facts.yml<\/code> playbook to install the facts on the managed host, serverb.lab.example.com. Use the file and copy modules to install the custom facts. The playbook should appear as follows:<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Install remote facts\r\n  hosts: lamp\r\n  vars:\r\n    remote_dir: \/etc\/ansible\/facts.d\r\n    facts_file: custom.fact\r\n  tasks:\r\n  - name: Create the remote directory\r\n    file:\r\n      state: directory\r\n      recurse: yes\r\n      path: \"{{ remote_dir }}\"\r\n  - name: Install the new facts\r\n    copy:\r\n      src: \"{{ facts_file }}\"\r\n      dest: \"{{ remote_dir }}\"<\/pre>\n<p>Run the playbook to install the custom facts and verify the facts are available as Ansible facts.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation lab-managing-vars]$ ansible-playbook setup_facts.yml\r\nPLAY [Install remote facts] ************************************************\r\nTASK [setup] ***************************************************************\r\nchanged: [serverb.lab.example.com]\r\nTASK [Create the remote directory] *****************************************\r\nok: [serverb.lab.example.com]\r\nTASK [Install the new facts] ***********************************************\r\nchanged: [serverb.lab.example.com]\r\nPLAY RECAP *****************************************************************\r\nserverb.lab.example.com : ok=3 changed=2 unreachable=0 failed=0<\/pre>\n<p>Ensure the newly created facts can be retrieved.<\/p>\n<pre class=\"lang:sh decode:true\">[student@workstation lab-managing-vars]$ ansible lamp -m setup -a\r\n'filter=ansible_local*'\r\nserverb.lab.example.com | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_local\": {\r\n\"custom\": {\r\n\"packages\": {\r\n\"db_package\": \"mariadb-server\",\r\n\"web_package\": \"httpd\"\r\n},\r\n\"services\": {\r\n\"db_service\": \"mariadb\",\r\n\"web_service\": \"httpd\"\r\n}\r\n}\r\n}\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>Create a directory for variables, called vars. Define a YAML variable file, called main.yml, in that directory that defines a new variable, called web_root, with a value of \/var\/www\/html.<\/p>\n<p>Create the variables directory, vars, inside the project directory.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation lab-managing-vars]$ mkdir vars<\/pre>\n<p>Create the variables file <code>vars\/main.yml<\/code>. The file should contain the following content:<\/p>\n<pre class=\"lang:sh decode:true \">---\r\nweb_root: \/var\/www\/html<\/pre>\n<p>From the project directory, lab-managing-vars, create a directory for tasks, called tasks. Define a task file in the subdirectory, called <code>main.yml<\/code>, that instructs Ansible to install both the web server package and the database package using facts Ansible gathered from serverb.lab.example.com. When they are installed, start the two services.<\/p>\n<p>Create the tasks directory inside the project directory.<\/p>\n<pre class=\"lang:sh decode:true\">[student@workstation lab-managing-vars]$ mkdir tasks<\/pre>\n<p>Create the tasks file,<code> tasks\/main.yml<\/code>. The tasks should install both the database and the web server, and start the services <em>httpd<\/em> and <em>mariadb<\/em>. Use the custom Ansible facts for the name of the services to manage. The file should appear as follows:<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- name: Install and start the database and web servers\r\n  yum:\r\n    name:\r\n      - \"{{ ansible_local.custom.packages.db_package }}\"\r\n      - \"{{ ansible_local.custom.packages.web_package }}\"\r\n    state: latest\r\n- name: Start the database service\r\n  service:\r\n    name: \"{{ ansible_local.custom.services.db_service }}\"\r\n    state: started\r\n    enabled: true\r\n- name: Start the web service\r\n  service:\r\n    name: \"{{ ansible_local.custom.services.web_service }}\"\r\n    state: started\r\n    enabled: true<\/pre>\n<p>Create the main playbook <code>playbook.yml<\/code> in the top-level directory for this lab. The playbook should be in the following order: target the lamp hosts groups and define a new variable, firewall with a value of firewalld.<br \/>\nCreate the following tasks:<br \/>\n\u2022 A task that includes the variable file<code> main.yml<\/code>.<br \/>\n\u2022 A task that includes the tasks defined in the tasks file.<br \/>\n\u2022 A task for installing the latest version of the firewall package.<br \/>\n\u2022 A task for for starting the firewall service.<br \/>\n\u2022 A task for opening TCP port 80 permanently.<br \/>\n\u2022 A task that uses the copy module to create the<code> index.html<\/code> page in the directory the variable defines.<br \/>\nThe index.html should appear as follows:<\/p>\n<pre class=\"lang:sh decode:true \">serverb.lab.example.com (172.25.250.11) has been customized by Ansible<\/pre>\n<p>Both the host name and the IP address should use Ansible facts.<\/p>\n<p>When complete, the tree should appear as follows:<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation lab-managing-vars]$ tree\r\n.\r\n\u251c\u2500\u2500 ansible.cfg\r\n\u251c\u2500\u2500 custom.fact\r\n\u251c\u2500\u2500 inventory\r\n\u251c\u2500\u2500 playbook.yml\r\n\u251c\u2500\u2500 setup_facts.yml\r\n\u251c\u2500\u2500 tasks\r\n\u2502 \u2514\u2500\u2500 main.yml\r\n\u2514\u2500\u2500 vars\r\n\u2514\u2500\u2500 main.yml\r\n2 directories, 7 files<\/pre>\n<p>The main playbook should appear as follows:<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- hosts: lamp\r\n  vars:\r\n    firewall: firewalld\r\n  tasks:\r\n  - name: Include the variable file\r\n    include_vars: vars\/main.yml\r\n  - name: Include the tasks\r\n    include: tasks\/main.yml\r\n  - name: Install the firewall\r\n    yum:\r\n      name: \"{{ firewall }}\"\r\n      state: latest\r\n  - name: Start the firewall\r\n    service:\r\n      name: \"{{ firewall }}\"\r\n      state: started\r\n      enabled: true\r\n  - name: Open the port for the web server\r\n    firewalld:\r\n      service: http\r\n      state: enabled\r\n      immediate: true\r\n      permanent: true\r\n  - name: Create index.html\r\n    copy:\r\n      content: \"{{ ansible_fqdn }}({{ ansible_default_ipv4.address }}) has been customized by Ansible\\n\"\r\n      dest: \"{{ web_root }}\/index.html\"<\/pre>\n<p>Explanation:<\/p>\n<p>First task includes the variables file located under vars\/main.yml. Second task imports the tasks file located under tasks\/main.yml. Next tasks that install the firewall, start the service, open port 80, and reload the service. Finally, create the task that uses the copy module to create a custom main page, index.html. Use the variable <code>web_root<\/code>, defined in the variables file, for the home directory of the web server.<\/p>\n<p>Run the playbook<code> playbook.yml<\/code> created in the previous step.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation lab-managing-vars]$ ansible-playbook playbook.yml\r\nPLAY ***********************************************************************\r\n... Output omitted ...\r\nPLAY RECAP *****************************************************************\r\nserverb.lab.example.com : ok=10 changed=5 unreachable=0 failed=0\r\n<\/pre>\n<p>From workstation, use curl to ensure the web server is reachable.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation lab-managing-vars]$ curl http:\/\/serverb\r\nserverb.lab.example.com(172.25.250.11) has been customized by Ansible<\/pre>\n<p>Also use an ad hoc command to connect to serverb as the devops user and ensure the mariadb service is running.<\/p>\n<pre class=\"lang:sh decode:true \">[student@workstation lab-managing-vars]$ ansible lamp -a 'systemctl status\r\nmariadb'\r\nserverb.lab.example.com | SUCCESS | rc=0 &gt;&gt;\r\n\u25cf mariadb.service - MariaDB database server\r\nLoaded: loaded (\/usr\/lib\/systemd\/system\/mariadb.service; disabled; vendor\r\npreset: disabled)\r\nActive: active (running) since Fri 2016-04-01 10:50:40 PDT; 7min ago\r\n... Output omitted ...<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When working with complex or long playbooks, administrators can use separate files to divide tasks and lists of variables into smaller pieces for easier management. There are multiple ways to include task files and variables in a playbook.<\/p>\n","protected":false},"author":1,"featured_media":3446,"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\/3441"}],"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=3441"}],"version-history":[{"count":13,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/3441\/revisions"}],"predecessor-version":[{"id":3456,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/3441\/revisions\/3456"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media\/3446"}],"wp:attachment":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media?parent=3441"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/categories?post=3441"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/tags?post=3441"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}