I have
- name: Replace group_ids with group_names in var_users
hosts: localhost
gather_facts: no
vars:
var_users:
- group_ids: ["e40c1163-269f-41f7-5555-57e1788a1999", "2742113c-44a6-59e3-48de-60b72e40ed83"]
name: "marko"
- group_ids: ["e40c1163-269f-41f7-5555-57e1788a1999"]
name: "user"
var_groups:
- id: "2742113c-44a6-59e3-48de-60b72e40ed83"
name: "admins"
- id: "e40c1163-269f-41f7-5555-57e1788a1999"
name: "users"
What is the approach to corelate var_groups
id
with var_users
group_ids
to have resulting var_users
have group name
intstead of group_ids
?
The expected results should be
var_users:
- group_ids: ["users", "admins"]
name: "marko"
- group_ids: ["users"]
name: "user"
Convert var_groups to a dictionary
var_groups_dict: "{{ var_groups |
items2dict(key_name='id', value_name='name') }}"
gives
var_groups_dict:
2742113c-44a6-59e3-48de-60b72e40ed83: admin
e40c1163-269f-41f7-5555-57e1788a1999: users
Use it to substitute id by name
group_ids: |
{% filter from_yaml %}
{% for ids in var_users | map(attribute='group_ids' )%}
- {group_ids: {{ ids | map('extract', var_groups_dict) }}}
{% endfor %}
{% endfilter %}
gives
group_ids:
- group_ids: [users, admin]
- group_ids: [users]
Then, zip the lists and combine the items
result: "{{ var_users | zip(group_ids) | map('combine') }}"
gives what you want
result:
- group_ids: [users, admin]
name: marko
- group_ids: [users]
name: user
Example of a complete playbook for testing
- hosts: localhost
vars:
var_users:
- group_ids: [e40c1163-269f-41f7-5555-57e1788a1999, 2742113c-44a6-59e3-48de-60b72e40ed83]
name: marko
- group_ids: [e40c1163-269f-41f7-5555-57e1788a1999]
name: user
var_groups:
- id: 2742113c-44a6-59e3-48de-60b72e40ed83
name: admin
- id: e40c1163-269f-41f7-5555-57e1788a1999
name: users
var_groups_dict: "{{ var_groups |
items2dict(key_name='id', value_name='name') }}"
group_ids: |
{% filter from_yaml %}
{% for ids in var_users | map(attribute='group_ids' )%}
- {group_ids: {{ ids | map('extract', var_groups_dict) }}}
{% endfor %}
{% endfilter %}
result: "{{ var_users | zip(group_ids) | map('combine') }}"
tasks:
- debug:
var: var_groups_dict
- debug:
var: group_ids | to_yaml
- debug:
var: result | to_yaml
Optionally, create the group_names dictionary
group_names: |
{% filter from_yaml %}
{% for i in var_users %}
{{ i.name }}: {{ i.group_ids | map('extract', var_groups_dict) }}
{% endfor %}
{% endfilter %}
In a minimal form, this gives what you need
group_names:
marko: [users, admin]
user: [users]
Then, you can convert it to any list if you want to. For example, the below declaration gives the same result
result: "{{ group_names |
dict2items(key_name='name', value_name='group_ids') }}"
Or, you can use the dictionary in a loop. For example,
- debug:
msg: "group: {{ item.0.key }} name: {{ item.1 }}"
loop: "{{ group_names | dict2items | subelements('value') }}"
gives (abridged)
msg: 'group: marko name: users'
msg: 'group: marko name: admin'
msg: 'group: user name: users'
Optionally, if you don't want to use Jinja, the below filters give the same result
result: "{{ var_users |
zip(var_users | map(attribute='group_ids')
| map('map', 'extract', var_groups_dict)
| map('community.general.dict_kv', 'group_ids')) |
map('combine') }}"
, or group_names
group_names: "{{ dict(var_users | map(attribute='name') |
zip(var_users | map(attribute='group_ids')
| map('map', 'extract', var_groups_dict))) }}"