Started up a new AWX instance as I am going to repurpose my old server with my existing AWX on it. So, I have taken this task, to build it all from scratch using Ansible. I have had some sticking points, but through frustration I have solved most parts
The bit I can’t figure out is Constructed Inventory. Official Docs tells you to create an inventory
first with some details, then edit it using inventory_source
- name: Add constructed inventory with two existing input inventories
inventory:
name: My Constructed Inventory
organization: Default
kind: constructed
input_inventories:
- "West Datacenter"
- "East Datacenter"
- name: Edit the constructed inventory source
inventory_source:
# The constructed inventory source will always be in the format:
# "Auto-created source for: <constructed inventory name>"
name: "Auto-created source for: My Constructed Inventory"
inventory: My Constructed Inventory
limit: host3,host4,host6
source_vars:
plugin: constructed
strict: true
use_vars_plugins: true
groups:
shutdown: resolved_state == "shutdown"
shutdown_in_product_dev: resolved_state == "shutdown" and account_alias == "product_dev"
compose:
resolved_state: state | default("running")
I have 2 Dynamic Inventories that pull data from 2 Proxmox Hosts, this I have got working fine and it populates hosts, groups etc. This Constructed Inventory, I want to pull out all LXC Containers, I have others that pull EL Only Hosts and Debian based Hosts. Here is my code based off of the example above:
- role: awx_inventory
vars:
awx_inventory:
- name: ConInv_Proxmox_LXC
description: Inventory Source for Proxmox LXC Containers
organization: SixteenOne
kind: constructed
input_inventories:
- DynInv_Oberon
- DynInv_Pandora
- role: awx_inventory_source
vars:
awx_inventory_source:
- name: ConInv_Proxmox_LXC
description: Inventory Source for Proxmox LXC Containers
organization: SixteenOne
inventory: ConInv_Proxmox_LXC
limit: proxmox_all_lxc
# timeout: 3600
source_vars:
plugin: constructed
strict: true
use_vars_plugins: true
I am using Roles, so that I can eventually put them on Galaxy, I have already put a couple on already. The Inventory creates fine, but the error that I get when trying to update using inventory_source
is as follows:
The full traceback is:
Traceback (most recent call last):
File "/Users/sixteenone/.ansible/tmp/ansible-tmp-1742853618.5283918-5908-254240443186731/AnsiballZ_inventory_source.py", line 107, in <module>
_ansiballz_main()
~~~~~~~~~~~~~~~^^
File "/Users/sixteenone/.ansible/tmp/ansible-tmp-1742853618.5283918-5908-254240443186731/AnsiballZ_inventory_source.py", line 99, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/sixteenone/.ansible/tmp/ansible-tmp-1742853618.5283918-5908-254240443186731/AnsiballZ_inventory_source.py", line 47, in invoke_module
runpy.run_module(mod_name='ansible_collections.awx.awx.plugins.modules.inventory_source', init_globals=dict(_module_fqn='ansible_collections.awx.awx.plugins.modules.inventory_source', _modlib_path=modlib_path),
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
run_name='__main__', alter_sys=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen runpy>", line 226, in run_module
File "<frozen runpy>", line 98, in _run_module_code
File "<frozen runpy>", line 88, in _run_code
File "/var/folders/5p/z5gs10rs4bn_lgc7k1j5cr040000gn/T/ansible_awx.awx.inventory_source_payload_qsgyl_lu/ansible_awx.awx.inventory_source_payload.zip/ansible_collections/awx/awx/plugins/modules/inventory_source.py", line 328, in <module>
File "/var/folders/5p/z5gs10rs4bn_lgc7k1j5cr040000gn/T/ansible_awx.awx.inventory_source_payload_qsgyl_lu/ansible_awx.awx.inventory_source_payload.zip/ansible_collections/awx/awx/plugins/modules/inventory_source.py", line 318, in main
KeyError: 'source'
failed: [localhost] (item={'name': 'ConInv_Proxmox_LXC', 'description': 'Inventory Source for Proxmox LXC Containers', 'organization': 'SixteenOne', 'inventory': 'ConInv_Proxmox_LXC', 'limit': 'proxmox_all_lxc', 'source_vars': {'plugin': 'constructed', 'strict': True, 'use_vars_plugins': True}}) => {
"ansible_loop_var": "item",
"changed": false,
"item": {
"description": "Inventory Source for Proxmox LXC Containers",
"inventory": "ConInv_Proxmox_LXC",
"limit": "proxmox_all_lxc",
"name": "ConInv_Proxmox_LXC",
"organization": "SixteenOne",
"source_vars": {
"plugin": "constructed",
"strict": true,
"use_vars_plugins": true
}
},
"module_stderr": "Traceback (most recent call last):\n File \"/Users/sixteenone/.ansible/tmp/ansible-tmp-1742853618.5283918-5908-254240443186731/AnsiballZ_inventory_source.py\", line 107, in <module>\n _ansiballz_main()\n ~~~~~~~~~~~~~~~^^\n File \"/Users/sixteenone/.ansible/tmp/ansible-tmp-1742853618.5283918-5908-254240443186731/AnsiballZ_inventory_source.py\", line 99, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/Users/sixteenone/.ansible/tmp/ansible-tmp-1742853618.5283918-5908-254240443186731/AnsiballZ_inventory_source.py\", line 47, in invoke_module\n runpy.run_module(mod_name='ansible_collections.awx.awx.plugins.modules.inventory_source', init_globals=dict(_module_fqn='ansible_collections.awx.awx.plugins.modules.inventory_source', _modlib_path=modlib_path),\n ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n run_name='__main__', alter_sys=True)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"<frozen runpy>\", line 226, in run_module\n File \"<frozen runpy>\", line 98, in _run_module_code\n File \"<frozen runpy>\", line 88, in _run_code\n File \"/var/folders/5p/z5gs10rs4bn_lgc7k1j5cr040000gn/T/ansible_awx.awx.inventory_source_payload_qsgyl_lu/ansible_awx.awx.inventory_source_payload.zip/ansible_collections/awx/awx/plugins/modules/inventory_source.py\", line 328, in <module>\n File \"/var/folders/5p/z5gs10rs4bn_lgc7k1j5cr040000gn/T/ansible_awx.awx.inventory_source_payload_qsgyl_lu/ansible_awx.awx.inventory_source_payload.zip/ansible_collections/awx/awx/plugins/modules/inventory_source.py\", line 318, in main\nKeyError: 'source'\n",
"module_stdout": "",
"msg": "MODULE FAILURE: No start of json char found\nSee stdout/stderr for the exact error",
"rc": 1
}
Inventory Role:
- name: Create Inventory
awx.awx.inventory:
controller_host: "{{ awx_controller_host }}"
controller_username: "{{ awx_controller_username }}"
controller_password: "{{ awx_controller_password }}"
name: "{{ item.name }}"
description: "{{ item.description | default(omit) }}"
##### Different Details #####
organization: "{{ item.organization }}"
copy_from: "{{ item.copy_from | default(omit) }}"
input_inventories: "{{ item.input_inventories | default(omit) }}"
instance_groups: "{{ item.instance_groups | default(omit) }}"
kind: "{{ item.kind | default(omit) }}"
new_name: "{{ item.new_name | default(omit) }}"
prevent_instance_group_fallback: "{{ item.prevent_instance_group_fallback | default(omit) }}"
request_timeout: "{{ item.request_timeout | default(omit) }}"
state: "{{ item.state | default('present') }}"
validate_certs: "{{ item.validate_certs | default(omit) }}"
variables: "{{ item.variables | default(omit) }}"
loop: "{{ awx_inventory }}"
Inventory Source Role
- name: Create Inventory Sources
awx.awx.inventory_source:
controller_host: "{{ awx_controller_host }}"
controller_username: "{{ awx_controller_username }}"
controller_password: "{{ awx_controller_password }}"
name: "{{ item.name }}"
description: "{{ item.description | default(omit) }}"
organization: "{{ item.organization }}"
##### Different Details #####
credential: "{{ item.credential | default(omit) }}"
custom_virtualenv: "{{ item.custom_virtualenv | default(omit) }}"
enabled_value: "{{ item.enabled_value | default(omit) }}"
enabled_var: "{{ item.enabled_var | default(omit) }}"
execution_environment: "{{ item.execution_environment | default(omit) }}"
host_filter: "{{ item.host_filter | default(omit) }}"
inventory: "{{ item.inventory | default(omit) }}"
limit: "{{ item.limit | default(omit) }}"
new_name: "{{ item.new_name | default(omit) }}"
notification_templates_error: "{{ item.notification_templates_error | default(omit) }}"
notification_templates_started: "{{ item.notification_templates_started | default(omit) }}"
notification_templates_success: "{{ item.notification_templates_success | default(omit) }}"
overwrite: "{{ item.overwrite | default(omit) }}"
overwrite_vars: "{{ item.overwrite_vars | default(omit) }}"
request_timeout: "{{ item.request_timeout | default(omit) }}"
scm_branch: "{{ item.scm_branch | default(omit) }}"
source: "{{ item.source | default(omit) }}"
source_path: "{{ item.source_path | default(omit) }}"
source_project: "{{ item.source_project | default(omit) }}"
source_vars: "{{ item.source_vars | default(omit) }}"
state: "{{ item.state | default('present') }}"
timeout: "{{ item.timeout | default(omit) }}"
update_cache_timeout: "{{ item.update_cache_timeout | default(omit) }}"
update_on_launch: "{{ item.update_on_launch | default(omit) }}"
validate_certs: "{{ item.validate_certs | default(omit) }}"
verbosity: "{{ item.verbosity | default(omit) }}"
loop: "{{ awx_inventory_source }}"
Any help is appreciated, or if anyone has a Repo where they have created one successfully let me know. Searching on the web is difficult as it keeps showing guides on doing this manually, I have done that, I now want to automate it