{"id":3413,"date":"2020-01-29T18:17:15","date_gmt":"2020-01-29T17:17:15","guid":{"rendered":"http:\/\/miro.borodziuk.eu\/?p=3413"},"modified":"2020-09-22T12:39:35","modified_gmt":"2020-09-22T10:39:35","slug":"ansible-facts","status":"publish","type":"post","link":"http:\/\/miro.borodziuk.eu\/index.php\/2020\/01\/29\/ansible-facts\/","title":{"rendered":"Ansible Facts"},"content":{"rendered":"<p>Ansible facts are variables that are automatically discovered by Ansible from a managed host. Facts are pulled by the setup module and contain useful information stored into variables that administrators can reuse. Ansible facts can be part of playbooks, in conditionals, loops, or any other dynamic statement that depends on a value for a managed host<br \/>\n<!--more--><\/p>\n<p><span style=\"color: #3366ff;\">What are facts<\/span><\/p>\n<ul>\n<li>Facts are information discovered by Ansible about a target system<\/li>\n<li>There are two ways facts are collected:\n<ul>\n<li>Using the setup module with an ad-hoc command:<code> ansible all -m setup<\/code><\/li>\n<li>Facts are gathered by default when a playbook is executed<\/li>\n<\/ul>\n<\/li>\n<li>Fact gathering in playbooks may be disabled using the<code> gather_facts<\/code> attribute<\/li>\n<\/ul>\n<p><span style=\"color: #3366ff;\">How to use facts<\/span><\/p>\n<ul>\n<li>Any collected facts, they may be accessed through variables:\n<ul>\n<li><code>{{ ansible_default_ipv4.address))<\/code><\/li>\n<\/ul>\n<\/li>\n<li>It is possible to use filters with regex, in ad-hoc<br \/>\nmode, to match certain fact names<\/li>\n<li>Facts may also be used with conditionals to have plays behave differently on hosts that meet certain criteria<\/li>\n<\/ul>\n<pre class=\"lang:sh decode:true\">[miro@controlnode playbooks]$ ansible managedhost1 -m setup -a \"filter=*ipv4\"\r\nmanagedhost1 | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_default_ipv4\": {\r\n\"address\": \"172.30.9.51\",\r\n\"alias\": \"ens192\",\r\n\"broadcast\": \"172.30.255.255\",\r\n\"gateway\": \"172.30.8.1\",\r\n\"interface\": \"ens192\",\r\n\"macaddress\": \"00:0c:29:75:74:f6\",\r\n\"mtu\": 1500,\r\n\"netmask\": \"255.255.0.0\",\r\n\"network\": \"172.30.0.0\",\r\n\"type\": \"ether\"\r\n}\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>The following table shows some of the facts gathered from a managed node that may be useful in a playbook:<\/p>\n<table style=\"border-collapse: collapse; width: 100%; height: 236px;\">\n<tbody>\n<tr style=\"height: 26px;\">\n<td style=\"width: 50%; height: 26px;\"><em><strong>Fact <\/strong><\/em><\/td>\n<td style=\"width: 50%; height: 26px;\"><em><strong>Variable<\/strong><\/em><\/td>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"width: 50%; height: 26px;\">Hostname<\/td>\n<td style=\"width: 50%; height: 26px;\"><code>{{ ansible_hostname }}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">FQDN<\/td>\n<td style=\"width: 50%;\"><code>{{ ansible_fqdn }}<\/code><\/td>\n<\/tr>\n<tr style=\"height: 53px;\">\n<td style=\"width: 50%; height: 53px;\">Main IPv4 address (based on<br \/>\nrouting)<\/td>\n<td style=\"width: 50%; height: 53px;\"><code>{{ ansible_default_ipv4.address }}<\/code><\/td>\n<\/tr>\n<tr style=\"height: 79px;\">\n<td style=\"width: 50%; height: 79px;\">Main disk first partition size<br \/>\n(based on disk name, such as<br \/>\nvda, vdb, and so on.)<\/td>\n<td style=\"width: 50%; height: 79px;\"><code>{{ ansible_devices.vda.partitions.vda1.size }}<\/code><\/td>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"width: 50%; height: 26px;\">DNS servers<\/td>\n<td style=\"width: 50%; height: 26px;\"><code>{{ ansible_dns.nameservers }}<\/code><\/td>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"width: 50%; height: 26px;\">kernel version<\/td>\n<td style=\"width: 50%; height: 26px;\"><code>\u00a0{{ ansible_kernel }}<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>When a fact is used in a playbook, Ansible dynamically substitutes the variable name with the corresponding value:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ cat playbook11.yml\r\n---\r\n- hosts: all\r\n  tasks:\r\n  - name: Prints various Ansible facts\r\n    debug:\r\n      msg: &gt;\r\n        The default IPv4 address of {{ ansible_fqdn }}\r\n        is {{ ansible_default_ipv4.address }}<\/pre>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ ansible-playbook playbook11.yml\r\n\r\nPLAY [all] ****************************************************************************************************************************************\r\n\r\nTASK [Gathering Facts] ****************************************************************************************************************************\r\nok: [managedhost1]\r\nok: [managedhost1.example.com]\r\nok: [managedhost2]\r\nok: [managedhost2.example.com]\r\n\r\nTASK [Prints various Ansible facts] ***************************************************************************************************************\r\nok: [managedhost1] =&gt; {\r\n\"msg\": \"The default IPv4 address of managedhost1.example.com is 172.30.9.51\\n\"\r\n}\r\nok: [managedhost2] =&gt; {\r\n\"msg\": \"The default IPv4 address of managedhost2.example.com is 172.30.10.25\\n\"\r\n}\r\nok: [managedhost1.example.com] =&gt; {\r\n\"msg\": \"The default IPv4 address of managedhost1.example.com is 172.30.9.51\\n\"\r\n}\r\nok: [managedhost2.example.com] =&gt; {\r\n\"msg\": \"The default IPv4 address of managedhost2.example.com is 172.30.10.25\\n\"\r\n}\r\n\r\nPLAY RECAP ****************************************************************************************************************************************\r\nmanagedhost1 : ok=2 changed=0 unreachable=0 failed=0\r\nmanagedhost1.example.com : ok=2 changed=0 unreachable=0 failed=0\r\nmanagedhost2 : ok=2 changed=0 unreachable=0 failed=0\r\nmanagedhost2.example.com : ok=2 changed=0 unreachable=0 failed=0<\/pre>\n<p>Administrators can manually disable facts for managed hosts if a large number of servers are being managed. To disable facts, set gather_facts to no in the playbook:<\/p>\n<pre class=\"lang:sh decode:true\">---\r\n- hosts: large_farm\r\n  gather_facts: no<\/pre>\n<p>Facts are always gathered by Ansible unless overridden in this way.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Custom Facts &#8211; Facts.d<br \/>\n<\/span><\/p>\n<ul>\n<li>It is possible to define custom facts on your servers using the <code>facts.d<\/code> directory<\/li>\n<li>Create \/<code>etc\/ansible\/facts.d<\/code> directory on target system. All valid files within this directory ending in .fact are returned under<code> ansible_local<\/code> with facts<\/li>\n<li>Fact files may be INI, JSON, or an executable that returns JSON<\/li>\n<\/ul>\n<pre class=\"lang:sh decode:true\">[root@managedhost1 facts.d]# mkdir \/etc\/ansible\/facts.d\r\n[root@managedhost1 facts.d]# cd \/etc\/ansible\/facts.d\r\n[root@managedhost1 facts.d]# touch data.fact\r\n[root@managedhost1 facts.d]# touch prefs.fact\r\n[root@managedhost1 facts.d]# touch software_inv.fact\r\n[root@managedhost1 facts.d]# su miro\r\n[miro@managedhost1 ~]$ tree -A \/etc\/ansible\r\n\/etc\/ansible\r\ntqq ansible.cfg\r\ntqq facts.d\r\nx tqq data.fact\r\nx tqq prefs.fact\r\nx mqq software_inv.fact\r\ntqq hosts\r\nmqq roles\r\n\r\n\r\n[miro@controlnode ansible]$ ansible managedhost1 -m setup -a \"filter=ansible_local\"\r\nmanagedhost1 | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_local\": {\r\n\"data\": {},\r\n\"prefs\": {},\r\n\"software_inv\": {}\r\n}\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Listing all facts from the <code>managedhost1<\/code>:<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode ansible]$ ansible managedhost1 -m setup | less\r\nmanagedhost1 | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_all_ipv4_addresses\": [\r\n\"172.30.9.51\"\r\n],\r\n\"ansible_all_ipv6_addresses\": [\r\n\"fe80::6335:25e9:80f:3d5a\",\r\n\"fddb:fe2a:ab1e::c0a8:3\",\r\n\"fe80::bc5f:4f03:654a:9167\"\r\n],\r\n\"ansible_apparmor\": {\r\n\"status\": \"disabled\"\r\n},\r\n\"ansible_architecture\": \"x86_64\",\r\n\"ansible_bios_date\": \"04\/05\/2016\",\r\n\"ansible_bios_version\": \"6.00\",\r\n\"ansible_cmdline\": {\r\n\"BOOT_IMAGE\": \"\/vmlinuz-3.10.0-1062.9.1.el7.x86_64\",\r\n\"LANG\": \"pl_PL.UTF-8\",\r\n\"crashkernel\": \"auto\",\r\n\"quiet\": true,\r\n\"rd.lvm.lv\": \"cl\/swap\",\r\n\"rhgb\": true,\r\n\"ro\": true,\r\n\"root\": \"\/dev\/mapper\/cl-root\"\r\n},\r\n\"ansible_date_time\": {\r\n\"date\": \"2020-02-02\",\r\n\"day\": \"02\",\r\n\"epoch\": \"1580680308\",\r\n\"hour\": \"22\",\r\n\"iso8601\": \"2020-02-02T21:51:48Z\",\r\n\"iso8601_basic\": \"20200202T225148534601\",\r\n\"iso8601_basic_short\": \"20200202T225148\",\r\n\"iso8601_micro\": \"2020-02-02T21:51:48.534718Z\",\r\n\"minute\": \"51\",\r\n\"month\": \"02\",\r\n\"second\": \"48\",\r\n\"time\": \"22:51:48\",\r\n\"tz\": \"CET\",\r\n\"tz_offset\": \"+0100\",\r\n\"weekday\": \"niedziela\",<\/pre>\n<p>Filter facts from the <code>managedhost1<\/code> for example with<em> &#8220;ip&#8221;<\/em> word:<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode ansible]$ ansible managedhost1 -m setup -a \"filter=*ip*\"\r\nmanagedhost1 | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_all_ipv4_addresses\": [\r\n\"172.30.9.51\"\r\n],\r\n\"ansible_all_ipv6_addresses\": [\r\n\"fe80::6335:25e9:80f:3d5a\",\r\n\"fddb:fe2a:ab1e::c0a8:3\",\r\n\"fe80::bc5f:4f03:654a:9167\"\r\n],\r\n\"ansible_default_ipv4\": {\r\n\"address\": \"172.30.9.51\",\r\n\"alias\": \"ens192\",\r\n\"broadcast\": \"172.30.255.255\",\r\n\"gateway\": \"172.30.8.1\",\r\n\"interface\": \"ens192\",\r\n\"macaddress\": \"00:0c:29:75:74:f6\",\r\n\"mtu\": 1500,\r\n\"netmask\": \"255.255.0.0\",\r\n\"network\": \"172.30.0.0\",\r\n\"type\": \"ether\"\r\n},\r\n\"ansible_default_ipv6\": {},\r\n\"ansible_fips\": false\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>Facts about distribution:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode ansible]$ ansible managedhost1 -m setup -a \"filter=*dist*\"\r\nmanagedhost1 | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_distribution\": \"CentOS\",\r\n\"ansible_distribution_file_parsed\": true,\r\n\"ansible_distribution_file_path\": \"\/etc\/redhat-release\",\r\n\"ansible_distribution_file_variety\": \"RedHat\",\r\n\"ansible_distribution_major_version\": \"7\",\r\n\"ansible_distribution_release\": \"Core\",\r\n\"ansible_distribution_version\": \"7.7.1908\"\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Creating local facts on <code>managedhost1<\/code>:<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode ansible]$ ssh managedhost1\r\nLast login: Sun Feb 2 22:55:38 2020 from controlnode.example.com\r\n[miro@managedhost1 ~]$ ll \/etc\/ansible\r\nls: nie ma dost\u0119pu do \/etc\/ansible: Nie ma takiego pliku ani katalogu<\/pre>\n<p>As we se above ansible is not iinstalled on the <code>managedhost1<\/code> because it only use ssh\u00a0 on the clients.<\/p>\n<pre class=\"lang:sh decode:true \">[miro@managedhost1 ~]$ sudo mkdir -p \/etc\/ansible\/facts.s\r\n[miro@managedhost1 ~]$ sudo mkdir \/etc\/ansible\/facts.d\r\n[miro@managedhost1 ~]$ sudo vim \/etc\/ansible\/facts.d\r\n[miro@managedhost1 ~]$ sudo vim \/etc\/ansible\/facts.d\/prefs.fact\r\n[miro@managedhost1 ~]$ cat \/etc\/ansible\/facts.d\/prefs.fact\r\n[location]\r\ntype=physical\r\ndatacenter=Katowice\r\n\r\n[miro@managedhost1 ~]$ logout\r\nConnection to managedhost1 closed.<\/pre>\n<p>On the controlnode we can print local facts from the <code>managedhost1<\/code>:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode ansible]$ ansible managedhost1 -m setup -a \"filter=ansible_local\"\r\nmanagedhost1 | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_local\": {\r\n\"prefs\": {\r\n\"location\": {\r\n\"datacenter\": \"Katowice\",\r\n\"type\": \"physical\"\r\n}\r\n}\r\n}\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Example 1.<\/span><\/p>\n<p>The Ansible setup module retrieves facts from a system. Run an ad hoc command to retrieve the facts for all servers in the labservers group.<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode ansible]$ ansible labservers -m setup \r\nmanagedhost1.example.com | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_all_ipv4_addresses\": [\r\n\"172.30.9.51\"\r\n],\r\n\"ansible_all_ipv6_addresses\": [\r\n\"fe80::6335:25e9:80f:3d5a\",\r\n\"fddb:fe2a:ab1e::c0a8:3\",\r\n\"fe80::bc5f:4f03:654a:9167\"\r\n],\r\n\"ansible_apparmor\": {\r\n\"status\": \"disabled\"\r\n},\r\n\"ansible_architecture\": \"x86_64\",\r\n\"ansible_bios_date\": \"04\/05\/2016\",\r\n\"ansible_bios_version\": \"6.00\",\r\n\"ansible_cmdline\": {\r\n\"BOOT_IMAGE\": \"\/vmlinuz-3.10.0-1062.9.1.el7.x86_64\",\r\n\"LANG\": \"pl_PL.UTF-8\",\r\n\"crashkernel\": \"auto\",\r\n\"quiet\": true,\r\n\"rd.lvm.lv\": \"cl\/swap\",\r\n\"rhgb\": true,\r\n\"ro\": true,\r\n\"root\": \"\/dev\/mapper\/cl-root\"\r\n},<\/pre>\n<p>Filter the facts matching the ansible_user expression. Append a wildcard to match all facts starting with ansible_user.<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode ansible]$ ansible labservers -m setup -a 'filter=ansible_user*'\r\nmanagedhost1.example.com | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_user_dir\": \"\/home\/miro\",\r\n\"ansible_user_gecos\": \"miro\",\r\n\"ansible_user_gid\": 1000,\r\n\"ansible_user_id\": \"miro\",\r\n\"ansible_user_shell\": \"\/bin\/bash\",\r\n\"ansible_user_uid\": 1000,\r\n\"ansible_userspace_architecture\": \"x86_64\",\r\n\"ansible_userspace_bits\": \"64\"\r\n},\r\n\"changed\": false\r\n}\r\nmanagedhost2.example.com | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_user_dir\": \"\/home\/miro\",\r\n\"ansible_user_gecos\": \"miro\",\r\n\"ansible_user_gid\": 1000,\r\n\"ansible_user_id\": \"miro\",\r\n\"ansible_user_shell\": \"\/bin\/bash\",\r\n\"ansible_user_uid\": 1000,\r\n\"ansible_userspace_architecture\": \"x86_64\",\r\n\"ansible_userspace_bits\": \"64\"\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>Create a fact file named <code>custom.fact<\/code>. The fact file defines the package to install and the service to start on servera. The file should read as follows:<\/p>\n<pre class=\"lang:sh decode:true \">[general]\r\npackage = httpd\r\nservice = httpd\r\nstate = started<\/pre>\n<p>Create the <code>setup_facts.yml<\/code> playbook to make the<code> \/etc\/ansible\/facts.d<\/code> remote directory and to save the <code>custom.fact<\/code> file to that directory.<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode playbooks]$ cat setup_facts.yml\r\n---\r\n- name: Install remote facts\r\n  hosts: managedhost2\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 an ad hoc command with the setup module. Since user-defined facts are put into the ansible_local section, use a filter to display only this section. There should not be any custom facts at this point.<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ ansible managedhost2 -m setup -a 'filter=ansible_local'\r\nmanagedhost2 | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_local\": {}\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>Run the <code>setup_facts.yml<\/code> playbook.<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ ansible-playbook setup_facts.yml\r\n\r\nPLAY [Install remote facts] ***********************************************************************************************************************\r\n\r\nTASK [Gathering Facts] ****************************************************************************************************************************\r\nok: [managedhost2]\r\n\r\nTASK [Create the remote directory] ****************************************************************************************************************\r\nfatal: [managedhost2]: FAILED! =&gt; {\"changed\": false, \"msg\": \"There was an issue creating \/etc\/ansible as requested: [Errno 13] Brak dost\u0119pu: '\/etc\/ansible'\", \"path\": \"\/etc\/ansible\/facts.d\", \"state\": \"absent\"}\r\nto retry, use: --limit @\/home\/miro\/ansible\/playbooks\/setup_facts.retry\r\n\r\nPLAY RECAP ****************************************************************************************************************************************\r\nmanagedhost2 : ok=1 changed=0 unreachable=0 failed=1<\/pre>\n<p>Run with become a root parameter:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ ansible-playbook setup_facts.yml -b\r\n\r\nPLAY [Install remote facts] ***********************************************************************************************************************\r\n\r\nTASK [Gathering Facts] ****************************************************************************************************************************\r\nok: [managedhost2]\r\n\r\nTASK [Create the remote directory] ****************************************************************************************************************\r\nchanged: [managedhost2]\r\n\r\nTASK [Install the new facts] **********************************************************************************************************************\r\nchanged: [managedhost2]\r\n\r\nPLAY RECAP ****************************************************************************************************************************************\r\nmanagedhost2 : ok=3 changed=2 unreachable=0 failed=0<\/pre>\n<p>To ensure the new facts have been properly installed, run an ad hoc command with the setup module again. Display only the ansible_local section. The custom facts should appear.<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ ansible managedhost2 -m setup -a 'filter=ansible_local'\r\nmanagedhost2 | SUCCESS =&gt; {\r\n\"ansible_facts\": {\r\n\"ansible_local\": {\r\n\"custom\": {\r\n\"general\": {\r\n\"package\": \"httpd\",\r\n\"service\": \"httpd\",\r\n\"state\": \"started\"\r\n}\r\n}\r\n}\r\n},\r\n\"changed\": false\r\n}<\/pre>\n<p>It is now possible to create the main playbook that uses both default and user facts to configure managedhost2. The first task installs the httpd package. Use the user fact for the name of the package. Second task\u00a0 uses the custom fact to start the httpd service.<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode playbooks]$ cat playbook12.yml\r\n---\r\n- name: Install Apache and starts the service\r\n  become: yes\r\n  hosts: managedhost2\r\n  tasks:\r\n  - name: Install the required package\r\n    yum:\r\n      name: \"{{ ansible_local.custom.general.package }}\"\r\n      state: latest\r\n  - name: Start the service\r\n    service:\r\n      name: \"{{ ansible_local.custom.general.service }}\"\r\n      state: \"{{ ansible_local.custom.general.state }}\"\r\n<\/pre>\n<p>Before running the playbook, use an ad hoc command to verify the httpd service is not currently running on managedhost2:<\/p>\n<pre class=\"lang:sh decode:true\">[miro@controlnode playbooks]$ ansible managedhost2 -m command -a 'systemctl status httpd'\r\nmanagedhost2 | FAILED | rc=3 &gt;&gt;\r\n\u25cf httpd.service - The Apache HTTP Server\r\nLoaded: loaded (\/usr\/lib\/systemd\/system\/httpd.service; enabled; vendor preset: disabled)\r\nActive: inactive (dead) since wto 2020-01-28 19:08:32 CET; 2 months 29 days ago\r\nDocs: man:httpd(8)\r\nman:apachectl(8)\r\nMain PID: 4432 (code=exited, status=0\/SUCCESS)\r\nStatus: \"Total requests: 0; Current requests\/sec: 0; Current traffic: 0 B\/sec\"\r\n\r\nWarning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.non-zero return code<\/pre>\n<p>Run the playbook using the ansible-playbook command. Watch the output as Ansible starts by installing the package, then enabling the service.<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ ansible-playbook playbook12.yml\r\n\r\nPLAY [Install Apache and starts the service] ******************************************************************************************************\r\n\r\nTASK [Gathering Facts] ****************************************************************************************************************************\r\nok: [managedhost2]\r\n\r\nTASK [Install the required package] ***************************************************************************************************************\r\nchanged: [managedhost2]\r\n\r\nTASK [Start the service] **************************************************************************************************************************\r\nchanged: [managedhost2]\r\n\r\nPLAY RECAP ****************************************************************************************************************************************\r\nmanagedhost2 : ok=3 changed=2 unreachable=0 failed=0<\/pre>\n<p>Use an ad hoc command to execute systemctl to check if the httpd service is now running on managedhost2:<\/p>\n<pre class=\"lang:sh decode:true \">[miro@controlnode playbooks]$ ansible -b managedhost2 -m command -a 'systemctl status httpd'\r\nmanagedhost2 | SUCCESS | rc=0 &gt;&gt;\r\n\u25cf httpd.service - The Apache HTTP Server\r\nLoaded: loaded (\/usr\/lib\/systemd\/system\/httpd.service; enabled; vendor preset: disabled)\r\nActive: active (running) since wto 2020-04-28 14:30:54 CEST; 1min 6s ago\r\nDocs: man:httpd(8)\r\nman:apachectl(8)\r\nMain PID: 4804 (httpd)\r\nStatus: \"Total requests: 0; Current requests\/sec: 0; Current traffic: 0 B\/sec\"\r\nCGroup: \/system.slice\/httpd.service\r\n\u251c\u25004804 \/usr\/sbin\/httpd -DFOREGROUND\r\n\u251c\u25004805 \/usr\/sbin\/httpd -DFOREGROUND\r\n\u251c\u25004806 \/usr\/sbin\/httpd -DFOREGROUND\r\n\u251c\u25004807 \/usr\/sbin\/httpd -DFOREGROUND\r\n\u251c\u25004808 \/usr\/sbin\/httpd -DFOREGROUND\r\n\u2514\u25004809 \/usr\/sbin\/httpd -DFOREGROUND\r\n\r\nkwi 28 14:30:53 managedhost2.example.com systemd[1]: Starting The Apache HTTP Server...\r\nkwi 28 14:30:54 managedhost2.example.com systemd[1]: Started The Apache HTTP Server.<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ansible facts are variables that are automatically discovered by Ansible from a managed host. Facts are pulled by the setup module and contain useful information stored into variables that administrators can reuse. Ansible facts can be part of playbooks, in conditionals, loops, or any other dynamic statement that depends on a value for a managed &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/miro.borodziuk.eu\/index.php\/2020\/01\/29\/ansible-facts\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Ansible Facts&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":3427,"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\/3413"}],"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=3413"}],"version-history":[{"count":14,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/3413\/revisions"}],"predecessor-version":[{"id":3798,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/3413\/revisions\/3798"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media\/3427"}],"wp:attachment":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media?parent=3413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/categories?post=3413"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/tags?post=3413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}