You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
This final lesson brings together everything you have learned into a practical, end-to-end network automation workflow. We will design a complete system for managing network configuration changes — from planning and development through testing, deployment, and validation.
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Plan │──>│ Develop │──>│ Test │──>│ Deploy │──>│ Validate │
│ │ │ │ │ │ │ │ │ │
│ - Ticket │ │ - Data │ │ - Lint │ │ - Ansible│ │ - pyATS │
│ - Design │ │ - Template│ │ - pytest │ │ - Nornir │ │ - Diff │
│ - Review │ │ - Git │ │ - Batfish│ │ - NAPALM │ │ - Alerts │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
Every automation workflow starts with understanding what needs to change and why:
| Activity | Description |
|---|---|
| Ticket / Request | Document the change request (e.g., "Add VLAN 100 to all access switches") |
| Impact analysis | Which devices are affected? What could go wrong? |
| Rollback plan | How do you undo the change if it fails? |
| Change window | When will the change be applied? |
| Approval | Get peer review and management sign-off |
network-automation/
├── inventory/
│ ├── production.yaml
│ └── lab.yaml
├── host_vars/
│ ├── core-rtr-01.yaml
│ └── access-sw-01.yaml
├── group_vars/
│ ├── routers.yaml
│ └── switches.yaml
├── templates/
│ ├── base_config.j2
│ ├── vlan_config.j2
│ └── ntp_config.j2
├── playbooks/
│ ├── deploy_vlans.yaml
│ ├── backup_configs.yaml
│ └── validate_state.yaml
├── tests/
│ ├── test_templates.py
│ ├── test_inventory.py
│ └── validation.yaml
├── configs/ # Generated configs for Batfish
├── backups/ # Device config backups
├── requirements.txt
├── ansible.cfg
└── README.md
The source of truth contains all the data about your intended network state:
# group_vars/switches.yaml
vlans:
- id: 10
name: SALES
- id: 20
name: ENGINEERING
- id: 30
name: MANAGEMENT
- id: 100
name: GUEST
ntp_servers:
- 10.0.0.50
- 10.0.0.51
dns_servers:
- 10.0.0.52
- 10.0.0.53
syslog_server: 10.0.0.60
snmp_community: readonly_community
{# templates/vlan_config.j2 #}
{% for vlan in vlans %}
vlan {{ vlan.id }}
name {{ vlan.name }}
{% endfor %}
# playbooks/deploy_vlans.yaml
---
- name: Deploy VLANs to switches
hosts: switches
gather_facts: false
tasks:
- name: Backup current configuration
cisco.ios.ios_config:
backup: true
backup_options:
dir_path: ../backups/
filename: "{{ inventory_hostname }}.cfg"
- name: Deploy VLAN configuration
cisco.ios.ios_config:
src: ../templates/vlan_config.j2
save_when: modified
register: config_result
- name: Display changes
ansible.builtin.debug:
msg: "{{ config_result.updates | default('No changes') }}"
# .github/workflows/network-ci.yaml (GitHub Actions)
name: Network CI
on:
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lint YAML
run: |
pip install yamllint
yamllint host_vars/ group_vars/ inventory/
- name: Lint Jinja2
run: |
pip install j2lint
j2lint templates/
unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run pytest
run: |
pip install -r requirements.txt
pytest tests/ -v
simulation:
runs-on: ubuntu-latest
services:
batfish:
image: batfish/batfish
ports:
- 9997:9997
steps:
- uses: actions/checkout@v4
- name: Analyse with Batfish
run: |
pip install pybatfish
python tests/batfish_analysis.py
| Strategy | Description | Risk |
|---|---|---|
| Canary | Deploy to one device first, validate, then roll out to the rest | Low |
| Rolling | Deploy to devices in batches (e.g., 5 at a time) | Medium |
| Blue-green | Prepare a new config set, switch over atomically | Low |
| Big bang | Deploy to all devices at once | High |
# deploy_canary.yaml
---
- name: Canary deployment - single device
hosts: access-sw-01
gather_facts: false
tasks:
- name: Deploy VLAN config
cisco.ios.ios_config:
src: ../templates/vlan_config.j2
save_when: modified
- name: Validate canary
cisco.ios.ios_command:
commands:
- show vlan brief
register: vlan_output
- name: Check VLANs exist
ansible.builtin.assert:
that:
- "'SALES' in vlan_output.stdout[0]"
- "'ENGINEERING' in vlan_output.stdout[0]"
fail_msg: "VLAN validation failed on canary device!"
success_msg: "Canary validation passed"
- name: Full rollout - all switches
hosts: switches
gather_facts: false
serial: 5 # Deploy 5 devices at a time
tasks:
- name: Deploy VLAN config
cisco.ios.ios_config:
src: ../templates/vlan_config.j2
save_when: modified
# validate_deployment.py
from genie.testbed import load
from genie.utils.diff import Diff
import json
import sys
testbed = load("testbed.yaml")
validation_passed = True
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.