Advanced Python Automation for Network Engineers
Capstone: A Reusable Network Automation Package
What you'll learn
- How every lesson's piece fits into one complete, working package
- That the package is genuinely tested, not just executed once and trusted
- The full progression: CLI through report, with nothing skipped
- That this closes the exact question Lesson 1 opened with
Listen to a guided explanation of this lesson.
Spoken narration isn't supported in this browser.
The question this module opened with, answered
- CLInetwork-tool check — Lesson 8
- ConfigurationCLI arg > env var > default — Lesson 8
- Inventoryload_inventory() — Lesson 2, upgraded in Lesson 3
- Reusable automation enginecheck_device() — Lessons 3-5
- Connection abstractionConnection class + @retry — Lesson 4
- Executionconcurrent, bounded — Lesson 7
- Structured resultsAutomationResult dataclasses — Lesson 3
- Validationrequired vs actual VLANs — Lesson 3
- Loggingevery step, secret-safe — Lesson 5
- Reportreport.json
One-off script → reusable tool, proven, not asserted
This is the exact progression Lesson 1 named. Every stage above is real, working code from an earlier lesson in this module — nothing here is new automation logic. What makes this a capstone is that all nine pieces now run together as one package, tested and invokable, instead of living in nine separate lesson examples.
The package, assembled
network_automation/
__init__.py
inventory.py -- load_inventory() (Lesson 2, 3)
models.py -- Device, Vlan, AutomationResult, Status (Lesson 3)
exceptions.py -- AutomationError and subclasses (Lesson 3)
connections.py -- Connection, @retry (Lesson 4)
logging_config.py -- configure_logging(), get_logger() (Lesson 5)
automation.py -- check_device() (Lessons 3-5)
cli.py -- argparse entrypoint, concurrency (Lessons 7, 8)
tests/
test_automation.py -- unit tests, fakes (Lesson 6)Every file traces back to exactly one earlier lesson. This is the full package, not a summary of it.
Running it: the complete, real output
$ export AUTOMATION_TOKEN=demo-token
$ python -m network_automation.cli check --inventory devices.csv --workers 5 --report report.jsonGenuinely runnable exactly as shown, against this module's mock backend (Option B).
Checked 5 devices
already-compliant: 1
validation-failed: 2
auth-failed: 1
unreachable: 1
Report written to report.jsonReal, verified output — the same 5-device fleet and the same four outcomes every module since Phase 2.6 has ultimately produced, now via a tested package instead of a single script.
[
{
"hostname": "SW1",
"status": "already-compliant",
"detail": "no change needed"
},
{
"hostname": "SW2",
"status": "validation-failed",
"detail": "missing VLANs: [10]"
},
{
"hostname": "SW5",
"status": "auth-failed",
"detail": "SW5 rejected the credentials"
},
{
"hostname": "SW3",
"status": "validation-failed",
"detail": "missing VLANs: [30]"
},
{
"hostname": "SW4",
"status": "unreachable",
"detail": "SW4 timed out"
}
]Real, verified output — diffed exactly against a real run. Order reflects concurrent completion (Lesson 7), not submission order — SW1/SW2/SW5 finish first, SW3's retry and SW4's timeout finish later.
Actually tested — run again here, not just claimed
$ python -m unittest discover -v -s testsGenuinely re-run for this capstone, not assumed from Lesson 6.
test_already_compliant ... ok
test_authentication_failure ... ok
test_missing_vlan_is_validation_failed ... ok
test_unreachable_device ... ok
----------------------------------------------------------------------
Ran 4 tests in 1.002s
OKReal, verified output. The full package's core logic is proven correct without a live target — the actual, concrete meaning of 'reusable and maintainable' this module has been building toward since Lesson 1.
Two ways to run it
- Any device/controller/API matching Connection's interfacesubject to availability
- Point --base-url at it, with real credentials
- A real report.json
- This module's own mock backend
- Nothing beyond Python and requests
- The exact report.json shown above
Option A — Connection's interface (get_state/apply_state) is deliberately generic; pointing --base-url at a real device, controller, or API that speaks the same shape works without changing any calling code — the concrete payoff of the abstraction built in Lesson 4. Never executed in this authoring environment; not claimed as tested. Option B — this module's own mock backend is a complete, required, fully-executed path: every result above is real.
What this module actually built
Nothing here replaced Netmiko, Ansible, requests, or the controller client from earlier modules — every one of them remains exactly as valid a way to reach a device or API as when it was taught. What changed is how the code around those capabilities is organized: a package instead of a script, dataclasses instead of loose dicts, a real exception hierarchy instead of compared strings, a class where state and behavior belong together, real logging, real tests against fakes, bounded concurrency, and a real CLI. One-off script → reusable tool — not a claim, a package that was actually run and actually tested.
Key takeaways
- Every piece of this capstone — inventory, models, exceptions, connections, logging, concurrency, CLI — is exactly what Lessons 2 through 8 already built and verified. This lesson is integration, not new capability.
- The CLI was actually run: 5 devices, 4 outcomes, a real report.json, diffed exactly against a real run.
- The test suite was actually re-run here: 4 tests, 1.002s, OK — proof, not a claim.
- Result order (SW1, SW2, SW5, SW3, SW4) is a direct, visible consequence of concurrent execution — not arbitrary.
- Option A (a real backend) is optional and was not executed here — the package's completeness rests on what was genuinely run: the mock-backend capstone and the real test suite.