Getting Started With Ansible - Part Four

In this article, we will be learning how to create a local config file, how to get started with playbook, and how to work with Ansible setup module.

This is in continuation of the articles of the series “Learning Ansible”. So, in this article, we will be doing lots of things; be patient and keep learning.
 
The list of topics which we will be covering is as below.
  • How to create your own local ansible config file. 
  • Playbook Introduction and writing your first playbook. 
  • Ansible setup module and fact variables.
So, let’s get started quickly.
 

How to create your own local Ansible config file

 
In the previous article Getting started with Ansible – Part 3, we have learned about the Ansible configuration. So here, we are going to see how you can set up your own local Ansible config. This local config should be present in the same directory where our inventory file is present.
 
Let’s create local config with the below command.
 
vim ansible.cfg
 
Now, add the below configuration which is similar to what we saw in the global Ansible configuration file previously.
  1. [defaults]  
  2. host_key_checking = False  
  3. inventory = invent  
  4. timeout = 15  
  5. log_path = /var/log/ansible.log  
  6.   
  7. [privilege_escalation]  
  8. become = True  
  9. become_method = sudo  
  10. become_user = root  
  11. become_ask_pass = False  
Note
Here, we have renamed our inventory file from inventory to invent using the below command.
  1. mv inventory invent  
Now, as we have given log_path for the Ansible log but we don’t have that file created.
 
So, we are going to create the Ansible.log file and will change the ownership for Ubuntu user with the below commands, so that the logs can be added to this file.
  1. sudo touch /var/log/ansible.log  
  2. sudo chown ubuntu:ubuntu /var/log/ansible.log  
TIP
 
As we have defined the inventory file inside the local Ansible config, so now we can execute ping on all the servers without giving the inventory path as opposed to earlier when we had to pass the inventory file.
 
So, the shortened new command will look like below.
  1. ansible -m ping all  
OUTPUT
 
Ansible
 
We can see that ping has executed successfully on all servers. Now, let’s do one more thing and install one more service called NTP on all servers using Ansible package module.
 
The below command will install NTP service on all the servers without giving –become command as we have defined all this configuration in our local ansible.config.
  1. ansible -m package -a "name=ntp state=present" all  
Great! So, by now, we have seen how we can define the configurations locally and run the Ansible modules with ease.
 
As we have created a log file, we can also see the log file using the below command to check if logs have been generated or not.
  1. cat /var/log/ansible.log  
OUTPUT
 
Ansible
 
We can see that logs are being registered properly inside the log file, i.e., we are good.
 
As everyone wants to simplify their work as much as possible, so with Ansible, we have something called Playbooks. So, let’s see what they are.
 

Introduction to Playbook and writing your first Playbook

 
Playbooks are the files where the Ansible code is written. Playbooks are written in YAML format. YAML stands for Yet Another Markup Language. Playbooks are one of the core features of Ansible and tell Ansible what to execute. They are like a to-do list for Ansible that contains a list of tasks.
 
Playbooks are a completely different way to use Ansible than in ad-hoc task execution mode and thus are particularly powerful.
 
That was enough for the introduction, let’s do some practical stuff and write our first Playbook.
 
Under our project named “superman”, I have created a folder named playbook exercise and we are going to create a file named web.yml which is the name of the playbook with the below command.
  1. vim web.yml  
Then add the below code inside web.yml file. (yml is the extension for YAML file)
  1. -- - -hosts: WebServersGroup  
  2. become: yes  
  3. tasks: -name: Install httpd service  
  4. yum: name: httpd  
  5. state: present - name: Start and Enable httpd service  
  6. service: name: httpd  
  7. state: started  
  8. enabled: yes  

Let’s understand what it is doing

 
So above in this playbook we have one play (play starts with -hosts). This is going to install apache service on all the webservers as we have given the web servers group in hosts and then will start and enable the service on all web servers. So it contains 2 tasks. 
  • Playbooks are pretty much self-explanatory.
  • To execute playbook, we use the below command  
  1. ansible-playbook web.yml  
OUTPUT
 
Ansible
 
We can see from the output that service has been installed on web server 01 and 02 but failed in webserver 03.
 
NOTE
Package could not be installed on web server 03 as web server 03 is an Ubuntu machine. Also, the package name is different for Ubuntu its apache2 not httpd. Ubuntu doesn’t have yum package as well, so we have to identify the type of OS and then take the decision accordingly.
 
Now to take a decision, we have something called Fact Variables. So, Let’s understand them now.
 

Ansible setup module and fact variables

 
In the above screenshot, we can see the default task is being executed for all the web servers and that task is called Gathering Facts.
 
Gathering facts is a default task and it generates fact variables. Before ansible executes any task on the target machine it executes a module called setup module and this module collects all information about the target machine.
 
We can also run the setup module directly on any server. Suppose for web server 01 we can run the setup module with the below command,
  1. ansible -m setup websrv01  
OUTPUT
  1. websrv01 | SUCCESS => {  
  2.     "ansible_facts": {  
  3.         "ansible_all_ipv4_addresses": ["172.31.4.33"],  
  4.         "ansible_all_ipv6_addresses": ["fe80::4a3:7ff:fe92:2f07"],  
  5.         "ansible_apparmor": {  
  6.             "status""disabled"  
  7.         },  
  8.         "ansible_architecture""x86_64",  
  9.         "ansible_bios_date""08/24/2006",  
  10.         "ansible_bios_version""4.2.amazon",  
  11.         "ansible_cmdline": {  
  12.             "BOOT_IMAGE""/boot/vmlinuz-3.10.0-957.1.3.el7.x86_64",  
  13.             "LANG""en_US.UTF-8",  
  14.             "console""ttyS0,115200",  
  15.             "crashkernel""auto",  
  16.             "ro"true,  
  17.             "root""UUID=f41e390f-835b-4223-a9bb-9b45984ddf8d"  
  18.         },  
  19.         "ansible_date_time": {  
  20.             "date""2019-08-13",  
  21.             "day""13",  
  22.             "epoch""1565705464",  
  23.             "hour""14",  
  24.             "iso8601""2019-08-13T14:11:04Z",  
  25.             "iso8601_basic""20190813T141104765176",  
  26.             "iso8601_basic_short""20190813T141104",  
  27.             "iso8601_micro""2019-08-13T14:11:04.765269Z",  
  28.             "minute""11",  
  29.             "month""08",  
  30.             "second""04",  
  31.             "time""14:11:04",  
  32.             "tz""UTC",  
  33.             "tz_offset""+0000",  
  34.             "weekday""Tuesday",  
  35.             "weekday_number""2",  
  36.             "weeknumber""32",  
  37.             "year""2019"  
  38.         },  
  39.         "ansible_default_ipv4": {  
  40.             "address""172.31.4.33",  
  41.             "alias""eth0",  
  42.             "broadcast""172.31.15.255",  
  43.             "gateway""172.31.0.1",  
  44.             "interface""eth0",  
  45.             "macaddress""06:a3:07:92:2f:07",  
  46.             "mtu": 9001,  
  47.             "netmask""255.255.240.0",  
  48.             "network""172.31.0.0",  
  49.             "type""ether"  
  50.         },  
  51.         "ansible_default_ipv6": {},  
  52.         "ansible_device_links": {  
  53.             "ids": {},  
  54.             "labels": {},  
  55.             "masters": {},  
  56.             "uuids": {  
  57.                 "xvda1": ["f41e390f-835b-4223-a9bb-9b45984ddf8d"]  
  58.             }  
  59.         },  
  60.         "ansible_devices": {  
  61.             "xvda": {  
  62.                 "holders": [],  
  63.                 "host""",  
  64.                 "links": {  
  65.                     "ids": [],  
  66.                     "labels": [],  
  67.                     "masters": [],  
  68.                     "uuids": []  
  69.                 },  
  70.                 "model"null,  
  71.                 "partitions": {  
  72.                     "xvda1": {  
  73.                         "holders": [],  
  74.                         "links": {  
  75.                             "ids": [],  
  76.                             "labels": [],  
  77.                             "masters": [],  
  78.                             "uuids": ["f41e390f-835b-4223-a9bb-9b45984ddf8d"]  
  79.                         },  
  80.                         "sectors""16775168",  
  81.                         "sectorsize": 512,  
  82.                         "size""8.00 GB",  
  83.                         "start""2048",  
  84.                         "uuid""f41e390f-835b-4223-a9bb-9b45984ddf8d"  
  85.                     }  
  86.                 },  
  87.                 "removable""0",  
  88.                 "rotational""0",  
  89.                 "sas_address"null,  
  90.                 "sas_device_handle"null,  
  91.                 "scheduler_mode""deadline",  
  92.                 "sectors""16777216",  
  93.                 "sectorsize""512",  
  94.                 "size""8.00 GB",  
  95.                 "support_discard""0",  
  96.                 "vendor"null,  
  97.                 "virtual": 1  
  98.             }  
  99.         },  
  100.         "ansible_distribution""CentOS",  
  101.         "ansible_distribution_file_parsed"true,  
  102.         "ansible_distribution_file_path""/etc/redhat-release",  
  103.         "ansible_distribution_file_variety""RedHat",  
  104.         "ansible_distribution_major_version""7",  
  105.         "ansible_distribution_release""Core",  
  106.         "ansible_distribution_version""7.6",  
  107.         "ansible_dns": {  
  108.             "nameservers": ["172.31.0.2"],  
  109.             "search": ["us-west-1.compute.internal"]  
  110.         },  
  111.         "ansible_domain""us-west-1.compute.internal",  
  112.         "ansible_effective_group_id": 0,  
  113.         "ansible_effective_user_id": 0,  
  114.         "ansible_env": {  
  115.             "HOME""/root",  
  116.             "LANG""C",  
  117.             "LC_ALL""C",  
  118.             "LC_MESSAGES""C",  
  119.             "LOGNAME""root",  
  120.             "LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:s    
  121.             g = 30;43: ca = 30;41: tw = 30;42: ow = 34;42: st = 37;44: ex = 01;32: * .tar = 01;31: * .tgz = 01;31: * .arc = 01;31: * .arj = 01;31: * .taz = 01;31: * .lha = 01;31: * .lz4 = 01;31: * .lzh = 01;31: * .lzma = 01;31: * .tlz = 01;31: * .txz = 01;31: * .tzo = 01;31: * .t7z = 01;31: * .zip = 01;31: * .z = 01;31: * .Z = 01;31: * .dz = 01;31: * .gz = 01;31: * .lrz = 01;31: * .lz = 01;31: * .lzo = 01;31: * .xz = 01;31: * .bz2 = 01;31: * .bz = 01;31: * .tbz = 01;31: * .tbz2 = 01;31: * .tz = 01;31: * .deb = 01;31: * .rpm = 01;31: * .jar = 01;31: * .war = 01;31: * .ear = 01;31: * .sar = 01;31: * .rar = 01;31: * .alz = 01;31: * .ace = 01;31: * .zoo = 01;31: * .cpio = 01;31: * .7 z = 01;31: * .rz = 01;31: * .cab = 01;31: * .jpg = 01;35: * .jpeg = 01;35: * .gif = 01;35: * .bmp = 01;35: * .pbm = 01;35: * .pgm = 01;35: * .ppm = 01;35: * .tga = 01;35: * .xbm = 01;35: * .xpm = 01;35: * .tif = 01;35: * .tiff = 01;35: * .png = 01;35: * .svg = 01;35: * .svgz = 01;35: * .mng = 01;35: * .pcx = 01;35: * .mov = 01;35: * .mpg = 01;35: * .mpeg = 01;35: * .m2v = 01;35: * .mkv = 01;35: * .webm = 01;35: * .ogm = 01;35: * .mp4 = 01;35: * .m4v = 01;35: * .mp4  
  122.             v = 01;35: * .vob = 01;35: * .qt = 01;35: * .nuv = 01;35: * .wmv = 01;35: * .asf = 01;35: * .rm = 01;35: * .rmvb = 01;35: * .flc = 01;35: * .avi = 01;35: * .fli = 01;35: * .flv = 01;35: * .gl = 01;35: * .dl = 01;35: * .xcf = 01;35: * .xwd = 01;35: * .yuv = 01;35: * .cgm = 01;35: * .emf = 01;35: * .axv = 01;35: * .anx = 01;35: * .ogv = 01;35: * .ogx = 01;35: * .aac = 01;36: * .au = 01;36: * .flac = 01;36: * .mid = 01;36: * .midi = 01;36: * .mka = 01;36: * .mp3 = 01;36: * .mpc = 01;36: * .ogg = 01;36: * .ra = 01;36: * .wav = 01;36: * .axa = 01;36: * .oga = 01;36: * .sp  
  123.             x = 01;36: * .xspf = 01;36: ",                                                                                                                            
  124.             "MAIL""/var/mail/devops",  
  125.             "PATH""/sbin:/bin:/usr/sbin:/usr/bin",  
  126.             "PWD""/home/devops",  
  127.             "SHELL""/bin/bash",  
  128.             "SHLVL""1",  
  129.             "SUDO_COMMAND": "/bin/sh -c echo BECOME-SUCCESS-uofgmphmzzbaydzazomtycditqzzedpj ; /usr/bin/python /home/devops/.ansible/tmp/ansibl    
  130.             e - tmp - 1565705463.54 - 247967255799117 / AnsiballZ_setup.py ",                                                                                           
  131.             "SUDO_GID""1001",  
  132.             "SUDO_UID""1001",  
  133.             "SUDO_USER""devops",  
  134.             "TERM""xterm",  
  135.             "USER""root",  
  136.             "USERNAME""root",  
  137.             "XDG_SESSION_ID""10",  
  138.             "_""/usr/bin/python"  
  139.         },  
  140.         "ansible_eth0": {  
  141.             "active"true,  
  142.             "device""eth0",  
  143.             "features": {  
  144.                 "busy_poll""off [fixed]",  
  145.                 "fcoe_mtu""off [fixed]",  
  146.                 "generic_receive_offload""on",  
  147.                 "generic_segmentation_offload""on",  
  148.                 "highdma""off [fixed]",  
  149.                 "hw_tc_offload""off [fixed]",  
  150.                 "l2_fwd_offload""off [fixed]",  
  151.                 "large_receive_offload""off [fixed]",  
  152.                 "loopback""off [fixed]",  
  153.                 "netns_local""off [fixed]",  
  154.                 "ntuple_filters""off [fixed]",  
  155.                 "receive_hashing""off [fixed]",  
  156.                 "rx_all""off [fixed]",  
  157.                 "rx_checksumming""on [fixed]",  
  158.                 "rx_fcs""off [fixed]",  
  159.                 "rx_gro_hw""off [fixed]",  
  160.                 "rx_udp_tunnel_port_offload""off [fixed]",  
  161.                 "rx_vlan_filter""off [fixed]",  
  162.                 "rx_vlan_offload""off [fixed]",  
  163.                 "rx_vlan_stag_filter""off [fixed]",  
  164.                 "rx_vlan_stag_hw_parse""off [fixed]",  
  165.                 "scatter_gather""on",  
  166.                 "tcp_segmentation_offload""on",  
  167.                 "tx_checksum_fcoe_crc""off [fixed]",  
  168.                 "tx_checksum_ip_generic""off [fixed]",  
  169.                 "tx_checksum_ipv4""on [fixed]",  
  170.                 "tx_checksum_ipv6""off [requested on]",  
  171.                 "tx_checksum_sctp""off [fixed]",  
  172.                 "tx_checksumming""on",  
  173.                 "tx_fcoe_segmentation""off [fixed]",  
  174.                 "tx_gre_csum_segmentation""off [fixed]",  
  175.                 "tx_gre_segmentation""off [fixed]",  
  176.                 "tx_gso_partial""off [fixed]",  
  177.                 "tx_gso_robust""on [fixed]",  
  178.                 "tx_ipip_segmentation""off [fixed]",  
  179.                 "tx_lockless""off [fixed]",  
  180.                 "tx_nocache_copy""off",  
  181.                 "tx_scatter_gather""on",  
  182.                 "tx_scatter_gather_fraglist""off [fixed]",  
  183.                 "tx_sctp_segmentation""off [fixed]",  
  184.                 "tx_sit_segmentation""off [fixed]",  
  185.                 "tx_tcp6_segmentation""off [requested on]",  
  186.                 "tx_tcp_ecn_segmentation""off [fixed]",  
  187.                 "tx_tcp_mangleid_segmentation""off",  
  188.                 "tx_tcp_segmentation""on",  
  189.                 "tx_udp_tnl_csum_segmentation""off [fixed]",  
  190.                 "tx_udp_tnl_segmentation""off [fixed]",  
  191.                 "tx_vlan_offload""off [fixed]",  
  192.                 "tx_vlan_stag_hw_insert""off [fixed]",  
  193.                 "udp_fragmentation_offload""off [fixed]",  
  194.                 "vlan_challenged""off [fixed]"  
  195.             },  
  196.             "hw_timestamp_filters": [],  
  197.             "ipv4": {  
  198.                 "address""172.31.4.33",  
  199.                 "broadcast""172.31.15.255",  
  200.                 "netmask""255.255.240.0",  
  201.                 "network""172.31.0.0"  
  202.             },  
  203.             "ipv6": [{  
  204.                 "address""fe80::4a3:7ff:fe92:2f07",  
  205.                 "prefix""64",  
  206.                 "scope""link"  
  207.             }],  
  208.             "macaddress""06:a3:07:92:2f:07",  
  209.             "module""xen_netfront",  
  210.             "mtu": 9001,  
  211.             "pciid""vif-0",  
  212.             "promisc"false,  
  213.             "timestamping": ["rx_software""software"],  
  214.             "type""ether"  
  215.         },  
  216.         "ansible_fibre_channel_wwn": [],  
  217.         "ansible_fips"false,  
  218.         "ansible_form_factor""Other",  
  219.         "ansible_fqdn""ip-172-31-4-33.us-west-1.compute.internal",  
  220.         "ansible_hostname""ip-172-31-4-33",  
  221.         "ansible_hostnqn""",  
  222.         "ansible_interfaces": ["lo""eth0"],  
  223.         "ansible_is_chroot"false,  
  224.         "ansible_iscsi_iqn""",  
  225.         "ansible_kernel""3.10.0-957.1.3.el7.x86_64",  
  226.         "ansible_lo": {  
  227.             "active"true,  
  228.             "device""lo",  
  229.             "features": {  
  230.                 "busy_poll""off [fixed]",  
  231.                 "fcoe_mtu""off [fixed]",  
  232.                 "generic_receive_offload""on",  
  233.                 "generic_segmentation_offload""on",  
  234.                 "highdma""on [fixed]",  
  235.                 "hw_tc_offload""off [fixed]",  
  236.                 "l2_fwd_offload""off [fixed]",  
  237.                 "large_receive_offload""off [fixed]",  
  238.                 "loopback""on [fixed]",  
  239.                 "netns_local""on [fixed]",  
  240.                 "ntuple_filters""off [fixed]",  
  241.                 "receive_hashing""off [fixed]",  
  242.                 "rx_all""off [fixed]",  
  243.                 "rx_checksumming""on [fixed]",  
  244.                 "rx_fcs""off [fixed]",  
  245.                 "rx_gro_hw""off [fixed]",  
  246.                 "rx_udp_tunnel_port_offload""off [fixed]",  
  247.                 "rx_vlan_filter""off [fixed]",  
  248.                 "rx_vlan_offload""off [fixed]",  
  249.                 "rx_vlan_stag_filter""off [fixed]",  
  250.                 "rx_vlan_stag_hw_parse""off [fixed]",  
  251.                 "scatter_gather""on",  
  252.                 "tcp_segmentation_offload""on",  
  253.                 "tx_checksum_fcoe_crc""off [fixed]",  
  254.                 "tx_checksum_ip_generic""on [fixed]",  
  255.                 "tx_checksum_ipv4""off [fixed]",  
  256.                 "tx_checksum_ipv6""off [fixed]",  
  257.                 "tx_checksum_sctp""on [fixed]",  
  258.                 "tx_checksumming""on",  
  259.                 "tx_fcoe_segmentation""off [fixed]",  
  260.                 "tx_gre_csum_segmentation""off [fixed]",  
  261.                 "tx_gre_segmentation""off [fixed]",  
  262.                 "tx_gso_partial""off [fixed]",  
  263.                 "tx_gso_robust""off [fixed]",  
  264.                 "tx_ipip_segmentation""off [fixed]",  
  265.                 "tx_lockless""on [fixed]",  
  266.                 "tx_nocache_copy""off [fixed]",  
  267.                 "tx_scatter_gather""on [fixed]",  
  268.                 "tx_scatter_gather_fraglist""on [fixed]",  
  269.                 "tx_sctp_segmentation""on",  
  270.                 "tx_sit_segmentation""off [fixed]",  
  271.                 "tx_tcp6_segmentation""on",  
  272.                 "tx_tcp_ecn_segmentation""on",  
  273.                 "tx_tcp_mangleid_segmentation""on",  
  274.                 "tx_tcp_segmentation""on",  
  275.                 "tx_udp_tnl_csum_segmentation""off [fixed]",  
  276.                 "tx_udp_tnl_segmentation""off [fixed]",  
  277.                 "tx_vlan_offload""off [fixed]",  
  278.                 "tx_vlan_stag_hw_insert""off [fixed]",  
  279.                 "udp_fragmentation_offload""on",  
  280.                 "vlan_challenged""on [fixed]"  
  281.             },  
  282.             "hw_timestamp_filters": [],  
  283.             "ipv4": {  
  284.                 "address""127.0.0.1",  
  285.                 "broadcast""host",  
  286.                 "netmask""255.0.0.0",  
  287.                 "network""127.0.0.0"  
  288.             },  
  289.             "ipv6": [{  
  290.                 "address""::1",  
  291.                 "prefix""128",  
  292.                 "scope""host"  
  293.             }],  
  294.             "mtu": 65536,  
  295.             "promisc"false,  
  296.             "timestamping": ["rx_software""software"],  
  297.             "type""loopback"  
  298.         },  
  299.         "ansible_local": {},  
  300.         "ansible_lsb": {},  
  301.         "ansible_machine""x86_64",  
  302.         "ansible_machine_id""05cb8c7b39fe0f70e3ce97e5beab809d",  
  303.         "ansible_memfree_mb": 658,  
  304.         "ansible_memory_mb": {  
  305.             "nocache": {  
  306.                 "free": 854,  
  307.                 "used": 135  
  308.             },  
  309.             "real": {  
  310.                 "free": 658,  
  311.                 "total": 989,  
  312.                 "used": 331  
  313.             },  
  314.             "swap": {  
  315.                 "cached": 0,  
  316.                 "free": 0,  
  317.                 "total": 0,  
  318.                 "used": 0  
  319.             }  
  320.         },  
  321.         "ansible_memtotal_mb": 989,  
  322.         "ansible_mounts": [{  
  323.             "block_available": 1814541,  
  324.             "block_size": 4096,  
  325.             "block_total": 2094336,  
  326.             "block_used": 279795,  
  327.             "device""/dev/xvda1",  
  328.             "fstype""xfs",  
  329.             "inode_available": 4167224,  
  330.             "inode_total": 4193792,  
  331.             "inode_used": 26568,  
  332.             "mount""/",  
  333.             "options""rw,seclabel,relatime,attr2,inode64,noquota",  
  334.             "size_available": 7432359936,  
  335.             "size_total": 8578400256,  
  336.             "uuid""f41e390f-835b-4223-a9bb-9b45984ddf8d"  
  337.         }],  
  338.         "ansible_nodename""ip-172-31-4-33.us-west-1.compute.internal",  
  339.         "ansible_os_family""RedHat",  
  340.         "ansible_pkg_mgr""yum",  
  341.         "ansible_proc_cmdline": {  
  342.             "BOOT_IMAGE""/boot/vmlinuz-3.10.0-957.1.3.el7.x86_64",  
  343.             "LANG""en_US.UTF-8",  
  344.             "console": ["tty0""ttyS0,115200n8""ttyS0,115200"],  
  345.             "crashkernel""auto",  
  346.             "ro"true,  
  347.             "root""UUID=f41e390f-835b-4223-a9bb-9b45984ddf8d"  
  348.         },  
  349.         "ansible_processor": ["0""GenuineIntel""Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz"],  
  350.         "ansible_processor_cores": 1,  
  351.         "ansible_processor_count": 1,  
  352.         "ansible_processor_threads_per_core": 1,  
  353.         "ansible_processor_vcpus": 1,  
  354.         "ansible_product_name""HVM domU",  
  355.         "ansible_product_serial""ec2627bf-8996-84cc-d65d-a54b5642cab9",  
  356.         "ansible_product_uuid""EC2627BF-8996-84CC-D65D-A54B5642CAB9",  
  357.         "ansible_product_version""4.2.amazon",  
  358.         "ansible_python": {  
  359.             "executable""/usr/bin/python",  
  360.             "has_sslcontext"true,  
  361.             "type""CPython",  
  362.             "version": {  
  363.                 "major": 2,  
  364.                 "micro": 5,  
  365.                 "minor": 7,  
  366.                 "releaselevel""final",  
  367.                 "serial": 0  
  368.             },  
  369.             "version_info": [  
  370.                 2,  
  371.                 7,  
  372.                 5, "final",  
  373.                 0  
  374.             ]  
  375.         },  
  376.         "ansible_python_version""2.7.5",  
  377.         "ansible_real_group_id": 0,  
  378.         "ansible_real_user_id": 0,  
  379.         "ansible_selinux": {  
  380.             "config_mode""enforcing",  
  381.             "mode""enforcing",  
  382.             "policyvers": 31,  
  383.             "status""enabled",  
  384.             "type""targeted"  
  385.         },  
  386.         "ansible_selinux_python_present"true,  
  387.         "ansible_service_mgr""systemd",  
  388.         "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOklEtADmwCE2vj32jD1W8gy9cvd0cIBhxw06GFeZ5R1v    
  389.         CDGXZ5xw + bjk3jjjoOSgOiORZKh2zOTMjZdruCbQmI = ",                                                                                                      
  390.         "ansible_ssh_host_key_ed25519_public""AAAAC3NzaC1lZDI1NTE5AAAAIN9z16imlEAENHPoLAlK4x2XwolWs6GSCMnQ/IefmiW0",  
  391.         "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQCYNMsV/GkMA0LQWBOI7Ng0OW24tPXGGA2B3MTZbWiXIBGtv8tsqnWFnOIt8al0zeUJmkM    
  392.         iDkV1ATVEJK5mhyJAKWXFUZl1nqD7W9 / nT60bHbqY / HIMgtqeZJquFNe3pyxZuAWBg9paTpJjBBGYU8NrL0a5c8LHL5YP + wLnBWqJo5evekfg6aYlJQ47OLJuecZEGKK0kwnXCX0tIQ1RTH  
  393.         W0NnwBlLLqjrBy2eXKsK58rCPo4Raihcn0x5aQm8TMcICTAiW1sNnIilwKVTDgJMJMTgB9vYeTc0bwn / 4 zmTF + OWlM1X + piT / SORgirCJh9Qp94a75Puy1kL8878SwSuTB ",               
  394.         "ansible_swapfree_mb": 0,  
  395.         "ansible_swaptotal_mb": 0,  
  396.         "ansible_system""Linux",  
  397.         "ansible_system_capabilities": ["cap_chown""cap_dac_override""cap_dac_read_search""cap_fowner""cap_fsetid""cap_kill""cap_setgid""cap_setuid""cap_setpcap""cap_linux_immutable""cap_net_bind_service""cap_net_broadcast""cap_net_admin""cap_net_raw""cap_ipc_lock""cap_ipc_owner""cap_sys_module""cap_sys_rawio""cap_sys_chroot""cap_sys_ptrace""cap_sys_pacct""cap_sys_admin""cap_sys_boot""cap_sys_nice""cap_sys_resource""cap_sys_time""cap_sys_tty_config""cap_mknod""cap_lease""cap_audit_write""cap_audit_control""cap_setfcap""cap_mac_override""cap_mac_admin""cap_syslog""35""36+ep"],  
  398.         "ansible_system_capabilities_enforced""True",  
  399.         "ansible_system_vendor""Xen",  
  400.         "ansible_uptime_seconds": 4414,  
  401.         "ansible_user_dir""/root",  
  402.         "ansible_user_gecos""root",  
  403.         "ansible_user_gid": 0,  
  404.         "ansible_user_id""root",  
  405.         "ansible_user_shell""/bin/bash",  
  406.         "ansible_user_uid": 0,  
  407.         "ansible_userspace_architecture""x86_64",  
  408.         "ansible_userspace_bits""64",  
  409.         "ansible_virtualization_role""guest",  
  410.         "ansible_virtualization_type""xen",  
  411.         "discovered_interpreter_python""/usr/bin/python",  
  412.         "gather_subset": ["all"],  
  413.         "module_setup"true  
  414.     },  
  415.     "changed"false  
  416. }  
We can see that it generates a json output with all the variables that contains lots of information about the target machine. This json output contains lots of variables and these are called Fact Variables.
 
Thus, based on the values of fact variables we can take decisions inside playbook while writing different tasks.
 
So, we can make use of ansible_os_family variable and depending on its value we can decide which module we can use to install the package on different types of target machines. Now, let’s write one more play for the database server (Centos7) as well. In this play, we are going to install MySQL service, start and enable this service. The package name for MySQL is maria-db.
 
Below is the updated playbook.
  1. -- - -hosts: WebServersGroup  
  2. become: yes  
  3. tasks: -name: Install httpd service  
  4. yum: name: httpd  
  5. state: present - name: Start and Enable httpd service  
  6. service: name: httpd  
  7. state: started  
  8. enabled: yes - hosts: DBServerGroup  
  9. become: yes  
  10. tasks: -name: Install mariadb service  
  11. yum: name: mariadb - server  
  12. state: present - name: Start and Enable mariadb service  
  13. service: name: mariadb  
  14. state: started  
  15. enabled: yes  
Below command will execute our playbook.
  1. ansible-playbook web_db.yml            
OUTPUT
Ansible
 
We can see from the output that service has been installed successfully on database server.
We can also note that still, we are getting the error for web server 03, this we will fix in the next article where we are going to discuss the conditionals in playbooks.
 
So, for now, if we get syntax error while writing playbook we can simply check if there are any errors in the playbook even before executing the playbook with the below command:
  1. ansible-playbook web_db.yml  --syntax-check  
OUTPUT
 
Ansible
Currently, there are no errors so it's not giving anything.
 

Summary

 
Finally, we can conclude and say that we have understood how local Ansible config can be written, we now know the playbook and we have also written our first playbook. I hope you are also now familiar with the fact variables. So, in the next article, we will take this forward and will learn a few more good things in Ansible.
 
You can also check out some of my previous articles of the series “Learning Ansible” here: