Chapter 4: Managing Variables and Facts
Exercise: Managing facts
You will print a host's facts, pick out specific ones, then create a custom fact file on servera and write a play that decides what to install and start purely from that file.
Managing facts
- Gather facts from a host.
- Create tasks that use the gathered facts, including custom facts.
Prerequisites: Complete control-node setup and the preceding lessons in this chapter. Run commands as student on workstation unless a step names another machine.
From the project directory, run the relevant home-lab check. For an exercise with several checkpoints, grade each state before changing or removing it:
lab grade data-factsThe grader reads project files and host state. A passing report covers the listed checks; also perform the task’s independent connection, repeat-run, and reboot checks where requested.
Change a custom fact to request a stopped service. Gather facts again and predict the resulting service state.
Record the published result first. The grader checks the original requirements, so a changed name or value may intentionally fail those checks.
Make servera's web configuration depend on gathered facts rather than package and service names hardcoded in tasks.
display_facts.ymlmust report all facts;display_specific_facts.ymlmust report FQDN, Python version, processor count, memory, and local custom facts./etc/ansible/facts.d/custom.factmust describe the web package and service, requested service state, and enabled setting.playbook.ymlmust apply those custom values.check_httpd.ymlmust demonstrate the service state before and after configuration.- Explain why editing a fact file requires gathering facts again before using the new values.
Move into the project directory
[student@workstation ~]$ cd ~/data-facts
[student@workstation data-facts]$Print every fact
Create display_facts.yml for the webserver host and run it. Scroll through the output and find a few facts you recognise.
---
- name: Display ansible_facts
hosts: webserver
tasks:
- name: Display facts
ansible.builtin.debug:
var: ansible_facts[student@workstation data-facts]$ ansible-navigator run \
> -m stdout display_facts.yml
...output omitted...
"system": "Linux",
"system_vendor": "Red Hat",
"user_dir": "/root",
...output omitted...The user_* facts describe the account that ran setup. Here they show root, which means this project escalates privileges.
Print specific facts
Create display_specific_facts.yml that prints one sentence built from four facts: the FQDN, the Python version, the processor count and the total memory in MiB.
---
- name: Display specific ansible_facts
hosts: webserver
tasks:
- name: Display specific facts
ansible.builtin.debug:
msg: >
Host "{{ ansible_facts['fqdn'] }}" with Python
version "{{ ansible_facts['python_version'] }}" has
"{{ ansible_facts['processor_count'] }}" processors and
"{{ ansible_facts['memtotal_mb'] }}" MiB of total system memory.ok: [servera.lab.example.com] => {
"msg": "Host \"servera.lab.example.com\" with Python version \"3.9.10\" has
\"1\" processors and \"960\" MiB of total system memory.\n"
}Check for custom facts
Add a second task to display_specific_facts.yml that prints ansible_facts['ansible_local'], and run it again. It is empty, because no custom facts exist yet.
- name: Display ansible_local variable
ansible.builtin.debug:
msg: The ansible_local variable is set to "{{ ansible_facts['ansible_local'] }}" "msg": "The ansible_local variable is set to \"{}\""Create a custom fact file on servera
Log in to servera, create the facts directory, and write custom.fact describing what the host should run.
[student@workstation data-facts]$ ssh servera
[student@servera ~]$ sudo mkdir -p /etc/ansible/facts.d
[sudo] password for student: student
[student@servera ~]$ sudo vim /etc/ansible/facts.d/custom.fact[general]
package = httpd
service = httpd
state = started
enabled = trueLog out of servera when done.
Write a play driven by custom facts
Create playbook.yml with a play, Install Apache and starts the service, for the webserver group. It has two tasks:
- install the latest version of the package named by the custom fact
package; - manage the service named by
service, using thestateandenabledcustom facts.
---
- name: Install Apache and starts the service
hosts: webserver
tasks:
- name: Install the required package
ansible.builtin.dnf:
name: "{{ ansible_facts['ansible_local']['custom']['general']['package'] }}"
state: latest
- name: Start the service
ansible.builtin.service:
name: "{{ ansible_facts['ansible_local']['custom']['general']['service'] }}"
state: "{{ ansible_facts['ansible_local']['custom']['general']['state'] }}"
enabled: "{{ ansible_facts['ansible_local']['custom']['general']['enabled'] }}"Nothing in the playbook says "httpd": change the fact file on a host and the same playbook installs something else there.
Check the syntax
[student@workstation data-facts]$ ansible-navigator run \
> -m stdout playbook.yml --syntax-check
playbook: /home/student/data-facts/playbook.ymlConfirm httpd is not running yet
Create check_httpd.yml, which runs systemctl status httpd, registers the result and prints it. Run it: it fails, because httpd is not installed yet.
---
- name: Check httpd status
hosts: webserver
tasks:
- name: Check httpd status
ansible.builtin.command: systemctl status httpd
register: result
- name: Display http status
ansible.builtin.debug:
var: resultfatal: [servera.lab.example.com]: FAILED! => {"changed": false, "msg": "Could not
find the requested service httpd: host"}Run the fact-driven playbook
[student@workstation data-facts]$ ansible-navigator run -m stdout playbook.yml
...output omitted...
TASK [Install the required package] ********************************************
changed: [servera.lab.example.com]
TASK [Start the service] *******************************************************
changed: [servera.lab.example.com]
PLAY RECAP *********************************************************************
servera.lab.example.com : ok=3 changed=2 unreachable=0 failed=0 ...Check again
Run check_httpd.yml once more. The registered result now shows the service loaded, enabled and active (running).
"stdout_lines": [
"● httpd.service - The Apache HTTP Server",
" Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; ...)",
" Active: active (running) since ...",
...output omitted...Finish
Check your work with lab grade data-facts, then put the exercise away with lab finish data-facts.