Advanced Ansible and Jinja2

Ansible's power lies in its ability to handle complex data structures with minimal code. By leveraging Jinja2 filters, you can elegantly transform data to meet automation requirements. This article explores a practical example of converting a simple list into a structured list of dictionaries, highlighting the flexibility and efficiency of Jinja2 in Ansible.

Scenario: Transforming vmlist to vmlist2

Imagine you have a list of virtual machine names (vmlist), and you need to convert it into a list of dictionaries (vmlist2), where each dictionary includes the key name with the corresponding value from vmlist.

Input Data

``yaml

vmlist:

- "a"

- "b"

`

Desired Output

`yaml

vmlist2:

- name: "a"

- name: "b"

`

The Jinja2 Solution

Here’s a compact and efficient way to achieve this transformation using Jinja2 filters:

`jinja

vmlist2: {{ vmlist | map('regex_replace', '(.*)', '{"name": "\\1"}') | map('from_json') | list }}

`

Step-by-Step Breakdown

1. map('regex_replace', '(.*)', '{"name": "\\1"}'):

- Applies a regex to each element in vmlist, wrapping it into a JSON string.

- Example: "a" becomes {"name": "a"}.

2. map('from_json'):

- Converts the JSON string into a Python dictionary.

- Example: {"name": "a"} is now a usable dictionary in Ansible.

3. list:

- Ensures the final output is a proper list of dictionaries.

Usage in an Ansible Playbook

Here’s how to use this transformation in an actual playbook:

`yaml

  • name: Transform vmlist to vmlist2

hosts: localhost

vars:

vmlist:

- "a"

- "b"

tasks:

- name: Transform vmlist to vmlist2

set_fact:

vmlist2: "{{ vmlist | map('regex_replace', '(.*)', '{"name": "\\1"}') | map('from_json') | list }}"

- name: Display transformed vmlist2

debug:

var: vmlist2

`

Output

When you run the playbook, the output will be:

`yaml

vmlist2:

- name: "a"

- name: "b"

`

Alternative Approaches

While the above method uses regex for transformation, alternative solutions avoid regex for simplicity and better readability. For example:

`jinja

vmlist2: [

{% for vm in vmlist %}

{"name": "{{ vm }}"}{% if not loop.last %},{% endif %}

{% endfor %}

]

`

This approach uses a loop to achieve the same result without relying on regex or JSON conversion.

Conclusion

Ansible's integration with Jinja2 provides a robust toolkit for handling data transformations, enabling complex automation workflows with concise code. By understanding filters like map, regex_replace, and from_json`, you can unlock powerful solutions tailored to your automation needs.

For more insights into advanced Ansible techniques, check out my book and video tutorials.