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: True or False values. Boolean: An ordered collection of items. List: Key-value pairs for complex data structures. Dictionary: Captures the output of tasks to use later in your playbook. Registered Variables: Auto-collected variables that provide details about the remote systems you are managing. Facts: Avoid conflicts in variable names by using bracket notation. NB: - 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. 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 . Here, we'll setup NGINX & Lighttpd, and then, output the name of the distro for each remote host. server_setup.yaml - 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 in your browser. http://localhost:2203 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!