Access layer for NetOrk/netork#765, phase 1 (netork#769): the driver builds the connection, netOrk does the talking. No container model and no parsing here.
Channel (channel.py)
CommandChannelMixin declares run_command(command, *, privileged, timeout, stdin) -> CommandResult and open_stream(command, *, privileged) -> ByteStream, under TYPE_CHECKING like the role bases.
run_on_transport() / open_stream_on_transport(): paramiko exec channel, no PTY, separate stderr, real exit status. Usable by any SSH driver (Proxmox, OpenWrt later).
ParamikoExecStream drains stderr on every read (shared window) and keeps its last 64 KiB. write() never half-closes: dial-stdio answers an unfinished request with HTTP 499 after a half-close.
Container engine (container_engine.py)
ContainerEngineMixin.container_engines() -> [{engine, api}], probed with command -v.
open_container_engine(engine) -> ContainerEngineConnection with open_api() (<binary> system dial-stdio), run_cli(args) and stream_cli(args, merge_stderr=False). Arguments are quoted with shlex.join.
Hook _container_engine_binary(engine): QNAP returns its Container Station path.
Mixed in by drivers, not role bases, so a Windows OSDriver without a shell channel does not claim it.
One change against the issue text: a driver without a channel does not raise NotImplementedError from open_stream; it simply has no run_command/open_stream, so hasattr(driver, "open_stream") is the test (the role-base rule, as decided in the netork#765 plan). open_container_engine raises ContainerEngineUnavailable (a NotImplementedError) for an engine it cannot reach. Windows stays open for a follow-up issue.
Additive (2.6.0). Docker*Dict stays until netOrk stops reading get_docker_info (phase 9 of the plan, then 3.0.0).
Tests: test_channel.py, test_container_engine.py; suite 380 passed.
Merge before NAPALM/napalm-linux and NAPALM/napalm-qnap-qts, whose CI installs this package from main.
Access layer for NetOrk/netork#765, phase 1 (netork#769): the driver builds the connection, netOrk does the talking. No container model and no parsing here.
**Channel** (`channel.py`)
- `CommandChannelMixin` declares `run_command(command, *, privileged, timeout, stdin) -> CommandResult` and `open_stream(command, *, privileged) -> ByteStream`, under `TYPE_CHECKING` like the role bases.
- `run_on_transport()` / `open_stream_on_transport()`: paramiko exec channel, no PTY, separate stderr, real exit status. Usable by any SSH driver (Proxmox, OpenWrt later).
- `ParamikoExecStream` drains stderr on every read (shared window) and keeps its last 64 KiB. `write()` never half-closes: `dial-stdio` answers an unfinished request with HTTP 499 after a half-close.
**Container engine** (`container_engine.py`)
- `ContainerEngineMixin.container_engines()` -> `[{engine, api}]`, probed with `command -v`.
- `open_container_engine(engine) -> ContainerEngineConnection` with `open_api()` (`<binary> system dial-stdio`), `run_cli(args)` and `stream_cli(args, merge_stderr=False)`. Arguments are quoted with `shlex.join`.
- Hook `_container_engine_binary(engine)`: QNAP returns its Container Station path.
- Mixed in by drivers, not role bases, so a Windows `OSDriver` without a shell channel does not claim it.
One change against the issue text: a driver without a channel does not raise `NotImplementedError` from `open_stream`; it simply has no `run_command`/`open_stream`, so `hasattr(driver, "open_stream")` is the test (the role-base rule, as decided in the netork#765 plan). `open_container_engine` raises `ContainerEngineUnavailable` (a `NotImplementedError`) for an engine it cannot reach. Windows stays open for a follow-up issue.
Additive (2.6.0). `Docker*Dict` stays until netOrk stops reading `get_docker_info` (phase 9 of the plan, then 3.0.0).
Tests: `test_channel.py`, `test_container_engine.py`; suite 380 passed.
Merge before NAPALM/napalm-linux and NAPALM/napalm-qnap-qts, whose CI installs this package from main.
Priority: P3
Closes #17
netOrk reached a host's shell through napalm-linux's private `_send`: an
interactive PTY with stdout and stderr merged and no exit code. For Docker
it went further and opened its own paramiko connections around the driver.
This adds the access layer only, no container model (NetOrk/netork#765):
- `channel.py`: `CommandChannelMixin` declares `run_command()` (stdout,
stderr, exit code) and `open_stream()` (a `ByteStream` to a running
command). Declared under TYPE_CHECKING, so hasattr stays truthful.
`run_on_transport()` and `open_stream_on_transport()` implement both on
a paramiko exec channel for any SSH driver; `ParamikoExecStream` drains
stderr on every read so the shared window never stalls.
- `container_engine.py`: `ContainerEngineMixin` with `container_engines()`
and `open_container_engine()`. The returned `ContainerEngineConnection`
opens the engine API over `<binary> system dial-stdio` and runs the CLI
with caller-chosen arguments. The driver decides the binary through
`_container_engine_binary()`; callers never see the path.
- README: why the container model lives in netOrk and not here.
Additive; the Docker*Dict declarations stay until netOrk no longer reads
them. Version 2.6.0.
Refs #17
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Access layer for NetOrk/netork#765, phase 1 (netork#769): the driver builds the connection, netOrk does the talking. No container model and no parsing here.
Channel (
channel.py)CommandChannelMixindeclaresrun_command(command, *, privileged, timeout, stdin) -> CommandResultandopen_stream(command, *, privileged) -> ByteStream, underTYPE_CHECKINGlike the role bases.run_on_transport()/open_stream_on_transport(): paramiko exec channel, no PTY, separate stderr, real exit status. Usable by any SSH driver (Proxmox, OpenWrt later).ParamikoExecStreamdrains stderr on every read (shared window) and keeps its last 64 KiB.write()never half-closes:dial-stdioanswers an unfinished request with HTTP 499 after a half-close.Container engine (
container_engine.py)ContainerEngineMixin.container_engines()->[{engine, api}], probed withcommand -v.open_container_engine(engine) -> ContainerEngineConnectionwithopen_api()(<binary> system dial-stdio),run_cli(args)andstream_cli(args, merge_stderr=False). Arguments are quoted withshlex.join._container_engine_binary(engine): QNAP returns its Container Station path.OSDriverwithout a shell channel does not claim it.One change against the issue text: a driver without a channel does not raise
NotImplementedErrorfromopen_stream; it simply has norun_command/open_stream, sohasattr(driver, "open_stream")is the test (the role-base rule, as decided in the netork#765 plan).open_container_engineraisesContainerEngineUnavailable(aNotImplementedError) for an engine it cannot reach. Windows stays open for a follow-up issue.Additive (2.6.0).
Docker*Dictstays until netOrk stops readingget_docker_info(phase 9 of the plan, then 3.0.0).Tests:
test_channel.py,test_container_engine.py; suite 380 passed.Merge before NAPALM/napalm-linux and NAPALM/napalm-qnap-qts, whose CI installs this package from main.
Priority: P3
Closes #17