Facts and Templates
— 3 min read
Overview
In Ansible, variables and facts, along with templates, are foundational tools for creating flexible automation workflows. Variables allow you to manage and change your configurations dynamically. Facts are a special subset of variables that Ansible gathers from the remote systems, providing context-specific information. Templates enable the generation of variable-driven configuration files, making your playbooks adaptable to varied environments and scenarios.
These tools make playbooks reusable and adaptable, allowing you to avoid hard-coding values and enabling customization for different environments.
Variables & Facts
Variables allow for parameters to be modified without altering the playbook's core logic.
-
Types of Variables:
-
Boolean: True or False values.
-
List: An ordered collection of items.
-
Dictionary: Key-value pairs for complex data structures.
-
Registered Variables: Captures the output of tasks to use later in your playbook.
-
Facts: Auto-collected variables that provide details about the remote systems you are managing.
-
NB: Avoid conflicts in variable names by using bracket notation.
- name: Print the distribution of the target hosts: all vars: curr_time: "{{ now() }}" tasks: - name: Distro Check ansible.builtin.debug: msg: "The target system is {{ ansible_facts['distribution'] }}. Timestamp: {{ curr_time }}"
Templates & Files
Templates in Ansible use the Jinja2 templating language to dynamically create files using variable interpolation, loops, and conditionals.
- name: Write distro name hosts: all tasks: - name: Write distro name ansible.builtin.template: src: distro.j2 dest: /root/distro.txt mode: '644'
# src: location of jinja2 template file# dest: location it will be copied to# permissions that will be granted to the file
Practice
We're going to use the OS Family to determine whether to install NGINX of Lighttpd then we'll deploy a custom homepage to the remote host containing NGINX all without hardcoding hostnames.
- Clone the repo
git clone https://github.com/perplexedyawdie/ansible-learn.git
2. Spin up the environment using docker-compose
docker compose up -d --build
3. SSH into the Ansible server
ssh -o StrictHostKeyChecking=no -o NoHostAuthenticationForLocalhost=yes root@localhost -p 2200# password: test123
4. Change directory to ansible_learn
cd ansible_learn
Variables & facts
5. Create a playbook called server_setup.yaml
. Here, we'll setup NGINX & Lighttpd then output the name of the distro for each remote host
- name: Install NGINX on Debian & Lighttpd on RedHat hosts: all vars: dev1: "Debian" dev2: "RedHat" tasks: - name: Install NGINX for Debian-based systems ansible.builtin.apt: name: nginx state: present when: ansible_facts['os_family'] == dev1
- name: Install Lighttpd for RedHat-based systems ansible.builtin.yum: name: lighttpd state: present when: ansible_facts['os_family'] == dev2
- name: Display the distribution ansible.builtin.debug: msg: "The server is running {{ ansible_facts['distribution'] }}"
6. Run ansible-lint
ansible-lint server_setup.yaml
7. Run the playbook
ansible-playbook --key-file /root/.ssh/id_rsa_ansible -u root -i inventory.yaml server_setup.yaml
8. Confirm that setup was successful
ssh -i /root/.ssh/id_rsa_ansible root@server3 nginx -V
ssh -i /root/.ssh/id_rsa_ansible root@server2 lighttpd -vssh -i /root/.ssh/id_rsa_ansible root@server1 lighttpd -v
Templates & Files
9. Create a Jinja2 template file called index.html.j2
It will get auto populated with the OS Family & Distribution.
<html><head> <title>Welcome to {{ ansible_facts['os_family'] }}</title></head><body> <h1>Server running on {{ ansible_facts['distribution'] }}</h1></body></html>
10. Create a playbook called custom_homepage.yaml
We're deploying the custom homepage created above to NGINX then restarting the server.
- name: Deploy Custom Homepage and restart hosts: all vars: dev1: "Debian" dev2: "RedHat" tasks: - name: Create Homepage with Jinja2 Template for NGINX ansible.builtin.template: src: index.html.j2 dest: /var/www/html/index.html mode: '644' when: ansible_facts['os_family'] == dev1 notify: restart nginx
handlers: - name: Restart NGINX listen: "restart nginx" ansible.builtin.service: name: nginx state: restarted when: ansible_facts['os_family'] == dev1
11. Run the linter
ansible-lint custom_homepage.yaml
12. Run the playbook
ansible-playbook --key-file /root/.ssh/id_rsa_ansible -u root -i inventory.yaml custom_homepage.yaml
13. Confirm deployment by visiting http://localhost:2203
in your browser.
Recap
Awesome effort! 🙌 We've learned how to use variables & facts in a playbook along with how to create dynamic files using templates. Next we'll look at modularization and error handling. Til then, take care!