From 14b1febf64f03d5d1b7b02acb7749055accd12fc Mon Sep 17 00:00:00 2001 From: Klaus Frank Date: Sat, 1 Feb 2020 14:37:27 +0100 Subject: [PATCH] Fix pacman: "IndexError: list index out of range" #63077 (#65750) * Fix #63077 If the package is already installed the stdout is not as expected by this function. Either remove `--needed` or just noop if we detect pacman returning. We cannot match the stdout string, as that is most likely localized. ``` [root@archBook user]# /usr/bin/pacman --upgrade --noconfirm --noprogressbar --needed /srv/aur/src/i3cat-git/i3cat-git-r38.c6d29dd-1-x86_64.pkg.tar.xz loading packages... warning: i3cat-git-r38.c6d29dd-1 is up to date -- skipping there is nothing to do ``` * Add comment Add comment * Add changelog fragment. Co-authored-by: Felix Fontein --- changelogs/fragments/65750-pacman.yml | 2 ++ lib/ansible/modules/packaging/os/pacman.py | 38 +++++++++++++--------- 2 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 changelogs/fragments/65750-pacman.yml diff --git a/changelogs/fragments/65750-pacman.yml b/changelogs/fragments/65750-pacman.yml new file mode 100644 index 00000000000..40995dde387 --- /dev/null +++ b/changelogs/fragments/65750-pacman.yml @@ -0,0 +1,2 @@ +bugfixes: +- "pacman - fix module crash with ``IndexError: list index out of range`` (https://github.com/ansible/ansible/issues/63077)" diff --git a/lib/ansible/modules/packaging/os/pacman.py b/lib/ansible/modules/packaging/os/pacman.py index dded7bd5149..4b9d6b2a903 100644 --- a/lib/ansible/modules/packaging/os/pacman.py +++ b/lib/ansible/modules/packaging/os/pacman.py @@ -329,14 +329,17 @@ def install_packages(module, pacman_path, state, packages, package_files): if rc != 0: module.fail_json(msg="failed to install %s: %s" % (" ".join(to_install_repos), stderr)) - data = stdout.split('\n')[3].split(' ')[2:] - data = [i for i in data if i != ''] - for i, pkg in enumerate(data): - data[i] = re.sub('-[0-9].*$', '', data[i].split('/')[-1]) - if module._diff: - diff['after'] += "%s\n" % pkg - - install_c += len(to_install_repos) + # As we pass `--needed` to pacman returns a single line of ` there is nothing to do` if no change is performed. + # The check for > 3 is here because we pick the 4th line in normal operation. + if len(stdout.split('\n')) > 3: + data = stdout.split('\n')[3].split(' ')[2:] + data = [i for i in data if i != ''] + for i, pkg in enumerate(data): + data[i] = re.sub('-[0-9].*$', '', data[i].split('/')[-1]) + if module._diff: + diff['after'] += "%s\n" % pkg + + install_c += len(to_install_repos) if to_install_files: cmd = "%s --upgrade --noconfirm --noprogressbar --needed %s %s" % (pacman_path, module.params["extra_args"], " ".join(to_install_files)) @@ -345,14 +348,17 @@ def install_packages(module, pacman_path, state, packages, package_files): if rc != 0: module.fail_json(msg="failed to install %s: %s" % (" ".join(to_install_files), stderr)) - data = stdout.split('\n')[3].split(' ')[2:] - data = [i for i in data if i != ''] - for i, pkg in enumerate(data): - data[i] = re.sub('-[0-9].*$', '', data[i].split('/')[-1]) - if module._diff: - diff['after'] += "%s\n" % pkg - - install_c += len(to_install_files) + # As we pass `--needed` to pacman returns a single line of ` there is nothing to do` if no change is performed. + # The check for > 3 is here because we pick the 4th line in normal operation. + if len(stdout.split('\n')) > 3: + data = stdout.split('\n')[3].split(' ')[2:] + data = [i for i in data if i != ''] + for i, pkg in enumerate(data): + data[i] = re.sub('-[0-9].*$', '', data[i].split('/')[-1]) + if module._diff: + diff['after'] += "%s\n" % pkg + + install_c += len(to_install_files) if state == 'latest' and len(package_err) > 0: message = "But could not ensure 'latest' state for %s package(s) as remote version could not be fetched." % (package_err)