Commit graph

4,607 commits

Author SHA1 Message Date
64e9fbff59 lib.FileContext.put(): Swap params path and content

Swap the positions of the "path" and "content" parameters of put(). Path comes always first, in every path related function I know.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
94eee5c4bb lib.FileContext.put(): Add parameter "atomic"

Add the parameter "atomic" to put() / _put(). If instructs the implementation to take extra precautions to make sure the operation either succeeds or fails entirely, i.e. doesn't leave a broken target file behind.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
bbb2d16956 lib.FileContext.put(): Simplify

.put() has some commands to _run(), and it uses its own CallContext for them. Since that pattern only replicates what run() does anyway, we could just as well use run() itself with less code, so do that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
0d6eeeadcf lib.FileContext.log_name: Beautify

Prepend the class name to .log_name. Not sure if that makes logs more legible, but we'll try it out for a while.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
4f98fd6c78 lib.FileTransfer: Rename to FileContext

Rename class FileTransfer to FileContext because that's the better name. It's the base class of ExecContext and also a context.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
2f1265b7b2 lib.ec.SSHClient: Fix return value type hints

Add proper type-hinting for port, hostname, username and password return values.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
64a5b5d429 lib.ec.Local._run(): Interpret env as mod_env

An env argument environment passed to Local._run() entirely replaces the environment. Make it modify the enviroment instead.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
9575339972 lib.ec.ssh.AsyncSSH: Declare Caps.Env

AsyncSSH's implementation already supports modifying the execution environment via env, so declare it to the base class with Caps.Env.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
f253466a3f lib.ec.ssh.Exec._run_ssh(): Fix: interactive ignored

Exec's _run_ssh() ignores its "interactive" parameter and uses the instances' default instead, fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
4a8ccfb0a6 lib.ec.ssh.Exec: Honour username and port

Username and port of an Exec SSH client are not passed to the ssh executable, fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
3574c0f1bf lib.ec.ssh.Exec: Support Caps.Env

Add support for modifying the execution environment via the env parameter to Exec.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
6cdcd23010 lib.ec.ssh.Exec._run_ssh(): Fix interactivity translation

cmd_input is passed as None to _run(), which is legal, but then used in a call to cmd_run(), which is a public API and, hence, illegal. InputMode.NonInteractive should be used instead, do that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:31 +02:00
910f10b194 lib.util.run_cmd(): Remove parameter interactive

run_cmd() is a thin layer over the public ExecContext API, which falls back to using a Local instance if not other ExecContext is specified explicitly. Both the default Local context as the subsequent call to run() should have the same idea about interactivity, so allowing to specify it in two parameters ("interactive" and "cmd_input") is a bad idea. Remove "interactive".

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:43:29 +02:00
fd336ecdcf lib.ec.SSHClient: Support JW_DEFAULT_SSH_CLIENT

Allow to configure via the environment which class ssh_client() picks. Can currently be exec, asyncssh, paramiko or a comma-separated search list. The list will be tried through until a class is found that can be instantiated.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:42:32 +02:00
193b8242d7 lib.Types.LoadTypes: Support JW_LOG_LEVEL_LOAD_TYPES

Allow to configure logging of LoadTypes' decisions whether or not a class is elegible for loading. Currently, the respective log level is "off", allow to set it via JW_LOG_LEVEL_LOAD_TYPES in the environment.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-18 10:42:32 +02:00
e472f6eb71 Release 1.0.0-206@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-17 23:10:09 +00:00
e1043db93b Release 1.0.0-206@suse-tumbleweed/x86_64
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-16 18:07:55 +00:00
0f84c6fc1b Start version: 1.0.0-206
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-16 18:06:59 +00:00
a1bb8897ac Release 1.0.0-205@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-16 17:54:42 +00:00
f78d08f0d8 lib.ec.ssh.Exec: Fix cmd_input == None

cmd_input is passed as None to _run(), which is legal, but then used in a call to cmd_run(), which is a public API and, hence, illegal. Fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 19:43:29 +02:00
6658d6e9e7 Release 1.0.0-205@suse-tumbleweed/x86_64
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-16 14:33:12 +00:00
17cd6b85f0 Start version: 1.0.0-205
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-16 14:32:27 +00:00
781393ad42 cmds.projects.ListRepos: Fix missing await

Fix

CmdListRepos.py:51: RuntimeWarning: coroutine 'FileTransfer.close' was never awaited

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 16:11:45 +02:00
f445b196c9 App.distro_pkg_ext: Add property

Add .distro_pkg_ext to App, in order to support something along the lines of

jw-pkg distro install "https://my-company.com/repos/%{id}/%{codename}/my-base-pkg-latest.%{pkg-ext}"

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 16:07:11 +02:00
beab4cb03c cmds.distro.CmdInstall: Support macro expansion

Support macro expansion similar to CmdCopy paths in CmdInstall as well.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 16:07:11 +02:00
c20091d7ac App.distro_info(): Accept and return lists

App.distro_info() accepts and returns str instances, interpret anything passed as fmt parameter which is not a str as iterable, and return lists of expanded strings in that case.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 16:07:11 +02:00
a19679fecc lib.ec.ssh.AsyncSSH: Revert "Reuse connection"

This reverts commit 04fef1e67a.

Reusing AsyncSSH's connection is fine and fast, but only if it's not combined with the AsyncRunner. See commit 67e51cf0 why it was introduced in the first place, along with a reasoning why it may be a bad idea. Looks like we're now reaping what we sowed.

The current plan to get this to fly is to sprinkle async / await all over the code paths to App.os_release(). That is a lot of churn, so postpone and revert for now to keep CI working.

File "~/local/src/jw.dev/proj/jw-pkg/scripts/jw/pkg/lib/ec/ssh/AsyncSSH.py", line 463, in _run_ssh return await self._run_on_conn( ^^^^^^^^^^^^^^^^^^^^^^^^ ...<7 lines>... ) ^ File "~/local/src/jw.dev/proj/jw-pkg/scripts/jw/pkg/lib/ec/ssh/AsyncSSH.py", line 403, in _run_on_conn proc = await conn.create_process( ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<7 lines>... ) ^ File "/usr/lib/python3.13/site-packages/asyncssh/connection.py", line 4492, in create_process chan, process = await self.create_session( ^^^^^^^^^^^^^^^^^^^^^^^^^^ SSHClientProcess, *args, **kwargs) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.13/site-packages/asyncssh/connection.py", line 4385, in create_session session = await chan.create(session_factory, command, subsystem, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<4 lines>... bool(self._agent_forward_path)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.13/site-packages/asyncssh/channel.py", line 1149, in create packet = await self._open(b'session') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.13/site-packages/asyncssh/channel.py", line 717, in _open return await self._open_waiter

^^^^^^^^^^^^^^^^^^^^^^^

RuntimeError: Task <Task pending name='Task-1' coro=<App.__run() running at ~/local/src/jw.dev/proj/jw-pkg/scripts/jw/pkg/lib/App.py:137> cb=[_run_until_complete_cb() at /usr/lib64/python3.13/asyncio/base_events.py:181]> got Future <Future pending> attached to a different loop
Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 16:07:11 +02:00
7478206c38 Release 1.0.0-204@suse-tumbleweed/x86_64
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-16 11:54:54 +00:00
b484e0b0b3 Start version: 1.0.0-204
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-16 11:54:09 +00:00
b72c417510 cmds.posix.CmdCopy: Support platform macros

Expand platform macros (as in %{codename}) in the src and dst command arguments. Expansion can be turned off by -F --fixed-strings.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 13:35:02 +02:00
ef21dc1b1e App.distro_info(): Add method

Add a method distro_info() to App, essentially providing CmdInfo's macro-expansion of platform information to other interested code.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 13:25:37 +02:00
d1df9f0ac7 lib.Distro.install(): Treat URL arguments specially

As of now, install() passes the "names" parameter on to _install(), which is expected to pass the list of package names on to the package manager for having it handle package download and installation. This commit makes it easier for Distro instances to support directly installing packages via an URL instead by providing a few callback methods to be overridden, in case the package manager doesn't handle package URLs the same way as package names.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 13:02:29 +02:00
45001144d7 lib.ec.Curl: Add class

Add class Curl as the first pure FileTransfer class without _run() / _sudo(). It doesn't use any PycURL / libcurl-like binding, but runs the curl binary in a subprocess. That looks the most portable still.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 12:59:42 +02:00
825dd1449c lib.FileTransfer: Split from ExecContext

ExecContext has get() / _get() and put() / _put(), which make a fine API for a file transfer class. A class supporting file transfer should not, however, be forced to implement _run() and _sudo(), so place this functionality in a new class FileTransfer, and derive ExecContext from it.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 12:57:32 +02:00
888c0495ec lib.base: Add module

Add lib.base to provide basic definitions.

For now, move the definiions of Result, Input and InputMode from ExecContext into lib.base. Having to import them from the ExecContect module is too heavy-handed for those simple types.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 12:57:04 +02:00
04fef1e67a lib.ec.ssh.AsyncSSH: Reuse connection

With CmdCopy as test case and ExecContext.close() in place, we can actually implement connection reuse, so do it for AsyncSSH.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 12:56:55 +02:00
e811b2dc14 cmds.posix.CmdCopy: Add module

Add CmdCopy, designed to copy data from the filesystem to another location in the filesystem. Not necessarily local file systems, the URLs can be all URLs supported by ExecContext.run().

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 12:56:43 +02:00
16bb4e5bed cmds.CmdPosix: Add command

Add a new group of commands - "posix". The current command categories are not a good fit for that: "projects" is for CI, "distro" is distribution-specific for CD, and secrets is for handling secrets specifically. Introduce the more general command group "posix", a class of commands not POSIX compliant in the exposed API, but primarily using POSIX utilities as workhorse.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 12:56:22 +02:00
63383cb683 lib.util.copy(): Add function

Add copy(src_uri, dst_uri), instatiating two ExecContext instances, and doing the obvious with them - copying from src_uri to dst_uri.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 12:55:47 +02:00
d803c66f70 App.__os_release(): Use ExecContext.get()

The property App.__os_release uses _run(['cat', '/etc/os-release']), use ExecContext.get() instead as the default way to fetch content.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:26 +02:00
60630676ef App.__aexit__(): Use to close exec context

Override lib.App.__aexit() to call close() on the App.exec_context instance if it exists.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:25 +02:00
3d27cc09d9 lib.App.run_sub_commands(): Instantiate as context manager

App currently has no hook to close async resources. Call it as context manager, so that __aexit__() gets invoked if run_sub_commands() exits.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:25 +02:00
4f17a9cc93 lib.ExecContext.log_name: Add property

Add a .log_name property to be used in log messages.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:25 +02:00
1214451c15 lib.ExecContext.close(): Add method

Add ExecContext.close() as a hook to clean up async resources living longer than an ExecContext method call.

Also, implement __aenter__() and __aexit__(), to allow using ExecContext as context manager. close() is invoked it goes out of scope.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:25 +02:00
f158ab76a8 lib.ExecContext: Add get(), _get(), put() and _put()

Add wrapper methods get() and put(), plus their wrapped methods _get() and _put(). The wrapped methods have default implementations, using POSIX utilities on the target machine over _run().

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:25 +02:00
dbf41d7b48 lib.ExecContext.create(): Support path-only URIs

ExecContext.create() relies on properly formed URLs with a schema for deciding which backend gets created. Create a Local instance if an URL doesn't have schema.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:25 +02:00
04b294917f lib.ExecContext: Support bytes-typed cmd_input

The Input instance passed as cmd_input to ExecContext.run() and .sudo() currently may be of type str. Allow to pass bytes, too.

At the same time, disallow None to be passed as cmd_input. Force the caller to be more explicit how it wants input to be handled, notably with respect to interactivity.

Along the way fix a bug: Content in cmd_input should result in CallContext.interactive == False but doesn't. Fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:25 +02:00
8ef478e63f lib.ExecContext: Code beautification

- Move _sudo() above sudo()

To have a pattern in lib.ExecContext and avoid future churn: If a public wrapper calls a protected method, define the protected method above the respective wrapper.

- sudo(): Make cmd_input default equal to run(): InputMode.OptInteractive

- CallContext: Expose parameters throw, wd, cmd as properties for later use
Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-16 10:21:16 +02:00
3ce893b74b Release 1.0.0-203@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-13 16:06:46 +00:00
4c417adedd Release 1.0.0-203@suse-tumbleweed/x86_64
Signed-off-by: janware DevOps <devops@janware.com>
2026-04-13 15:33:06 +00:00