![在 Ansible 中的字典列表中访问指定字典键的值](https://linux22.com/image/782159/%E5%9C%A8%20Ansible%20%E4%B8%AD%E7%9A%84%E5%AD%97%E5%85%B8%E5%88%97%E8%A1%A8%E4%B8%AD%E8%AE%BF%E9%97%AE%E6%8C%87%E5%AE%9A%E5%AD%97%E5%85%B8%E9%94%AE%E7%9A%84%E5%80%BC.png)
我正在安装 ansible 注册变量中的包列表并使用以下命令输出它debug
:
community.general.homebrew:
name: "{{ package }}"
state: present
register: package_install
until: package_install is succeeded
loop:
- pam-reattach
- pinentry-mac
- jorgelbg/tap/pinentry-touchid
loop_control:
loop_var: package
- debug:
msg: "{{ package_install }}"
输出如下所示:
msg:
changed: true
msg: All items completed
results:
- ansible_loop_var: package
attempts: 1
changed: false
changed_pkgs: []
failed: false
invocation:
module_args:
install_options: []
name:
- pam-reattach
path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
state: present
update_homebrew: false
upgrade_all: false
upgrade_options: []
msg: 'Package already installed: pam-reattach'
package: pam-reattach
unchanged_pkgs:
- pam-reattach
- ansible_loop_var: package
attempts: 1
changed: true
changed_pkgs:
- pinentry-mac
failed: false
invocation:
module_args:
install_options: []
name:
- pinentry-mac
path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
state: present
update_homebrew: false
upgrade_all: false
upgrade_options: []
msg: 'Package installed: pinentry-mac'
package: pinentry-mac
unchanged_pkgs: []
- ansible_loop_var: package
attempts: 1
changed: true
changed_pkgs:
- jorgelbg/tap/pinentry-touchid
failed: false
invocation:
module_args:
install_options: []
name:
- jorgelbg/tap/pinentry-touchid
path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
state: present
update_homebrew: false
upgrade_all: false
upgrade_options: []
msg: 'Package installed: jorgelbg/tap/pinentry-touchid'
package: jorgelbg/tap/pinentry-touchid
unchanged_pkgs: []
skipped: false
注册的变量包含一个字典列表(或地图/哈希 - 如果我错了请纠正我),其中包含与每个安装package_install.results
相关的数据。package
我需要检查在之前的任务中是否安装了pinentry-mac
或包(每个项目中的键pinentry-touchid
的值是否相等或),如果是,则运行指定的命令,例如:changed
true
false
- command: <command>
when: >
`pinentry-mac` item's attribute `changed` is `True` within `package_install.results` \
OR \
`pinentry-touchid` item's attribute `changed` is `True` within `package_install.results`
我该如何做呢?
现在我做以下事情:
- command: <command>
when: "'pinentry' in item.package and item.changed"
loop: "{{ macterm_package_install.results }}"
但是在这种情况下,如果两个包都是在上一步中安装的,则该命令将运行两次,尽管该命令只需运行一次。
有什么方法可以正确做到这一点?任何想法都非常感谢。
更新
我能找到的“最佳”方法是这样的(分为两步):
- name: Check if any of the pinentry packages were installed during previous tasks
set_fact:
pinentry_changed: True
when: "'pinentry-' in item.package and item.changed"
loop: "{{ macterm_package_install.results }}"
- command: <command>
when: pinentry_changed | default(false)
但实际上,有没有更优雅的方法来解决这个问题?
答案1
有很多选项。选择最适合您用例的选项。
- 创建词典
package_changed: "{{ package_install.results|
items2dict(key_name='package', value_name='changed') }}"
给出
package_changed:
jorgelbg/tap/pinentry-touchid: true
pam-reattach: false
pinentry-mac: true
那么条件就很简单了
- command: <command>
when: package_changed['pinentry-mac'] or
package_changed['jorgelbg/tap/pinentry-touchid']
- 创建已更改软件包的列表
changed_pkgs: "{{ package_install.results|
map(attribute='changed_pkgs')|flatten }}"
给出
changed_pkgs:
- pinentry-mac
- jorgelbg/tap/pinentry-touchid
测试每个包
- command: <command>
when: ('pinentry-mac' in changed_pkgs) or
('jorgelbg/tap/pinentry-touchid' in changed_pkgs)
或者如果可以将测试过的包放入列表中,则将列表相交
- command: <command>
when: changed_pkgs|intersect(test_pkgs)|length > 0
vars:
test_pkgs: [pinentry-mac, jorgelbg/tap/pinentry-touchid]
- 创建列表并映射基本名称
changed_pkgs: "{{ package_install.results|
map(attribute='changed_pkgs')|flatten|
map('basename')|list }}"
给出
changed_pkgs:
- pinentry-mac
- pinentry-touchid
仅使用包的名称
- command: <command>
when: ('pinentry-mac' in changed_pkgs) or
('pinentry-touchid' in changed_pkgs)