Hello everyone, for those I haven’t met yet, I’m Steve Fulmer, a Product Manager for Ansible here at Red Hat. I work closely with community leaders like Don Naro, Gundalow Barker, Anwesha Das, Daniel Brennand, and Andrei Klychkov. My primary focus is collaborating with Partner and Community Engineering to grow our certified and community content, ensuring it delivers real value to both our community and Red Hat customers. I’m reaching out today to introduce an exciting new Ansible feature focused on enhanced resource reporting and management.
Today, Ansible modules often interact with external systems, such as clouds, hypervisors, network controllers to manage resources that aren’t declared in your inventory. Until now, there hasn’t been a standard way for collections to expose structured metadata about what they’re actually touching.
Red Hat has developed a mechanism for Ansible collections that maps module return values to a standardized resource taxonomy. We’re calling this resource reporting, and we want to share it with you to get your thoughts.
Resource reporting lets you declare resource types in a minimal YAML file inside your collection using lightweight jq expressions to query module return values at runtime, no special dependencies required. It’s entirely optional for community collections, but we think it brings massive value to the ecosystem.
Why are we building this?
For collection developers, resource reporting is like having excellent return-value documentation, except it’s machine-readable.
It allows users to understand exactly what their playbooks are touching, even for resources that never appear in the inventory. Ultimately, it creates a consistent, unified picture of automation activity across different vendors and platforms.
How it works
Adding resource reporting to your collection is straightforward:
- Check the taxonomy. Resources are mapped to standard names across vendors. For example, a VMware VM and an AWS EC2 instance are both considered a
virtual_machine. (See the full taxonomy reference at the bottom of this post). - Add a query file. Create an
extensions/audit/event_query.ymlfile in your collection. Each entry maps a module FQCN (Fully Qualified Collection Name) to ajqexpression. - Write your
jqexpression. The expression runs against your module’s return values and outputs a JSON object with three fields:name(required) — A human-readable resource name.canonical_facts(required) — Stable, unique identifiers for deduplication (e.g., UUIDs, serial numbers, permanent MAC addresses).facts(optional) — Categorization metadata, including thedevice_type.
Vendor-Specific Query Examples
Different platforms require slightly different querying strategies based on how their APIs are structured. Here is how you can handle a few common scenarios:
VMware (Flat Structure)
VMware has a flat return structure where the top-level key typically defines the node type. You can map directly to the returned keys.
# extensions/audit/event_query.yml
community.vmware.vmware_guest:
query: >-
{
name: .instance.hw_name,
canonical_facts: {
host_name: .instance.hw_name,
uuid: .instance.hw_product_uuid
},
facts: {
device_type: "virtual_machine",
guest_id: .instance.hw_guest_id
}
}
Azure (Hierarchical Structure)
Azure resources are hierarchical and use verbose Resource IDs. Because the full ID contains the resource type, you can use a jq regex to dynamically capture and categorize it.
azure.azcollection.azure_rm_virtualmachine:
query: >-
{
name: .name,
canonical_facts: {
id: .id
},
facts: {
device_type: "virtual_machine",
# Dynamically extract "compute" using regex capture on the Azure ID
azure_type: ((.id | capture("/providers/[Mm]icrosoft.(?<resourcetype>[^/]+)/")? | .resourcetype) | ascii_downcase)
}
}
AWS (Implied Types & Lists)
AWS info modules often return a list of resources (like .instances), so your jq query will need to iterate over them. The type is implied entirely by the module you are querying.
amazon.aws.ec2_instance_info:
query: >-
.instances[] | {
name: (.tags.Name // .instance_id),
canonical_facts: {
instance_id: .instance_id
},
facts: {
device_type: "virtual_machine",
status: .state.name
}
}
Testing your expression locally:
You can easily test your jq expressions locally via the CLI before publishing your collection updates:
# Capture module output into a file, then pipe it to jq
cat module_output.json | jq '{
name: .instance.hw_name,
canonical_facts: {
uuid: .instance.hw_uuid
},
facts: {
device_type: "virtual_machine"
}
}'
When defining your resource, use the snake_case value in the facts.device_type field.
Compute
| Resource | device_type value |
|---|---|
| Virtual Machines | virtual_machine |
| Containers (Managed) | container |
| Hypervisors | hypervisor |
| Bare Metal | bare_metal |
| Serverless Functions | serverless_function |
| Auto Scaling Groups | auto_scaling_group |
Networking
| Resource | device_type value |
|---|---|
| Switches | switch |
| Routers | router |
| Firewalls | firewall |
| Load Balancers | load_balancer |
| Virtual Private Clouds | vpc |
| Subnets | subnet |
| VPNs | vpn |
| Gateways | gateway |
| DNS Services | dns_service |
| Wireless Access Points | wireless_access_point |
| SD-WAN | sd_wan |
Storage
| Resource | device_type value |
|---|---|
| Object Storage | object_storage |
| Block Storage | block_storage |
| File Storage | file_storage |
| Archive Storage | archive_storage |
Database
| Resource | device_type value |
|---|---|
| Relational (SQL) | database_relational |
| NoSQL | database_nosql |
| Data Warehouse | data_warehouse |
| In-Memory/Cache | database_cache |
DevOps and App Integration
| Resource | device_type value |
|---|---|
| CI/CD Platforms | ci_cd_platform |
| Container Registries | container_registry |
| Message Queues | message_queue |
| API Endpoints | api_endpoint |
We’d love your feedback!
It’s early days for this feature, and community input will shape where this goes next. We’d love to hear your thoughts, particularly on the following:
- Use cases: Do you have scenarios where structured visibility into off-inventory resources would be useful to you?
- Adoption: Would you consider adding resource reporting to a collection you maintain? What would make it easier (or harder) to adopt?
- Tooling: What kind of tooling or integrations would you want to see built around this data?
- Taxonomy: Are there resource types missing from the taxonomy lists above that you’d like us to add?
Drop your thoughts, questions, or concerns in the thread below!