paint-brush
Ansible 101: Working With Facts and Templatesby@cloudkungfu
977 reads
977 reads

Ansible 101: Working With Facts and Templates

by cloud-kung-fuJanuary 30th, 2024
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

Ansible utilizes variables, facts, and templates to create adaptable automation workflows. Variables enable dynamic configuration management, facts provide system-specific information, and templates generate customizable configuration files. This approach ensures playbooks are reusable and flexible across different environments.
featured image - Ansible 101: Working With Facts and Templates
cloud-kung-fu HackerNoon profile picture
0-item

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.

How facts, variables, 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 }}"
      

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, and 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


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

Variables & Facts

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

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!