Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from contextlib import asynccontextmanager
from functools import partial
from os import PathLike

from jumpstarter.client import DriverClient
from jumpstarter.client.adapters import blocking
Expand Down Expand Up @@ -37,6 +38,7 @@ async def UnixPortforwardAdapter(
*,
client: DriverClient,
method: str = "connect",
path: PathLike | None = None,
):
async with TemporaryUnixListener(partial(handler, client, method)) as addr:
async with TemporaryUnixListener(partial(handler, client, method), path=path) as addr:
yield addr
Original file line number Diff line number Diff line change
@@ -1,12 +1,65 @@
from contextlib import AbstractContextManager
from ipaddress import IPv6Address, ip_address
from threading import Event

from .adapters import DbusAdapter
import asyncclick as click
Comment thread
NickCao marked this conversation as resolved.

from .adapters import DbusAdapter, TcpPortforwardAdapter, UnixPortforwardAdapter
from .driver import DbusNetwork
from jumpstarter.client import DriverClient


class NetworkClient(DriverClient):
pass
def cli(self):
@click.group
def base():
"""Generic Network Connection"""
pass

@base.command()
@click.option("--address", default="localhost", show_default=True)
@click.argument("port", type=int)
def forward_tcp(address: str, port: int):
"""
Forward local TCP port to remote network

PORT is the TCP port to listen on.
"""

with TcpPortforwardAdapter(
client=self,
local_host=address,
local_port=port,
) as addr:
host = ip_address(addr[0])
port = addr[1]
match host:
case IPv6Address():
click.echo("[{}]:{}".format(host, port))
case _:
click.echo("{}:{}".format(host, port))

Event().wait()

@base.command()
@click.argument("path", type=click.Path(), required=False)
def forward_unix(path: str | None):
"""
Forward local Unix domain socket to remote network

PATH is the path of the Unix domain socket to listen on,
defaults to a random path under $XDG_RUNTIME_DIR.
"""

with UnixPortforwardAdapter(
client=self,
path=path,
) as addr:
click.echo(addr)

Event().wait()

return base


class DbusNetworkClient(NetworkClient, AbstractContextManager):
Expand Down
1 change: 1 addition & 0 deletions packages/jumpstarter-driver-network/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies = [
"pexpect>=4.9.0",
"fabric>=3.2.2",
"wsproto>=1.2.0",
"asyncclick>=8.1.8",
]

[project.entry-points."jumpstarter.drivers"]
Expand Down
12 changes: 9 additions & 3 deletions packages/jumpstarter/jumpstarter/common/tempfile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from contextlib import asynccontextmanager, contextmanager
from contextlib import asynccontextmanager, contextmanager, nullcontext
from os import PathLike
from pathlib import Path
from socket import AddressFamily
from tempfile import TemporaryDirectory
Expand All @@ -15,8 +16,13 @@ def TemporarySocket():


@asynccontextmanager
async def TemporaryUnixListener(handler):
with TemporarySocket() as path:
async def TemporaryUnixListener(handler, path: PathLike | None = None):
if path is not None:
cm = nullcontext(path)
else:
cm = TemporarySocket()

with cm as path:
async with await create_unix_listener(path) as listener:
async with create_task_group() as tg:
tg.start_soon(listener.serve, handler, tg)
Expand Down
2 changes: 2 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading