Inventories Done Right: From Static Hosts to Dynamic Cloud Discovery
Constructed Inventories in Depth
As explained earlier, a constructed inventory is a special type that builds itself from a list of input inventories. For example, you can create one that contains all hosts from NebulaInventory and SolaraInventory, or just a particular group from each. Constructed inventories use the Ansible core constructed inventory model and address some limitations of the now-deprecated Smart Inventory host filtering model.
Before starting, we're going to create a new organization called AllOrganization to group every inventory and credential under one umbrella. This kind of catch-all is useful for the super admin to centralize all resources in one place.
Click on Organizations in the left-side menu and then click on the Add button. Provide a name for the organization and click on the Save button.
To create a constructed inventory, follow these steps:
- Click on Inventories then click on the Add button.
- Select the Constructed type and provide a name. Let's call it
AllInventory. - Add a description if you want.
- Assign it to the
AllOrganizationorganization. - In the Input Inventories section, add
NebulaInventoryandSolaraInventory.
The Cache timeout field defines how long (in seconds) the inventory source cache remains valid. The default is 0, which means the cache never expires. Set it to a value greater than 0 to refresh the cache after that interval. This is useful when you have a large number of hosts and don't want to refresh the inventory on every job run.
- Set the cache timeout to
86400seconds (1 day) for this example.
The Verbosity field sets the verbosity level for the inventory source. The default is 0, which means no verbosity. You can set it higher if you want more information in the output.
- Set the verbosity to
2for this example.
Limit restricts the hosts returned by the auto-created inventory source. For example, the following values in the limit field return the following hosts:
allor*=> all hosts.group1=> all hosts in a specific group ("group1" in this case).group1:host3=> all hosts in "group1" and "host3".group1,host3=> all hosts in "group1" and "host3" (using,is the same as using:).group1:group2=> all hosts in "group1" and "group2".group1:!host2=> all hosts in "group1" except "host2".group1:!group2=> all hosts in "group1" except those in "group2".group1:&group2=> all hosts that are in both "group1" and "group2".group1:group2:!group3=> all hosts that are in "group1" and "group2" but not in "group3".group1:group2:&group3:!group4=> all machines in the groups "group1" and "group2" that are also in the group "group3", except for any machines in the group "group4".- and so on.
The processing order is
:(colon) >&(ampersand) >!(exclamation mark) no matter how they are written in the limit field.a:b:&c:!d:!e==&c:a:!d:b:!e==!d:a:!e:&c:band they all mean "host is in (a OR b), AND in c, AND NOT in d or e."
Groups are going to be created based on the Source vars, so let's configure them. This text area defines the variables for the constructed inventory and tells the plugin how to build groups.
The configuration should start with plugin: constructed. You can then add strict: false to make the plugin ignore errors when creating the inventory (or true to fail on any error). Next, define the list of groups you want to create using groups:. Here is an example that creates a single group called all_hosts containing all hosts from the input inventories (not a useful group in our case, but we'll keep it for demonstration purposes).
---
plugin: constructed
strict: false
groups:
all_hosts: ['nebula', 'solara']
Since we have a single group (all_hosts), we're going to use it in the Limit field. This is where you filter hosts based on the groups created in the constructed inventory. Note that leaving the Limit field empty returns all hosts (the same result as all_hosts in our case, though once you have multiple groups it becomes a real filter).
Constructed Inventory
After creating the inventory, click on Sync to populate it with hosts from the input inventories. This launches a job, and based on the verbosity level you set, you'll see the output after clicking the Last Job Status indicator. If the job succeeds, the input hosts will appear in the "Hosts" tab of the constructed inventory.
Go back to the Inventories view and click on the AllInventory inventory. Examine the list of groups created by the constructed inventory. You'll see the all_hosts group listed there. Click on it, then click on the Hosts tab to see the hosts from the input inventories. You can manually disable or enable hosts from this view.
When you go to Hosts on the side menu to see all hosts known by your AWX, you will see the new hosts from the input inventories marked as imported. In our case, since Nebula and Solara were already added manually to NebulaInventory and SolaraInventory, they'll appear duplicated, with the AllInventory copies marked as imported.
The constructed inventory we created is simple and straightforward, but you can build more complex ones. Let's look at a few more advanced examples.
Suppose our goal is to create the following groups:
production: Contains all hosts with theenvironmentvariable starting with the wordprod.administrated_by_theglobaltechcompany: Contains all hosts with theadministratorcontaining@theglobaltechcompany.audited_by_charlie: Contains all hosts with theauditorcontainingcharlie.
As a reminder, these are the variables we set for the nebula and solara hosts:
For nebula:
---
ansible_host:
environment: production
administrator: alice@theglobaltechcompany
auditor: charlie@theglobaltechcompany
For solara:
---
ansible_host:
environment: production
administrator: bob@theglobaltechcompany
auditor: charlie@theglobaltechcompany
Here are the source vars for the constructed inventory that you can use to create the groups:
AWX in Action
Ansible Orchestration at ScaleEnroll now to unlock all content and receive all future updates for free.

