Repository: ansible-collections/community.general

Issue:
Homebrew: module does not report useful error when `become: true` is passed
### Summary

When I try to install git with homebrew while setting `become: true`, the error message given is not useful in determining the reason for failure.

Through debugging I found out that I should not use `become: true`, but I wasted a lot of time trying to find other solutions to the stack trace I was receiving before.

I would like to raise a fix for this, to improve the error messaging.

### Issue Type

Bug Report

### Component Name

homebrew

### Ansible Version

```console (paste below)
$ ansible --version
ansible [core 2.16.4]
  config file = None
  configured module search path = ['/Users/michaelwall/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/michaelwall/Library/Application Support/pipx/venvs/ansible/lib/python3.12/site-packages/ansible
  ansible collection location = /Users/michaelwall/.ansible/collections:/usr/share/ansible/collections
  executable location = /Users/michaelwall/.local/bin/ansible
  python version = 3.12.2 (main, Feb  6 2024, 20:19:44) [Clang 15.0.0 (clang-1500.1.0.2.5)] (/Users/michaelwall/Library/Application Support/pipx/venvs/ansible/bin/python)
  jinja version = 3.1.3
  libyaml = True
```


### Community.general Version

```console (paste below)
$ ansible-galaxy collection list community.general

# /Users/michaelwall/Library/Application Support/pipx/venvs/ansible/lib/python3.12/site-packages/ansible_collections
Collection        Version
----------------- -------
community.general 8.4.0
```


### Configuration

```console (paste below)
$ ansible-config dump --only-changed

```


### OS / Environment

mac os sonoma 14.3 (23D56)

### Steps to Reproduce

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
- hosts: localhost
  become: true
  tasks:
    - name: Install Git
      community.general.homebrew:
        name: git
        state: present
```


### Expected Results

I expect to receive an error message stating that I should not try to become root when using Homebrew.

### Actual Results

```console (paste below)
michaelwall@UK-MICHAELW ansible % sudo ansible-playbook dev.yaml -e 'ansible_python_interpreter=/opt/homebrew/bin/python3.10'
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] **********************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Install Git] ********************************************************************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/var/root/.ansible/tmp/ansible-tmp-1709159481.450751-75442-19469324576457/AnsiballZ_homebrew.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/var/root/.ansible/tmp/ansible-tmp-1709159481.450751-75442-19469324576457/AnsiballZ_homebrew.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/var/root/.ansible/tmp/ansible-tmp-1709159481.450751-75442-19469324576457/AnsiballZ_homebrew.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.general.plugins.modules.homebrew', init_globals=dict(_module_fqn='ansible_collections.community.general.plugins.modules.homebrew', _modlib_path=modlib_path),\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 224, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 96, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 86, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 986, in <module>\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 971, in main\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 464, in run\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 541, in _run\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 657, in _install_packages\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 615, in _install_current_package\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 496, in _current_package_is_installed\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/__init__.py\", line 346, in loads\n    return _default_decoder.decode(s)\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/decoder.py\", line 337, in decode\n    obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/decoder.py\", line 355, in raw_decode\n    raise JSONDecodeError(\"Expecting value\", s, err.value) from None\njson.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct
Homebrew: module does not report useful error when `become: true` is passed
### Summary

When I try to install git with homebrew while setting `become: true`, the error message given is not useful in determining the reason for failure.

Through debugging I found out that I should not use `become: true`, but I wasted a lot of time trying to find other solutions to the stack trace I was receiving before.

I would like to raise a fix for this, to improve the error messaging.

### Issue Type

Bug Report

### Component Name

homebrew

### Ansible Version

```console (paste below)
$ ansible --version
ansible [core 2.16.4]
  config file = None
  configured module search path = ['/Users/michaelwall/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/michaelwall/Library/Application Support/pipx/venvs/ansible/lib/python3.12/site-packages/ansible
  ansible collection location = /Users/michaelwall/.ansible/collections:/usr/share/ansible/collections
  executable location = /Users/michaelwall/.local/bin/ansible
  python version = 3.12.2 (main, Feb  6 2024, 20:19:44) [Clang 15.0.0 (clang-1500.1.0.2.5)] (/Users/michaelwall/Library/Application Support/pipx/venvs/ansible/bin/python)
  jinja version = 3.1.3
  libyaml = True
```


### Community.general Version

```console (paste below)
$ ansible-galaxy collection list community.general

# /Users/michaelwall/Library/Application Support/pipx/venvs/ansible/lib/python3.12/site-packages/ansible_collections
Collection        Version
----------------- -------
community.general 8.4.0
```


### Configuration

```console (paste below)
$ ansible-config dump --only-changed

```


### OS / Environment

mac os sonoma 14.3 (23D56)

### Steps to Reproduce

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
- hosts: localhost
  become: true
  tasks:
    - name: Install Git
      community.general.homebrew:
        name: git
        state: present
```


### Expected Results

I expect to receive an error message stating that I should not try to become root when using Homebrew.

### Actual Results

```console (paste below)
michaelwall@UK-MICHAELW ansible % sudo ansible-playbook dev.yaml -e 'ansible_python_interpreter=/opt/homebrew/bin/python3.10'
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] **********************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Install Git] ********************************************************************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/var/root/.ansible/tmp/ansible-tmp-1709159481.450751-75442-19469324576457/AnsiballZ_homebrew.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/var/root/.ansible/tmp/ansible-tmp-1709159481.450751-75442-19469324576457/AnsiballZ_homebrew.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/var/root/.ansible/tmp/ansible-tmp-1709159481.450751-75442-19469324576457/AnsiballZ_homebrew.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.general.plugins.modules.homebrew', init_globals=dict(_module_fqn='ansible_collections.community.general.plugins.modules.homebrew', _modlib_path=modlib_path),\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 224, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 96, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 86, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 986, in <module>\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 971, in main\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 464, in run\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 541, in _run\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 657, in _install_packages\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 615, in _install_current_package\n  File \"/tmp/ansible_community.general.homebrew_payload_2r9s6y84/ansible_community.general.homebrew_payload.zip/ansible_collections/community/general/plugins/modules/homebrew.py\", line 496, in _current_package_is_installed\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/__init__.py\", line 346, in loads\n    return _default_decoder.decode(s)\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/decoder.py\", line 337, in decode\n    obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n  File \"/opt/homebrew/Cellar/python@3.10/3.10.13_2/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/decoder.py\", line 355, in raw_decode\n    raise JSONDecodeError(\"Expecting value\", s, err.value) from None\njson.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* [`plugins/callback/say.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/callback/say.py)

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](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @Akasurde @danieljaouen @indrajitr @kyleabenson @martinm82
[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Files identified in the description:
* [`plugins/callback/say.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/callback/say.py)

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](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @Akasurde @danieljaouen @indrajitr @kyleabenson @martinm82
[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/plugins/modules/homebrew.py b/plugins/modules/homebrew.py
--- a/plugins/modules/homebrew.py
+++ b/plugins/modules/homebrew.py
@@ -488,6 +488,10 @@ def _current_package_is_installed(self):
             self.current_package,
         ]
         rc, out, err = self.module.run_command(cmd)
+        if err:
+            self.failed = True
+            self.message = err.strip()
+            raise HomebrewException(self.message)
         data = json.loads(out)
 
         return _check_package_in_json(data, "formulae") or _check_package_in_json(data, "casks")


Test patch: