Postman & Ansible – Network Automation, REST APIs, and Playbooks
1. Why Network Automation? — The Context
Traditional network management relies on engineers logging into each device individually, typing commands manually, and verifying changes one by one. In small networks this is manageable. In enterprise environments with hundreds or thousands of devices, it is slow, error-prone, and impossible to scale.
Network automation replaces manual CLI work with programmatic control — using APIs, scripts, and automation platforms to configure, verify, and manage devices consistently and at scale. Postman and Ansible are two of the most widely used tools in this space and appear explicitly in the CCNA DevNet curriculum.
Manual workflow:
Engineer → SSH to Switch 1 → type commands → verify → SSH to Switch 2 → repeat × 200
Automated workflow:
Engineer writes playbook/API call once →
Tool executes against all 200 devices simultaneously →
Results reported back centrally → idempotent: safe to re-run
Key benefits:
┌─────────────────────────────────────────────────────┐
│ Speed — minutes instead of hours │
│ Consistency — identical config on every device │
│ Auditability — changes tracked in version control │
│ Scalability — same effort for 1 device or 1000 │
│ Idempotency — re-run safely; no duplicate changes │
└─────────────────────────────────────────────────────┘
Related pages: Network Programmability | REST APIs | Ansible Overview | NETCONF & RESTCONF | Python for Networking | JSON, XML & YAML | SSH Overview | SD-WAN
2. Postman — REST API Testing and Development
What Is Postman?
Postman is a graphical API development and testing platform that enables engineers to construct, send, inspect, and automate HTTP/HTTPS requests without writing code. In networking it is used to interact with the programmable interfaces (REST APIs) of network controllers (Cisco DNA Center, NSO), cloud platforms (AWS, Azure), and individual devices that support RESTCONF or a vendor API.
Postman sits between you and the API: Engineer Postman Network API (builds request) ──→ (sends HTTP request) ──→ (returns JSON/XML response) ←── (displays response) ←── Without Postman: write curl commands or code for every test. With Postman: point-and-click request builder + automated test scripts.
HTTP Methods — The CRUD Verbs
REST APIs map operations to HTTP methods. Understanding which method to use for each operation is a CCNA exam requirement:
| HTTP Method | CRUD Operation | Purpose | Request Body? | Network Example |
|---|---|---|---|---|
| GET | Read | Retrieve a resource or list of resources; does not modify anything | No | Fetch device interface status, retrieve VLAN list, get routing table |
| POST | Create | Create a new resource; body contains the resource definition in JSON or XML | Yes | Create a new VLAN, add a static route, provision a new device |
| PUT | Update (full) | Replace an existing resource completely with the data in the request body | Yes | Update full interface configuration, replace an ACL policy |
| PATCH | Update (partial) | Modify only specific fields of an existing resource — does not replace the whole object | Yes (partial) | Change only the description field of an interface without affecting other parameters |
| DELETE | Delete | Remove an existing resource | No | Delete a VLAN, remove a static route, deprovision a device |
HTTP Status Codes — Reading API Responses
Every HTTP response includes a status code. Knowing these is essential for writing Postman test scripts and diagnosing API failures:
| Code | Category | Meaning | Common Cause |
|---|---|---|---|
| 200 | Success | OK — request succeeded; response body contains result | Successful GET, PUT, PATCH, DELETE |
| 201 | Success | Created — new resource successfully created | Successful POST |
| 204 | Success | No Content — request succeeded but no body returned | Successful DELETE |
| 400 | Client Error | Bad Request — malformed syntax, invalid JSON, missing required field | Typo in request body; wrong Content-Type header |
| 401 | Client Error | Unauthorised — authentication required or token invalid | Missing or expired Bearer token; wrong credentials |
| 403 | Client Error | Forbidden — authenticated but not permitted to perform this action | Insufficient privileges; RBAC policy denying access |
| 404 | Client Error | Not Found — the requested resource does not exist | Wrong URL path; resource ID that does not exist |
| 500 | Server Error | Internal Server Error — the API server encountered an unexpected error | Bug in the API; server overloaded; database error |
3. Postman Interface — Key Components
| Component | What It Does | Network Automation Use |
|---|---|---|
| Collections | Group related API requests into named folders; can be exported as JSON and shared | Organise all API calls for a device type (e.g., all Cisco DNA Center endpoints in one collection) |
| Requests | Individual HTTP requests — define method, URL, headers, authentication, and body per request | One request per API operation: GET interfaces, POST VLAN, DELETE route, etc. |
| Environments | Named sets of variables — switch between environments (dev/test/prod) without editing request URLs | Store different controller IPs, API tokens, and credentials per environment |
| Variables | Placeholders in double braces ({{name}})
that resolve to values at runtime; scoped globally,
per-environment, per-collection, or per-request |
{{base_url}}, {{auth_token}},
{{vlan_id}} — keep requests reusable |
| Pre-request Scripts | JavaScript that runs before a request is sent — used to generate tokens, set dynamic variables, or prepare the request | Auto-fetch and store auth token before every API call in the collection |
| Tests tab | JavaScript that runs after a response is received — used to validate status codes, response body fields, and timing; results shown in the Test Results panel | Assert that a VLAN was created (status 201), that the returned VLAN ID matches the one sent, and that RTT is under 500ms |
| Collection Runner | Run an entire collection sequentially with optional data files (CSV/JSON) to iterate over multiple inputs | Provision 50 VLANs from a CSV file in one run |
| Workspaces | Personal or team project spaces with version history and collaboration features | Team workspace for the NOC to share and maintain all network API collections |
4. Postman Variables and Environments — In Depth
Variables eliminate hardcoded values from requests, making collections portable across environments. Variable resolution follows a scope hierarchy — more specific scopes override broader ones:
Variable scope (highest priority first):
Request variable → Data variable (Collection Runner CSV) →
Local variable (set in script) → Environment variable →
Collection variable → Global variable
Practical example:
┌─────────────────────────────────────────────────────────────┐
│ Environment: Production │
│ base_url = https://dnac.prod.example.com │
│ auth_token = eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ... │
│ │
│ Environment: Lab │
│ base_url = https://10.10.20.85 │
│ auth_token = eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ... │
└─────────────────────────────────────────────────────────────┘
Request URL (same for both environments):
GET {{base_url}}/api/v1/network-device
Switch from Lab to Production: change active environment → no URL edits needed.
Setting Variables from Scripts
// Pre-request Script — fetch token and store it as environment variable:
pm.sendRequest({
url: pm.environment.get("base_url") + "/api/v1/auth/token",
method: "POST",
header: { "Content-Type": "application/json" },
body: {
mode: "raw",
raw: JSON.stringify({
username: pm.environment.get("username"),
password: pm.environment.get("password")
})
}
}, function(err, res) {
pm.environment.set("auth_token", res.json().Token);
});
// Test Script — validate response and extract a value:
pm.test("Status is 200", function () {
pm.response.to.have.status(200);
});
pm.test("VLAN ID matches request", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.vlanId).to.eql(200);
});
// Store returned device ID for use in the next request:
var responseJson = pm.response.json();
pm.environment.set("device_id", responseJson.id);
5. Newman — Running Postman Collections from the CLI
Newman is the official command-line companion to Postman. It executes Postman collections without the GUI, making it the bridge between Postman and CI/CD pipelines. Newman produces pass/fail test results and rich reports in multiple formats.
Install Newman (requires Node.js):
npm install -g newman
Basic collection run:
newman run MyCollection.json
Run with a specific environment:
newman run MyCollection.json -e ProductionEnv.json
Run with a data file (iterate over CSV rows):
newman run VlanProvision.json -d vlans.csv
Run with HTML report output:
newman run MyCollection.json -e ProdEnv.json --reporters html --reporter-html-export report.html
Common flags:
-e --environment Environment file
-d --iteration-data CSV/JSON data file for Collection Runner
-n --iteration-count Number of times to run the collection
--delay-request Milliseconds to wait between requests
--reporters Output format: cli, json, html, junit
CI/CD integration example (Jenkins pipeline snippet):
pipeline {
stages {
stage('API Regression Tests') {
steps {
sh 'newman run collections/NetworkAPI.json \
-e environments/Production.json \
--reporters cli,junit \
--reporter-junit-export results/api-test-results.xml'
}
}
}
}
// If any Postman test assertion fails, Newman exits with a non-zero code
// → Jenkins marks the build as FAILED automatically
6. Complete Postman Scenario — Cisco DNA Center VLAN Workflow
A network engineer needs to create VLAN 200 ("Engineering") on the fabric managed by Cisco DNA Center using its REST API. The workflow requires authentication first, then the VLAN creation, then verification.
Environment variables set up:
base_url = https://sandboxdnac.cisco.com
username = devnetuser
password = Cisco123!
auth_token = (will be set by the first request)
── Request 1: Authenticate ──────────────────────────────────────
Method: POST
URL: {{base_url}}/dna/system/api/v1/auth/token
Auth: Basic Auth (username + password)
Body: none
Expected response (200):
{
"Token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Test Script:
pm.test("Status 200", () => pm.response.to.have.status(200));
pm.environment.set("auth_token", pm.response.json().Token);
── Request 2: Create VLAN ────────────────────────────────────────
Method: POST
URL: {{base_url}}/api/v1/network/vlan
Headers: X-Auth-Token: {{auth_token}}
Content-Type: application/json
Body:
{
"vlanId": 200,
"vlanName": "Engineering"
}
Expected response (201):
{
"executionId": "b47e8f12-...",
"executionStatusUrl": "/dna/intent/api/v1/task/b47e8f12-..."
}
Test Script:
pm.test("VLAN created (201)", () => pm.response.to.have.status(201));
── Request 3: Verify VLAN Exists ────────────────────────────────
Method: GET
URL: {{base_url}}/api/v1/network/vlan/200
Headers: X-Auth-Token: {{auth_token}}
Expected response (200) body snippet:
{
"vlanId": 200,
"vlanName": "Engineering"
}
Test Script:
pm.test("VLAN 200 exists", function() {
pm.expect(pm.response.json().vlanName).to.eql("Engineering");
});
7. Ansible — Agentless Network Automation
What Is Ansible?
Ansible is an open-source, agentless automation platform developed by Red Hat. "Agentless" means that no additional software needs to be installed on the devices being managed — Ansible connects to them over SSH (for Linux servers) or over the device's API/SSH (for network devices like Cisco IOS, NX-OS, Arista EOS, Juniper JunOS). This makes deployment extremely simple and is the characteristic that most distinguishes Ansible from tools like Chef or Puppet, which require an agent to be installed and running on every managed node.
Ansible Architecture:
┌──────────────────────┐ SSH / API / NETCONF
│ Control Node │ ──────────────────────────→ Cisco Switch
│ (admin PC or CI/CD) │ Cisco Router
│ │ ──────────────────────────→ Arista Switch
│ ansible installed │ Linux Server
│ playbooks stored │ ──────────────────────────→ Juniper Router
│ inventory here │
└──────────────────────┘
No agents on managed devices — Ansible connects, runs tasks, disconnects.
Python-based modules are transferred and executed temporarily, then removed.
Core Concepts
| Concept | Description | File/Format |
|---|---|---|
| Inventory | List of all managed hosts and devices, optionally organised into named groups (by role, site, vendor, etc.) | INI format (inventory.ini) or YAML;
can also be dynamic (generated from a CMDB or cloud API) |
| Playbook | The automation workflow — one or more "plays" that target a host group and define a list of tasks to execute in sequence | YAML (playbook.yml); must start with
--- |
| Play | A single section within a playbook that maps a set of tasks to a target group of hosts | Defined by - hosts: in the playbook |
| Task | An individual action — calls a module with specific parameters; tasks run in the order listed | YAML block under tasks: |
| Module | A reusable unit of code that performs a specific function — Ansible ships with hundreds of built-in modules; community modules add thousands more | Referenced by name in tasks
(e.g., ios_config:) |
| Variables | Named values used in playbooks and templates; can be defined in the inventory, in variable files, passed on the command line, or set dynamically | Referenced with {{ variable_name }}
(Jinja2 syntax) |
| Handlers | Tasks that only run when notified by another task — typically used to restart services or reload configurations after a change | Defined under handlers: |
| Roles | A structured directory layout for reusable automation — bundles playbooks, tasks, handlers, templates, variables, and files for a specific function (e.g., "configure-ospf") | Defined directory structure under
roles/ |
| Ansible Vault | Built-in encryption for sensitive data — passwords, API keys, and tokens can be stored encrypted in playbooks or variable files | Encrypted with AES-256; decrypted at runtime with a vault password |
8. Ansible Inventory File
The inventory tells Ansible which devices to manage and how to connect to them. Groups allow a single playbook to target different device sets.
INI-format inventory (inventory.ini):
────────────────────────────────────────────────────────
[core_switches]
core1 ansible_host=10.0.0.1 ansible_network_os=ios ansible_user=admin ansible_password=Cisco123!
core2 ansible_host=10.0.0.2 ansible_network_os=ios ansible_user=admin ansible_password=Cisco123!
[access_switches]
access1 ansible_host=10.0.1.10 ansible_network_os=ios ansible_user=admin ansible_password=Cisco123!
access2 ansible_host=10.0.1.11 ansible_network_os=ios ansible_user=admin ansible_password=Cisco123!
[arista_switches]
eos1 ansible_host=10.0.2.1 ansible_network_os=eos ansible_user=admin ansible_password=arista123
[all_switches:children]
core_switches
access_switches
arista_switches
────────────────────────────────────────────────────────
Key connection variables:
ansible_host → IP address or hostname of the device
ansible_network_os → tells Ansible which module family to use
(ios, nxos, eos, junos, etc.)
ansible_user → SSH username
ansible_password → SSH password (better: use Ansible Vault)
ansible_become → yes/no for privilege escalation
ansible_become_method → enable (for Cisco IOS)
ansible_connection → network_cli (IOS), httpapi (NX-OS/DNA Center)
9. Ansible Playbook — YAML Syntax and Structure
Playbooks are YAML files. YAML uses indentation (2 spaces, never tabs) to represent structure. A playbook contains one or more plays, each targeting a host group and listing tasks to execute.
Annotated playbook structure:
--- ← YAML document start (required)
- name: Configure VLANs ← play name (human-readable description)
hosts: access_switches ← which inventory group to target
gather_facts: no ← skip automatic fact gathering (faster for network devices)
connection: network_cli ← use SSH CLI mode for network devices
vars: ← variables scoped to this play
vlan_id: 200
vlan_name: Engineering
tasks: ← list of tasks — run in order, top to bottom
- name: Create VLAN {{ vlan_id }} ← task name (shown in output)
ios_config: ← module to call
lines: ← module parameter
- vlan {{ vlan_id }}
- name {{ vlan_name }}
register: vlan_result ← save the module output to a variable
- name: Verify VLAN was created ← second task
ios_command:
commands:
- show vlan brief
register: vlan_output
- name: Display VLAN output ← debug task for visibility
debug:
var: vlan_output.stdout_lines
Idempotency — The Critical Property
Idempotency means that running the same playbook multiple times produces the same end result — it will not create duplicate VLANs or apply duplicate configuration lines. Ansible modules check the current state before making changes and only apply a change if the current state differs from the desired state.
Idempotency in practice:
Run 1 (VLAN 200 does not exist):
TASK [Create VLAN 200] → changed: [access1] ← change was applied
Run 2 (VLAN 200 already exists):
TASK [Create VLAN 200] → ok: [access1] ← no change needed
Run 3 (same):
TASK [Create VLAN 200] → ok: [access1] ← still no change
Safe to run in a scheduled job or CI/CD pipeline without risk
of creating duplicate configuration or breaking a working device.
10. Key Ansible Modules for Network Automation
| Module | Platform | Purpose | Example Use |
|---|---|---|---|
| ios_config | Cisco IOS / IOS-XE | Push configuration lines; compares desired lines against running config and only applies differences | Configure VLANs, interfaces, routing protocols, ACLs on IOS switches and routers |
| ios_command | Cisco IOS / IOS-XE | Run show commands and return output for parsing or verification; does not change config | show version, show ip route,
show vlan brief |
| ios_facts | Cisco IOS / IOS-XE | Gather structured facts about the device — hostname, version, interfaces, routing — for use in templates or conditionals | Collect device inventory automatically from all managed routers |
| nxos_config | Cisco NX-OS | Push configuration to Nexus data-centre switches | Configure VPC, VRF, BGP on Nexus 9000 series |
| eos_config | Arista EOS | Push configuration to Arista switches | Configure MLAG, BGP, VLANs on Arista EOS |
| junos_config | Juniper JunOS | Push configuration to Juniper routers and switches | Configure interfaces, routing policies on MX/EX series |
| net_vlan | Multi-vendor | Vendor-agnostic VLAN management — works across IOS, NX-OS, EOS using a single task | Provision the same VLAN on a mixed-vendor environment with one play |
| uri | Any (HTTP/REST) | Make HTTP requests to REST APIs from within Ansible — enables Ansible to interact with any REST API | Call Cisco DNA Center API, Meraki API, or any RESTCONF endpoint |
11. Ansible Vault — Securing Secrets
Storing passwords and API tokens in plain text in inventory files or playbooks is a significant security risk — especially when those files are committed to a Git repository. Ansible Vault solves this by encrypting sensitive data with AES-256.
Create an encrypted variable file:
ansible-vault create secrets.yml
(prompted for a vault password)
Edit an existing encrypted file:
ansible-vault edit secrets.yml
Encrypt a single string value (for embedding in a playbook):
ansible-vault encrypt_string 'Cisco123!' --name 'ansible_password'
Output:
ansible_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62343132313234313...
Run a playbook using vault-encrypted data:
ansible-playbook playbook.yml --ask-vault-pass
(or)
ansible-playbook playbook.yml --vault-password-file ~/.vault_pass.txt
View without decrypting:
ansible-vault view secrets.yml
Rekey (change the vault password):
ansible-vault rekey secrets.yml
12. Jinja2 Templates in Ansible
Jinja2 is the templating engine built into Ansible. It allows dynamic generation of configuration files — a single template can produce unique device configurations for hundreds of devices by substituting variables, running loops, and applying conditional logic.
Template file: interface_config.j2
────────────────────────────────────────
interface {{ interface_name }}
description {{ description }}
ip address {{ ip_address }} {{ subnet_mask }}
no shutdown
{% if ospf_enabled %}
ip ospf {{ ospf_process_id }} area {{ ospf_area }}
{% endif %}
────────────────────────────────────────
Variables in playbook:
vars:
interface_name: GigabitEthernet0/1
description: "Uplink to Core"
ip_address: 192.168.10.1
subnet_mask: 255.255.255.0
ospf_enabled: true
ospf_process_id: 1
ospf_area: 0
Task using the template:
- name: Generate interface config
template:
src: interface_config.j2
dest: /tmp/interface_config.cfg
Generated output:
interface GigabitEthernet0/1
description Uplink to Core
ip address 192.168.10.1 255.255.255.0
no shutdown
ip ospf 1 area 0
13. Complete Ansible Scenario — Multi-VLAN Provisioning
An engineer needs to provision VLANs 100, 200, and 300 on all access switches, using variables for reusability and Ansible Vault for credentials.
── inventory.ini ────────────────────────────────────────────────
[access_switches]
access1 ansible_host=10.0.1.10
access2 ansible_host=10.0.1.11
access3 ansible_host=10.0.1.12
[access_switches:vars]
ansible_network_os=ios
ansible_user=admin
ansible_connection=network_cli
ansible_become=yes
ansible_become_method=enable
── secrets.yml (encrypted with Ansible Vault) ───────────────────
ansible_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62343132...
── vlan_vars.yml ────────────────────────────────────────────────
vlans:
- id: 100
name: Sales
- id: 200
name: Engineering
- id: 300
name: Management
── vlan_provision.yml (playbook) ────────────────────────────────
---
- name: Provision VLANs on Access Switches
hosts: access_switches
gather_facts: no
vars_files:
- secrets.yml
- vlan_vars.yml
tasks:
- name: Create each VLAN
ios_config:
lines:
- vlan {{ item.id }}
- name {{ item.name }}
loop: "{{ vlans }}"
loop_control:
label: "VLAN {{ item.id }} - {{ item.name }}"
- name: Verify VLANs created
ios_command:
commands: show vlan brief
register: vlan_output
- name: Display result
debug:
var: vlan_output.stdout_lines
── Execute ───────────────────────────────────────────────────────
ansible-playbook -i inventory.ini vlan_provision.yml --ask-vault-pass
── Sample output ─────────────────────────────────────────────────
PLAY [Provision VLANs on Access Switches] ****
TASK [Create each VLAN] ****
changed: [access1] => (item=VLAN 100 - Sales)
changed: [access1] => (item=VLAN 200 - Engineering)
changed: [access1] => (item=VLAN 300 - Management)
changed: [access2] => (item=VLAN 100 - Sales)
...
PLAY RECAP ****
access1: ok=3 changed=1 unreachable=0 failed=0
access2: ok=3 changed=1 unreachable=0 failed=0
access3: ok=3 changed=1 unreachable=0 failed=0
14. Postman vs Ansible — When to Use Each
| Dimension | Postman | Ansible |
|---|---|---|
| Primary use | Exploring, testing, and debugging REST APIs; API-driven workflow automation | Configuration management; bulk provisioning; multi-device automation at scale |
| Interface | Graphical (GUI) with optional CLI via Newman | Command-line; YAML-based declarative files |
| Transport | HTTP/HTTPS (REST APIs, RESTCONF) | SSH, network_cli, httpapi, NETCONF |
| Automation language | JavaScript (test scripts, pre-request scripts) | YAML (playbooks); Jinja2 (templates) |
| Idempotency | Not inherent — depends on API and test logic | Built-in — modules check state before applying |
| Multi-vendor | Works with any HTTP API regardless of vendor | Vendor-specific modules (ios, nxos, eos, junos)
plus generic net_* and uri
modules |
| Best for | API exploration; CI/CD API regression tests; SDN controller interaction; development teams documenting APIs | Mass device provisioning; configuration drift correction; scheduled compliance checks; multi-vendor environments |
| CCNA DevNet relevance | Understanding REST API concepts, HTTP methods, and JSON — directly tested | Understanding agentless automation, YAML syntax, playbook structure, and idempotency — directly tested |
15. Troubleshooting Common Issues
| Tool | Symptom | Likely Cause | Fix |
|---|---|---|---|
| Postman | 401 Unauthorised on every request | Auth token missing, expired, or not in the correct header | Re-run the auth request to get a fresh token; verify the header name matches what the API expects (Authorization vs X-Auth-Token vs api-key) |
| Postman | 400 Bad Request on POST/PUT | Malformed JSON body; wrong Content-Type header; missing required field | Check the JSON syntax in the body tab; ensure
Content-Type: application/json header
is set; compare body to API documentation |
| Postman | Could not send request / SSL error | Self-signed certificate on lab device; HTTPS strict validation failing | In Postman settings, disable SSL certificate verification for lab environments (never in production) |
| Ansible | UNREACHABLE — SSH connection failed | Wrong IP in inventory; SSH not enabled on device; firewall blocking port 22; wrong credentials | Test manually: ssh [email protected];
verify ansible_host IP;
check ansible_user and
ansible_password; confirm SSH is
enabled on the device |
| Ansible | YAML syntax error / parsing failed | Incorrect indentation (tabs instead of spaces); missing colon after key; unclosed string | Validate YAML with yamllint playbook.yml
before running; use a YAML-aware editor; never use
tabs — always 2 spaces |
| Ansible | Module not found / No module named ios_config | Missing Ansible collections for network devices | Install the required collection:
ansible-galaxy collection install
cisco.ios |
| Ansible | Decryption failed — vault password wrong | Wrong vault password provided at runtime | Re-encrypt with the correct password:
ansible-vault rekey secrets.yml;
or use a password file with
--vault-password-file |
Ansible Verbosity Flags
ansible-playbook playbook.yml -v # Basic verbose — show task results
ansible-playbook playbook.yml -vv # Show files and directories searched
ansible-playbook playbook.yml -vvv # Show SSH connection details
ansible-playbook playbook.yml -vvvv # Show all connection debug info
Dry run (check mode — don't actually make changes):
ansible-playbook playbook.yml --check
List hosts that will be targeted:
ansible-playbook playbook.yml --list-hosts
Limit execution to specific hosts or groups:
ansible-playbook playbook.yml --limit access1
ansible-playbook playbook.yml --limit access_switches
16. Exam Tips & Key Points
- Postman: Know the five HTTP methods and their CRUD equivalents — GET (Read), POST (Create), PUT (Update/Replace), PATCH (Update/Partial), DELETE (Delete).
- Know the key HTTP status codes: 200 (OK), 201 (Created), 400 (Bad Request), 401 (Unauthorised), 403 (Forbidden), 404 (Not Found), 500 (Server Error).
- Postman variables use
{{double_braces}}. Environments are named sets of variables — switch environment to change all variable values at once without editing requests. - Newman is the CLI tool that runs Postman collections — it integrates Postman with CI/CD pipelines (Jenkins, GitLab CI, Azure DevOps).
- Ansible is agentless — no software installed on managed devices; connects over SSH or API.
- Ansible playbooks are written in YAML — indentation is significant; 2 spaces, never tabs.
- Ansible idempotency — running the same playbook multiple times produces the same result; modules check current state before applying changes.
- Know the three-part Ansible topology: Control Node (where Ansible runs), Managed Nodes (devices being configured), Inventory (list of managed nodes).
- Key modules: ios_config (push IOS config lines), ios_command (run show commands), ios_facts (gather device facts).
- Ansible Vault encrypts sensitive data (passwords,
tokens) with AES-256; run playbooks with
--ask-vault-passor a vault password file. - Jinja2 templates use
{{ variable }},{% if condition %}, and{% for item in list %}to dynamically generate device configurations.
17. Summary Reference Table
| Topic | Postman | Ansible |
|---|---|---|
| Primary role | REST API testing and development | Agentless configuration management and automation |
| Language | JavaScript (scripts); JSON (collections) | YAML (playbooks); Jinja2 (templates) |
| HTTP methods | GET, POST, PUT, PATCH, DELETE | N/A directly (uses uri module for REST) |
| Variable syntax | {{variable_name}} |
{{ variable_name }} |
| CLI/automation tool | Newman (newman run collection.json) |
ansible-playbook playbook.yml |
| Secrets management | Environments (not encrypted by default) | Ansible Vault (AES-256 encryption) |
| Key network module | Any REST API endpoint | ios_config, ios_command,
ios_facts |
| Idempotency | Not built-in | Built-in at module level |