Skip to content

Latest commit

Β 

History

121 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Network Automation (NetDevOps Labs)

πŸ‡¨πŸ‡΄ EspaΓ±ol

A network automation repository built as Infrastructure as Code on Cisco devices (IOSv, CSR1000v) in a lab environment (PNETLab). It is organized as a series of progressive labs (Lab 2 to Lab 6), each building a complete network configuration and validation pipeline.

This is not an application or an installable package: it is a collection of pipelines where Git is the Source of Truth and every network change follows the same flow:

  1. Intent β€” declarative topology/intent in YAML versioned in Git.
  2. Render β€” configuration generation with Jinja2 templates.
  3. Pre-deploy validation with Batfish (labs 5 and 6).
  4. Precheck β€” verification of the current device state.
  5. Deploy β€” with Ansible (cisco.ios.ios_config, network_cli connection + libssh) or Netmiko (lab 3).
  6. Postcheck and evidence collection with Nornir.
  7. Validation with pyATS / Genie and artifact generation in artifacts/.

Platform components

Component URL / Detail Role
NetBox http://192.168.1.16:8000 Source of Truth and dynamic inventory (netbox.netbox.nb_inventory)
AWX http://192.168.1.13:30143 Job Template orchestrator
Jenkins β€” Triggers AWX Job Templates via REST API (Lab 5), with automatic rollback
Management network 172.30.30.0/26 OOB connectivity to all devices

Repository structure

β”œβ”€β”€ ansible.cfg                     # Global config: NetBox inventory, legacy libssh
β”œβ”€β”€ collections/requirements.yml    # Required Ansible collections
β”œβ”€β”€ inventories/netbox/             # Dynamic inventory (nb_inventory plugin)
β”œβ”€β”€ group_vars/                     # Cisco IOS connection vars (root)
β”œβ”€β”€ execution-environments/         # Containerfiles for AWX Execution Environments
β”‚   β”œβ”€β”€ iosv/                       # Minimal EE (ansible-core 2.15.13) for IOSv
β”‚   └── lab5-csr1000v/              # Full EE (nornir, pyats, genie, pybatfish...)
β”œβ”€β”€ scripts/netbox/                 # NetBox bootstrap from intent (labs 4 and 5)
β”œβ”€β”€ shared/                         # Shared Nornir inventory and scripts (Lab 2)
β”œβ”€β”€ playbooks/awx/                  # AWX smoke test (show_version.yml)
β”œβ”€β”€ docs/                           # Phase documentation
β”œβ”€β”€ lab2-inter-vlan/                # Lab 2: Inter-VLAN routing (Ansible pipeline)
β”œβ”€β”€ lab3-router-on-a-stick/         # Lab 3: Router-on-a-Stick (Python pipeline)
β”œβ”€β”€ lab4-ospf-ansible-pipeline/     # Lab 4: OSPF single-area (100% Ansible)
β”œβ”€β”€ lab5-ospf-multiarea-jenkins-pipeline/  # Lab 5: OSPF multi-area + Jenkins/AWX
└── lab6-eigrp-cicd-pipeline/       # Lab 6: EIGRP + CI/CD + APIs (in progress)

Labs

Each lab is self-contained (its own ansible.cfg, inventories, vars and artifacts/ where applicable).

Lab 2 β€” Inter-VLAN Routing (lab2-inter-vlan/)

Pure Ansible pipeline. playbooks/lab2_full_change.yml imports the phases render β†’ precheck β†’ deploy β†’ postcheck and then invokes the Nornir/Genie scripts from shared/scripts/.

  • Intent: intent/lab2_intent.yml (VLANs 10/20/30/40, switches SW_DMZ, DSW1, ASW1, ASW2).
  • Jinja2 templates in templates/.

Lab 3 β€” Router-on-a-Stick (lab3-router-on-a-stick/)

Same flow as Lab 2 but orchestrated with Python scripts: scripts/lab3_full_change.py runs render β†’ precheck β†’ deploy (Netmiko) β†’ postcheck β†’ nornir β†’ genie.

  • Devices: R1 (router), SW_DMZ, ASW1, ASW2.
  • Note: the scripts have hardcoded lab credentials (netdevops/cisco); this is a known historical exception, not a pattern to replicate.

Lab 4 β€” OSPF Single-Area (lab4-ospf-ansible-pipeline/)

Orchestrated 100% by Ansible with numbered playbooks 00_–07_; playbooks/lab4_pipeline.yml imports them in order.

  • Source of truth: intent/lab4_source_of_truth.yml; dynamic inventory from NetBox (local host_vars/ and group_vars/).
  • Topology: R1–R4 (OSPF area 0, /30 links 10.0.x.x), SW_DMZ, ASW1, PC1 (LAN 10.10.30.0/24). See lab4-ospf-ansible-pipeline/README.md for the full addressing.
  • Lab rule: only the management configuration is done manually via CLI; everything else is applied by Ansible.

Lab 5 β€” OSPF Multi-Area + Jenkins (lab5-ospf-multiarea-jenkins-pipeline/)

Multi-area OSPF on CSR1000v with Ansible roles (lab5_render, lab5_batfish, lab5_precheck, lab5_ospf, lab5_postcheck, lab5_nornir, lab5_pyats, lab5_validate, lab5_cleanup). playbooks/lab5_pipeline.yml imports playbooks 01_–08_.

  • Introduces Batfish as a pre-deploy validation gate.
  • The Jenkinsfile locates the AWX Job Template by name, launches it only if EXECUTE_PIPELINE=true, waits for the result and, on failure, triggers an automatic rollback (template ID 16).
  • Credentials in group_vars/vault.yml (Ansible Vault).

Lab 6 β€” EIGRP + CI/CD + APIs (lab6-eigrp-cicd-pipeline/)

Declarative topology in vars/topology.yml (6 CSR1000v, LAB6). API-first approach:

  • scripts/sync_netbox.py β€” syncs the Git topology into NetBox.
  • validation/validate_netbox_sot.py β€” validates NetBox against Git (read-only).
  • scripts/render_eigrp.py and scripts/render_batfish_candidates.py β€” config rendering and Batfish snapshots.
  • Playbooks 01_–03_ (pre-change backup, Batfish pre-deploy, precheck) with lab6_* roles.
  • The batfish/, jenkins/, netconf/, nornir/, postman/, pyats/, restconf/ subdirectories are reserved for future work.

Prerequisites

  • Automation environment Python: /opt/automation/venv/bin/python.
  • Ansible with the collections from collections/requirements.yml:
    ansible-galaxy collection install -r collections/requirements.yml
  • Access to NetBox, AWX and the management network 172.30.30.0/26.

Environment variables

Variable Usage
NETBOX_TOKEN Required for NetBox API scripts (bootstrap_*, sync_netbox.py, validate_netbox_sot.py)
NETBOX_URL Optional (default http://192.168.1.16:8000)
IOS_PASSWORD SSH password for IOS devices in the root inventory and Lab 4
awx-api-token Jenkins credential holding the AWX API token (Lab 5)

Ansible Vault

lab5*/group_vars/vault.yml and lab6*/group_vars/vault.yml are encrypted and define vault_ios_username, vault_ios_password, vault_ios_enable_password. Run with --ask-vault-pass or a vault password file.

Main commands

From the repository root, unless otherwise noted:

# Verify the NetBox dynamic inventory
ansible-inventory --graph

# Reachability of inventory hosts
ansible all -m ansible.builtin.command -a 'ping -c 2 {{ ansible_host }}' -c local

# AWX smoke test
ansible-playbook playbooks/awx/show_version.yml

# Lab 2 (full Ansible pipeline)
ansible-playbook lab2-inter-vlan/playbooks/lab2_full_change.yml

# Lab 3 (full Python pipeline)
python3 lab3-router-on-a-stick/scripts/lab3_full_change.py

# Lab 4 (uses its local ansible.cfg)
cd lab4-ospf-ansible-pipeline && ansible-playbook playbooks/lab4_pipeline.yml

# Lab 5 (requires vault password)
cd lab5-ospf-multiarea-jenkins-pipeline && ansible-playbook playbooks/lab5_pipeline.yml --ask-vault-pass

# Lab 6
cd lab6-eigrp-cicd-pipeline
export NETBOX_TOKEN=<token>
python3 scripts/sync_netbox.py                  # sync NetBox
python3 validation/validate_netbox_sot.py       # validate NetBox vs Git
python3 scripts/render_eigrp.py                 # render configs to configs/
ansible-playbook playbooks/01_backup_prechange.yml --ask-vault-pass

# Build Execution Environments (example)
cd execution-environments/lab5-csr1000v && podman build -t ee-lab5-csr1000v .

artifacts/ convention

Each lab stores evidence in artifacts/:

  • rendered/ β€” rendered configurations (versioned in Git).
  • precheck/, postcheck/, deploy/ β€” evidence from each phase.
  • nornir/ β€” show outputs collected with Nornir.
  • genie/ / pyats/ β€” JSON validation reports.
  • batfish/ β€” pre-deploy validation results.
  • backups/ β€” pre-change backups (some ignored in .gitignore due to size).

.gitkeep files keep empty directories under version control.

Validation and testing

There is no traditional test framework (pytest, unit-test CI): validation is domain-specific and acts as a pipeline gate β€” each phase aborts the flow if it fails.

  • Batfish (offline pre-deploy validation): labs 5 and 6, output in artifacts/batfish/output/.
  • pyATS / Genie: parse the show outputs collected by Nornir and generate JSON reports; exit code β‰  0 on any FAIL.
  • SoT validation: lab6*/validation/validate_netbox_sot.py compares NetBox against vars/topology.yml (read-only).
  • When modifying a pipeline: at minimum run ansible-playbook --syntax-check on the affected playbook and, if possible, a render/precheck run without deploy.

Code conventions

  • Language: mix of Spanish and English. Documentation, Jenkinsfile and recent scripts (labs 5 and 6) in Spanish; labs 2 and 3 in English. Keep the language of the file being edited.
  • Playbooks numbered by phase (00_cleanup, 01_render, 02_precheck, ...) plus a *_pipeline.yml that only does import_playbook in order.
  • Ansible roles prefixed with the lab name (lab5_*, lab6_*), with defaults/, tasks/, vars/ and files/ for Python scripts.
  • Deployment always from a rendered file: cisco.ios.ios_config with src: .../artifacts/rendered/{{ inventory_hostname }}.cfg and save_when.
  • All evidence is saved with delegate_to: localhost.
  • Python scripts: #!/usr/bin/env python3, paths relative with Path(__file__).resolve().parent, console output with [OK] / [FAIL] / [PASS] prefixes and sys.exit(1) on error.

Security considerations

  • Never commit plaintext credentials: use Ansible Vault or environment variables (NETBOX_TOKEN, IOS_PASSWORD).
  • Connections use ansible.netcommon.network_cli with libssh and legacy algorithms (ssh-rsa, diffie-hellman-group-exchange-sha1, ...) because the lab IOSv devices are old; host_key_checking = False is a lab environment requirement, not a general recommendation.
  • NetBox scripts disable TLS verification (verify=False) because the lab NetBox uses HTTP/self-signed certificates; deliberate and only valid for the lab.
  • The Lab 5 Jenkinsfile has a safe mode: without EXECUTE_PIPELINE=true it only validates that the Job Template exists, without launching it.

πŸ“„ License

This project is licensed under the MIT License.

Additional documentation

  • AGENTS.md β€” detailed guide for AI agents (structure, commands, conventions).
  • lab4-ospf-ansible-pipeline/README.md β€” full Lab 4 addressing and topology.
  • docs/lab4/ β€” phase documentation (e.g. NetBox dynamic inventory).

About

Multi-vendor Network Automation and NetDevOps CI/CD labs using Ansible, AWX, NetBox, Jenkins, GitLab, GiHub, Python, Jinja2, Nornir, pyATS/Genie, Batfish, REST APIs, NETCONF, RESTCONF, Docker, Podman and Kubernetes.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages