Repository: ansible-collections/community.general

Issue:
Ansible Jira Community Module exits with error 
### Summary

When I use ansible jira module for creating jira ticket , it exits with below error . The interesting part it had created the jira ticket , but the task exists with an error . 

To see the full traceback, use -vvv. The error was: KeyError: 'body'
fatal: [f51 -> localhost]: FAILED! => {"changed": false, "msg": "Module failed with exception: 'body'", "output": {"restbase": "https://jira2.domain/rest/api/2", "state": "create"}, "restbase": "https://jira2.domain.com/rest/api/2", "state": "create", "vars": {"restbase": "https://jira2.domain/rest/api/2", "state": "create"}}


### Issue Type

Bug Report

### Component Name

jira

### Ansible Version

```console (paste below)
ansible [core 2.11.3]
  config file = None
  configured module search path = ['/Users/user1/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
  ansible collection location = /Users/user1/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.6 (default, Jun 29 2021, 05:25:02) [Clang 12.0.5 (clang-1205.0.22.9)]
  jinja version = 3.0.1
  libyaml = True
```


### Configuration

```console (paste below)
$ ansible-config dump --only-changed

```


### OS / Environment

MAC OSX  BigSur : Version 11.3.1
darwin  20.4.0 Darwin Kernel Version 20.4.0: Thu Apr 22 21:46:47 PDT 2021; root:xnu-7195.101.2~1/RELEASE_X86_64 x86_64

### Steps to Reproduce

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
- name: Create Subtask Jira for each expiring cert
  jira: 
    uri: https://jira2.domain.com/
    username: "{{jira_username}}"
    password: "{{jira_password}}"
    project: "INF"
    operation: create
    summary: "Certificate:{{outer_item.name}} expiring on {{outer_item.expiration_date}} "
    description: "Certificate Details {{outer_item}}"
    
    issuetype: Sub-task
    validate_certs: False
    
  args:
    fields:
      parent:
        key: 'INF-12345'
      components:
         - name: "INF OPS"
     # labels:
     #   - autocreated
     #   - ansible
        
  delegate_to: localhost
  loop_control: 
    extended: yes 
    label: 
      - "{{outer_item.name}}"

  register: subtask_jira_output
```


### Expected Results

I expect ok and completion of task so that it can continue executing further . but it errors out and stops the task

### Actual Results

```console (paste below)
TASK [Create Subtask Jira for each expiring cert] **********************************************************************************************************************************************************************************
To see the full traceback, use -vvv. The error was: KeyError: 'body'
fatal: [f51 -> localhost]: FAILED! => {"changed": false, "msg": "Module failed with exception: 'body'", "output": {"restbase": "https://jira2.domain/rest/api/2", "state": "create"}, "restbase": "https://jira2.domain.com/rest/api/2", "state": "create", "vars": {"restbase": "https://jira2.domain/rest/api/2", "state": "create"}}
```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* `lib/ansible/cli/__init__.py`
* [`plugins/modules/packaging/language/ansible_galaxy_install.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/modules/packaging/language/ansible_galaxy_install.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 --->
You should really run the module with `-vvv` to provide the stack trace.
Files identified in the description:
* [`plugins/modules/web_infrastructure/jira.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/modules/web_infrastructure/jira.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 @DWSR @Slezhuk @pertoft @tarka
[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Hi @felixfontein  ,  I was trying to reproduce this issue , and it is very intermittent . But today I was able to catch similar error while looking up for a Jira Issue

Please see the details here :

TASK [Get Parent Jira details] *******************************************************************************************************************************************************************************************
task path: /Users/david/code/ansible/dev/playbooks/project-f5/dev-test/playbooks/jira-error-test.yml:62
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: david
<localhost> EXEC /bin/sh -c 'echo ~david && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /Users/david/.ansible/tmp `"&& mkdir "` echo /Users/david/.ansible/tmp/ansible-tmp-1635294120.542293-84232-181104301591571 `" && echo ansible-tmp-1635294120.542293-84232-181104301591571="` echo /Users/david/.ansible/tmp/ansible-tmp-1635294120.542293-84232-181104301591571 `" ) && sleep 0'
redirecting (type: modules) ansible.builtin.jira to community.general.jira
Using module file /Users/david/.ansible/collections/ansible_collections/community/general/plugins/modules/jira.py
<localhost> PUT /Users/david/.ansible/tmp/ansible-local-84229ndnhjpzu/tmpuqv74v06 TO /Users/david/.ansible/tmp/ansible-tmp-1635294120.542293-84232-181104301591571/AnsiballZ_jira.py
<localhost> EXEC /bin/sh -c 'chmod u+x /Users/david/.ansible/tmp/ansible-tmp-1635294120.542293-84232-181104301591571/ /Users/david/.ansible/tmp/ansible-tmp-1635294120.542293-84232-181104301591571/AnsiballZ_jira.py && sleep 0'
<localhost> EXEC /bin/sh -c '/Users/david/ansible-test/bin/python3.9 /Users/david/.ansible/tmp/ansible-tmp-1635294120.542293-84232-181104301591571/AnsiballZ_jira.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /Users/david/.ansible/tmp/ansible-tmp-1635294120.542293-84232-181104301591571/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/var/folders/0s/gfpv95490sdcjhj09rq1cgdr0000gq/T/ansible_jira_payload__tqcejhu/ansible_jira_payload.zip/ansible_collections/community/general/plugins/modules/jira.py", line 670, in request
KeyError: 'body'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/folders/0s/gfpv95490sdcjhj09rq1cgdr0000gq/T/ansible_jira_payload__tqcejhu/ansible_jira_payload.zip/ansible_collections/community/general/plugins/module_utils/mh/deco.py", line 42, in wrapper
    func(self, *args, **kwargs)
  File "/var/folders/0s/gfpv95490sdcjhj09rq1cgdr0000gq/T/ansible_jira_payload__tqcejhu/ansible_jira_payload.zip/ansible_collections/community/general/plugins/module_utils/mh/base.py", line 60, in run
    self.__run__()
  File "/var/folders/0s/gfpv95490sdcjhj09rq1cgdr0000gq/T/ansible_jira_payload__tqcejhu/ansible_jira_payload.zip/ansible_collections/community/general/plugins/module_utils/mh/mixins/state.py", line 36, in __run__
    return func()
  File "/var/folders/0s/gfpv95490sdcjhj09rq1cgdr0000gq/T/ansible_jira_payload__tqcejhu/ansible_jira_payload.zip/ansible_collections/community/general/plugins/modules/jira.py", line 508, in operation_fetch
  File "/var/folders/0s/gfpv95490sdcjhj09rq1cgdr0000gq/T/ansible_jira_payload__tqcejhu/ansible_jira_payload.zip/ansible_collections/community/general/plugins/modules/jira.py", line 698, in get
  File "/var/folders/0s/gfpv95490sdcjhj09rq1cgdr0000gq/T/ansible_jira_payload__tqcejhu/ansible_jira_payload.zip/ansible_collections/community/general/plugins/modules/jira.py", line 672, in request
KeyError: 'body'
fatal: [localhost -> localhost]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "account_id": null,
            "assignee": null,
            "attachment": null,
            "comment": null,
            "comment_visibility": null,
            "description": null,
            "fields": {},
            "inwardissue": null,
            "issue": "INF-200663",
            "issuetype": null,
            "jql": null,
            "linktype": null,
            "maxresults": null,
            "operation": "fetch",
            "outwardissue": null,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "project": "INF",
            "status": null,
            "summary": null,
            "timeout": 10.0,
            "uri": "https://jira2-test.mydomain.com/",
            "username": "david",
            "validate_certs": false
        }
    },
    "msg": "Module failed with exception: 'body'",
    "output": {
        "restbase": "https://jira2-test.mydomain.com/rest/api/2",
        "state": "fetch"
    },
    "restbase": "https://jira2-test.mydomain.com/rest/api/2",
    "state": "fetch",
    "vars": {
        "restbase": "https://jira2-test.mydomain.com/rest/api/2",
        "state": "fetch"
    }
}

Playbook:
- name: Get Parent Jira details
      jira:
       uri: https://jira2-test.mydomain.com/
       username: "{{jira_username}}"
       password: "{{jira_password}}"
       project: "INF"
       operation: fetch
       issue: INF-200663
       validate_certs: False
      register: parent_jira
      delegate_to: localhost


This works fine 99% of the time . But whenever it errors out it comes back with An exception occurred during task execution. To see the full traceback, use -vvv. The error was: KeyError: 'body'
https://github.com/ansible-collections/community.general/blob/main/plugins/modules/web_infrastructure/jira.py#L672 causes this, it assumes that `info['body']` is there, which isn't. It should use `.get()` instead of `[]`, and also output other helpful information (like which status code was returned, which URL the request was to, which HTTP operation was used, ...).

Resolving patch:
diff --git a/plugins/modules/web_infrastructure/jira.py b/plugins/modules/web_infrastructure/jira.py
--- a/plugins/modules/web_infrastructure/jira.py
+++ b/plugins/modules/web_infrastructure/jira.py
@@ -669,7 +669,14 @@ def request(
             try:
                 error = json.loads(info['body'])
             except Exception:
-                self.module.fail_json(msg=to_native(info['body']), exception=traceback.format_exc())
+                msg = 'The request "{method} {url}" returned the unexpected status code {status} {msg}\n{body}'.format(
+                    status=info['status'],
+                    msg=info['msg'],
+                    body=info.get('body'),
+                    url=url,
+                    method=method,
+                )
+                self.module.fail_json(msg=to_native(msg), exception=traceback.format_exc())
             if error:
                 msg = []
                 for key in ('errorMessages', 'errors'):


Test patch: