diff --git a/extensions/audit/README.md b/extensions/audit/README.md new file mode 100644 index 00000000..47f3e2ad --- /dev/null +++ b/extensions/audit/README.md @@ -0,0 +1,54 @@ +# Indirect Node Counts in Ansible Collections + +## Overview + +In the context of Ansible automation, **indirect node counts** refer to the +practice of calculating or verifying the capacity or availability of computing +nodes **through external systems or controllers**, rather than directly +querying the nodes themselves. This approach is especially useful in complex, +public cloud, or on prem environments . + +This file explains: +- What indirect node counts are +- Why they are required +- What they enable +- Their value + +## What Are Indirect Node Counts? + +Rather than connecting directly to each node to assess its state of +automation(e.g., Service, DB, VM, etc), **indirect node counts** leverage tools +like ** APIs**, or other management layers to obtain usage information. + +In an Ansible role or collection, this might involve: +- Querying a cloud service for the list of DBs or VMs and their status of if + they are being automated + +## Why Are They Required? + +Directly connecting to every node: +- Is **inefficient** in large-scale environments +- May be **prohibited** due to security, network segmentation, or policy +- **Doesn't scale** across multiple clusters or providers +- Often leads to **incomplete or stale data** + +Using indirect node counts via cluster managers: +- Enables **centralized insight** into resource usage +- Works well in **managed or disconnected environments** +- Allows **non-invasive** assessment (e.g., read-only API access) + +## What Does It Do? + +In practical terms, using indirect node counts in an Ansible collection: +- Enables **guardrails** to verify into knowing what you are automating +- Reduces operational risk and improves **predictability** of automation workflows + +## Why This Is a Good Practice + +| Benefit | Description | +|--------|-------------| +| ✅ Scalable | Works across many clusters and environments | +| ✅ Secure | Limits direct access to sensitive nodes | +| ✅ Efficient | Avoids per-node polling, uses cached or aggregated data | +| ✅ Integrated | Leverages our existing Certified and Validated collections | +| ✅ Reliable | Provides consistent data source for automation decisions | diff --git a/extensions/audit/taxonomy.jq b/extensions/audit/taxonomy.jq new file mode 100644 index 00000000..b14b5d17 --- /dev/null +++ b/extensions/audit/taxonomy.jq @@ -0,0 +1,54 @@ +( + { + "google.cloud.gcp_bigquery_dataset": "Database", + "google.cloud.gcp_bigquery_table": "Database", + "google.cloud.gcp_compute_address": "Network", + "google.cloud.gcp_compute_disk": "Storage", + "google.cloud.gcp_compute_firewall": "Security & Identity", + "google.cloud.gcp_compute_instance": "Compute", + "google.cloud.gcp_compute_instance_group_manager": "Compute", + "google.cloud.gcp_compute_instance_template": "Compute", + "google.cloud.gcp_compute_network": "Network", + "google.cloud.gcp_compute_ssl_certificate": "Security & Identity", + "google.cloud.gcp_container_cluster": "Containers", + "google.cloud.gcp_container_node_pool": "Containers", + "google.cloud.gcp_dns_managed_zone": "Network", + "google.cloud.gcp_dns_resource_record_set": "Network", + "google.cloud.gcp_filestore_instance": "Storage", + "google.cloud.gcp_iam_role": "Security & Identity", + "google.cloud.gcp_iam_service_account": "Security & Identity", + "google.cloud.gcp_kms_key_ring": "Security & Identity", + "google.cloud.gcp_pubsub_subscription": "App Integration", + "google.cloud.gcp_pubsub_topic": "App Integration", + "google.cloud.gcp_resource_record_set": "Network", + "google.cloud.gcp_sourcerepo_repository": "Developer Tools", + "google.cloud.gcp_sql_instance": "Database", + "google.cloud.gcp_storage_bucket": "Storage", + } as $actions| + .[] | + (if has("results") then # if ran in a loop, flatten it + .results[] as $result | + . + $result | + del(.results) + else + . + end) as $data | + select($data.action | in($actions)) | # only select objects defined in the action mapping + ($data.id // $data.etag // $data.selfLink // $data.name) as $id | # not everything returns an ID + ($data.name // $id) as $name | # not everything returns a name + ($data.kind // "missing") as $kind | # not everything returns a kind + select($name != null and $id != null) | + { + name: $name, + canonical_facts: { + id: $id, + name: $name, + kind: $kind, + }, + facts: { + infra_type: "PublicCloud", + infra_bucket: ($actions[$data.action] // "Unknown" | ascii_upcase), + device_type: $kind, + } + } +)