AWX provides a web-based user interface, REST API, and task engine built on top of Ansible. It is one of the upstream projects for Red Hat Ansible Automation Platform.
Other
13.66k
stars
3.37k
forks
source link
The module awx.awx.inventory is failing to create constructed inventories - Edge case uncaught #15310
[X] I understand that AWX is open source software provided for free and that I might not receive a timely response.
[X] I am NOT reporting a (potential) security vulnerability. (These should be emailed to security@ansible.com instead.)
Bug Summary
Edge Case
hello, I believe there is an edge case uncaught with the module awx.awx.inventory when attempting to add an input_inventories which causes the error message below:
“msg”: “The requested object could not be found at /api/v2/constructed_inventories/24/input_inventories/”
It's due to the fact the URL built is wrong when adding an associations of type input_inventories to a resource constructed_inventory
I believe the problematic code that caused the URL to be built wrong and cause the 404 to happen is combination of the snippets below in awx/awx_collection/plugins/module_utils/controller_api.py
# awx/awx_collection/plugins/module_utils/controller_api.py
def create_if_needed(self, existing_item, new_item, endpoint, on_create=None, auto_exit=True, item_type='unknown', associations=None):
...
if response['status_code'] in [200, 201]:
self.json_output['name'] = 'unknown'
for key in ('name', 'username', 'identifier', 'hostname'):
if key in response['json']:
self.json_output['name'] = response['json'][key]
self.json_output['id'] = response['json']['id']
self.json_output['changed'] = True
item_url = response['json']['url']
else:
if 'json' in response and '__all__' in response['json']:
self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, item_name, response['json']['__all__'][0]))
elif 'json' in response:
self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, item_name, response['json']))
else:
self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, item_name, response['status_code']))
# Process any associations with this item
if associations is not None:
for association_type in associations:
sub_endpoint = '{0}{1}/'.format(item_url, association_type)
self.modify_associations(sub_endpoint, associations[association_type])
and
# awx/awx_collection/plugins/module_utils/controller_api.py
def modify_associations(self, association_endpoint, new_association_list):
# if we got None instead of [] we are not modifying the association_list
if new_association_list is None:
return
# First get the existing associations
response = self.get_all_endpoint(association_endpoint)
existing_associated_ids = [association['id'] for association in response['json']['results']]
Explanation
In ControllerAPIModule.create_if_needed(self) (code ref link)
if associations is not None:
for association_type in associations:
sub_endpoint = '{0}{1}/'.format(item_url, association_type)
self.modify_associations(sub_endpoint, associations[association_type])
then later on, when self.get_all_endpoint(association_endpoint) which calls response = self.get_endpoint(endpoint, *args, **kwargs) with this /api/v2/constructed_inventories/<id>/input_inventories it will cause the 404 as that enpoint isn't defined.
def modify_associations(self, association_endpoint, new_association_list):
# if we got None instead of [] we are not modifying the association_list
if new_association_list is None:
return
# First get the existing associations
response = self.get_all_endpoint(association_endpoint)
existing_associated_ids = [association['id'] for association in response['json']['results']]
Hope this makes sense. Please let me know what the action items are from this, or suggested course of action I can take.
Please confirm the following
security@ansible.com
instead.)Bug Summary
Edge Case
hello, I believe there is an edge case uncaught with the module
awx.awx.inventory
when attempting to add aninput_inventories
which causes the error message below:It's due to the fact the URL built is wrong when adding an
associations
of typeinput_inventories
to a resourceconstructed_inventory
Related discussion: https://forum.ansible.com/t/awx-awx-inventory-is-failing-to-create-constructed-inventories-potential-edge-case/6845
Problematic Code Snippets
I believe the problematic code that caused the URL to be built wrong and cause the
404
to happen is combination of the snippets below inawx/awx_collection/plugins/module_utils/controller_api.py
and
Explanation
In
ControllerAPIModule.create_if_needed(self)
(code ref link)The url and the body for the POST call
will yield the successful response
this is then stored in
item_url
which used to build the associationsub_endpoint
(code ref link)`sub_endpoint=/api/v2/constructed_inventories//input_inventories
then later on, when
self.get_all_endpoint(association_endpoint)
which callsresponse = self.get_endpoint(endpoint, *args, **kwargs)
with this/api/v2/constructed_inventories/<id>/input_inventories
it will cause the 404 as that enpoint isn't defined.Hope this makes sense. Please let me know what the action items are from this, or suggested course of action I can take.
FYI @TheRealHaoLiu @relrod (@cidrblock fom AnsibleFest 2024 conference Denver, US )
AWX version
22.0.0
Select the relevant components
Installation method
kubernetes
Modifications
no
Ansible version
2.17.1
Operating system
No response
Web browser
No response
Steps to reproduce
ANSIBLE_KEEP_REMOTE_FILES=1 ansible localhost -m awx.awx.inventory -a '<module_args>' -vvv
cd /path/to/temporary/file
python AnsiballZ_inventory.py explode
python AnsiballZ_inventory.py execute
this assumes an inventory already exists when added to the
input_inventory
field. used arguments:Expected results
The built URL should be
inventories/<id>/input_inventories
when adding association of typeinput_inventories
to aconstruced_inventory
Actual results
Additional information
13448
Commit: https://github.com/ansible/awx/commit/e22967d28de40fe40d94fd4818aa9248942f6b4c