NetAuto Academy

Network Controllers

Policies, Templates, and Controller-Driven Change

Advanced12 min read

What you'll learn

  • How a desired-state change is expressed as intent, not a CLI command list
  • How submitting a policy change reuses the exact task/polling pattern already learned
  • Why controller-driven change still needs the same lab-only mutation discipline
  • How this differs from directly rendering and pushing configuration (Phase 2.9/3.0)
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

Intent, not commands

Configuration & Template Automation rendered exact CLI lines from a Jinja2 template. Ansible's ios_config sent specific configuration-mode lines. A controller task is different again: the request describes what should be true, and the controller — not the caller — decides what southbound commands actually achieve it.

desired_state.py
desired_vlans = [{"id": 10, "name": "USERS"}]

response = requests.post(
  "http://127.0.0.1:8766/tasks",
  json={"device_id": "SW2", "type": "vlan_config", "desired_vlans": desired_vlans},
  headers={"Authorization": "Bearer demo-token"},
  timeout=2,
)
print(response.status_code, response.json())

desired_vlans describes the outcome — VLAN 10 named USERS should exist. Nothing here says 'run vlan 10, then name USERS' the way Ansible's ios_config lines: did. That translation is the controller's job, on its southbound side, entirely opaque to this request.

output
202 {'task_id': 'task-SW2-1', 'device_id': 'SW2', 'status': 'queued'}

Real, verified output — the exact same submit-then-poll pattern from Lesson 4, now carrying a real desired-state payload instead of a bare device_id/type pair.

Quick checkConcept check
What does desired_vlans in the request body actually describe?

The same workflow, not a new one

Direct device config (Netmiko / Ansible / direct REST)
  1. You (or your template) specify the exact commands
  2. Sent to one device at a time
  3. Synchronous — you know the outcome from the response
Controller-driven change
  1. You specify the desired outcome
  2. One task can represent policy across many devices
  3. Asynchronous — poll to find out (Lesson 4's pattern, reused)
Quick checkScenario
A task is submitted to change SW3's VLANs. What confirms whether it actually succeeded?
Quick checkIdentify the correct code
Which request body correctly expresses controller-driven intent for SW3, rather than direct CLI commands?

Still lab-only, still read-first

The same discipline, one more time

Every mutating example in this module runs only against the local mock controller. A real controller change follows the exact same caution "Making Configuration Changes Safely," Reliable Automation's dry-run default, Ansible's check mode, and Phase 3.1's mutation lesson all already established: read/query first, review before changing, and never treat a real controller's mutation endpoints as safe to experiment against outside a controlled lab.

Quick checkMyth check
Does submitting a desired-state change through a controller require less caution than a direct send_config_set()/ios_config call, since the controller 'figures out the details'?

Key takeaways

  • A controller task describes desired outcome (intent), not exact CLI commands — the controller decides the southbound details.
  • Submitting a policy/config change reuses Lesson 4's exact submit-then-poll workflow — no new mechanism, just a richer request body.
  • One task can represent an intent that applies across however many devices a policy targets, unlike a single device-targeted Netmiko/Ansible/REST call.
  • The same lab-only, read-first, review-before-mutating discipline from every prior module applies without exception — a controller's abstraction doesn't reduce the real risk of a real change.