mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-10-03 09:10:11 +03:00
5.2 KiB
5.2 KiB
name, description, version
| name | description | version |
|---|---|---|
| gns3-api-testing | Use this skill when testing GNS3 server REST API endpoints with curl — covers JWT auth, common patterns, and marker/link examples. | 1.0.0 |
GNS3 Server API Testing with curl
Core Principle
Fixed routine for testing the GNS3 server API: get a JWT token first, then send Authorization: Bearer <token> with every request.
Default address http://127.0.0.1:3080, API prefix /v3.
Authentication (always first)
TOKEN=$(curl -s -X POST http://127.0.0.1:3080/v3/access/users/authenticate \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
Persist to a file for reuse (avoids re-logging in each time):
echo "$TOKEN" > /tmp/gns3_token.txt
TOKEN=$(cat /tmp/gns3_token.txt)
Then attach to every request:
AUTH="Authorization: Bearer $TOKEN"
curl -s -H "$AUTH" http://127.0.0.1:3080/v3/...
Endpoint note: login is
/v3/access/users/authenticate, not/v3/auth/login. OpenAPI spec is at/openapi.json(not/v3/openapi.json).
Common Variables
BASE="http://127.0.0.1:3080/v3"
PID=<project_id>
LID=<link_id>
NID=<node_id>
AUTH="Authorization: Bearer $TOKEN"
Generic Request Patterns
GET (query)
curl -s -H "$AUTH" $BASE/projects/$PID/links | python3 -m json.tool
POST (create) — with JSON body
curl -s -X POST -H "$AUTH" -H "Content-Type: application/json" \
-d '{"name":"foo","bpf":"icmp"}' \
$BASE/projects/$PID/links/$LID/markers
HTTP status code only (body not needed)
curl -s -o /dev/null -w "HTTP %{http_code}\n" -X DELETE -H "$AUTH" \
$BASE/projects/$PID/links/$LID/markers/global-icmp
Extract a field from the response
LID=$(curl -s -H "$AUTH" -X POST ... | python3 -c "import sys,json; print(json.load(sys.stdin)['link_id'])")
Status Code Reference
| Code | Meaning |
|---|---|
| 200 | GET/PUT succeeded |
| 201 | POST created |
| 204 | DELETE succeeded (no body) |
| 401 | Not authenticated (token missing/expired) |
| 404 | Resource not found |
| 409 | Conflict (e.g. per-link edit of an inherited marker) |
| 422 | Schema validation failed (e.g. marker name starting with global) |
Marker Cheat Sheet
Project-level global marker definitions (inheritance)
# Create a def → fans out to every link automatically
curl -s -X POST -H "$AUTH" -H "Content-Type: application/json" \
-d '{"name":"icmp","bpf":"icmp","tag":1,"color":"#ff5722"}' \
$BASE/projects/$PID/marker-definitions
# List all defs + the link_ids each is bound to
curl -s -H "$AUTH" $BASE/projects/$PID/marker-definitions
# Update a def → syncs to every link
curl -s -X PUT -H "$AUTH" -H "Content-Type: application/json" \
-d '{"bpf":"icmp","tag":99}' \
$BASE/projects/$PID/marker-definitions/icmp
# Delete a def → removes the inherited marker from every link
curl -s -X DELETE -H "$AUTH" $BASE/projects/$PID/marker-definitions/icmp
Per-link markers
# List markers on a link
curl -s -H "$AUTH" $BASE/projects/$PID/links/$LID/markers
# Create a private marker (name cannot start with "global")
curl -s -X POST -H "$AUTH" -H "Content-Type: application/json" \
-d '{"bpf":"tcp port 80"}' \
$BASE/projects/$PID/links/$LID/markers
# Delete (inherited markers return 409)
curl -s -X DELETE -H "$AUTH" $BASE/projects/$PID/links/$LID/markers/<name>
Project-level aggregation query
curl -s -H "$AUTH" $BASE/projects/$PID/markers # all markers across links, flattened
Link / Node Cheat Sheet
# List all links in a project (includes the markers field)
curl -s -H "$AUTH" $BASE/projects/$PID/links
# List nodes (check ports[].link_id to find free ports)
curl -s -H "$AUTH" $BASE/projects/$PID/nodes
# Create a VPCS
curl -s -X POST -H "$AUTH" -H "Content-Type: application/json" \
-d '{"name":"t1","node_type":"vpcs","compute_id":"local"}' \
$BASE/projects/$PID/nodes
# Start a node
curl -s -o /dev/null -X POST -H "$AUTH" $BASE/projects/$PID/nodes/$NID/start
# Create a link (both ends: node + adapter/port)
curl -s -X POST -H "$AUTH" -H "Content-Type: application/json" \
-d "{\"nodes\":[{\"node_id\":\"$N1\",\"adapter_number\":0,\"port_number\":0},{\"node_id\":\"$N2\",\"adapter_number\":0,\"port_number\":0}]}" \
$BASE/projects/$PID/links
Port occupancy: VPCS has only one interface (port 0); once linked it cannot connect again. Confirm
ports[].link_idis empty before creating a link;"Port is already used"means the port is taken.
Gotchas
POST /linksresponse may showmarkers: []— the create response is serialized before the inheritance hook runs. The inherited marker is actually applied; checkGET /links/{lid}/markersor refreshGET /linksto see it.- Restart gns3server after code changes — the Python process does not hot-reload.
- Wrap JSON bodies in single quotes in the shell (double quotes inside); to interpolate a shell variable use
\"$VAR\". - Pipe long output through
python3 -m json.toolto pretty-print; extract fields withpython3 -c "import sys,json; ...".