DEV Community

Harsh Mishra
Harsh Mishra

Posted on

Ansible Jinja2: Complete Guide for Beginners

Jinja2 Templating in Ansible: Complete Guide

Jinja2 is a powerful and flexible templating engine used by Ansible to allow dynamic generation of configuration files, conditional logic, and other forms of text manipulation. It is an essential tool for creating reusable and customizable automation tasks, and it forms the foundation for many Ansible features, including variable interpolation, conditionals, loops, and more.

In this comprehensive guide, we will cover everything you need to know about using Jinja2 in Ansible, from basic syntax to advanced features. By the end of this guide, you will have a deep understanding of how to leverage Jinja2 templating in your Ansible automation.


1. What is Jinja2?

Jinja2 is a templating engine for Python, and it is used in Ansible to render templates dynamically based on variables, facts, or conditions. It allows you to create text-based configurations (e.g., configuration files, scripts) that change based on the input data, providing flexibility and automation.

Jinja2 uses curly braces ({{ }}) to denote expressions that will be replaced with values, and {% %} for control structures like loops or conditionals.


2. Basic Syntax of Jinja2

Jinja2 allows you to use variables, expressions, filters, and control structures inside templates. Below are the most important components of Jinja2 syntax:

2.1 Variables

Variables in Jinja2 are surrounded by {{ }} and can be directly accessed or manipulated.

Example:

# Using a simple variable
- name: Display a variable
  debug:
    msg: "The value of the variable is {{ my_variable }}"
Enter fullscreen mode Exit fullscreen mode

If my_variable is defined as my_variable: "Hello", the output will be:

The value of the variable is Hello
Enter fullscreen mode Exit fullscreen mode

2.2 Expressions

You can perform simple arithmetic or string operations directly inside Jinja2 expressions.

Example:

- name: Add numbers
  debug:
    msg: "The sum is {{ 5 + 10 }}"
Enter fullscreen mode Exit fullscreen mode

Output:

The sum is 15
Enter fullscreen mode Exit fullscreen mode

3. Control Structures in Jinja2

Jinja2 allows you to use control structures to apply logic, loops, and conditionals. These structures allow you to manipulate data dynamically based on conditions.

3.1 if Statements (Conditionals)

The if statement allows you to execute a block of code based on a condition.

Example:

- name: Check if a variable is defined
  debug:
    msg: "The variable is defined"
  when: my_variable is defined
Enter fullscreen mode Exit fullscreen mode

3.2 for Loops

The for loop is used to iterate over a list, dictionary, or other iterable objects.

Example:

- name: Loop through a list
  debug:
    msg: "Item: {{ item }}"
  with_items:
    - apple
    - banana
    - cherry
Enter fullscreen mode Exit fullscreen mode

3.3 else and elif Statements

Jinja2 also supports else and elif branches for more complex conditions.

Example:

- name: Check condition with elif
  debug:
    msg: "{{ 'The number is greater than 10' if number > 10 else 'The number is 10 or less' }}"
Enter fullscreen mode Exit fullscreen mode

3.4 not, and, or (Logical Operators)

Jinja2 supports logical operators for combining conditions.

Example:

- name: Logical operators in Jinja2
  debug:
    msg: "{{ 'True' if my_var > 10 and my_var < 20 else 'False' }}"
Enter fullscreen mode Exit fullscreen mode

4. Filters in Jinja2

Filters allow you to modify variables or expressions before they are rendered. Ansible provides a wide range of built-in filters to transform data.

4.1 Using Filters

Filters are applied using the pipe (|) symbol.

Example:

- name: Use the `lower` filter to convert text to lowercase
  debug:
    msg: "{{ my_string | lower }}"
Enter fullscreen mode Exit fullscreen mode

Common built-in filters:

  • lower: Converts a string to lowercase.
  • upper: Converts a string to uppercase.
  • default: Provides a default value if a variable is undefined.
  • join: Joins a list of strings into a single string.
  • length: Returns the length of a list, string, or dictionary.

Example:

- name: Join a list of strings with a comma
  debug:
    msg: "{{ my_list | join(', ') }}"
Enter fullscreen mode Exit fullscreen mode

5. Templates in Ansible

Jinja2 is used extensively for templating configuration files in Ansible. You can create templates using Jinja2 syntax and use the template module to generate configuration files dynamically.

5.1 Creating a Template

You can create a template file (e.g., nginx.conf.j2) that uses Jinja2 syntax.

Example of nginx.conf.j2:

server {
    listen {{ nginx_port }};
    server_name {{ server_name }};

    location / {
        root {{ document_root }};
        index index.html;
    }
}
Enter fullscreen mode Exit fullscreen mode

5.2 Using the Template Module

You can use the template module to generate the configuration file from a Jinja2 template.

- name: Deploy Nginx config
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
Enter fullscreen mode Exit fullscreen mode

In this example, Ansible will substitute {{ nginx_port }}, {{ server_name }}, and {{ document_root }} with values defined in the playbook or inventory.


6. Built-in Jinja2 Filters in Ansible

Jinja2 filters are a powerful way to manipulate data inside Ansible. Some of the most useful built-in filters include:

6.1 default Filter

The default filter provides a fallback value when a variable is not defined.

Example:

- name: Set default value if variable is undefined
  debug:
    msg: "{{ my_variable | default('Default Value') }}"
Enter fullscreen mode Exit fullscreen mode

6.2 length Filter

The length filter returns the length of a list, string, or dictionary.

Example:

- name: Get the length of a list
  debug:
    msg: "The length of the list is {{ my_list | length }}"
Enter fullscreen mode Exit fullscreen mode

6.3 unique Filter

The unique filter removes duplicate items from a list.

Example:

- name: Remove duplicates from a list
  debug:
    msg: "{{ my_list | unique }}"
Enter fullscreen mode Exit fullscreen mode

6.4 to_json and to_yaml Filters

These filters allow you to convert data to JSON or YAML format.

Example:

- name: Convert a dictionary to JSON
  debug:
    msg: "{{ my_dict | to_json }}"
Enter fullscreen mode Exit fullscreen mode

7. Using Jinja2 in Ansible Playbooks

In Ansible, you use Jinja2 expressions in playbooks for variable substitution, loops, conditionals, and more. This provides a powerful mechanism for creating flexible and dynamic automation workflows.

7.1 Variable Substitution

Variables can be referenced within playbooks and templates using Jinja2.

Example:

- name: Install a package
  apt:
    name: "{{ package_name }}"
    state: present
Enter fullscreen mode Exit fullscreen mode

7.2 Loops in Playbooks

You can loop over lists or dictionaries using Jinja2 loops.

Example:

- name: Install multiple packages
  apt:
    name: "{{ item }}"
    state: present
  with_items:
    - nginx
    - curl
    - git
Enter fullscreen mode Exit fullscreen mode

7.3 Using with_dict for Dictionaries

You can loop over key-value pairs in a dictionary.

Example:

- name: Configure multiple users
  user:
    name: "{{ item.key }}"
    state: present
    groups: "{{ item.value }}"
  with_dict:
    user1: wheel
    user2: sudo
Enter fullscreen mode Exit fullscreen mode

8. Advanced Jinja2 Features

8.1 Macros

Jinja2 supports macros, which allow you to define reusable blocks of code.

Example:

# In a template file:
{% macro greet(name) %}
Hello, {{ name }}!
{% endmacro %}

{{ greet('John') }}
Enter fullscreen mode Exit fullscreen mode

8.2 Inheritance and Includes

Jinja2 supports template inheritance and includes. This feature allows you to create a base template and then extend or include other templates.

Example:

{% extends "base_template.j2" %}

{% block content %}
  Content from the child template
{% endblock %}
Enter fullscreen mode Exit fullscreen mode

8.3 Tests

Jinja2 provides a variety of built-in tests to check the properties of variables.

Example:

- name: Check if a variable is a string
  debug:
    msg: "The variable is a string"
  when: my_variable is string
Enter fullscreen mode Exit fullscreen mode

8.4 include Statements

You can include other templates inside the main template.

Example:

{% include 'header.j2' %}
Enter fullscreen mode Exit fullscreen mode

9. Debugging Jinja2 Templates

Debugging Jinja2 templates can be tricky, but there are tools and techniques that can help.

9.1 Debugging in Playbooks

Use the debug module to print variables and the results of Jinja2 expressions.

Example:

- name: Debug Jinja2 expression
  debug:
    msg: "{{ my_variable }}"
Enter fullscreen mode Exit fullscreen mode

9.2 ansible-playbook --check

You can run your playbook with the --check flag to test whether the output will work as expected without making any changes.


10. Best Practices for Using Jinja2 in Ansible

  1. Use Descriptive Variable Names: Ensure variable names are meaningful to enhance readability.
  2. Leverage Filters: Use filters like default, length, and to_json to transform data efficiently.
  3. Keep Templates Modular: Use Jinja2 macros and includes to create reusable templates.
  4. Avoid Complex Logic: Keep your logic in playbooks simple and easy to follow.
  5. Use debug to Test Expressions: Always debug your Jinja2 expressions before applying them in production environments.

11. Conclusion

Jinja2 templating is a fundamental part of Ansible that enables dynamic, flexible, and powerful automation. Understanding Jinja2 syntax, control structures, filters, and templates allows you to generate configuration files, execute complex logic, and manage dynamic inventories, among many other use cases. Whether you're using simple variable substitutions or creating complex, multi-level templates, Jinja2 helps bring automation to life.

Key Takeaways

  • Jinja2 enables dynamic content generation in Ansible.
  • Filters, loops, and conditionals allow you to create flexible automation.
  • Templates let you generate configuration files and scripts dynamically.
  • Debugging tools and best practices help you write efficient, reusable templates.

By mastering Jinja2, you can unlock the full potential of Ansible and create more sophisticated and adaptable automation workflows.

Top comments (0)