NetAuto Academy

Ansible for Network Engineers

Why Ansible? Declarative Automation

Intermediate10 min read

What you'll learn

  • The difference between imperative and declarative automation
  • Which parts of the Reliable Automation project were really 'the automation' vs. 'making it safe'
  • Why a framework taking over that safety machinery is a genuine upgrade, not a detour
  • That this module extends everything already built, rather than replacing it
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

Everything so far has been imperative

Every script this curriculum has built — from "Your First Network Automation" through Configuration & Template Automation — shares one trait: you wrote every step. Connect. Check the current state. Decide whether a change is needed. Apply it. Verify it worked. Classify the result. Every one of those steps was a line of Python you were responsible for getting right.

That's called imperative automation: you describe how to do the thing, step by step.

the imperative shape, from Reliable Automation
connection, attempts = connect_with_retry(device)
outcome = apply_ntp_config(connection, REQUIRED_NTP_SERVER, dry_run=dry_run)
# every one of those steps is a function *you* wrote and are responsible for

Nothing wrong with this — it's exactly how this curriculum built real understanding of what automation actually has to handle. But notice: retry logic, the idempotency check, the verification step — none of that is specific to NTP. It's generic machinery, rewritten by hand for every new kind of change.

Quick checkConcept check
In the imperative style used throughout this curriculum so far, who is responsible for writing the retry logic, the idempotency check, and the verification step?

Declarative: describe the end state, not the steps

Declarative automation flips this. Instead of writing the steps, you describe the desired state — "VLAN 10 named USERS should exist on this switch" — and a framework figures out how to check the current state, decide if a change is needed, apply it safely, and verify it. Ansible is built entirely around this idea.

Imperative (what you've built so far)
  1. Connect, with retryyou wrote connect_with_retry()
  2. Check current stateyou wrote the pre-check
  3. Decide and applyyou wrote the idempotency check
  4. Verifyyou wrote the post-check
Declarative (Ansible)
  1. Describe desired state"VLAN 10 named USERS should exist"
  2. One task, one module
  3. The module checks, decides, applies, and reports back
Quick checkConcept check
What does 'declarative' mean in the context of Ansible?

This isn't a new idea to you — it's a new place for one

Look closely at what an Ansible module actually replaces:

apply_ntp_config() — Reliable Automation, hand-written
def apply_ntp_config(connection, required_ntp_server, dry_run=True):
  pre_check = connection.send_command("show run | include ntp server")
  already_configured = required_ntp_server in pre_check
  if already_configured:
      return {"changed": False, "verified": True, "dry_run": dry_run}
  if dry_run:
      return {"changed": False, "verified": None, "dry_run": True}
  connection.send_config_set([f"ntp server {required_ntp_server}"])
  post_check = connection.send_command("show run | include ntp server")
  verified = required_ntp_server in post_check
  return {"changed": True, "verified": verified, "dry_run": False}

Pre-check, decide, apply-if-needed, post-check, report. This exact shape — check before changing, only change if needed, verify afterward — is precisely what a well-built Ansible module does internally, for you, every single time it runs.

Idempotency isn't new here — it's finally automatic

"Idempotency Explained for Network Engineers" (Network Automation Fundamentals) taught check-before-change as a principle. Reliable Automation made you implement that principle by hand, function by function. Ansible's modules are built to be idempotent by design — the framework guarantees the check-before-change behavior that used to be your responsibility to get right on every new script.

Quick checkScenario
A team has ten different hand-written Python functions, each with its own copy of check-before-change logic for a different setting (NTP, VLANs, hostname, etc.). What's the real cost of that approach, compared to using idempotent Ansible modules for the same ten settings?

What doesn't change

This module does not throw away Reliable Automation or Configuration & Template Automation. The inventory concept, the VLAN deployment problem, the Jinja2 template file, the idea that a preview must come before a real change — all of it carries forward. What changes is who writes the check-decide-apply-verify machinery: you, by hand, in Python — or a framework, declaratively, in YAML.

Quick checkMyth check
Does learning Ansible mean the Python, Netmiko, and Jinja2 skills from earlier modules are now obsolete?

Key takeaways

  • Imperative automation (what this curriculum has built so far) means you write every check-decide-apply-verify step by hand.
  • Declarative automation (Ansible) means you describe the desired state; a well-built module handles checking, deciding, applying, and verifying.
  • Idempotency — a principle this curriculum has taught since Network Automation Fundamentals — is what Ansible's modules guarantee by design, instead of something you reimplement per project.
  • This module extends, not replaces: the same VLAN deployment problem, the same inventory concept, and the same Jinja2 template file from earlier modules carry forward into this one.