NetAuto Academy

Network Controllers

Inventory and Resources: Querying a Controller's View of the Network

Advanced11 min read

What you'll learn

  • Why a controller's inventory is queried, not locally maintained
  • Sites as a new resource layer above individual devices
  • How to retrieve a controller's device inventory with a real GET request
  • That pagination and scale become real concerns at real controller size
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

You maintain devices.csv. A controller doesn't need you to.

Every capstone since Phase 2.6 started with a local file — devices.csv, or an Ansible inventory built from it. That file was the source of truth you maintained. A controller flips this: the controller itself is the inventory — you query it to find out what devices exist, rather than telling it.

devices.csv / Ansible inventory
  1. You author ita local file you keep up to date
  2. The automation reads your file
Controller inventory
  1. The controller maintains itas devices are onboarded
  2. Your automation queries the controllerGET /devices
Quick checkConcept check
Where does a network controller's device inventory actually come from?

Sites: a new layer above devices

query_sites.py
import requests

response = requests.get("http://127.0.0.1:8766/sites", timeout=2)
print(response.json())

A real GET request — the exact requests.get() call from Phase 3.1, not re-taught here, just reused.

output
{'sites': [{'name': 'HQ', 'devices': ['SW1', 'SW2', 'SW3']}, {'name': 'Branch1', 'devices': ['SW4', 'SW5']}]}

Real, verified output against this module's mock controller. Sites are a genuinely new inventory concept — a grouping layer above individual devices that neither devices.csv nor an Ansible inventory file had by default.

Quick checkPredict output
Based on the sites data above, which site does SW4 belong to?

The device inventory itself

query_devices.py
response = requests.get("http://127.0.0.1:8766/devices", timeout=2)
for device in response.json()["devices"]:
  print(device["hostname"], "-", device["site"], "-", device["ip"])

Looping over a list of dicts — the exact same pattern used on devices.csv rows since Phase 2.6, now over data the controller supplied instead of a local file.

output
SW1 - HQ - 10.10.10.1
SW2 - HQ - 10.10.10.2
SW3 - HQ - 10.10.10.3
SW4 - Branch1 - 10.10.10.4
SW5 - Branch1 - 10.10.10.5

Real, verified output — the same SW1–SW5 fleet from every prior capstone, now grouped by site and retrieved from the controller instead of read from a file.

Quick checkIdentify the correct code
Which line correctly retrieves a single device's detail from the controller, given hostname = "SW2"?

At real controller scale

Pagination and rate limits become real concerns

This mock controller returns every device in one response — fine for a 5-device fleet. A real controller managing thousands of devices typically paginates GET /devices (returning a page at a time with a "next page" token) and may rate-limit how often it can be queried. Neither is demonstrated here — mentioned honestly as a real-world scale concern this module's small fleet doesn't need to exercise.

Quick checkScenario
A real controller manages 5,000 devices. Why might GET /devices behave differently there than it does against this module's 5-device mock?

Key takeaways

  • A controller's inventory is queried, not locally maintained — GET /devices replaces devices.csv as the source of what exists.
  • Sites are a genuinely new inventory concept: a grouping layer above individual devices.
  • Every GET request here reuses Phase 3.1's requests.get() and response.json() skills directly — nothing new about the HTTP mechanics.
  • Real controllers at scale typically paginate and rate-limit inventory queries — a real consideration this module's small teaching fleet doesn't need to exercise.

Done with this lesson?

Next lesson

Asynchronous Controller Workflows: Tasks and Polling