/dev/blog/ID10T

Ansible: Extracting dictionary values into a list

Ansible Comments

Advertisement

Scenario:

In Ansible you have a list of dictionaries containing some values, e.g. a list of mount points:

mymounts:
  basedir: /srv/mymounts
  mounts:
    -
      name: first_mount
      opts: defaults
    -
      name: second_mount
      opts: noauto,x-systemd.automount,_netdev,reconnect
    -
      name: third_mount
      opts: defaults

And you want to extract a list of mount pathes combined from basedir and name for further usage, so the result looks like this:

['/srv/mymounts/first_mount', '/srv/mymounts/second_mount', '/srv/mymounts/third_mount']

Advertisement

Sadly, I could not find an easy or intuitive way to do this. You can neither use Jinja2 {% for %} loops in Playbooks or variable files, nor Python loops.
But I found a way using set_fact:

- Name: Expand mount dirs for later use
  set_fact:
    # Sets a list of mount directories
    expanded_mounts: "\
      {{ expanded_mounts | default([]) }} + \
      [ '{{ mymounts['basedir'] }}/{{ item['name'] }}' ]"
  with_items: "{{ mymounts['mounts'] }}"

As expanded_mounts is not defined in the first run, it is created as an empty list via the default([]) filter. Afterwards the expanded string is created and appended to the empty list via list addition. As we use with_items, this is done for every dictionary in the mounts list.

What do I need this for? I have a similar list of mountpoints I map SSHFS mounts to. I want to reuse those mountdirs during the creation of a Jinja2 template for Borg Backup. As I have other sources as well, I only needed a list of pathes to back up.

- Name: Add files for backups and enable them
  include_tasks: borgmatic.yml
  with_items:
    -
      job_name: "{{ borg['borgmatic']['local_backup']['name'] }}"
      job_time: "{{ borg['borgmatic']['local_backup']['time'] }}"
      backup_dirs: "{{ borg['borgmatic']['local_backup']['dirs'] }}"
      exclude_list: "{{ borg['borgmatic']['local_backup']['exclude_list'] }}"
      target_repos: "{{ uberspace_mounts['backup']['repositories'] }}"
    -
      job_name: "{{ uberspace_mounts['backup']['name'] }}"
      job_time: "{{ uberspace_mounts['backup']['time'] }}"
      backup_dirs: ""{{ expanded_mounts }}""
      exclude_list: "{{ uberspace_mounts['backup']['exclude_list'] }}"
      target_repos: ""{{ borg['borgmatic']['local_backup']['repositories'] }}"

Perhaps a bit complicated, but works like a charm. If you found this article helpful but just not the exact solution, I can recommend you the “How to append to lists in Ansible” post from the Crisp blog which also helped me find my solution.

Advertisement

comments powered by isso

Advertisement