Australia | Automating the Resynchronisation of Constructed Inventories in the Ansible Automation Platform

Sebastian Baszcyj - 10.10.202320231010

Automating the Resynchronisation of Constructed Inventories in the Ansible Automation Platform

Australia | Automating the Resynchronisation of Constructed Inventories in the Ansible Automation Platform

Ansible Automation Controller constructed inventories are a new feature that allows you to create a dynamic inventory from a list of input inventories. You can use this feature to run jobs against hosts and groups from multiple inventories and apply custom logic and filters to them. For example, you can create a constructed inventory that combines hosts from AWS, Azure, and VMware, and add variables and groups based on their attributes. 

To create a constructed inventory, you need to specify the input inventories, the limit pattern, and the source vars. The input inventories are the existing inventories that provide the inventory content for the constructed inventory. The limit pattern is an optional parameter that allows you to filter the hosts using the standard Ansible host pattern syntax. The source vars is a YAML dictionary that defines the logic for adding groups and variables to the constructed inventory. You can use Ansible-style Jinja2 expressions and filters in the source vars. 

The constructed inventory is refreshed every time you run a job that uses it. Ansible Automation Controller runs the ansible-inventory command with the constructed plugin and the parameters you provided and generates a temporary inventory file for the job. This ensures that the constructed inventory always reflects the latest state of the input inventories and your custom logic. 

There are a few limitations to constructed inventories: 

  • They are currently only supported in Ansible Automation Platform (AAP) 2.4 and higher 
  • They cannot be used as input inventories for other constructed inventories 
  • If the input inventories are large or complex, the refresh process can take some time 

The refresh/resync process for the constructed inventory activates whenever its associated template launches, potentially extending the overall duration of the job more than necessary. While constructed inventories allow manual resync and support caching, manual intervention remains the sole alternative for resynchronisation in case you want to run an ad-hoc job or you want to verify the hosts and groups. As of AAP 2.4.x, there’s no built-in scheduling feature for constructed inventories within the GUI. 

Although scheduled resync is not supported in the current version, the API does allow for source updates to the Constructed Inventories. You can execute the API call using the URL link  below: 

https://aap01.example.net/api/v2/inventories/386/update_inventory_sources/

Note: 386 in the above URL is the inventory id of one of the constructed inventories in your environment.  

To update multiple constructed inventories, one can leverage Ansible Code alongside the ansible.controller collection (available to those with access to console.redhat.com) or the awx.awx ansible collection. 

This blog outlines two methods for updating Constructed Inventories. Because the hosts and groups within the constructed inventory rely on the source inventory and its associated query, it’s essential first to refresh the dynamic inventory serving as the source before synchronising the constructed inventory. 

I am going to describe the code necessary to update all the constructed inventories first 

Ansible Code Description: aap-inv-refresh role 

Directory Structure:  
aap-inv-refresh/

├── aap-inv-refresh/
│ └── tasks/
│ ├── inv_refresh.yml
│ └── main.yml

├── README.md
├── site.yml
└── vars/
├── aap_vars.yml
└── creds.yml

Purpose: 

The Ansible role aap-inv-refresh is designed to refresh constructed inventories on Ansible Automation Platform (AAP). 

Key Files and Content: 

site.yml: Main playbook file. 

---  
- name: Refresh constructed inventory
hosts: all
roles:
- role: aap-inv-refresh
  1. vars/aap_vars.yml: Contains variables specific to AAP and configured Inventories: 
# defaults for aap-gcp  
ee_validate_certs: false
aap_controller_host: aap01.example.net
aap_organisation: SharedInventory
constructed_inventories_list:
- INV-CONSTRUCTED-AZURE-LINUX-ALL
- INV-CONSTRUCTED-AZURE-OEL-SAP
- INV-CONSTRUCTED-AZURE-RHEL-NONSAP
- INV-CONSTRUCTED-AZURE-RHEL-SAP
- INV-CONSTRUCTED-AZURE-SLES-SAP
- INV-CONSTRUCTED-AZURE-WINDOWS
- INV-CONSTRUCTED-AZURE-WINDOWS-SAP
- INV-CONSTRUCTED-GCP-RHEL
- INV-CONSTRUCTED-GCP-WINDOWS
gcp_shared_inventory: INV-SHARED-GCP-ALL
  1. vars/creds.yml: The creds.yml file can be encrypted with ansible-vault. It contains credentials for authentication with AAP. 
# AAP credentials  
aap_controller_username: svc_ansible_token
aap_controller_password: svc_ansible_token
  1. Tasks
    • main.yml: Contains tasks to include default variables, query the inventory by its name, update all inventory sources, and refresh tasks for constructed inventories.
---  
- name: Include default extension files in vars
ansible.builtin.include_vars:
dir: "{{ playbook_dir }}/vars"
extensions:
- 'yml'
tags:
- azure_refresh
- gcp_refresh


- name: Query the inventory by its name
set_fact:
inventory_id: "{{ (query('ansible.controller.controller_api', 'inventories', host=aap_controller_host, username=aap_controller_username, password=aap_controller_password, query_params={ 'name': gcp_shared_inventory }) | first).id }}"
inventory_org: "{{ (query('ansible.controller.controller_api', 'inventories', host=aap_controller_host, username=aap_controller_username, password=aap_controller_password, query_params={ 'name': gcp_shared_inventory }) | first).summary_fields.organization.name }}"
inventory_name: "{{ gcp_shared_inventory }}"
tags:
- gcp_refresh




- name: Update all inventory sources
ansible.controller.inventory_source_update:
name: "{{ item }}"
inventory: "{{ inventory_name }}"
organization: "{{ inventory_org }}"
controller_username: "{{ aap_controller_username }}"
controller_password: "{{ aap_controller_password }}"
validate_certs: "{{ ee_validate_certs | default(omit) }}"
controller_host: "{{ aap_controller_host | default(omit) }}"
wait: true
loop: "{{ query('ansible.controller.controller_api', 'inventory_sources', host=aap_controller_host, username=aap_controller_username, password=aap_controller_password, query_params={ 'inventory': inventory_id }, return_ids=True ) }}"
tags:
- gcp_refresh
ignore_errors: true
no_log: true


- name: Refresh Task
include_tasks: inv_refresh.yml
loop: "{{ constructed_inventories_list }}"
tags:
- azure_refresh
- gcp_refresh
  • inv_refresh.yml: Contains tasks to query specific inventories by their name, display the ID of the queried inventory, and update all the inventory sources.
---                                                                                                                                                                                                                                                          
- name: Query the inventory by its name
set_fact:
inventory_id: "{{ (query('ansible.controller.controller_api', 'inventories', host=aap_controller_host, username=aap_controller_username, password=aap_controller_password, query_params={ 'name': item }) | first).id }}"
inventory_org: "{{ (query('ansible.controller.controller_api', 'inventories', host=aap_controller_host, username=aap_controller_username, password=aap_controller_password, query_params={ 'name': item }) | first).summary_fields.organization.name }}}
"
inventory_name: "{{ item }}"
tags:
- azure_refresh
- gcp_refresh


- name: Display the ID of the queried inventory
debug:
msg: "{{ inventory_name }} has inventory_id: {{ inventory_id }} and is in organization: {{ inventory_org }}"
tags:
- azure_refresh
- gcp_refresh




- name: Update all inventory sources
ansible.controller.inventory_source_update:
name: "{{ inventory_source_item }}"
inventory: "{{ inventory_name }}"
organization: "{{ inventory_org }}"
controller_username: "{{ aap_controller_username }}"
controller_password: "{{ aap_controller_password }}"
validate_certs: "{{ ee_validate_certs | default(omit) }}"
controller_host: "{{ aap_controller_host | default(omit) }}"
loop: "{{ query('ansible.controller.controller_api', 'inventory_sources', host=aap_controller_host, username=aap_controller_username, password=aap_controller_password, query_params={ 'inventory': inventory_id }, return_ids=True ) }}"
loop_control:
loop_var: inventory_source_item
tags:
- azure_refresh
- gcp_refresh

Note: There’s potential to enhance the code by saving the results from an initial query into a variable and then conducting local searches on that result. I’ve observed that performance may vary based on the number of inventories present in the environment. In contexts with hundreds of inventories, the resulting JSON file can be substantially large, potentially impacting the solution’s efficiency. In such cases, I prefer utilising multiple API calls, as each call yields a single-page result. 

Resync for Azure 

The dynamic inventory for Azure Cloud varies compared to GCP. For Azure, each dynamic inventory source corresponds to a single Azure subscription, effectively limiting the number of sources in the dynamic inventory. In contrast, for GCP, there’s a source for each project, which could potentially lead to a significantly large number of sources. 

For Azure, the strategy involved creating a workflow. This workflow processes the dynamic inventory’s sources, updates them, and once all have been refreshed, triggers a template to update all the constructed inventories that use this dynamic inventory as their source. 

Ansible Automation Platform Templates 

There are two templates: 

  1. TMPL-CONSTRUCTED-INV-REFRESH-AZURE
    • Tag: azure_refresh 
    • Related variable: constructed_inventories_list specific to Azure
  - INV-CONSTRUCTED-AZURE-LINUX-ALL  
- INV-CONSTRUCTED-AZURE-OEL-SAP
- INV-CONSTRUCTED-AZURE-RHEL-NONSAP
- INV-CONSTRUCTED-AZURE-RHEL-SAP
- INV-CONSTRUCTED-AZURE-SLES-SAP
- INV-CONSTRUCTED-AZURE-WINDOWS
- INV-CONSTRUCTED-AZURE-WINDOWS-SAP
Australia | Automating the Resynchronisation of Constructed Inventories in the Ansible Automation Platform

In this example, I created a new execution environment that includes the ansible.controller collection (you might need to replace it with awx.awx collection if you don’t have a valid Red Hat subscription). The following snippet provides all the collections included in the execution environment:

---  
collections:
- ansible.posix
- community.crypto
- community.general
- community.podman
- ansible.controller
- community.hashi_vault
- containers.podman

Both templates are configured within the SharedInventory organisation and utilise the specified execution environment. They draw upon the PRJ-AAP-CONSTRUCTED-INV-REFRESH project, the Demo Inventory, the site.yml playbook, and the CREDS-AAP-VAULT vault credential. Considering all tasks utilise API calls to AAP, there’s no need for a designated host to run the code. Consequently, I employ the Demo Inventory, which lists localhost as its sole host configuration.

Resync for GCP 

As highlighted earlier, the dynamic inventory for GCP could include a large number of sources, given there’s one for each project. This extensive list makes utilising a WORKFLOW challenging. The recommended approach is to deploy Ansible code to refresh all sources within the dynamic inventory. Once this step is completed, the constructed inventory can be updated. Note that the task dedicated to refreshing GCP’s dynamic inventory is set to bypass errors. This design choice ensures that an update error in one GCP project doesn’t stop the refreshing of the constructed inventory.

Ansible Automation Platform Template 

  1. TMPL-CONSTRUCTED-INV-REFRESH-GCP
    • Tag: gcp_refresh 
    • Related variable: constructed_inventories_list specific to GCP
constructed_inventories_list:  
- INV-CONSTRUCTED-GCP-RHEL
- INV-CONSTRUCTED-GCP-WINDOW

Usage

To refresh Azure constructed inventories, execute the following workflow:  

TMPL-CONSTRUCTED-INV-REFRESH-AZURE-WORKFLOW 

This workflow will:  

  • resync all the Azure inventory sources in INV-SHARED-AZURE-ALL inventory
  • resync all Azure constructed inventories  

To refresh GCP constructed inventories, execute the following Template: 

TMPL-CONSTRUCTED-INV-REFRESH-GCP 

The template will: 

  • resync all GCP sources in INV-SHARED-GCP inventory
  • resync all GCP constructed inventories

Modifications

In case additional constructed inventories are created in future, add the name of the inventory to the Azure or GCP template.  

For example, TMPL-CONSTRUCTED-INV-REFRESH-AZURE template has the following Extended Variables:

---  
constructed_inventories_list:
- INV-CONSTRUCTED-AZURE-LINUX-ALL
- INV-CONSTRUCTED-AZURE-OEL-SAP
- INV-CONSTRUCTED-AZURE-RHEL-NONSAP
- INV-CONSTRUCTED-AZURE-RHEL-SAP
- INV-CONSTRUCTED-AZURE-SLES-SAP
- INV-CONSTRUCTED-AZURE-WINDOWS
- INV-CONSTRUCTED-AZURE-WINDOWS-SAP

TMPL-CONSTRUCTED-INV-REFRESH-GCP template has the following Extended Variables:

---  
constructed_inventories_list:
- INV-CONSTRUCTED-GCP-RHEL
- INV-CONSTRUCTED-GCP-WINDOWS

If you have any questions or need further details about refreshing constructed inventories using Ansible Automation Platform, feel free to contact us!

THANK YOU FOR YOUR SUBMISSION!

Australia | Automating the Resynchronisation of Constructed Inventories in the Ansible Automation Platform

The form was submitted successfully.

Join the Insentra Community with the Insentragram Newsletter

Hungry for more?

If you’re waiting for a sign, this is it.

We’re a certified amazing place to work, with an incredible team and fascinating projects – and we’re ready for you to join us! Go through our simple application process. Once you’re done, we will be in touch shortly!

Who is Insentra?

Imagine a business which exists to help IT Partners & Vendors grow and thrive.

Insentra is a 100% channel business. This means we provide a range of Advisory, Professional and Managed IT services exclusively for and through our Partners.

Our #PartnerObsessed business model achieves powerful results for our Partners and their Clients with our crew’s deep expertise and specialised knowledge.

We love what we do and are driven by a relentless determination to deliver exceptional service excellence.

Australia | Automating the Resynchronisation of Constructed Inventories in the Ansible Automation Platform

Insentra ISO 27001:2013 Certification

SYDNEY, WEDNESDAY 20TH APRIL 2022 – We are proud to announce that Insentra has achieved the  ISO 27001 Certification.