在断言之外使用 ansible.builtin.version

在断言之外使用 ansible.builtin.version

我的工作任务如下:

- 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

笔记

  1. 可以使用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

  1. 一个优雅的选择是定制事实. 在要检查 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 -qawhen -all 并非绝对必要。尽管在 rpm 的情况下,它使用的是 Python 绑定而不是程序。

assert 是一个动作插件,因此不需要远程访问任何地方或运行外部命令。因此,合并任务不会节省太多的运行时间。

仅收集数据的任务,因此会增加播放摘要中的任务数量,但从不改变任何事情,对我来说是可以接受的风格。在 Ansible 中执行许多不平凡的事情需要设置,而这些任务并不总是会改变任何事情。

小建议,考虑将版本字符串设为变量。应用程序的主要版本要求可能不会经常更改。但是,在测试您的角色时,最好看看故障情况是什么样的。

相关内容