我的工作任务如下:
- name: Get Package infos
ansible.builtin.package_facts:
manager: auto
- name: Test redis-server version
ansible.builtin.assert:
that:
- ansible_facts.packages['redis-server'][0].version is version('4.0', '>=')
我想知道是否能够将这些任务合并为一个任务:
- name: Get Package infos
tags: redis
ansible.builtin.package_facts:
manager: auto
failed_when: ansible_facts.packages['redis-server'][0].version is version('4.0', '<')
但如果我这样做,我会收到相当长的错误信息,其结尾是:
The error was: error while evaluating conditional
(ansible_facts.packages['redis-server'][0].version is version('4.0', '<')):
'dict object' has no attribute 'packages'. 'dict object' has no attribute 'packages'"}
看起来该字段packages
此时不存在。有什么方法可以修复此方法?
答案1
一个简约的选择是
- command: redis-cli --version
register: out
failed_when: out.stdout|split|last is version(7.0, '<')
或者,也可以测试rc
- command: redis-cli --version
register: out
failed_when:
out.rc != 0 or
out.stdout|split|last is version(7.0, '<')
这项任务不会改变任何事情。禁止报告已更改地位
- command: redis-cli --version
register: out
failed_when:
out.rc != 0 or
out.stdout|split|last is version(7.0, '<')
changed_when: false
笔记
- 可以使用ansible_facts.packages来自注册变量。但是,模块包装事实检查 redis 的版本并不实用,因为它依赖于操作系统并且速度很慢。例如,
- package_facts:
register: out
- debug:
msg: |
{{ out.ansible_facts.packages['redis-server'] |
map(attribute='version') }}"
{{ out.failed }}
在 Ubuntu 上提供
msg: |-
['5:7.0.12-1']
False
相当于上面的命令任务是
- package_facts:
register: out
failed_when:
out.failed or
ver is version(7.0, '<')
vars:
ver: "{{ out.ansible_facts.packages['redis-server'] |
map(attribute='version') |
first |
split(':') |
last }}"
changed_when: false
- 一个优雅的选择是定制事实. 在要检查 redis 版本的远程主机上创建以下脚本
shell> cat /etc/ansible/facts.d/redis.fact
#!/usr/bin/sh
ver=`(redis-cli --version | cut -d ' ' -f 2)`
echo {\"redis_version\": \"$ver\"}
测试一下
shell> /etc/ansible/facts.d/redis.fact
{"redis_version": "7.0.12"}
然后,下面的游戏
- hosts: localhost
tasks:
- setup:
gather_subset: facter
- debug:
var: ansible_local
给出(节选)
ansible_local:
redis:
redis_version: 7.0.12
答案2
正确,ansible_facts 不会在任务完成和同一任务评估其 failed_when 之间更新。
按原样使用您的第一次尝试,package_facts
然后断言。完全可以理解它在做什么。
package_facts 检查系统包管理器,这对于集中管理软件的安装方式来说是一个不错的选择。(如果您的操作系统发行版支持此模块。)您可以以其他方式安装,但这需要其他方法来维护和修补它。
以标准格式收集有关所有软件包的事实,从六个软件包管理器中提取信息,值得花费软件包管理器查询的少量性能成本。类似于执行rpm -qa
when -all 并非绝对必要。尽管在 rpm 的情况下,它使用的是 Python 绑定而不是程序。
assert 是一个动作插件,因此不需要远程访问任何地方或运行外部命令。因此,合并任务不会节省太多的运行时间。
仅收集数据的任务,因此会增加播放摘要中的任务数量,但从不改变任何事情,对我来说是可以接受的风格。在 Ansible 中执行许多不平凡的事情需要设置,而这些任务并不总是会改变任何事情。
小建议,考虑将版本字符串设为变量。应用程序的主要版本要求可能不会经常更改。但是,在测试您的角色时,最好看看故障情况是什么样的。