← Interview Prep

Ansible — Cases & Usage

Runnable network-automation playbooks: ad-hoc facts, config push with backup/check/diff, Jinja2 templating, declarative resource modules, safe rolling changes (serial), dynamic inventory from NetBox, and a CI/CD pipeline.

Theory sticks once you've seen the playbooks. Here are the network-automation cases that come up most — each with a runnable snippet and the point an interviewer is checking. Companion to Ansible — Theory.

Inventory & connection setup

Network hosts need a connection plugin and ansible_network_os. Put shared creds in group_vars (vault the password).

# inventory.yml
all:
  children:
    ios:
      hosts:
        r1: { ansible_host: 10.0.0.1 }
        r2: { ansible_host: 10.0.0.2 }
      vars:
        ansible_connection: ansible.netcommon.network_cli
        ansible_network_os: cisco.ios.ios
        ansible_user: admin
        ansible_password: "{{ vault_ios_password }}"   # from ansible-vault

Case 1 — Ad-hoc: run a show command fleet-wide

ansible ios -m cisco.ios.ios_command -a "commands='show version'"
# gather structured facts:
ansible ios -m cisco.ios.ios_facts -a "gather_subset=hardware"

Point: ad-hoc is for one-off reads/checks; no playbook needed.

Case 2 — Config push with backup, check mode & diff

- name: NTP + logging, safely
  hosts: ios
  gather_facts: false
  tasks:
    - name: Push baseline config
      cisco.ios.ios_config:
        backup: true                 # snapshot running-config first
        lines:
          - ntp server 10.0.0.53
          - logging host 10.0.0.60
      register: result

    - name: Save if changed
      cisco.ios.ios_config:
        save_when: changed
      when: result.changed

Run --check --diff first to preview. Point: idempotency + a backup + save-on-change is the safe pattern.

Case 3 — Templated config from group_vars (Jinja2)

# group_vars/ios.yml
vlans:
  - { id: 10, name: users }
  - { id: 20, name: voice }
# templates/vlans.j2
{% for v in vlans %}
vlan {{ v.id }}
 name {{ v.name }}
{% endfor %}
- name: Render + apply VLANs
  cisco.ios.ios_config:
    src: templates/vlans.j2

Point: data (SoT) in vars, structure in the template — one template, many devices.

Case 4 — Declarative resource module (idempotent state)

- name: VLANs as data, fully declarative
  cisco.ios.ios_vlans:
    config:
      - { vlan_id: 10, name: users }
      - { vlan_id: 20, name: voice }
    state: overridden      # make the device match exactly (prunes extras)

Point: resource modules beat raw ios_config lines — merged vs replaced vs overridden vs deleted give true desired-state config.

Case 5 — Safe rolling change: serial, assert, handlers

- name: Rolling change, 1 device at a time
  hosts: ios
  serial: 1                          # batch size — blast-radius control
  gather_facts: false
  tasks:
    - name: Pre-check reachability
      cisco.ios.ios_ping: { dest: 10.0.0.53 }

    - name: Apply change
      cisco.ios.ios_config:
        lines: [ "ip name-server 10.0.0.53" ]
      notify: save config

    - name: Post-check (fail the batch if broken)
      cisco.ios.ios_command:
        commands: show ip name-server
      register: out
      failed_when: "'10.0.0.53' not in out.stdout[0]"
  handlers:
    - name: save config
      cisco.ios.ios_config: { save_when: changed }

Point: serial + pre/post checks stop a bad change from hitting the whole fleet.

Case 6 — Dynamic inventory from NetBox (SoT)

# netbox_inv.yml  (ansible-inventory -i netbox_inv.yml --graph)
plugin: netbox.netbox.nb_inventory
api_endpoint: https://netbox.example.com
token: "{{ lookup('env','NETBOX_TOKEN') }}"
group_by: [device_roles, sites]

Point: the inventory becomes a live query against your source of truth — no hand-maintained host lists. (Build your own in Python: Ansible Lab.)

Case 7 — CI/CD pipeline for network config

Treat config as code: lint + dry-run on a PR, deploy on merge.

# .gitlab-ci.yml (or GitHub Actions equiv)
stages: [lint, check, deploy]

lint:
  stage: lint
  script:
    - ansible-lint site.yml
    - yamllint .

check:                      # runs on merge requests
  stage: check
  script:
    - ansible-playbook site.yml -i inventory.yml --check --diff
  rules: [ { if: '$CI_PIPELINE_SOURCE == "merge_request_event"' } ]

deploy:                     # runs only on main after merge
  stage: deploy
  script:
    - ansible-playbook site.yml -i inventory.yml
  rules: [ { if: '$CI_COMMIT_BRANCH == "main"' } ]

Point: the interview answer for "how do you make network changes safe & reviewable" — Git PR review, automated lint, --check --diff as a required gate, deploy only from main, secrets from the CI vault. Pair with molecule to test roles in containers.

Likely interview questions

Related: Ansible — Theory · Ansible Lab (Python).