Command-line implementation

The modules behind the ngsw entry point. The user-facing reference is ngsw command line; this documents the implementation, which is worth reading if you are embedding ngsw’s switch resolution or its write gates in your own tool.

The ngsw command-line interface (a thin layer over SyncSwitch).

Entry point

ngsw entry point: argparse wiring, dispatch, and error handling.

netgear_switch.cli.main.build_parser()[source]
Return type:

ArgumentParser

netgear_switch.cli.main.main(
argv=None,
*,
switch_factory=None,
stdin=None,
stdout=None,
stderr=None,
env=None,
prompt=getpass.getpass,
)[source]
Return type:

int

Switch and credential resolution

The shared path the CLI and the MCP server use to turn arguments, environment variables and an inventory into a ready SyncSwitch.

Resolve the target SyncSwitch from CLI args (inventory or host+model).

Credential precedence (design spec Sec5.1): CLI flag -> environment variable -> config value -> interactive prompt.

netgear_switch.cli.resolve.resolve_switch(args, *, env=None, prompt=None)[source]

Build a SyncSwitch from --config/--switch/--host/--model.

Resolution: an inventory lookup (--switch, requires --config) wins when given; otherwise --host/--model build a switch directly. Credential precedence for the SNMP read community is CLI flag -> NGSW_COMMUNITY env var -> inventory config value -> prompt (if supplied). The write community only ever comes from a CLI flag or NGSW_WRITE_COMMUNITY/inventory spec, resolved lazily by SyncSwitch.

Return type:

SyncSwitch

Shared CLI context and exit-code policy (leaf module, no cli/ imports).

class netgear_switch.cli.context.CliContext(out, err, inp, as_json, verbose)[source]

Bases: object

Streams and global flags threaded through every command handler.

out: TextIO
err: TextIO
inp: TextIO
as_json: bool
verbose: bool
netgear_switch.cli.context.exit_code_for(exc)[source]

Map a library error to a distinct process exit code.

Return type:

int

Write safety

The single gate every disruptive subcommand passes through: dry-run, confirm, execute, report.

Write-safety gates for disruptive ngsw commands (design spec §6).

netgear_switch.cli.safety.add_write_args(parser)[source]

Attach the shared –dry-run / –yes / –force gates to a subparser.

netgear_switch.cli.safety.confirm(prompt, *, assume_yes, ctx)[source]

Ask for confirmation on stderr; read one line from ctx.inp.

Return type:

bool

netgear_switch.cli.safety.do_write(ctx, *, dry_run, assume_yes, host, description, action, warning=None)[source]

The single disruptive-write gate: dry-run -> confirm -> execute -> report.

action is the verify-after-write facade call; any NetgearSwitchError it raises propagates to main() for clean reporting. The CLI describes the operation at facade granularity (method + args + host) rather than re-encoding the SNMP SET / NSDP packet / HTTP form, so no library logic is duplicated here.

Return type:

int

Output and capture

Pure output formatting for ngsw: JSON and human-readable tables.

Every function is a pure model object(s) -> str map (except emit, which prints), so the whole module is unit-testable without a switch or network.

netgear_switch.cli.format.jsonify(obj)[source]

Recursively convert dataclasses / enums / sets into JSON-native values.

Return type:

object

netgear_switch.cli.format.to_json(obj)[source]
Return type:

str

netgear_switch.cli.format.emit(ctx, obj, table_fn)[source]

Print obj as JSON (when ctx.as_json) or via table_fn.

netgear_switch.cli.format.ports_table(ports)[source]
Return type:

str

netgear_switch.cli.format.poe_table(entries)[source]
Return type:

str

netgear_switch.cli.format.vlans_table(vlans)[source]
Return type:

str

netgear_switch.cli.format.pvids_table(pvids)[source]
Return type:

str

netgear_switch.cli.format.lldp_table(neighbors)[source]
Return type:

str

netgear_switch.cli.format.macs_table(entries)[source]
Return type:

str

netgear_switch.cli.format.stats_table(stats)[source]
Return type:

str

netgear_switch.cli.format.sensors_table(sensors)[source]
Return type:

str

netgear_switch.cli.format.detected_model_text(detected)[source]

Render an SNMP model-detection result. key is None (shown as (unmatched)) when the sysDescr matched no registered model – never a fabricated guess (see models.DetectedModel).

Return type:

str

netgear_switch.cli.format.nsdp_device_text(device)[source]

Render the headline fields of a raw NSDP device record. The full record (per-port status/statistics, VLANs, QoS, etc.) is available via --json.

Return type:

str

netgear_switch.cli.format.mgmt_ip_text(cfg)[source]
Return type:

str

netgear_switch.cli.format.hostname_text(name)[source]
Return type:

str

netgear_switch.cli.format.users_table(users)[source]

Local accounts, showing the firmware’s OWN wording for the access mode.

access_mode is printed verbatim and privileged beside it: the two images word the same level differently (Privilege-15 vs Read/Write), so showing only a normalised flag would hide what the switch actually said, and showing only the text would make two switches look incomparable.

Return type:

str

netgear_switch.cli.format.services_table(services)[source]
Return type:

str

netgear_switch.cli.format.syslog_text(cfg)[source]
Return type:

str

netgear_switch.cli.format.snapshot_text(data)[source]
Return type:

str

ngsw capture: record a real switch’s state + protocol exchanges.

Opt-in, live-switch, never run in CI. The state snapshot uses the public SyncSwitch.snapshot() (works against any backend); the reference raw walk (snmpbulkwalk output) requires live-switch access and is only recorded when a raw_walk callable is supplied. Output is a JSON file used for reference when hand-authoring fixtures (design spec Sec7.1) – never committed as-is.

class netgear_switch.cli.capture.CaptureRecord(
model: 'str',
host: 'str',
captured_at: 'str',
snapshot: 'object',
raw_exchanges: 'list[dict[str,
object]]'=<factory>,
notes: 'list[str]' = <factory>,
)[source]

Bases: object

model: str
host: str
captured_at: str
snapshot: object
raw_exchanges: list[dict[str, object]]
notes: list[str]
netgear_switch.cli.capture.default_raw_walk(host, base, *, community='public', runner=subprocess.run)[source]

Shell out to net-snmp’s snmpbulkwalk (live hardware) for a reference walk.

Never uses shell=True or string interpolation – the argv is a fixed list, so there is no shell-injection surface even though host/base are caller-controlled. A missing binary or a timeout propagates as the normal subprocess exception (FileNotFoundError / subprocess.TimeoutExpired); a nonzero exit is turned into a RuntimeError carrying the process’s stderr. run_capture is responsible for catching these and recording an honest failure instead of crashing the whole capture.

Return type:

list[str]

netgear_switch.cli.capture.run_capture(switch, out_path, *, snapshot_only=False, raw_walk=None, now=None)[source]
Return type:

CaptureRecord