Commit graph

15 commits

Author SHA1 Message Date
3c9ce19deb lib.ec.ssh.Paramiko: Fix exception logging

The catch-block around Paramiko's connect code throws another exception, fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-03 17:29:44 +02:00
b21d2d1c21 lib.ec.ssh.AsyncSSH: Add interactivity

Request a remote PTY from AsyncSSH, and wire the local terminal's stdin up with it if interactive == True. This gives a real interactive session if local stdin belongs to a terminal. Also, thanks to AsyncSSH understanding that, forward terminal size changes to the remote end.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
737cbc3e24 lib.ec.ssh.AsyncSSH: Add class

Add a SSHClient implementation using AsyncSSH. This is the first and currently only class derived from SSHClient which implements SSHClient.Cap.LogOutput, designed to consume and log command output as it streams in. It felt like the lower hanging fruit not to do that with Paramiko: Paramiko doesn't provide a native async API, so it would need to spawn additional worker threads. I think.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
279b7789e2 lib.ec.SSHClient: Add property port

Add a port property to SSHClient, parsed from the ctor's URL, to supply the obvious information.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
3a84408436 lib.ec.SSHClient.__init__(): Add parameter caps

Add an optional caps ("capabilities") argument to the constructor of SSHClient. It is meant to be used by derived classes in order to declare that they don't want the base class to handle a default behaviour for a certain capability, but that they want to implement it themselves instead.

Also, give the _run_ssh() callbacks the necessary info as parameters, so that the derived classes have the means to do so.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
21e67291b5 Fix: Decode run_cmd() result

Since commit 02697af5, ExecContext.run() returns bytes for stdout and stderr and fixes that in calling code. The thing it did not fix was the code calling run_cmd(), which also made return bytes. This commit catches up on that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:45 +01:00
f4c76ebab9 lib.ec.SSHClientInternal|SSHClientCmd: Own .py

Move the code of SSHClientInternal and SSCClientCmd into lib.ec.ssh, as "Paramiko" and "Exec", respectively. This makes the class layout a little more modular, and along the way fixes a bug where SSHClientInternal could be instantiated but was unusable (if the Paramiko is not installed).

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 13:35:50 +01:00
f37f025b17 lib.SSHClient: Move to lib.ec

SSHClient in an ExecContext, hence it's better off in lib.ec, move it there and adapt the references.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 13:35:11 +01:00
02697af568 lib.ExecContext: Align .sudo() prototype to .run()

ExecContext's .sudo() omits many of run()'s parameters, and this commit adds them. To avoid redundancy around repeating and massaging the long parameter list of both functions and their return values, it also adds some deeper changes:

- Make run(), _run(), sudo() and _sudo() always return instances of Result. Before it was allowed to return a triplet of stdout, stderr, and exit status.
- Have ExecContext stay out of the business of decoding the result entirely. Result provides a convenience method .decode() operating on stdout and stderr and leaves the decision to the caller.
This entails miniscule adaptations in calling code, namely in App.os_release, util.get_profile_env() and CmdListRepos._run().
- Wrap the _run() and _sudo() callbacks in a context manager object of type CallContext to avoid code duplication.
- Consistently name the first argument to run(), _run(), sudo() and _sudo() "cmd", not "args". The latter suggests that the caller is omitting the executable, which is not the case.
Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
52dd3b8f21 lib.ExecContext.run(): Push code up into base class

Take implementation burden from the derived classes _run() callback by moving the respective code into the run() wrapper methods of the base class.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
888c1e7f16 lib.ExecContext.__init__(): Add parameter uri

Take a positional uri argument to the constructor of ExecContext, forcing SSHClient to follow suit. The latter was instantiated with a hostname as only argument up to now, which still works as a special case of an uri.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
72bd5e3555 lib.Local.run(): Be less dramatic about exit != 0

Don't mention "error" in log message for exit codes > 0 from spawned processes, because sometimes they don't mean an error.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-09 20:03:01 +01:00
1325222fbd lib.ExecContext,Local: Remove callback default params

Remove defaults from protected callback function parameters. They have to be decided by the base class's public API.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-06 19:02:22 +01:00
fadf1bca49 lib.util.run_cmd(): Add parameter ec: ExecContext

Allow to specify the ExecContext in a call to run_cmd(). This effectively makes run_cmd() an thin wrapper around ExecContext.run(), which is what's going to be used in the future. The wrapper is for backwards-compatibility.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-06 15:14:13 +01:00
3e897f4df8 lib.Distro, ExecContext: Add classes, refactor lib.distro

The code below lib.distro, as left behind by the previous commit, is geared towards being directly used as a command-line API. This commit introduces the abstract base class Distro, a proxy for distribution-specific interactions. The proxy abstracts distro specifics into an API with proper method prototypes, not argparse.Namespace contents, and can thus be more easily driven by arbitrary code.

The Distro class is initialized with a member variable of type ExecContext, another new class introduced by this commit. It is designed to abstract the communication channel to the distribution instance. Currently only one specialization exists, Local, which interacts with the distribution and root file system it is running in, but is planned to be subclassed to support interaction via SSH, serial, chroot, or chains thereof.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-06 14:56:46 +01:00