DEV Community

Cover image for Ansible 101: Facts & Templates
Javel Rowe
Javel Rowe

Posted on • Edited on • Originally published at javel.dev

Ansible 101: Facts & Templates

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.

Diagram showing how variables, facts and templates work together

  • 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 }}"

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

  1. Clone the repo
git clone https://github.com/perplexedyawdie/ansible-learn.git
Enter fullscreen mode Exit fullscreen mode

2. Spin up the environment using docker-compose

docker compose up -d --build
Enter fullscreen mode Exit fullscreen mode

3. SSH into the Ansible server

ssh -o StrictHostKeyChecking=no -o NoHostAuthenticationForLocalhost=yes root@localhost -p 2200# password: test123
Enter fullscreen mode Exit fullscreen mode

4. Change directory to ansible_learn

cd ansible_learn
Enter fullscreen mode Exit fullscreen mode

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'] }}"
Enter fullscreen mode Exit fullscreen mode

6. Run ansible-lint

ansible-lint server_setup.yaml
Enter fullscreen mode Exit fullscreen mode

7. Run the playbook

ansible-playbook --key-file /root/.ssh/id_rsa_ansible -u root -i inventory.yaml server_setup.yaml
Enter fullscreen mode Exit fullscreen mode

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 -v
ssh -i /root/.ssh/id_rsa_ansible root@server1 lighttpd -v
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

11. Run the linter

ansible-lint custom_homepage.yaml

Enter fullscreen mode Exit fullscreen mode

12. Run the playbook


ansible-playbook --key-file /root/.ssh/id_rsa_ansible -u root -i inventory.yaml custom_homepage.yaml
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)