Skip to content

Commit 855e352

Browse files
authored
Merge pull request #36 from stevefulme1/feat/indirect-node-counting
feat: add indirect node counting for AAP 2.6+ subscription compliance
2 parents 40887c5 + e55d38f commit 855e352

4 files changed

Lines changed: 232 additions & 1 deletion

File tree

changelogs/config.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ changelog_filename_template: CHANGELOG.rst
33
changelog_filename_version_depth: 0
44
changes_file: changelog.yaml
55
changes_format: combined
6+
flatmap: true
7+
is_other_project: false
68
keep_fragments: false
7-
notes_dir: fragments
9+
mention_ancestor: true
10+
new_plugins_after_name: removed_features
11+
notesdir: fragments
812
prelude_section_name: release_summary
913
prelude_section_title: Release Summary
1014
sanitize_changelog: true
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
minor_changes:
3+
- "Added ``extensions/audit/event_query.yml`` for AAP 2.6+ indirect node counting support."
4+
- "AAP can now accurately count network devices managed indirectly through the Catalyst Center API."

extensions/audit/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This directory, and the event_query.yml file, are used by AAP (Red Hat) to capture metadata about certain module usage for indirect node counting.

extensions/audit/event_query.yml

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
---
2+
# Indirect Node Counting Query — cisco.catalystcenter collection
3+
# Applies to: Ansible Automation Platform 2.6+
4+
# Path: extensions/audit/event_query.yml
5+
#
6+
# SCOPE
7+
# -----
8+
# Cisco Catalyst Center manages network devices (switches, routers, wireless
9+
# controllers, access points) indirectly through its REST API. Ansible
10+
# connects to localhost and talks to the Catalyst Center API, which in turn
11+
# manages hundreds or thousands of network devices. Without this file AAP
12+
# would count only the single localhost connection, not the actual managed
13+
# infrastructure.
14+
#
15+
# The queries below extract per-device identity from the module return data
16+
# so AAP can accurately count every network device managed through the
17+
# Catalyst Center API as an indirect managed node.
18+
#
19+
# RETURN DATA STRUCTURE
20+
# ---------------------
21+
# The cisco.catalystcenter workflow manager modules inherit from
22+
# CatalystCenterBase and return:
23+
#
24+
# {
25+
# "changed": bool,
26+
# "diff": [{"before": {...}, "after": {...}}, ...],
27+
# "response": [<message_or_dict>, ...],
28+
# "warnings": [...]
29+
# }
30+
#
31+
# Device identity (management IP, hostname, serial number) is available in
32+
# the diff entries when devices are added, updated, provisioned, or deleted.
33+
# The diff[].after dict typically contains keys from the Catalyst Center
34+
# device API: managementIpAddress, hostname, serialNumber, id, etc.
35+
#
36+
# INCLUDED MODULES
37+
# ----------------
38+
# cisco.catalystcenter.inventory_workflow_manager
39+
# — Adds, updates, deletes, resyncs, and provisions network devices.
40+
# This is the primary module that manages the device lifecycle.
41+
# diff[].after contains the full device record from Catalyst Center.
42+
#
43+
# cisco.catalystcenter.provision_workflow_manager
44+
# — Provisions devices to sites, assigns templates, and manages
45+
# wired/wireless device provisioning.
46+
# diff[].after contains the provisioned device details.
47+
#
48+
# cisco.catalystcenter.pnp_device_claim_to_site
49+
# — Claims a Plug and Play device to a site.
50+
# Return data contains the claimed device serial and hostname.
51+
#
52+
# cisco.catalystcenter.pnp_device_claim
53+
# — Claims one or more Plug and Play devices.
54+
# Return data contains claimed device details.
55+
#
56+
# cisco.catalystcenter.pnp_device
57+
# — Manages Plug and Play device records (add/update/delete).
58+
# Return data contains the PnP device record.
59+
#
60+
# EXCLUDED MODULES
61+
# ----------------
62+
# *_info modules — Read-only queries that do not manage devices.
63+
# Including them would inflate the count with
64+
# every status check or inventory query.
65+
# compliance_device — Runs compliance checks, does not manage the
66+
# device lifecycle.
67+
# device_replacement — Tracks replacement workflow state; the actual
68+
# device add/remove goes through
69+
# inventory_workflow_manager.
70+
# assign_device_to_site — Site assignment only; the device already
71+
# exists and is counted via
72+
# inventory_workflow_manager.
73+
# swim_* — Software image management; operates on images,
74+
# not device identity.
75+
# network_device_export — Exports device data to CSV; read-only.
76+
# network_device_custom_prompt — Configures CLI prompts, not device lifecycle.
77+
#
78+
# NOTE: Wildcard module matching (cisco.catalystcenter.*) is intentionally
79+
# NOT used. It would include info/query/compliance modules and inflate the
80+
# count. Only modules that perform device lifecycle operations (add, update,
81+
# provision, claim, delete) are listed.
82+
83+
# -----------------------------------------------------------------
84+
# cisco.catalystcenter.inventory_workflow_manager
85+
#
86+
# Primary device lifecycle module. Manages add/update/delete/resync
87+
# of network devices in Catalyst Center inventory.
88+
#
89+
# diff[].after contains device attributes from the Catalyst Center API:
90+
# managementIpAddress, hostname, serialNumber, id, type, role, etc.
91+
#
92+
# Guard: managementIpAddress must be non-null — a device without a
93+
# management IP was not successfully committed to inventory.
94+
# -----------------------------------------------------------------
95+
cisco.catalystcenter.inventory_workflow_manager:
96+
query: >-
97+
.diff[]? | .after? // empty |
98+
select((.managementIpAddress // null) != null) |
99+
{
100+
name: (.hostname // .managementIpAddress),
101+
canonical_facts: {
102+
management_ip: .managementIpAddress,
103+
serial_number: (.serialNumber // null),
104+
catalyst_center_id: (.id // null)
105+
},
106+
facts: {
107+
device_type: (
108+
if (.family // "" | test("Unified AP"; "i"))
109+
then "access_point"
110+
elif (.role // "" | test("ACCESS"; "i"))
111+
then "network_switch"
112+
elif (.role // "" | test("CORE|DISTRIBUTION"; "i"))
113+
then "network_switch"
114+
elif (.role // "" | test("BORDER ROUTER"; "i"))
115+
then "network_router"
116+
else "network_device"
117+
end
118+
),
119+
platform: "cisco_catalyst_center",
120+
hostname: (.hostname // null),
121+
role: (.role // null),
122+
family: (.family // null),
123+
software_type: (.softwareType // null)
124+
}
125+
}
126+
127+
# -----------------------------------------------------------------
128+
# cisco.catalystcenter.provision_workflow_manager
129+
#
130+
# Provisions devices to sites and applies templates.
131+
# diff[].after contains provisioned device data.
132+
# -----------------------------------------------------------------
133+
cisco.catalystcenter.provision_workflow_manager:
134+
query: >-
135+
.diff[]? | .after? // empty |
136+
select((.managementIpAddress // null) != null) |
137+
{
138+
name: (.hostname // .managementIpAddress),
139+
canonical_facts: {
140+
management_ip: .managementIpAddress,
141+
serial_number: (.serialNumber // null),
142+
catalyst_center_id: (.id // null)
143+
},
144+
facts: {
145+
device_type: "network_device",
146+
platform: "cisco_catalyst_center",
147+
hostname: (.hostname // null)
148+
}
149+
}
150+
151+
# -----------------------------------------------------------------
152+
# cisco.catalystcenter.pnp_device_claim_to_site
153+
#
154+
# Claims a PnP device to a site. The return data contains the
155+
# device details in the catalystcenter_response dict.
156+
# -----------------------------------------------------------------
157+
cisco.catalystcenter.pnp_device_claim_to_site:
158+
query: >-
159+
.catalystcenter_response? // empty |
160+
.response? // empty |
161+
select(type == "object") |
162+
select((.serialNumber // .deviceInfo.serialNumber // null) != null) |
163+
{
164+
name: (.hostname // .deviceInfo.hostname // .serialNumber // .deviceInfo.serialNumber),
165+
canonical_facts: {
166+
serial_number: (.serialNumber // .deviceInfo.serialNumber),
167+
management_ip: (.managementIpAddress // .deviceInfo.httpHeaders[0].value // null),
168+
catalyst_center_id: (.id // ._id // null)
169+
},
170+
facts: {
171+
device_type: "network_device",
172+
platform: "cisco_catalyst_center"
173+
}
174+
}
175+
176+
# -----------------------------------------------------------------
177+
# cisco.catalystcenter.pnp_device_claim
178+
#
179+
# Claims one or more PnP devices.
180+
# -----------------------------------------------------------------
181+
cisco.catalystcenter.pnp_device_claim:
182+
query: >-
183+
.catalystcenter_response? // empty |
184+
.response? // empty |
185+
select(type == "object") |
186+
select((.serialNumber // .deviceInfo.serialNumber // null) != null) |
187+
{
188+
name: (.hostname // .deviceInfo.hostname // .serialNumber // .deviceInfo.serialNumber),
189+
canonical_facts: {
190+
serial_number: (.serialNumber // .deviceInfo.serialNumber),
191+
management_ip: (.managementIpAddress // null),
192+
catalyst_center_id: (.id // ._id // null)
193+
},
194+
facts: {
195+
device_type: "network_device",
196+
platform: "cisco_catalyst_center"
197+
}
198+
}
199+
200+
# -----------------------------------------------------------------
201+
# cisco.catalystcenter.pnp_device
202+
#
203+
# Manages PnP device records (add/update/delete).
204+
# -----------------------------------------------------------------
205+
cisco.catalystcenter.pnp_device:
206+
query: >-
207+
.catalystcenter_response? // empty |
208+
.response? // empty |
209+
select(type == "object") |
210+
select((.serialNumber // .deviceInfo.serialNumber // null) != null) |
211+
{
212+
name: (.hostname // .deviceInfo.hostname // .serialNumber // .deviceInfo.serialNumber),
213+
canonical_facts: {
214+
serial_number: (.serialNumber // .deviceInfo.serialNumber),
215+
management_ip: (.managementIpAddress // null),
216+
catalyst_center_id: (.id // ._id // null)
217+
},
218+
facts: {
219+
device_type: "network_device",
220+
platform: "cisco_catalyst_center"
221+
}
222+
}

0 commit comments

Comments
 (0)