otgctl
A command-line tool for making Open Traffic Generator (OTG) REST API calls from YAML or JSON input.
Installation
pip install .
Building from source uses the PEP 517/PEP 621 configuration in
pyproject.toml and requires setuptools 61 or newer plus wheel. Installing
a prebuilt wheel does not require setuptools. In a constrained build
environment where those tools are already installed, use:
python3 -m pip install --no-build-isolation .
Development
Run the tests against the source tree with:
python3 -m pytest
To build a wheel and run the tests against that installed wheel in a clean environment:
sh ci/test.sh
The wrapper uses ci/Dockerfile.test and accepts PYTHON_VERSION and OTGCTL_TEST_IMAGE environment
variables, for example PYTHON_VERSION=3.13 sh ci/test.sh.
See docs/RELEASE_PROCESS.md for the release
checklist and artifact-publishing process.
Usage
otgctl [-s SERVER] [-m METHOD] [-o json] [-k] [-v] [--cert FILE] [--key FILE] [--timeout SECONDS] [--list-methods] FILE_OR_STRING ...
Options
| Flag | Description |
|---|---|
-s, --server |
OTG server URL (default: $OTG_API or https://localhost:8443) |
-m, --method |
OTG method name or REST path (see Methods) |
-o, --output-format |
yaml (default) or json |
-k, --insecure |
Skip TLS certificate verification |
-v, --verbose |
Print request and response details to stderr |
--cert |
Client certificate file for mTLS |
--key |
Client private key file for mTLS (optional if cert file contains both) |
--timeout |
HTTP request timeout in seconds (default: 30) |
--list-methods |
List available method names for -m and exit |
--version |
Print the code version and exit |
For GET methods (GetConfig, GetVersion), input files can be omitted:
otgctl -m GetVersion
Environment Variables
| Variable | Description |
|---|---|
OTG_API |
default server URL |
OTG_INSECURE |
when set to true, 1, or another non-false value, behaves like -k |
Exit Codes
Exit codes:
0: all requests completed with 2xx HTTP status.1: input parsing failed, method resolution failed, request execution failed, or an HTTP response was non-2xx.2: command-line usage error from argparse.
Input formats
otgctl accepts four input formats. Multiple inputs can be given on a single command line and are executed sequentially.
1. YAML with method and request
When the YAML contains method and request keys, the method is taken from the file and the request body is sent as-is. Files may contain multiple YAML documents separated by ---, each executed in order.
method: SetConfig
request:
ports:
- location: Ethernet1
name: p1
flows:
- name: f1
tx_rx:
choice: port
port:
tx_name: p1
otgctl -s https://otg-server:8443 config.yaml
This format is produced by OTG RPC loggers (both gRPC and HTTP) and can be replayed directly.
2. Raw data (YAML or JSON)
When the input has no method key, you must supply one with -m:
otgctl -s https://otg-server:8443 -m SetConfig traffic.yaml
otgctl -s https://otg-server:8443 -m SetConfig config.json
JSON files are detected by .json extension.
3. Protobuf text format
Files ending in .textproto, .textpb, or .pbtxt are parsed using the
protobuf request model from the optional snappi package. Select the gRPC
operation with -m:
pip install 'otgctl[snappi]'
otgctl -s https://otg-server:8443 -m SetConfig config.textproto
For example, a SetConfigRequest textproto contains a top-level config
field. otgctl removes that request wrapper before sending the REST body, so
the REST request contains the contents of config rather than a nested
config property. If strict parsing fails because the installed snappi
schema is older than the input, otgctl retries with unknown fields allowed and
prints a warning.
4. API path
A compact notation for simple requests, prefixed with //. The slash-separated path builds a nested object with choice keys at each level. The leaf segment contains one or more key=value pairs.
otgctl -m SetControlState //traffic/flow_transmit/state=start
This is equivalent to sending:
choice: traffic
traffic:
choice: flow_transmit
flow_transmit:
state: start
Multiple keys are separated by ;, and list values by ,:
otgctl -m GetMetrics '//port/port_names=Ethernet1,Ethernet2;column_names=transmit,capture'
Produces:
choice: port
port:
port_names:
- Ethernet1
- Ethernet2
column_names:
- transmit
- capture
Keys ending in "s" always produce a list, even with a single value (matching the OTG API convention where plural property names are arrays). Non-plural keys with commas also produce a list.
A simple string will result in just a "choice", e.g.,
otgctl -m GetMetrics //flow
Produces:
choice: flow
The // prefix distinguishes an API path from a file path, so there is no ambiguity with files that start with /.
API path syntax limitations
The // API-path syntax is intended for simple string-valued requests. It does
not perform YAML/JSON type conversion: values are sent as strings, except that
comma-separated values and keys ending in s become lists of strings. Use YAML
or JSON input when you need booleans, numbers, nested arrays, escaping commas,
or more complex request bodies. Empty path segments and keys are rejected, as
are duplicate keys in a leaf.
Stdin
Use - to read from stdin:
cat config.yaml | otgctl -m SetConfig -
Methods
Methods can be specified as gRPC names, REST operation IDs (snake_case), or REST paths. All three forms are equivalent:
| gRPC name | Operation ID | HTTP | REST path |
|---|---|---|---|
| SetConfig | set_config | POST | /config |
| GetConfig | get_config | GET | /config |
| UpdateConfig | update_config | PATCH | /config |
| AppendConfig | append_config | PATCH | /config/append |
| DeleteConfig | delete_config | PATCH | /config/delete |
| SetControlState | set_control_state | POST | /control/state |
| SetControlAction | set_control_action | POST | /control/action |
| GetMetrics | get_metrics | POST | /monitor/metrics |
| GetStates | get_states | POST | /monitor/states |
| GetCapture | get_capture | POST | /monitor/capture |
| GetVersion | get_version | GET | /capabilities/version |
You can also specify an explicit verb and path: -m "POST /config".
Output
JSON responses are printed as YAML by default. Use -o json for JSON output.
Non-2xx HTTP responses include the status code in the output. Binary responses (e.g. pcap data from GetCapture) print a warning on a terminal; redirect stdout to capture the data:
otgctl -m GetCapture capture_request.yaml > capture.pcap
mTLS
For servers requiring mutual TLS authentication:
otgctl --cert client.crt --key client.key -s https://otg-server:8443 config.yaml
If the certificate and key are in a single PEM file, --key can be omitted:
otgctl --cert client.pem -s https://otg-server:8443 config.yaml
Examples
# Set a configuration from a YAML file
otgctl -s https://otg:8443 -k -m SetConfig topology.yaml
# Replay a recorded RPC log (multi-document YAML with methods embedded)
otgctl -s https://otg:8443 -k rpclog.yaml
# Start traffic flows
otgctl -s https://otg:8443 -m SetControlState //traffic/flow_transmit/state=start
# Get port metrics for specific ports
otgctl -s https://otg:8443 -m GetMetrics //port/port_names=Ethernet1,Ethernet2
# Get flow metrics as JSON
echo '{"choice": "flow"}' | otgctl -s https://otg:8443 -m GetMetrics -o json -
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file otgctl-0.9.2.tar.gz.
File metadata
- Download URL: otgctl-0.9.2.tar.gz
- Upload date:
- Size: 24.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e27dcf026c02a54efa989511033b34341c57e2a48b0c461ef59cea741bd130c7
|
|
| MD5 |
55aecb03b2ebfba187dc7dee1eebb10f
|
|
| BLAKE2b-256 |
718c8848b45bf983ade3aaf9a85fde82fb0441fb3d2656c8e5c421791e32e3c9
|
Provenance
The following attestation bundles were made for otgctl-0.9.2.tar.gz:
Publisher:
pypi.yaml on aristanetworks/otgctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
otgctl-0.9.2.tar.gz -
Subject digest:
e27dcf026c02a54efa989511033b34341c57e2a48b0c461ef59cea741bd130c7 - Sigstore transparency entry: 2667084211
- Sigstore integration time:
-
Permalink:
aristanetworks/otgctl@c65cf9e96fe9d983807db3e5c2af9eaade9ef047 -
Branch / Tag:
refs/tags/v0.9.2 - Owner: https://github.com/aristanetworks
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yaml@c65cf9e96fe9d983807db3e5c2af9eaade9ef047 -
Trigger Event:
release
-
Statement type:
File details
Details for the file otgctl-0.9.2-py3-none-any.whl.
File metadata
- Download URL: otgctl-0.9.2-py3-none-any.whl
- Upload date:
- Size: 18.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8f148228ca2112df15621a5b05d1e0e445db89524be25cd21be23ba287422ce
|
|
| MD5 |
9907866bea33377743954916b931fbfb
|
|
| BLAKE2b-256 |
ca7555c9ffe45a971e6109479be6eb8be6df9f654cae9da932eb0119e954e421
|
Provenance
The following attestation bundles were made for otgctl-0.9.2-py3-none-any.whl:
Publisher:
pypi.yaml on aristanetworks/otgctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
otgctl-0.9.2-py3-none-any.whl -
Subject digest:
b8f148228ca2112df15621a5b05d1e0e445db89524be25cd21be23ba287422ce - Sigstore transparency entry: 2667084250
- Sigstore integration time:
-
Permalink:
aristanetworks/otgctl@c65cf9e96fe9d983807db3e5c2af9eaade9ef047 -
Branch / Tag:
refs/tags/v0.9.2 - Owner: https://github.com/aristanetworks
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yaml@c65cf9e96fe9d983807db3e5c2af9eaade9ef047 -
Trigger Event:
release
-
Statement type: