Back to Learn

Ansible network automation lab

A multi-vendor playbook lab (Cisco IOS & Juniper JunOS) that teaches core Ansible network patterns one runnable playbook at a time.

Ansible
Cisco IOS
Juniper JunOS
Network Automation
Variables, loops & dynamic device lists
Conditionals & multi-vendor branching
Handlers, roles, Vault & Jinja2 templating

Playbooks by concept

config_backup.yml
Variables + loops

Iterates a list of devices and writes a config backup file per host into a backup directory.

config_backup.yml
yaml
---
- name: Network Config Backup Automation
  hosts: localhost
  gather_facts: false
  vars:
    backup_dir: "./backup"
    devices:
      - { hostname: jarvis-rtr-blr-01, ip: 10.0.0.1, type: cisco_ios,  site: Bangalore }
      - { hostname: jarvis-fw-blr-01,  ip: 10.0.0.3, type: juniper_srx, site: Bangalore }
  tasks:
    - name: Create backup directory
      ansible.builtin.file:
        path: "{{ backup_dir }}"
        state: directory

    - name: Back up config for each device
      ansible.builtin.copy:
        content: |
          hostname {{ item.hostname }}
          interface GigabitEthernet0/0
           ip address {{ item.ip }} 255.255.255.0
           no shutdown
          end
        dest: "{{ backup_dir }}/{{ item.hostname }}_backup.txt"
      loop: "{{ devices }}"
bgp_health_check.yml
Conditionals (when)

Reports each BGP neighbour state and raises a warning for any neighbour not in Established.

bgp_health_check.yml
yaml
---
- name: BGP Neighbor Health Check
  hosts: localhost
  gather_facts: false
  vars:
    bgp_neighbors:
      - { ip: 10.10.10.1, state: Established }
      - { ip: 10.10.10.3, state: Idle }
  tasks:
    - name: Show BGP status
      ansible.builtin.debug:
        msg: "Neighbor {{ item.ip }} is {{ item.state }}"
      loop: "{{ bgp_neighbors }}"

    - name: Alert for failed neighbors
      ansible.builtin.debug:
        msg: "WARNING: Neighbor {{ item.ip }} is DOWN"
      when: item.state != "Established"
      loop: "{{ bgp_neighbors }}"
conditionals.yml
Multi-vendor logic

Branches on device type and environment so the same playbook applies Cisco vs Juniper logic safely.

conditionals.yml
yaml
---
- name: Conditionals Practice
  hosts: localhost
  gather_facts: false
  vars:
    device_type: "cisco"
    env_type: "production"
  tasks:
    - name: Cisco specific config
      ansible.builtin.debug:
        msg: "Applying Cisco IOS commands"
      when: device_type == "cisco"

    - name: Juniper specific config
      ansible.builtin.debug:
        msg: "Applying Juniper JunOS commands"
      when: device_type == "juniper"

    - name: Production safety check
      ansible.builtin.debug:
        msg: "WARNING - Production change, double check"
      when: env_type == "production"
handlers.yml
Event-driven (notify)

Tasks notify handlers only when they report a change, so services restart just once at the end.

handlers.yml
yaml
---
- name: Handlers Practice
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Update NTP config
      ansible.builtin.debug:
        msg: "NTP config updated"
      changed_when: true
      notify: Restart NTP service
  handlers:
    - name: Restart NTP service
      ansible.builtin.debug:
        msg: "HANDLER - NTP service restarted"

Inventory

inventory.ini
ini
[local]
localhost ansible_connection=local

[routers]
# Add real devices here

[all:vars]
ansible_python_interpreter=/usr/bin/python3

Run it

terminal
bash
# Install the vendor collections
ansible-galaxy collection install cisco.ios junipernetworks.junos

# Run any lab playbook
ansible-playbook -i inventory.ini config_backup.yml
ansible-playbook -i inventory.ini bgp_health_check.yml
ansible-playbook -i inventory.ini conditionals.yml