Ansible v2.9.25
I'm trying to merge two data structures with Ansible. I'm almost there but I'm not able to merge all data.
Let me explain:
I want to merge main_roles together with default_roles:
main_roles:
- name: admin
role_ref: admin
subjects:
- name: test
kind: ServiceAccount
- name: test2
kind: ServiceAccount
- name: edit
role_ref: edit
subjects:
- name: test
kind: ServiceAccount
default_roles:
- name: edit
role_ref: edit
subjects:
- name: merge_me
kind: ServiceAccount
I'm successfully combining with the following task:
- name: "Setting var roles_managed"
set_fact:
roles_managed: "{{ roles_managed | default([]) + [ item | combine(default_roles|selectattr('name', 'match', item.name) |list)] }}"
loop: "{{ main_roles }}"
Printing the var via loop.
- name: "print all roles"
ansible.builtin.debug:
msg: "{{ item }}"
loop: "{{ roles_managed }}"
ok: [] => (item={u'subjects': [{u'kind': u'ServiceAccount', u'name': u'test'}, {u'kind': u'ServiceAccount', u'name': u'test2'}], u'name': u'admin', u'role_ref': u'admin'}) => {
"msg": {
"name": "admin",
"role_ref": "admin",
"subjects": [
{
"kind": "ServiceAccount",
"name": "test"
},
{
"kind": "ServiceAccount",
"name": "test2"
}
]
}
}
ok: [] => (item={u'subjects': [{u'kind': u'ServiceAccount', u'name': u'merge_me'}], u'name': u'edit', u'role_ref': u'edit'}) => {
"msg": {
"name": "edit",
"role_ref": "edit",
"subjects": [
{
"kind": "ServiceAccount",
"name": "merge_me"
}
]
}
}
This results in a combine on the item.name. But I want the result to be also a merge of the subjects. So i would need a end result of merge_me and test (the subjects under name:edit):
- name: edit
role_ref: edit
subjects:
- name: merge_me
kind: ServiceAccount
- name: test
kind: ServiceAccount
What I'm understanding Ansible is not merging recursively by default. So I would need to set recursive=true in the combine filter. See: Combining hashes/dictionaries
But I'm not able to set this successfully in my context.
When I try: {{ roles_managed | default([]) + [ item | combine(default_role_bindings, recursive=true|selectattr('name', 'match', item.name) |list)] }} for example I'm getting an 'bool' object is not iterable" error code...
I've tried many variations and searched many other posts. But I'm still unsuccessfully after probably too many hours ;). Hoping someone has a solution!