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