Jinja2 and a nested list of lists

Hi,

I’m new to this forum, so allow me to introduce myself. I’m an Austrian IT guy living in South France, I’m working daily with Linux, and I discovered Ansible a few months back.

I’m slowly but steadily adopting it for real work. It’s a slippery fish, but once you get the hang of it, you won’t miss it.

So right, here goes. I’ve written a playbook to manage my (local and public) backup servers using Rocky Linux and Rsnapshot. To write the rsnapshot.conf configuration file, I used a Jinja2 template file. Here’s a snippet from the file:

#######################
# BACKUP TARGET HOSTS #
#######################

{% for backup_target in backup_targets %}
# {{ backup_target }}
{% for backup_dir in backup_dirs %}
backup  root@{{ backup_target }}:{{ backup_dir}}  {{ backup_target }}
{% endfor %}

{% endfor %}

The corresponding variables are in the host_vars section and look like this:

backup_targets:
  - alphamule.microlinux.lan
  - gustave.microlinux.lan
  - proxy.microlinux.lan
backup_dirs:
  - /etc
  - /home

With all this, here’s what the resulting configuration file on the target looks like:

#######################
# BACKUP TARGET HOSTS #
#######################

# alphamule.microlinux.lan
backup  root@alphamule.microlinux.lan:/etc  alphamule.microlinux.lan
backup  root@alphamule.microlinux.lan:/home alphamule.microlinux.lan

# gustave.microlinux.lan
backup  root@gustave.microlinux.lan:/etc    gustave.microlinux.lan
backup  root@gustave.microlinux.lan:/home   gustave.microlinux.lan

# proxy.microlinux.lan
backup  root@proxy.microlinux.lan:/etc  proxy.microlinux.lan
backup  root@proxy.microlinux.lan:/home proxy.microlinux.lan

So far this works fine.

Now here comes the tricky part. For now I’m assuming that Rsnapshot does backups of the same directory trees on every host, e. g. /etc and /home in the example above.

I’m now encountering a situation where I have different backup_dirs for different backup_targets. Something like this:

- alphamule.microlinux.lan:
    - /etc
    - /home
- gustave.microlinux.lan:
    - /home
- proxy.microlinux.lan:
    - /etc
    - /var
    - /srv

How can I make Jinja2 loop over this list of lists? I think this is a list of lists… I have yet to bend my head around all the things YAML. It looks like I’m missing some IQ points to translate this into correct Jinja2 syntax. So I thought I’d ask the competent crowd in this forum for a little help.

Cheers from the sunny South of France,

Niki

Can I for a moment assume that you control that file? What you got there is actually a list of dictionaries with one key and a list as a value. How about you create a variable containing a dictionary of lists? Like this:

backup_targets:
  alphamule.microlinux.lan:
    - /etc
    - /home

Or (probably even more future proof), a list of items with name and directories:

backup_targets:
  - name: alphamule
    fqdn: alphamule.microlinux.lan
    dirs:
      - /etc
      - /home
  - name: gustave
    fqdn: gustave.microlinux.lan
    dirs:
      - /home
...

(You woudn’t need the name attributes now, but that’s how it’s extendable.)
Your template should then look like

{%- for backup_target in backup_targets %}
# {{ backup_target.name }}
{%- for backup_dir in backup_target.dirs %}
backup  root@{{ backup_target.fqdn }}:{{ backup_dir}}  {{ backup_target.fqdn }}
{% endfor %}

{% endfor %}

[not tested, expect typos]

Enjoy the sun!

4 Likes

Thanks very much ! I experimented some more and now everything works perfectly as expected.

Cheers !

2 Likes