使用 Ansible 合并两个数据结构
Merging two data structures with Ansible
Ansible v2.9.25
我正在尝试使用 Ansible 合并两个数据结构。我快到了,但我无法合并所有数据。
让我解释一下:
我想合并 main_roles 和 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
我成功地完成了以下任务:
- 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 }}"
通过循环打印变量。
- 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"
}
]
}
}
这导致 item.name
上的联合收割机。但我希望结果也是主题的合并。所以我需要 merge_me
和 test
的最终结果(name:edit
下的 subjects
):
- name: edit
role_ref: edit
subjects:
- name: merge_me
kind: ServiceAccount
- name: test
kind: ServiceAccount
据我了解,Ansible 默认情况下不会递归合并。所以我需要在 combine
过滤器中设置 recursive=true
。参见:Combining hashes/dictionaries
但我无法在我的上下文中成功设置它。
当我尝试时:例如 {{ roles_managed | default([]) + [ item | combine(default_role_bindings, recursive=true|selectattr('name', 'match', item.name) |list)] }}
我得到一个 'bool' object is not iterable"
错误代码...
我尝试了很多变体并搜索了许多其他帖子。但是在可能太多小时之后我仍然没有成功;)。希望有人有解决方案!
main_roles和default_roles都是列表。无法合并列表。相反,可以添加它们和 groupby 名称。然后合并同名的字典,例如
- set_fact:
my_roles: "{{ my_roles|d([]) + [item.1|combine(list_merge='append')] }}"
loop: "{{ (main_roles + default_roles)|groupby('name') }}"
给予
my_roles:
- name: admin
role_ref: admin
subjects:
- kind: ServiceAccount
name: test
- kind: ServiceAccount
name: test2
- name: edit
role_ref: edit
subjects:
- kind: ServiceAccount
name: test
- kind: ServiceAccount
name: merge_me
使用从 2.10 开始可用的 list_merge='append' 来附加列表的项目。
如果 append 选项在您的版本中不可用,请自行添加 subjects,例如下面的任务给出了相同的结果
- set_fact:
my_roles: "{{ my_roles|d([]) + [item.1.0|combine({'subjects':_subj})] }}"
loop: "{{ (main_roles + default_roles)|groupby('name') }}"
vars:
_subj: "{{ item.1|map(attribute='subjects')|flatten }}"
Ansible v2.9.25
我正在尝试使用 Ansible 合并两个数据结构。我快到了,但我无法合并所有数据。
让我解释一下:
我想合并 main_roles 和 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
我成功地完成了以下任务:
- 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 }}"
通过循环打印变量。
- 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"
}
]
}
}
这导致 item.name
上的联合收割机。但我希望结果也是主题的合并。所以我需要 merge_me
和 test
的最终结果(name:edit
下的 subjects
):
- name: edit
role_ref: edit
subjects:
- name: merge_me
kind: ServiceAccount
- name: test
kind: ServiceAccount
据我了解,Ansible 默认情况下不会递归合并。所以我需要在 combine
过滤器中设置 recursive=true
。参见:Combining hashes/dictionaries
但我无法在我的上下文中成功设置它。
当我尝试时:例如 {{ roles_managed | default([]) + [ item | combine(default_role_bindings, recursive=true|selectattr('name', 'match', item.name) |list)] }}
我得到一个 'bool' object is not iterable"
错误代码...
我尝试了很多变体并搜索了许多其他帖子。但是在可能太多小时之后我仍然没有成功;)。希望有人有解决方案!
main_roles和default_roles都是列表。无法合并列表。相反,可以添加它们和 groupby 名称。然后合并同名的字典,例如
- set_fact:
my_roles: "{{ my_roles|d([]) + [item.1|combine(list_merge='append')] }}"
loop: "{{ (main_roles + default_roles)|groupby('name') }}"
给予
my_roles:
- name: admin
role_ref: admin
subjects:
- kind: ServiceAccount
name: test
- kind: ServiceAccount
name: test2
- name: edit
role_ref: edit
subjects:
- kind: ServiceAccount
name: test
- kind: ServiceAccount
name: merge_me
使用从 2.10 开始可用的 list_merge='append' 来附加列表的项目。
如果 append 选项在您的版本中不可用,请自行添加 subjects,例如下面的任务给出了相同的结果
- set_fact:
my_roles: "{{ my_roles|d([]) + [item.1.0|combine({'subjects':_subj})] }}"
loop: "{{ (main_roles + default_roles)|groupby('name') }}"
vars:
_subj: "{{ item.1|map(attribute='subjects')|flatten }}"