ansible-collections / community.general

Ansible Community General Collection
https://galaxy.ansible.com/ui/repo/published/community/general/
GNU General Public License v3.0
832 stars 1.53k forks source link

pacman: Install of group base-devel does not install member package make #6290

Open kisp opened 1 year ago

kisp commented 1 year ago

Summary

When I use community.general.pacman to install the group base-devel, I expect that all member packages will be installed. As an example, make is a member package, but for some reason it does not get installed.

Issue Type

Bug Report

Component Name

pacman

Ansible Version

$ ansible --version
ansible [core 2.14.4]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.10 (main, Mar  5 2023, 22:26:53) [GCC 12.2.1 20230201] (/usr/bin/python)
  jinja version = 3.1.2
  libyaml = True

Community.general Version

$ ansible-galaxy collection list community.general
# /home/user/repos/repo/ansible/ansible_collections
Collection        Version
----------------- -------
community.general 5.2.0

# /usr/lib/python3.10/site-packages/ansible_collections
Collection        Version
----------------- -------
community.general 6.5.0

I believe that upgrading the local ansible_collections to community.general 6.5.0 does not change the observed behaviour (but I can double check that again if desired).

Configuration

$ ansible-config dump --only-changed
COLLECTIONS_PATHS(/home/user/repos/repo/ansible/ansible.cfg) = ['/home/user/repos/repo/ansible']
CONFIG_FILE() = /home/user/repos/repo/ansible/ansible.cfg
DEFAULT_ROLES_PATH(/home/user/repos/repo/ansible/ansible.cfg) = ['/home/user/repos/repo/ansible/>
DEFAULT_STDOUT_CALLBACK(/home/user/repos/repo/ansible/ansible.cfg) = debug
HOST_KEY_CHECKING(/home/user/repos/repo/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/home/user/repos/repo/ansible/ansible.cfg) = auto_silent

OS / Environment

Arch Linux

Steps to Reproduce

---
- name: Test playbook
  hosts: all
  vars:
    ansible_python_interpreter: /usr/bin/python3
  tasks:
    - name: Ensure make is not installed
      community.general.pacman:
        state: absent
        name:
          - make
    - name: Install base-devel
      community.general.pacman:
        state: present
        name:
          - base-devel
    - name: Run make -v
      ansible.builtin.command:
        cmd: make -v
      register: make_v
    - name: Show make -v output
      ansible.builtin.debug:
        msg: "{{ make_v.stdout }}"

Expected Results

I expect make to be available after installing base-devel.

PLAY [Test playbook] **********************************************************************

TASK [Gathering Facts] ********************************************************************
ok: [172.105.72.134]

TASK [Ensure make is not installed] *******************************************************
ok: [172.105.72.134]

TASK [Install base-devel] *****************************************************************
ok: [172.105.72.134]

TASK [Run make -v] ************************************************************************
changed: [172.105.72.134]

TASK [Show make -v output] ****************************************************************
ok: [172.105.72.134] => {}

MSG:

GNU Make 4.4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

PLAY RECAP ********************************************************************************
172.105.72.134             : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Actual Results

PLAY [Test playbook] **********************************************************************

TASK [Gathering Facts] ********************************************************************
ok: [172.105.72.134]

TASK [Ensure make is not installed] *******************************************************
ok: [172.105.72.134]

TASK [Install base-devel] *****************************************************************
ok: [172.105.72.134]

TASK [Run make -v] ************************************************************************
fatal: [172.105.72.134]: FAILED! => {
    "changed": false,
    "cmd": "make -v",
    "rc": 2
}

MSG:

[Errno 2] No such file or directory: b'make'

PLAY RECAP ********************************************************************************
172.105.72.134             : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Code of Conduct

ansibullbot commented 1 year ago

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot commented 1 year ago

cc @indrajitr @tchernomax click here for bot help

javanaut-de commented 1 year ago

The whole base-devel group is not installed. The following output is generated when running pacman -S with the same package list as before with the pacman ansible module. All packages of the base-devel group are missing, so there is no old version shown for them: image

Wouterkoorn commented 1 year ago

pacman --query --groups will output the group name of some installed packages even though the base-devel group and its other package are not installed

base-devel binutils
base-devel gcc
base-devel libtool
...

The pacman module uses this command as its source of truth: https://github.com/ansible-collections/community.general/blob/main/plugins/modules/pacman.py#L716-L729

I cannot find a single command that will list all the groups without this problem, but this could be fixed by adding a verification in the loop. Which is running pacman --query {group}.

Unless someone know a better way to list all installed groups in one go, I'm happy to submit a PR adding this extra command in the loop.

ansibullbot commented 1 year ago

cc @jraby click here for bot help

jraby commented 1 year ago

I tried to reproduce this here without much success, the test case provided indeed doesn't work, but unless I'm missing something obvious, make doesn't seem to be part of the base-devel group:

$ pacman -Sgg base-devel
base-devel binutils
base-devel gcc
base-devel libtool

(it doesn't seem to be part of a group either, by looking at pacman -Sgg | grep make)

If, instead of make, we use gcc, it seems to work properly:

---
- name: Test playbook
  hosts: localhost
  vars:
    ansible_python_interpreter: /usr/bin/python3
  tasks:
    - name: Ensure group member is not installed
      community.general.pacman:
        state: absent
        force: true
        name:
          - gcc
    - name: Install group
      community.general.pacman:
        state: present
        name:
          - base-devel
    - name: Run cmd
      ansible.builtin.command:
        cmd: gcc --version
      register: output
    - name: Show output
      ansible.builtin.debug:
        msg: "{{ output.stdout }}"
PLAY [Test playbook] ***********************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Ensure group member is not installed] ************************************************************************************************************************************************************************
--- before
+++ after
@@ -1 +0,0 @@
-gcc-12.2.1-2

changed: [localhost]

TASK [Install group] ***********************************************************************************************************************************************************************************************
--- before
+++ after
@@ -0,0 +1 @@
+gcc-12.2.1-2

changed: [localhost]

TASK [Run cmd] *****************************************************************************************************************************************************************************************************
changed: [localhost]

TASK [Show output] *************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "gcc (GCC) 12.2.1 20230201\nCopyright (C) 2022 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
}

PLAY RECAP *********************************************************************************************************************************************************************************************************
localhost                  : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

@kisp can you confirm this behavior?

jraby commented 1 year ago

Of course I find the problem minutes after sending the above...

make is a dependency of the base-devel package group, but it isn't a member of the group.

The current logic of the module doesn't account for dependencies of groups, it simply adds all group members to the list of package to install.

I don't recall exactly why I implemented group expansion that way, instead of letting pacman do it, possibly to generate diffs of package to install/remove.

I haven't looked closely at the code in a while, so take this with a grain of salt, but I think the module should let pacman handle the groups and their dependencies, otherwise we'd end up reimplementing even more of pacman in the module, it doesn't sound right.

felixfontein commented 1 year ago

Just as a generic comment: the tricky part is usually getting diff and check mode to work. These might have been reasons to implement it as it is now.

If there's a way to tell pacman "Tell me what exactly would happen if I try to install / remove this package, but don't do it" it's probably best to use that instead.

mhdry commented 1 year ago

This is related to the recent switch to the base-devel meta package.

There seems to be a new (meta) package named base-devel which contains all other packages as dependencies, while at the same time there is also the old base-devel package group, which still contains binutils, gcc and libtool.

I've brought this issue up in the Arch Linux forum.

mhdry commented 1 year ago
$ pacman --query --groups | grep base-devel
$ pacman -Sgg base-devel

Both are now empty, so there is only the new meta package installing base-devel. I think this should now work fine.