Using dictionary and list together in Ansible

Viewed 70
mydatabases:
  group1:
    db_name: group1_database
  group2:
    db_name: group2_database

For example in this non working snippet, which you should be able to get an idea what I'm trying to do, I want to install multiple postgresql extensions (from a list) against the 2 databases group1_database and group2_database in the dictionary.

name: add postgresql extension
postgresql_ext:
  name: "{{ item }}"
  db: "{{ item.value.db_name }}"
with_dict: "{{ mydatabases }}"
loop:
  - timescaledb
  - pg_partman

I've tried nested loops (which I didn't think it would work anyway) to no avail. Is there anyway I can do this to use a dictionary and list together or multiple dictionaries?

1 Answers

One approach would be to use dict2items, which does exactly what you are looking for, translate a dictionary into a list.

Then use a product of the two lists.

Giving the task:

- postgresql_ext:
    name: "{{ item.1 }}"
    db: "{{ item.0.value.db_name }}"
  loop: "{{ (mydatabases | dict2items) | product(extensions) }}"
  vars:
    extensions:
      - timescaledb
      - pg_partman

Here is a fake example with a debug instead of your Postgres task:

- hosts: all
  gather_facts: no

  tasks:
    - debug:
        msg: "I need to install {{ item.1 }} on {{ item.0.value.db_name }}"
      loop: "{{ (mydatabases | dict2items) | product(extensions) }}"
      vars:
        mydatabases:
          group1:
            db_name: group1_database
          group2:
            db_name: group2_database
        extensions:
          - timescaledb
          - pg_partman

This would yield the recap:

PLAY [all] *********************************************************************

TASK [debug] *******************************************************************
ok: [localhost] => (item=[{'key': 'group1', 'value': {'db_name': 'group1_database'}}, 'timescaledb']) => 
  msg: I need to install timescaledb on group1_database
ok: [localhost] => (item=[{'key': 'group1', 'value': {'db_name': 'group1_database'}}, 'pg_partman']) => 
  msg: I need to install pg_partman on group1_database
ok: [localhost] => (item=[{'key': 'group2', 'value': {'db_name': 'group2_database'}}, 'timescaledb']) => 
  msg: I need to install timescaledb on group2_database
ok: [localhost] => (item=[{'key': 'group2', 'value': {'db_name': 'group2_database'}}, 'pg_partman']) => 
  msg: I need to install pg_partman on group2_database

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Another approach is to use dictionary.keys() in order to get a list of keys out of your dictionary.

Then use the product filter, once again.

Giving the task:

- postgresql_ext:
    name: "{{ item.1 }}"
    db: "{{ mydatabases[item.0].db_name }}"
  loop: "{{ mydatabases.keys() | product(extensions) }}"
  vars:
    extensions:
      - timescaledb
      - pg_partman

Here is a fake example with a debug instead of your Postgres task:

- hosts: all
  gather_facts: no

  tasks:
    - debug:
        msg: "I need to install {{ item.1 }} on {{ mydatabases[item.0].db_name }}"
      loop: "{{ mydatabases.keys() | product(extensions) }}"
      vars:
        mydatabases:
          group1:
            db_name: group1_database
          group2:
            db_name: group2_database
        extensions:
          - timescaledb
          - pg_partman

This would yield the recap:

PLAY [all] *********************************************************************

TASK [debug] *******************************************************************
ok: [localhost] => (item=['group1', 'timescaledb']) => 
  msg: I need to install timescaledb on group1_database
ok: [localhost] => (item=['group1', 'pg_partman']) => 
  msg: I need to install pg_partman on group1_database
ok: [localhost] => (item=['group2', 'timescaledb']) => 
  msg: I need to install timescaledb on group2_database
ok: [localhost] => (item=['group2', 'pg_partman']) => 
  msg: I need to install pg_partman on group2_database

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
Related