Repository: ansible-collections/community.general

Issue:
pacman does not honor the "ignore" settings in package diff
**Summary**

I have an ignore setting on one of my systems, telling it to ignore any php upgrade. When I then upgrade said system the diff shows that it upgraded php, but it doesn't actually upgrades php. Using the playbook I check which services need to be restarted to use new versions and it always restarts `php-fpm` in this case.


**Issue Type**

Bug Report

**Component Name**

pacman

**Ansible Version**

```
ansible 2.9.17
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/mschlapa/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.8/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.7 (default, Jan 20 2021, 00:00:00) [GCC 10.2.1 20201125 (Red Hat 10.2.1-9)]
```


**Configuration**

```paste below

```


**OS / Environment**

ArchLinux

**Steps To Reproduce**

`/etc/pacman.conf`
```
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
IgnorePkg   = php php-apcu php-fpm php-gd php-imagick php-imap php-intl imagemagick
#IgnoreGroup =
```

**Expected Results**

No diff.

**Actual Results**

```diff
--- before
+++ after
@@ -1,11 +1,11 @@
-imagemagick-7.0.10.60-1
-php-7.4.14-1
-php-apcu-5.1.19-1
-php-fpm-7.4.14-1
-php-gd-7.4.14-1
-php-imagick-3.4.4-8
-php-imap-7.4.14-1
-php-intl-7.4.14-1
+imagemagick-7.0.10.62-1
+php-8.0.2-1
+php-apcu-5.1.19-2
+php-fpm-8.0.2-1
+php-gd-8.0.2-1
+php-imagick-3.4.4.r66.g448c1cd-2
+php-imap-8.0.2-1
+php-intl-8.0.2-1
```




Discussion:
Files identified in the description:
* [`plugins/modules/packaging/os/pacman.py`](https://github.com/ansible-collections/community.general/blob/master/plugins/modules/packaging/os/pacman.py)

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

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @indrajitr @tchernomax
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
The problem is pacman asks for packages in `IgnorePkg` like this:
`:: pkg_name is in IgnorePkg/IgnoreGroup. Install anyway? [Y/n] n`
But it will installs it anyway when `--noconfirm` is present.

~~Module should check for `ignorepkg` and `ignoregroup` in `/etc/pacman.conf` and passes them to cmd using `--ignore` and `--ignoregroup` flags.~~ pacman will upgrade package even when you `--ignore` it.
```
$ sudo pacman -S pkg_name --ignore pkg_name
:: pkg_name is in IgnorePkg/IgnoreGroup. Install anyway? [Y/n]
```

Edit: On a second thought I think this behaviour is acceptable as you're passing packages to module explicitly and pacman asks and upgrades packages in `IgnorePkg` if you ask it to do it explicitly.

What do you think module should do?

needs_info
I'm not passing any package to the pacman module:
```yaml
  tasks:
  - name: Update repos and upgrade servers (pacman)
    pacman:
      update_cache: yes 
      upgrade: yes
```
I'm just upgrading stuff. But this is not even the problem.

The output of the module is wrong. It outputs that it updated the package while not updating it. My handler for restarting updated services checks the output of the pacman module and then restarts the not updated service.
So the problem is something else, because I've just tested your playbook and it did not upgrade ignored packages.
It executed this command which does not upgrade ignored packages, so we're good at that.
`/usr/bin/pacman --sync --sysupgrade --quiet --noconfirm`

About changed, you're right, this is a bug. The package which I held back (shaderc) did not get upgraded, but module returned changed anyhow.

```
changed: [localhost] => {
    "changed": true,
    "diff": {
        "after": "",
        "before": ""
    },
    "invocation": {
        "module_args": {
            "executable": "pacman",
            "extra_args": "",
            "force": false,
            "name": null,
            "state": "present",
            "update_cache": true,
            "update_cache_extra_args": "",
            "upgrade": true,
            "upgrade_extra_args": ""
        }
    },
    "msg": "System upgraded",
    "packages": [
        "shaderc"
    ]
}
```

Resolving patch:
diff --git a/plugins/modules/packaging/os/pacman.py b/plugins/modules/packaging/os/pacman.py
--- a/plugins/modules/packaging/os/pacman.py
+++ b/plugins/modules/packaging/os/pacman.py
@@ -254,16 +254,23 @@ def upgrade(module, pacman_path):
         # e.g., "ansible 2.7.1-1 -> 2.7.2-1"
         regex = re.compile(r'([\w+\-.@]+) (\S+-\S+) -> (\S+-\S+)')
         for p in data:
-            m = regex.search(p)
-            packages.append(m.group(1))
-            if module._diff:
-                diff['before'] += "%s-%s\n" % (m.group(1), m.group(2))
-                diff['after'] += "%s-%s\n" % (m.group(1), m.group(3))
+            if '[ignored]' not in p:
+                m = regex.search(p)
+                packages.append(m.group(1))
+                if module._diff:
+                    diff['before'] += "%s-%s\n" % (m.group(1), m.group(2))
+                    diff['after'] += "%s-%s\n" % (m.group(1), m.group(3))
         if module.check_mode:
-            module.exit_json(changed=True, msg="%s package(s) would be upgraded" % (len(data)), packages=packages, diff=diff)
+            if packages:
+                module.exit_json(changed=True, msg="%s package(s) would be upgraded" % (len(data)), packages=packages, diff=diff)
+            else:
+                module.exit_json(changed=False, msg='Nothing to upgrade', packages=packages)
         rc, stdout, stderr = module.run_command(cmdupgrade, check_rc=False)
         if rc == 0:
-            module.exit_json(changed=True, msg='System upgraded', packages=packages, diff=diff)
+            if packages:
+                module.exit_json(changed=True, msg='System upgraded', packages=packages, diff=diff)
+            else:
+                module.exit_json(changed=False, msg='Nothing to upgrade', packages=packages)
         else:
             module.fail_json(msg="Could not upgrade")
     else:


Test patch: