Ansible dnf 模块 returns 即使 dnf 失败也能成功

Ansible dnf module returns success even when dnf fails

  1. 这是我系统的初始状态:
    /root# rpm -q myrpm
    myrpm-2.0-0.x86_64
    /root# rpm -ql myrpm-2.0-0.x86_64
    /usr/share
    /usr/share/myfile
    /root# ls -lrt /usr/share | grep myfile
    -rw-r--r--   1 root root     11 May 25 17:32 myfile
    /root#
  1. 现在我正在模拟错误情况。我手动删除了该文件并在其位置创建了一个目录。
    /root# ls -lrt /usr/share | grep myfile
    drwxr-xr-x   2 root root   4096 May 25 18:33 myfile
    /root#
  1. 我准备了一个相同rpm的高版本3.0,复制了相同的文件
    /root# rpm -ql /root/update/myrpm-3.0-0.x86_64.rpm
    /usr/share
    /usr/share/myfile
    /root#

4-Test-1:尝试使用 ansible 的内置 dnf 模块进行 rpm 升级。 以下是我的剧本:

/root# cat test.yaml
---
- hosts: localhost
  tasks:
    - name: update rpm
      dnf:
        name: "myrpm"
        state: latest
/root#

执行此剧本将 return 代码设为 0。

/root# ansible-playbook -vvv test.yaml
...
changed: [localhost] => {
    "changed": true,
    "invocation": {
        "module_args": {
            "allow_downgrade": false,
            "autoremove": false,
            "bugfix": false,
            "conf_file": null,
            "disable_excludes": null,
            "disable_gpg_check": false,
            "disable_plugin": [],
            "disablerepo": [],
            "download_dir": null,
            "download_only": false,
            "enable_plugin": [],
            "enablerepo": [],
            "exclude": [],
            "install_repoquery": true,
            "install_weak_deps": true,
            "installroot": "/",
            "list": null,
            "lock_timeout": 30,
            "name": [
                "myrpm"
            ],
            "releasever": null,
            "security": false,
            "skip_broken": false,
            "state": "latest",
            "update_cache": false,
            "update_only": false,
            "validate_certs": true
        }
    },
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: myrpm-3.0-0.x86_64",
        "Removed: myrpm-2.0-0.x86_64"
    ]
}
META: ran handlers
META: ran handlers

PLAY RECAP *******************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

/root# echo $?
0
/root#

根据详细日志,rc 为 0。 但是,我可以看到 dnf 命令失败了。

/root# dnf history | head -n 3
ID     | Command line             | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
    27 |                          | 2022-05-25 18:39 | Upgrade        |    1 EE
/root# dnf history info 27 | tail -6
Packages Altered:
 ** Upgrade  myrpm-3.0-0.x86_64 @My_Update
    Upgraded myrpm-2.0-0.x86_64 @@System
Scriptlet output:
   1 error: unpacking of archive failed on file /usr/share/myfile: cpio: File from package already exists as a directory in system
   2 error: myrpm-3.0-0.x86_64: install failed
/root#

4-Test-2:我让我的系统处于与 3 完全相同的状态,并使用直接 dnf 命令而不是 playbook。

/root# dnf update myrpm
...
  Preparing        :                                                                              1/1
  Upgrading        : myrpm-3.0-0.x86_64                                                           1/2
Error unpacking rpm package myrpm-3.0-0.x86_64
error: unpacking of archive failed on file /usr/share/myfile: cpio: File from package already exists as a directory in system

  Cleanup          : myrpm-2.0-0.x86_64                                                           2/2
error: myrpm-3.0-0.x86_64: install failed

  Verifying        : myrpm-3.0-0.x86_64                                                           1/2
  Verifying        : myrpm-2.0-0.x86_64                                                           2/2

Failed:
  myrpm-3.0-0.x86_64

Error: Transaction failed
/root# echo $?
1
/root# 

关于为什么 playbook 没有将任务显示为失败的任何线索?

才知道这是ansible高版本修复的bug。 参考 https://github.com/ansible/ansible/issues/77917