ansible/awx

awx.awx.inventory module input_inventories parameter fails when inventory names are duplicated across organisations

Open

#16393 opened on Apr 8, 2026

View on GitHub
 (2 comments) (0 reactions) (0 assignees)Python (13,071 stars) (3,333 forks)batch import
communitygood first issuehelp wantedtype:bug

Description

Please confirm the following

  • I agree to follow this project's code of conduct.
  • I have checked the current issues for duplicates.
  • I understand that AWX is open source software provided for free and that I might not receive a timely response.
  • I am NOT reporting a (potential) security vulnerability. (These should be emailed to security@ansible.com instead.)

Bug Summary

When using input_inventories on a constructed inventory, the module internally calls resolve_name_to_id('inventories', item) without scoping the lookup to any organisation. If the same inventory name exists in multiple organisations, the lookup returns more than one result and the module fails with: Request to /api/v2/inventories/?name=<inventory_name> returned 2 items, expected 1 This occurs despite the organization parameter being correctly set on the constructed inventory itself. The organization parameter scopes the constructed inventory lookup correctly (as seen in module.get_one with data={'organization': org_id}) but this org scope is not passed to the resolve_name_to_id call for input_inventories.

AWX version

24.6.1

Select the relevant components

  • UI
  • UI (tech preview)
  • API
  • Docs
  • Collection
  • CLI
  • Other

Installation method

kubernetes

Modifications

no

Ansible version

2.19.4 with awx.awx collection 24.6.1

Operating system

Debian

Web browser

No response

Steps to reproduce

Create two organisations — org-a and org-b Create an inventory named my-inventory in both org-a and org-b Create a constructed inventory in org-a referencing my-inventory as an input inventory:

- name: Create constructed inventory
  awx.awx.inventory:
    name: my-constructed-inventory
    organization: org-a
    kind: constructed
    input_inventories:
      - my-inventory
    state: present
    controller_host: "{{ awx_host }}"
    controller_oauthtoken: "{{ awx_token }}"

Expected results

The module should scope the input_inventories lookup to the same organisation as the constructed inventory, or provide a parameter to specify the lookup organisation for input inventories.

Actual results

Request to /api/v2/inventories/?name=my-inventory returned 2 items, expected 1

Additional information

Workaround

Pass inventory IDs instead of names in input_inventories:

- name: Get inventory IDs scoped to org
  set_fact:
    input_inventory_ids: "{{ query('awx.awx.controller_api', 'inventories',
        query_params={'organization__name': 'org-a'},
        host=awx_host,
        oauth_token=awx_token,
        return_all=true,
        max_objects=2000)
      | selectattr('name', 'equalto', 'my-inventory')
      | map(attribute='id')
      | map('string')
      | list }}"

- name: Create constructed inventory using IDs
  awx.awx.inventory:
    name: my-constructed-inventory
    organization: org-a
    kind: constructed
    input_inventories: "{{ input_inventory_ids }}"
    state: present
    controller_host: "{{ awx_host }}"
    controller_oauthtoken: "{{ awx_token }}"

Root cause

In inventory.py, the input_inventories resolution loop does not pass org scoping data to resolve_name_to_id:

for item in input_inventory_names:
    association_fields['input_inventories'].append(module.resolve_name_to_id('inventories', item))

Compare to the correctly scoped inventory lookup earlier in the same file:

inventory = module.get_one('inventories', name_or_id=name, **{'data': {'organization': org_id}})

Suggested fix

Pass org_id as a data filter to resolve_name_to_id for input_inventories:

for item in input_inventory_names:
    association_fields['input_inventories'].append(
        module.resolve_name_to_id('inventories', item, data={'organization': org_id})
    )

Note on suggested fix: resolve_name_to_id is defined in controller_api.py at line 488 and does not currently accept additional keyword arguments or data filters. The fix therefore requires two changes:

  1. Update resolve_name_to_id to accept an optional data parameter and pass it through to the underlying lookup
  2. Update the input_inventories loop in inventory.py to pass data={'organization': org_id}

Alternatively the input_inventories loop could be refactored to use get_one directly instead of resolve_name_to_id, since get_one already supports the data parameter for scoped lookups as demonstrated elsewhere in the same file.

Contributor guide