From f6ee2177a2134a916ef0f21d521529e51dd0af4c Mon Sep 17 00:00:00 2001 From: Alexei Znamensky <103110+russoz@users.noreply.github.com> Date: Sat, 8 Jul 2023 20:14:22 +1200 Subject: [PATCH] pacman: support yay as root (#6713) * pacman: support yay as root * make pylint happy * minor adjustments * rollback some test actions * removal of user and pkgs in handlers * add comment to note * add changelog frag * fix doc * Update tests/integration/targets/pacman/tasks/yay-become.yml Co-authored-by: Felix Fontein * Update tests/integration/targets/pacman/tasks/yay-become.yml Co-authored-by: Felix Fontein * simplify pkg install in int. tests --------- Co-authored-by: Felix Fontein --- changelogs/fragments/6713-yay-become.yml | 2 + plugins/modules/pacman.py | 36 ++++++---- .../targets/pacman/handlers/main.yml | 23 +++++++ .../integration/targets/pacman/tasks/main.yml | 1 + .../targets/pacman/tasks/yay-become.yml | 66 +++++++++++++++++++ 5 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 changelogs/fragments/6713-yay-become.yml create mode 100644 tests/integration/targets/pacman/handlers/main.yml create mode 100644 tests/integration/targets/pacman/tasks/yay-become.yml diff --git a/changelogs/fragments/6713-yay-become.yml b/changelogs/fragments/6713-yay-become.yml new file mode 100644 index 0000000000..389b4c23e4 --- /dev/null +++ b/changelogs/fragments/6713-yay-become.yml @@ -0,0 +1,2 @@ +bugfixes: + - pacman - module recognizes the output of ``yay`` running as ``root`` (https://github.com/ansible-collections/community.general/pull/6713). diff --git a/plugins/modules/pacman.py b/plugins/modules/pacman.py index 83b2492317..7f67b91039 100644 --- a/plugins/modules/pacman.py +++ b/plugins/modules/pacman.py @@ -133,6 +133,9 @@ notes: it is much more efficient to pass the list directly to the O(name) option. - To use an AUR helper (O(executable) option), a few extra setup steps might be required beforehand. For example, a dedicated build user with permissions to install packages could be necessary. + - > + In the tests, while using C(yay) as the O(executable) option, the module failed to install AUR packages + with the error: C(error: target not found: ). """ RETURN = """ @@ -263,6 +266,7 @@ EXAMPLES = """ reason_for: all """ +import re import shlex from ansible.module_utils.basic import AnsibleModule from collections import defaultdict, namedtuple @@ -418,7 +422,7 @@ class Pacman(object): for p in name_ver: # With Pacman v6.0.1 - libalpm v13.0.1, --upgrade outputs "loading packages..." on stdout. strip that. # When installing from URLs, pacman can also output a 'nothing to do' message. strip that too. - if "loading packages" in p or "there is nothing to do" in p: + if "loading packages" in p or "there is nothing to do" in p or 'Avoid running' in p: continue name, version = p.split() if name in self.inventory["installed_pkgs"]: @@ -706,11 +710,12 @@ class Pacman(object): installed_pkgs = {} dummy, stdout, dummy = self.m.run_command([self.pacman_path, "--query"], check_rc=True) # Format of a line: "pacman 6.0.1-2" + query_re = re.compile(r'^\s*(?P\S+)\s+(?P\S+)\s*$') for l in stdout.splitlines(): - l = l.strip() - if not l: + query_match = query_re.match(l) + if not query_match: continue - pkg, ver = l.split() + pkg, ver = query_match.groups() installed_pkgs[pkg] = ver installed_groups = defaultdict(set) @@ -721,11 +726,12 @@ class Pacman(object): # base-devel file # base-devel findutils # ... + query_groups_re = re.compile(r'^\s*(?P\S+)\s+(?P\S+)\s*$') for l in stdout.splitlines(): - l = l.strip() - if not l: + query_groups_match = query_groups_re.match(l) + if not query_groups_match: continue - group, pkgname = l.split() + group, pkgname = query_groups_match.groups() installed_groups[group].add(pkgname) available_pkgs = {} @@ -747,11 +753,12 @@ class Pacman(object): # vim-plugins vim-airline-themes # vim-plugins vim-ale # ... + sync_groups_re = re.compile(r'^\s*(?P\S+)\s+(?P\S+)\s*$') for l in stdout.splitlines(): - l = l.strip() - if not l: + sync_groups_match = sync_groups_re.match(l) + if not sync_groups_match: continue - group, pkg = l.split() + group, pkg = sync_groups_match.groups() available_groups[group].add(pkg) upgradable_pkgs = {} @@ -759,9 +766,14 @@ class Pacman(object): [self.pacman_path, "--query", "--upgrades"], check_rc=False ) + stdout = stdout.splitlines() + if stdout and "Avoid running" in stdout[0]: + stdout = stdout[1:] + stdout = "\n".join(stdout) + # non-zero exit with nothing in stdout -> nothing to upgrade, all good # stderr can have warnings, so not checked here - if rc == 1 and stdout == "": + if rc == 1 and not stdout: pass # nothing to upgrade elif rc == 0: # Format of lines: @@ -771,7 +783,7 @@ class Pacman(object): l = l.strip() if not l: continue - if "[ignored]" in l: + if "[ignored]" in l or "Avoid running" in l: continue s = l.split() if len(s) != 4: diff --git a/tests/integration/targets/pacman/handlers/main.yml b/tests/integration/targets/pacman/handlers/main.yml new file mode 100644 index 0000000000..484482bba3 --- /dev/null +++ b/tests/integration/targets/pacman/handlers/main.yml @@ -0,0 +1,23 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +- name: Remove user yaybuilder + ansible.builtin.user: + name: yaybuilder + state: absent + +- name: Remove yay + ansible.builtin.package: + name: yay + state: absent + +- name: Remove packages for yay-become + ansible.builtin.package: + name: + - base-devel + - yay + - git + - nmap + state: absent diff --git a/tests/integration/targets/pacman/tasks/main.yml b/tests/integration/targets/pacman/tasks/main.yml index 12d28a2d3e..1f6001a669 100644 --- a/tests/integration/targets/pacman/tasks/main.yml +++ b/tests/integration/targets/pacman/tasks/main.yml @@ -17,3 +17,4 @@ - include_tasks: 'update_cache.yml' - include_tasks: 'locally_installed_package.yml' - include_tasks: 'reason.yml' + - include_tasks: 'yay-become.yml' diff --git a/tests/integration/targets/pacman/tasks/yay-become.yml b/tests/integration/targets/pacman/tasks/yay-become.yml new file mode 100644 index 0000000000..30f322effe --- /dev/null +++ b/tests/integration/targets/pacman/tasks/yay-become.yml @@ -0,0 +1,66 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +# This is more convoluted that one might expect, because: +# - yay is not available or installation in ArchLinux (as it is in Manjaro - issue 6184 reports using it) +# - to install yay in ArchLinux requires building the package +# - makepkg cannot be run as root, but the user running it must have sudo to install the resulting package + +- name: create user + ansible.builtin.user: + name: yaybuilder + state: present + notify: Remove user yaybuilder + +- name: grant sudo powers to builder + community.general.sudoers: + name: yaybuilder + user: yaybuilder + commands: ALL + nopassword: true + +- name: Install base packages + ansible.builtin.package: + name: + - base-devel + - git + - go + state: present + notify: Remove packages for yay-become + +- name: Hack permssions for the remote_tmp_dir + ansible.builtin.file: + path: "{{ remote_tmp_dir }}" + mode: '0777' + +- name: Create temp directory for builder + ansible.builtin.file: + path: "{{ remote_tmp_dir }}/builder" + owner: yaybuilder + state: directory + mode: '0755' + +- name: clone yay git repo + become: true + become_user: yaybuilder + ansible.builtin.git: + repo: https://aur.archlinux.org/yay.git + dest: "{{ remote_tmp_dir }}/builder/yay" + depth: 1 + +- name: make package + become: true + become_user: yaybuilder + ansible.builtin.command: + chdir: "{{ remote_tmp_dir }}/builder/yay" + cmd: makepkg -si --noconfirm + notify: Remove yay + +- name: Install nmap + community.general.pacman: + name: nmap + state: present + executable: yay + extra_args: --builddir /var/cache/yay