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 allow for parameters to be modified without altering the playbook's core logic.
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 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
We're going to use the OS Family to determine whether to install NGINX of Lighttpd, and then, we'll deploy a custom homepage to the remote host containing NGINX all without hardcoding hostnames.
git clone https://github.com/perplexedyawdie/ansible-learn.git
2. Change directory to facts-and-templates
cd ansible-learn/facts-and-templates
3. Spin up the environment using docker-compose
docker compose up -d --build
4. SSH into the Ansible server
ssh -o StrictHostKeyChecking=no -o NoHostAuthenticationForLocalhost=yes root@localhost -p 2200
# password: test123
5. Create a playbook called server_setup.yaml
. Here, we'll setup NGINX & Lighttpd, and 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 the setup was successful.
ssh -i /root/.ssh/id_rsa_ansible root@server3 nginx -V
ssh -i /root/.ssh/id_rsa_ansible root@server2 lighttpd -v
ssh -i /root/.ssh/id_rsa_ansible root@server1 lighttpd -v
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.
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!