Repository: ansible-collections/community.general

Issue:
passwordstore: Improve error messages
### Summary

When using the passwordstore lookup plugin and the execution of pass fails (e.g. because the repository doesn't exist, the GPG key isn't present, ...) the output from Ansible simply is:
> {"msg": "An unhandled exception occurred while running the lookup plugin 'pass'. Error was a <class 'ansible.errors.AnsibleError'>, original message: Command '['pass', 'show', 'my/secret']' returned non-zero exit status 1."}

This is quite unhelpful, since the exit codes from pass aren't documented.

### Issue Type

Feature Idea

### Component Name

passwordstore

### Additional Information

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
- debug:
    var: 'lookup("passwordstore", "my/secret")'
```
When no password store is present, this should output helpful information, such as
> {"msg": "An unhandled exception occured while running the lookup plugin 'pass'. Error was a <class 'ansible.errors.AnsibleError'>, original message: Command '['pass', 'show', 'my/secret']' returned non-zero exit status 1, standard error: "Error: You must run:
    pass init your-gpg-id
before you may use the password store.".

This information even is available to the `AnsibleError` class, because the parent exception is a `submodule.CalledProcessError` which has a `output` attribute which is populated by the module.

### Code of Conduct

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


Discussion:
Files identified in the description:
* [`plugins/lookup/passwordstore.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/lookup/passwordstore.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 --->
Maybe my old code can be used for this, if the password store module is maintained now: https://github.com/ansible/ansible/pull/47120

(Back then, nobody had merging rights so it was stuck in limbo)
I don't think it's actively maintained, but if someone creates a PR that looks reasonable I'll merge it.

Resolving patch:
diff --git a/plugins/lookup/passwordstore.py b/plugins/lookup/passwordstore.py
--- a/plugins/lookup/passwordstore.py
+++ b/plugins/lookup/passwordstore.py
@@ -268,7 +268,7 @@ def is_real_pass(self):
                 )
                 self.realpass = 'pass: the standard unix password manager' in passoutput
             except (subprocess.CalledProcessError) as e:
-                raise AnsibleError(e)
+                raise AnsibleError('exit code {0} while running {1}. Error output: {2}'.format(e.returncode, e.cmd, e.output))
 
         return self.realpass
 
@@ -354,7 +354,7 @@ def check_pass(self):
         except (subprocess.CalledProcessError) as e:
             # 'not in password store' is the expected error if a password wasn't found
             if 'not in the password store' not in e.output:
-                raise AnsibleError(e)
+                raise AnsibleError('exit code {0} while running {1}. Error output: {2}'.format(e.returncode, e.cmd, e.output))
 
         if self.paramvals['missing'] == 'error':
             raise AnsibleError('passwordstore: passname {0} not found and missing=error is set'.format(self.passname))
@@ -387,7 +387,7 @@ def update_password(self):
         try:
             check_output2([self.pass_cmd, 'insert', '-f', '-m', self.passname], input=msg, env=self.env)
         except (subprocess.CalledProcessError) as e:
-            raise AnsibleError(e)
+            raise AnsibleError('exit code {0} while running {1}. Error output: {2}'.format(e.returncode, e.cmd, e.output))
         return newpass
 
     def generate_password(self):
@@ -399,7 +399,7 @@ def generate_password(self):
         try:
             check_output2([self.pass_cmd, 'insert', '-f', '-m', self.passname], input=msg, env=self.env)
         except (subprocess.CalledProcessError) as e:
-            raise AnsibleError(e)
+            raise AnsibleError('exit code {0} while running {1}. Error output: {2}'.format(e.returncode, e.cmd, e.output))
         return newpass
 
     def get_passresult(self):


Test patch: