将默认值插入 Ansible 中的字典列表
Inserting default values into list of dicts in Ansible
我有一个 Web 应用程序及其配置列表。简化的数据结构看起来像这样(字典列表)
web_app_details:
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\alexsapp'
loadUserProfile: false
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\bodhi'
现在,我不希望用户每次都指定一些默认值(单个字典)
defaults_only:
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: true
如果用户未在 defaults_only
词典的任何字段中提供值,则应使用默认值。否则,应丢弃默认值。
所以结果是:
web_app_details:
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\alexsapp'
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: false # Because user provided the override value
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\bodhi'
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: true
我尝试了一些方法,例如
- 调用 Powershell 脚本在 Ansible 之外执行此操作
- 复制默认字典的次数与
web_app_detail
中一样多,然后使用组合过滤器
- 使用 JMESPath 查询插入
null
值:
- name: Pad web_app_details with null values
set_fact:
web_app_details_with_defaults: "{{ web_app_details | json_query(jmesquery) }}"
vars:
jmesquery:
"[*].{web_sourcedir: web_sourcedir, web_destdir: web_destdir, web_cleancopy: web_cleancopy }"
但没有任何效果。
有人可以帮忙吗?
您可以重新创建该列表,添加带有 combine
过滤器的默认值。
这将利用这样一个事实,即在两个词典中定义的 属性 将被您要合并的词典覆盖。
所以,您将完成这项 set_fact
任务:
- set_fact:
web_app_details_with_defaults: >-
{{
web_app_details_with_defaults | default([]) + [
defaults_only | combine(item)
]
}}
loop: "{{ web_app_details }}"
给定两个任务:
- set_fact:
web_app_details_with_defaults: >-
{{
web_app_details_with_defaults | default([]) + [
defaults_only | combine(item)
]
}}
loop: "{{ web_app_details }}"
vars:
defaults_only:
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: true
web_app_details:
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\alexsapp'
loadUserProfile: false
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\bodhi'
- debug:
var: web_app_details_with_defaults
这会产生预期的结果:
web_app_details_with_defaults:
- enable32BitAppOnWin64: false
identityType: LocalSystem
loadUserProfile: false
web_destdir: E:\alexsapp
web_sourcedir: UWT_Optimus_UI
- enable32BitAppOnWin64: false
identityType: LocalSystem
loadUserProfile: true
web_destdir: E:\bodhi
web_sourcedir: UWT_Optimus_UI
有多种方法可以解决这个问题,但我的首选解决方案是:
- hosts: localhost
vars:
web_app_details:
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\alexsapp'
loadUserProfile: false
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\bodhi'
defaults_only:
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: true
web_app_details_with_defaults: "{{ [defaults_only] | product(web_app_details) | map('combine') }}"
tasks:
- debug:
msg: "{{ web_app_details_with_defaults }}"
表达式 {{ [defaults_only] | product(web_app_details) | map('combine') }}
创建列表 [defaults_only]
(内联 single-element 列表)和 web_app_details
的乘积,然后使用 map
组合每个字典列表合并到一个字典中。
PLAY [localhost] ***************************************************************
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
{
"enable32BitAppOnWin64": false,
"identityType": "LocalSystem",
"loadUserProfile": false,
"web_destdir": "E:\alexsapp",
"web_sourcedir": "UWT_Optimus_UI"
},
{
"enable32BitAppOnWin64": false,
"identityType": "LocalSystem",
"loadUserProfile": true,
"web_destdir": "E:\bodhi",
"web_sourcedir": "UWT_Optimus_UI"
}
]
}
如果您使用的是没有自动展开功能的旧版 Ansible,您需要在表达式中的某些点添加 | list
以将生成器转换为列表。可能只是 {{ [defaults_only] | product(web_app_details) | map('combine') | list }}
,但我还没有测试过。
我有一个 Web 应用程序及其配置列表。简化的数据结构看起来像这样(字典列表)
web_app_details:
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\alexsapp'
loadUserProfile: false
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\bodhi'
现在,我不希望用户每次都指定一些默认值(单个字典)
defaults_only:
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: true
如果用户未在 defaults_only
词典的任何字段中提供值,则应使用默认值。否则,应丢弃默认值。
所以结果是:
web_app_details:
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\alexsapp'
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: false # Because user provided the override value
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\bodhi'
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: true
我尝试了一些方法,例如
- 调用 Powershell 脚本在 Ansible 之外执行此操作
- 复制默认字典的次数与
web_app_detail
中一样多,然后使用组合过滤器 - 使用 JMESPath 查询插入
null
值:
- name: Pad web_app_details with null values
set_fact:
web_app_details_with_defaults: "{{ web_app_details | json_query(jmesquery) }}"
vars:
jmesquery:
"[*].{web_sourcedir: web_sourcedir, web_destdir: web_destdir, web_cleancopy: web_cleancopy }"
但没有任何效果。
有人可以帮忙吗?
您可以重新创建该列表,添加带有 combine
过滤器的默认值。
这将利用这样一个事实,即在两个词典中定义的 属性 将被您要合并的词典覆盖。
所以,您将完成这项 set_fact
任务:
- set_fact:
web_app_details_with_defaults: >-
{{
web_app_details_with_defaults | default([]) + [
defaults_only | combine(item)
]
}}
loop: "{{ web_app_details }}"
给定两个任务:
- set_fact:
web_app_details_with_defaults: >-
{{
web_app_details_with_defaults | default([]) + [
defaults_only | combine(item)
]
}}
loop: "{{ web_app_details }}"
vars:
defaults_only:
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: true
web_app_details:
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\alexsapp'
loadUserProfile: false
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\bodhi'
- debug:
var: web_app_details_with_defaults
这会产生预期的结果:
web_app_details_with_defaults:
- enable32BitAppOnWin64: false
identityType: LocalSystem
loadUserProfile: false
web_destdir: E:\alexsapp
web_sourcedir: UWT_Optimus_UI
- enable32BitAppOnWin64: false
identityType: LocalSystem
loadUserProfile: true
web_destdir: E:\bodhi
web_sourcedir: UWT_Optimus_UI
有多种方法可以解决这个问题,但我的首选解决方案是:
- hosts: localhost
vars:
web_app_details:
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\alexsapp'
loadUserProfile: false
- web_sourcedir: UWT_Optimus_UI
web_destdir: 'E:\bodhi'
defaults_only:
identityType: LocalSystem
enable32BitAppOnWin64: false
loadUserProfile: true
web_app_details_with_defaults: "{{ [defaults_only] | product(web_app_details) | map('combine') }}"
tasks:
- debug:
msg: "{{ web_app_details_with_defaults }}"
表达式 {{ [defaults_only] | product(web_app_details) | map('combine') }}
创建列表 [defaults_only]
(内联 single-element 列表)和 web_app_details
的乘积,然后使用 map
组合每个字典列表合并到一个字典中。
PLAY [localhost] ***************************************************************
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
{
"enable32BitAppOnWin64": false,
"identityType": "LocalSystem",
"loadUserProfile": false,
"web_destdir": "E:\alexsapp",
"web_sourcedir": "UWT_Optimus_UI"
},
{
"enable32BitAppOnWin64": false,
"identityType": "LocalSystem",
"loadUserProfile": true,
"web_destdir": "E:\bodhi",
"web_sourcedir": "UWT_Optimus_UI"
}
]
}
如果您使用的是没有自动展开功能的旧版 Ansible,您需要在表达式中的某些点添加 | list
以将生成器转换为列表。可能只是 {{ [defaults_only] | product(web_app_details) | map('combine') | list }}
,但我还没有测试过。