prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [api] Confusing error when trying to sync project set to scm_type Manual
  ### Please confirm the following
  
  - [X] I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
  - [X] I have checked the [current issues](https://github.com/ansible/awx/issues) for duplicates.
  - [X] I understand that AWX is open source software provided for free and that I might not receive a timely response.
  
  ### Bug Summary
  
  Creating a project and accidentally setting it to be `scm_type: manual` (the default in the awx collection), and then trying to do a project update on it, leads to a very confusing error:
  
  ```
  fatal: [localhost]: FAILED! => {"changed": false, "msg": "Cannot make a request with the POST method to this endpoint /api/v2/projects/8/update/"}
  ```
  
  Although it is "technically" correct, it would be nice if we could show something nicer in this scenario (e.g. "Unable to trigger a project update because the project scm type (Manual) does not support it.")
  
  ### AWX version
  
  devel
  
  ### Select the relevant components
  
  - [ ] UI
  - [X] API
  - [ ] Docs
  - [ ] Collection
  - [ ] CLI
  - [ ] Other
  
  ### Installation method
  
  docker development environment
  
  ### Modifications
  
  no
  
  ### Ansible version
  
  _No response_
  
  ### Operating system
  
  _No response_
  
  ### Web browser
  
  _No response_
  
  ### Steps to reproduce
  
  - Create a project, set its type to Manual
  - Use the API (or `awx.awx.project_update`) to try to update it
  
  ### Expected results
  
  An error explaining the problem
  
  ### Actual results
  
  An error telling me that I can't POST to an endpoint that I expect to be able to POST to.
  
  ### Additional information
  
  _No response_
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `awx_collection/plugins/modules/project_update.py`
  Content:
  ```
  1 #!/usr/bin/python
  2 # coding: utf-8 -*-
  3 
  4 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
  5 
  6 from __future__ import absolute_import, division, print_function
  7 
  8 __metaclass__ = type
  9 
  10 ANSIBLE_METADATA = {'metadata_version': '1.0', 'status': ['preview'], 'supported_by': 'community'}
  11 
  12 DOCUMENTATION = '''
  13 ---
  14 module: project_update
  15 author: "Sean Sullivan (@sean-m-sullivan)"
  16 short_description: Update a Project in Automation Platform Controller
  17 description:
  18     - Update a Automation Platform Controller Project. See
  19       U(https://www.ansible.com/tower) for an overview.
  20 options:
  21     name:
  22       description:
  23         - The name or id of the project to update.
  24       required: True
  25       type: str
  26       aliases:
  27         - project
  28     organization:
  29       description:
  30         - Organization the project exists in.
  31         - Used to help lookup the object, cannot be modified using this module.
  32         - If not provided, will lookup by name only, which does not work with duplicates.
  33       type: str
  34     wait:
  35       description:
  36         - Wait for the project to update.
  37         - If scm revision has not changed module will return not changed.
  38       default: True
  39       type: bool
  40     interval:
  41       description:
  42         - The interval to request an update from the controller.
  43       required: False
  44       default: 2
  45       type: float
  46     timeout:
  47       description:
  48         - If waiting for the project to update this will abort after this
  49           amount of seconds
  50       type: int
  51 extends_documentation_fragment: awx.awx.auth
  52 '''
  53 
  54 RETURN = '''
  55 id:
  56     description: project id of the updated project
  57     returned: success
  58     type: int
  59     sample: 86
  60 status:
  61     description: status of the updated project
  62     returned: success
  63     type: str
  64     sample: pending
  65 '''
  66 
  67 
  68 EXAMPLES = '''
  69 - name: Launch a project with a timeout of 10 seconds
  70   project_update:
  71     project: "Networking Project"
  72     timeout: 10
  73 
  74 - name: Launch a Project with extra_vars without waiting
  75   project_update:
  76     project: "Networking Project"
  77     wait: False
  78 '''
  79 
  80 from ..module_utils.controller_api import ControllerAPIModule
  81 
  82 
  83 def main():
  84     # Any additional arguments that are not fields of the item can be added here
  85     argument_spec = dict(
  86         name=dict(required=True, aliases=['project']),
  87         organization=dict(),
  88         wait=dict(default=True, type='bool'),
  89         interval=dict(default=2.0, type='float'),
  90         timeout=dict(default=None, type='int'),
  91     )
  92 
  93     # Create a module for ourselves
  94     module = ControllerAPIModule(argument_spec=argument_spec)
  95 
  96     # Extract our parameters
  97     name = module.params.get('name')
  98     organization = module.params.get('organization')
  99     wait = module.params.get('wait')
  100     interval = module.params.get('interval')
  101     timeout = module.params.get('timeout')
  102 
  103     # Attempt to look up project based on the provided name or id
  104     lookup_data = {}
  105     if organization:
  106         lookup_data['organization'] = module.resolve_name_to_id('organizations', organization)
  107     project = module.get_one('projects', name_or_id=name, data=lookup_data)
  108     if project is None:
  109         module.fail_json(msg="Unable to find project")
  110 
  111     if wait:
  112         scm_revision_original = project['scm_revision']
  113 
  114     # Update the project
  115     result = module.post_endpoint(project['related']['update'])
  116 
  117     if result['status_code'] != 202:
  118         module.fail_json(msg="Failed to update project, see response for details", response=result)
  119 
  120     module.json_output['changed'] = True
  121     module.json_output['id'] = result['json']['id']
  122     module.json_output['status'] = result['json']['status']
  123 
  124     if not wait:
  125         module.exit_json(**module.json_output)
  126 
  127     # Invoke wait function
  128     result = module.wait_on_url(
  129         url=result['json']['url'], object_name=module.get_item_name(project), object_type='Project Update', timeout=timeout, interval=interval
  130     )
  131     scm_revision_new = result['json']['scm_revision']
  132     if scm_revision_new == scm_revision_original:
  133         module.json_output['changed'] = False
  134 
  135     module.exit_json(**module.json_output)
  136 
  137 
  138 if __name__ == '__main__':
  139     main()
  140
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/awx_collection/plugins/modules/project_update.py b/awx_collection/plugins/modules/project_update.py
  --- a/awx_collection/plugins/modules/project_update.py
  +++ b/awx_collection/plugins/modules/project_update.py
  @@ -114,7 +114,12 @@
       # Update the project
       result = module.post_endpoint(project['related']['update'])
   
  -    if result['status_code'] != 202:
  +    if result['status_code'] == 405:
  +        module.fail_json(
  +            msg="Unable to trigger a project update because the project scm_type ({0}) does not support it.".format(project['scm_type']),
  +            response=result
  +        )
  +    elif result['status_code'] != 202:
           module.fail_json(msg="Failed to update project, see response for details", response=result)
   
       module.json_output['changed'] = True
  
verification_info: {"golden_diff": "diff --git a/awx_collection/plugins/modules/project_update.py b/awx_collection/plugins/modules/project_update.py\n--- a/awx_collection/plugins/modules/project_update.py\n+++ b/awx_collection/plugins/modules/project_update.py\n@@ -114,7 +114,12 @@\n     # Update the project\n     result = module.post_endpoint(project['related']['update'])\n \n-    if result['status_code'] != 202:\n+    if result['status_code'] == 405:\n+        module.fail_json(\n+            msg=\"Unable to trigger a project update because the project scm_type ({0}) does not support it.\".format(project['scm_type']),\n+            response=result\n+        )\n+    elif result['status_code'] != 202:\n         module.fail_json(msg=\"Failed to update project, see response for details\", response=result)\n \n     module.json_output['changed'] = True\n", "issue": "[api] Confusing error when trying to sync project set to scm_type Manual\n### Please confirm the following\n\n- [X] I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).\n- [X] I have checked the [current issues](https://github.com/ansible/awx/issues) for duplicates.\n- [X] I understand that AWX is open source software provided for free and that I might not receive a timely response.\n\n### Bug Summary\n\nCreating a project and accidentally setting it to be `scm_type: manual` (the default in the awx collection), and then trying to do a project update on it, leads to a very confusing error:\r\n\r\n```\r\nfatal: [localhost]: FAILED! => {\"changed\": false, \"msg\": \"Cannot make a request with the POST method to this endpoint /api/v2/projects/8/update/\"}\r\n```\r\n\r\nAlthough it is \"technically\" correct, it would be nice if we could show something nicer in this scenario (e.g. \"Unable to trigger a project update because the project scm type (Manual) does not support it.\")\n\n### AWX version\n\ndevel\n\n### Select the relevant components\n\n- [ ] UI\n- [X] API\n- [ ] Docs\n- [ ] Collection\n- [ ] CLI\n- [ ] Other\n\n### Installation method\n\ndocker development environment\n\n### Modifications\n\nno\n\n### Ansible version\n\n_No response_\n\n### Operating system\n\n_No response_\n\n### Web browser\n\n_No response_\n\n### Steps to reproduce\n\n- Create a project, set its type to Manual\r\n- Use the API (or `awx.awx.project_update`) to try to update it\n\n### Expected results\n\nAn error explaining the problem\n\n### Actual results\n\nAn error telling me that I can't POST to an endpoint that I expect to be able to POST to.\n\n### Additional information\n\n_No response_\n", "before_files": [{"content": "#!/usr/bin/python\n# coding: utf-8 -*-\n\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\nfrom __future__ import absolute_import, division, print_function\n\n__metaclass__ = type\n\nANSIBLE_METADATA = {'metadata_version': '1.0', 'status': ['preview'], 'supported_by': 'community'}\n\nDOCUMENTATION = '''\n---\nmodule: project_update\nauthor: \"Sean Sullivan (@sean-m-sullivan)\"\nshort_description: Update a Project in Automation Platform Controller\ndescription:\n    - Update a Automation Platform Controller Project. See\n      U(https://www.ansible.com/tower) for an overview.\noptions:\n    name:\n      description:\n        - The name or id of the project to update.\n      required: True\n      type: str\n      aliases:\n        - project\n    organization:\n      description:\n        - Organization the project exists in.\n        - Used to help lookup the object, cannot be modified using this module.\n        - If not provided, will lookup by name only, which does not work with duplicates.\n      type: str\n    wait:\n      description:\n        - Wait for the project to update.\n        - If scm revision has not changed module will return not changed.\n      default: True\n      type: bool\n    interval:\n      description:\n        - The interval to request an update from the controller.\n      required: False\n      default: 2\n      type: float\n    timeout:\n      description:\n        - If waiting for the project to update this will abort after this\n          amount of seconds\n      type: int\nextends_documentation_fragment: awx.awx.auth\n'''\n\nRETURN = '''\nid:\n    description: project id of the updated project\n    returned: success\n    type: int\n    sample: 86\nstatus:\n    description: status of the updated project\n    returned: success\n    type: str\n    sample: pending\n'''\n\n\nEXAMPLES = '''\n- name: Launch a project with a timeout of 10 seconds\n  project_update:\n    project: \"Networking Project\"\n    timeout: 10\n\n- name: Launch a Project with extra_vars without waiting\n  project_update:\n    project: \"Networking Project\"\n    wait: False\n'''\n\nfrom ..module_utils.controller_api import ControllerAPIModule\n\n\ndef main():\n    # Any additional arguments that are not fields of the item can be added here\n    argument_spec = dict(\n        name=dict(required=True, aliases=['project']),\n        organization=dict(),\n        wait=dict(default=True, type='bool'),\n        interval=dict(default=2.0, type='float'),\n        timeout=dict(default=None, type='int'),\n    )\n\n    # Create a module for ourselves\n    module = ControllerAPIModule(argument_spec=argument_spec)\n\n    # Extract our parameters\n    name = module.params.get('name')\n    organization = module.params.get('organization')\n    wait = module.params.get('wait')\n    interval = module.params.get('interval')\n    timeout = module.params.get('timeout')\n\n    # Attempt to look up project based on the provided name or id\n    lookup_data = {}\n    if organization:\n        lookup_data['organization'] = module.resolve_name_to_id('organizations', organization)\n    project = module.get_one('projects', name_or_id=name, data=lookup_data)\n    if project is None:\n        module.fail_json(msg=\"Unable to find project\")\n\n    if wait:\n        scm_revision_original = project['scm_revision']\n\n    # Update the project\n    result = module.post_endpoint(project['related']['update'])\n\n    if result['status_code'] != 202:\n        module.fail_json(msg=\"Failed to update project, see response for details\", response=result)\n\n    module.json_output['changed'] = True\n    module.json_output['id'] = result['json']['id']\n    module.json_output['status'] = result['json']['status']\n\n    if not wait:\n        module.exit_json(**module.json_output)\n\n    # Invoke wait function\n    result = module.wait_on_url(\n        url=result['json']['url'], object_name=module.get_item_name(project), object_type='Project Update', timeout=timeout, interval=interval\n    )\n    scm_revision_new = result['json']['scm_revision']\n    if scm_revision_new == scm_revision_original:\n        module.json_output['changed'] = False\n\n    module.exit_json(**module.json_output)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "awx_collection/plugins/modules/project_update.py"}], "after_files": [{"content": "#!/usr/bin/python\n# coding: utf-8 -*-\n\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\nfrom __future__ import absolute_import, division, print_function\n\n__metaclass__ = type\n\nANSIBLE_METADATA = {'metadata_version': '1.0', 'status': ['preview'], 'supported_by': 'community'}\n\nDOCUMENTATION = '''\n---\nmodule: project_update\nauthor: \"Sean Sullivan (@sean-m-sullivan)\"\nshort_description: Update a Project in Automation Platform Controller\ndescription:\n    - Update a Automation Platform Controller Project. See\n      U(https://www.ansible.com/tower) for an overview.\noptions:\n    name:\n      description:\n        - The name or id of the project to update.\n      required: True\n      type: str\n      aliases:\n        - project\n    organization:\n      description:\n        - Organization the project exists in.\n        - Used to help lookup the object, cannot be modified using this module.\n        - If not provided, will lookup by name only, which does not work with duplicates.\n      type: str\n    wait:\n      description:\n        - Wait for the project to update.\n        - If scm revision has not changed module will return not changed.\n      default: True\n      type: bool\n    interval:\n      description:\n        - The interval to request an update from the controller.\n      required: False\n      default: 2\n      type: float\n    timeout:\n      description:\n        - If waiting for the project to update this will abort after this\n          amount of seconds\n      type: int\nextends_documentation_fragment: awx.awx.auth\n'''\n\nRETURN = '''\nid:\n    description: project id of the updated project\n    returned: success\n    type: int\n    sample: 86\nstatus:\n    description: status of the updated project\n    returned: success\n    type: str\n    sample: pending\n'''\n\n\nEXAMPLES = '''\n- name: Launch a project with a timeout of 10 seconds\n  project_update:\n    project: \"Networking Project\"\n    timeout: 10\n\n- name: Launch a Project with extra_vars without waiting\n  project_update:\n    project: \"Networking Project\"\n    wait: False\n'''\n\nfrom ..module_utils.controller_api import ControllerAPIModule\n\n\ndef main():\n    # Any additional arguments that are not fields of the item can be added here\n    argument_spec = dict(\n        name=dict(required=True, aliases=['project']),\n        organization=dict(),\n        wait=dict(default=True, type='bool'),\n        interval=dict(default=2.0, type='float'),\n        timeout=dict(default=None, type='int'),\n    )\n\n    # Create a module for ourselves\n    module = ControllerAPIModule(argument_spec=argument_spec)\n\n    # Extract our parameters\n    name = module.params.get('name')\n    organization = module.params.get('organization')\n    wait = module.params.get('wait')\n    interval = module.params.get('interval')\n    timeout = module.params.get('timeout')\n\n    # Attempt to look up project based on the provided name or id\n    lookup_data = {}\n    if organization:\n        lookup_data['organization'] = module.resolve_name_to_id('organizations', organization)\n    project = module.get_one('projects', name_or_id=name, data=lookup_data)\n    if project is None:\n        module.fail_json(msg=\"Unable to find project\")\n\n    if wait:\n        scm_revision_original = project['scm_revision']\n\n    # Update the project\n    result = module.post_endpoint(project['related']['update'])\n\n    if result['status_code'] == 405:\n        module.fail_json(\n            msg=\"Unable to trigger a project update because the project scm_type ({0}) does not support it.\".format(project['scm_type']),\n            response=result\n        )\n    elif result['status_code'] != 202:\n        module.fail_json(msg=\"Failed to update project, see response for details\", response=result)\n\n    module.json_output['changed'] = True\n    module.json_output['id'] = result['json']['id']\n    module.json_output['status'] = result['json']['status']\n\n    if not wait:\n        module.exit_json(**module.json_output)\n\n    # Invoke wait function\n    result = module.wait_on_url(\n        url=result['json']['url'], object_name=module.get_item_name(project), object_type='Project Update', timeout=timeout, interval=interval\n    )\n    scm_revision_new = result['json']['scm_revision']\n    if scm_revision_new == scm_revision_original:\n        module.json_output['changed'] = False\n\n    module.exit_json(**module.json_output)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "awx_collection/plugins/modules/project_update.py"}]}