← all cheatsheets
Network Automation

Network Automation

Python · Ansible · GitOps

1. Why Automate?2. The Tool Landscape3. Netmiko Essentials4. Ansible for Network Devices5. Modern Interfaces: Beyond Screen-Scraping6. Source of Truth & GitOps7. Where to Start (Pragmatic Path)

1. Why Automate?

Manual CLI changes do not scale past a handful of devices and are the leading cause of outages from typos and drift. Automation gives you consistency, speed, audit trails, and rollback — the config becomes code you can review and version.

Config drift

Scheduled backups + diffs catch unauthorized or forgotten changes

Mass changes

Push a VLAN or ACL update to 200 switches in minutes, not days

Compliance

Assert NTP, SNMP, AAA settings across the fleet automatically

Documentation

Inventory and interface reports generated from live state

2. The Tool Landscape

ToolTypeBest for
NetmikoPython library (SSH)Sending commands / configs to CLI devices, multi-vendor
NAPALMPython library (API/SSH)Structured getters (facts, interfaces, BGP) + config replace
NornirPython frameworkInventory + concurrent task execution, pure Python (no DSL)
AnsibleFramework (YAML DSL)Agentless playbooks, large module ecosystem, idempotency
TerraformIaC (declarative)Cloud networking (VPCs, LBs, firewalls), state-driven
pyATS / GenieCisco test frameworkParsing show output, network state validation

Rule of thumb

Ansible for orchestrated changes and compliance, Netmiko/Nornir for custom Python logic, NAPALM when you want vendor-neutral structured data.

3. Netmiko Essentials

Backup configs from a device list
from netmiko import ConnectHandler

devices = [
    {
        'device_type': 'cisco_ios',
        'host': '10.0.0.1',
        'username': 'admin',
        'password': 'secret',
    },
]

for device in devices:
    with ConnectHandler(**device) as conn:
        hostname = conn.send_command('show run | include hostname')
        config = conn.send_command('show running-config')
        with open(f"{device['host']}.cfg", 'w') as f:
            f.write(config)
device_typePlatform
cisco_iosCisco IOS / IOS-XE
cisco_nxosCisco Nexus
arista_eosArista EOS
juniper_junosJuniper JunOS
fortinetFortiGate
alcatel_aosAlcatel-Lucent OmniSwitch

4. Ansible for Network Devices

playbook.yml — save config + set NTP
- name: Baseline IOS devices
  hosts: switches
  gather_facts: false
  tasks:
    - name: Ensure NTP server
      cisco.ios.ios_config:
        lines:
          - ntp server 10.0.0.123

    - name: Save running to startup
      cisco.ios.ios_config:
        save_when: modified
  • Idempotent — running twice makes no second change
  • Inventory groups map to device roles (core, access, edge)
  • Use ansible-vault for credentials, never plaintext
  • `--check --diff` = dry run showing what would change

5. Modern Interfaces: Beyond Screen-Scraping

InterfaceTransportData
NETCONFSSH (port 830)XML, YANG models, transactions + rollback
RESTCONFHTTPSJSON/XML over REST, YANG models
gNMIgRPC / HTTP2Streaming telemetry + config, protobuf
CLI scrapingSSHUnstructured text — parse with TextFSM / Genie

Telemetry shift

SNMP polling every 5 minutes is being replaced by gNMI streaming telemetry — the device pushes counters the moment they change.

6. Source of Truth & GitOps

  • NetBox / Nautobot = intended state: devices, IPs, VLANs, circuits
  • Configs generated from Jinja2 templates + source-of-truth data
  • Changes go through Git pull requests — peer review before production
  • CI pipeline validates (lint, dry-run, lab test) before deploy
  • Live network is compared to intended state; drift raises alerts
Jinja2 template snippet
{% for vlan in vlans %}
vlan {{ vlan.id }}
 name {{ vlan.name }}
{% endfor %}

7. Where to Start (Pragmatic Path)

  • 1. Read-only first: automated backups and inventory reports — zero risk, instant value
  • 2. Diff configs daily; alert on drift
  • 3. Automate one boring change type (VLANs, descriptions, NTP)
  • 4. Add validation: pre/post checks around every change
  • 5. Move templates + data into Git; require reviews
  • 6. Only then: full zero-touch provisioning

Interview favorite

"How do you roll back a bad automated change?" — config archive + `configure replace` (IOS), commit rollback (JunOS), or re-render the previous Git version and push.