runspec-linux 0.13.2__tar.gz → 0.14.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of runspec-linux might be problematic. Click here for more details.

Files changed (35) hide show
  1. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/CHANGELOG.md +26 -0
  2. runspec_linux-0.14.0/PKG-INFO +108 -0
  3. runspec_linux-0.14.0/README.md +88 -0
  4. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/pyproject.toml +11 -2
  5. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/runspec.toml +36 -0
  6. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/venvs.py +20 -1
  7. runspec_linux-0.13.2/PKG-INFO +0 -13
  8. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/.gitignore +0 -0
  9. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/__init__.py +0 -0
  10. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/_escalation.py +0 -0
  11. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/commands.py +0 -0
  12. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/containers.py +0 -0
  13. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/cron.py +0 -0
  14. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/files.py +0 -0
  15. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/fs/__init__.py +0 -0
  16. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/fs/_dispatch.py +0 -0
  17. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/fs/_worker.py +0 -0
  18. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/fs/cli.py +0 -0
  19. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/investigate.py +0 -0
  20. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/logs.py +0 -0
  21. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/nc_command.py +0 -0
  22. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/network.py +0 -0
  23. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/packages.py +0 -0
  24. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/perf.py +0 -0
  25. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/power.py +0 -0
  26. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/security.py +0 -0
  27. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/services.py +0 -0
  28. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/sudoers.py +0 -0
  29. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/system_info.py +0 -0
  30. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/runspec_linux/webops.py +0 -0
  31. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/tests/__init__.py +0 -0
  32. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/tests/test_escalation.py +0 -0
  33. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/tests/test_fs.py +0 -0
  34. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/tests/test_nc_send.py +0 -0
  35. {runspec_linux-0.13.2 → runspec_linux-0.14.0}/tests/test_webops.py +0 -0
@@ -1,5 +1,31 @@
1
1
  # runspec-linux Changelog
2
2
 
3
+ ## [0.14.0] — 2026-09-25
4
+
5
+ ### Added
6
+
7
+ - **`share-venv-logs` — make an existing venv's `logs/` dir shared.** The repair
8
+ path for a venv that wasn't created with `create-venv --group` (hand-made or
9
+ legacy): sets `<venv>/logs` to `2775` (setgid + group-writable) and, with
10
+ `--group`, `chgrp`s the `logs/` dir, so the per-venv runs index
11
+ (`runspec_runs.db`, `runspec` 0.57.0) and the audit-log files are writable by
12
+ every console / service account in a shared group. Takes the same per-invocation
13
+ `--run-as` / `--become-method` escalation as the other venv runnables (empty =
14
+ the SSH login user), `autonomy = "confirm"`. Thin wrapper over the new
15
+ `runspec_linux_core.share_venv_logs`; core pin bumped to `>=0.7.0`.
16
+ (`create-venv --group` already sets this up at build time — this brings a
17
+ pre-existing venv up to the same state without recreating it.)
18
+
19
+ ## [0.13.3] — 2026-09-20
20
+
21
+ ### Changed
22
+
23
+ - **Packaging metadata for the runspec-console Marketplace.** Add a README
24
+ (rendered in the Marketplace card's Details view) and publish `keywords`
25
+ and Documentation / Source / Changelog / Issues project URLs, so the
26
+ package's Marketplace card shows a description, tags and links. No
27
+ runnable, argument, or behaviour changes.
28
+
3
29
  ## [0.13.2] — 2026-09-17
4
30
 
5
31
  ### Fixed
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.5
2
+ Name: runspec-linux
3
+ Version: 0.14.0
4
+ Summary: Linux system admin runnables for runspec
5
+ Project-URL: Documentation, https://runspec.app/
6
+ Project-URL: Source, https://github.com/jasonfinestone/runspec/tree/main/packages/python/runspec-linux
7
+ Project-URL: Changelog, https://github.com/jasonfinestone/runspec/blob/main/packages/python/runspec-linux/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/jasonfinestone/runspec/issues
9
+ Keywords: linux,ops,runnable,runspec,ssh,sysadmin,venv
10
+ Requires-Python: >=3.10
11
+ Requires-Dist: runspec-fs-core>=0.3.0
12
+ Requires-Dist: runspec-linux-core>=0.7.0
13
+ Requires-Dist: runspec-webops-core>=0.3.0
14
+ Requires-Dist: runspec>=0.50.1
15
+ Provides-Extra: dev
16
+ Requires-Dist: mypy; extra == 'dev'
17
+ Requires-Dist: pytest>=8.0; extra == 'dev'
18
+ Requires-Dist: ruff==0.15.20; extra == 'dev'
19
+ Description-Content-Type: text/markdown
20
+
21
+ # runspec-linux
22
+
23
+ Linux system-administration runnables (plus Python-venv management, crontab,
24
+ filesystem, and the cross-platform web/TLS/API probes) for
25
+ [runspec](https://pypi.org/project/runspec/). `pip install` it into a venv and
26
+ the runnables are discoverable by `runspec local`, `runspec serve` (MCP), and
27
+ runspec-console.
28
+
29
+ All runnables emit JSON on stdout. Read-only runnables are `autonomy =
30
+ "autonomous"`; state-changing ones are `autonomy = "confirm"`. The privileged
31
+ runnables declare `run_as = "root"`, so runspec-console escalates them via
32
+ `sudo` — run `enable-passwordless-sudo` once to install a `visudo`-validated
33
+ `/etc/sudoers.d` drop-in so they run without a password prompt.
34
+
35
+ ## Install
36
+
37
+ ```
38
+ pip install runspec-linux
39
+ ```
40
+
41
+ ## Runnables
42
+
43
+ | Group | Runnables |
44
+ |---|---|
45
+ | System | `system-info`, `disk-usage`, `check-memory`, `cpu-info`, `pressure` |
46
+ | Processes | `list-processes` |
47
+ | Services | `list-services`, `check-service`, `restart-service`, `service-detail`, `failed-units` |
48
+ | Logs | `tail-log`, `search-log`, `journalctl` |
49
+ | Network | `ping-host`, `check-port`, `show-connections`, `trace-route`, `route-table`, `socket-stats`, `dns-config`, `open-ports` |
50
+ | Kernel params | `get-sysctl`, `set-sysctl` |
51
+ | Files | `find-large-files`, `backup-files`, `owning-package` |
52
+ | Sessions | `last-logins`, `who` |
53
+ | Containers | `list-containers`, `container-logs`, `restart-container` |
54
+ | Packages | `list-packages`, `list-upgrades`, `upgrade-packages`, `install-package`, `remove-package` |
55
+ | Power | `reboot-host` |
56
+ | Sudo bootstrap | `enable-passwordless-sudo` |
57
+ | Python venvs | `create-venv`, `install-into-venv`, `configure-pip` |
58
+ | TCP | `nc-command` |
59
+ | Commands | `which` |
60
+ | Cron | `cron` (multi-verb: `list`/`add`/`remove`/`clear`) |
61
+ | Filesystem | `filesystem` (multi-verb, backed by `runspec-fs-core`) |
62
+ | Web / TLS / API | `cert-check`, `cert-chain`, `tls-info`, `http-check`, `http-headers`, `redirect-trace`, `dns-lookup`, `api-spec` |
63
+
64
+ The package-management runnables auto-detect apt / dnf / yum / zypper / pacman.
65
+ The web/TLS/API probes are pure HTTP (shared with `runspec-windows` via
66
+ `runspec-webops-core`) and run anywhere.
67
+
68
+ ```
69
+ system-info
70
+ list-upgrades
71
+ check-port --host db-01 --port 5432
72
+ cert-check --url https://internal.example.com
73
+ ```
74
+
75
+ ### Python venvs
76
+
77
+ `create-venv`, `install-into-venv` and `configure-pip` take a **per-invocation**
78
+ `--run-as <user>` (+ `--become-method sudo|su`) rather than a declarative
79
+ `run_as`, so the service account that owns a shared venv is chosen per call:
80
+
81
+ ```
82
+ create-venv --python /usr/bin/python3.12 --dest /opt/venvs/ops --run-as svc-ops --group ops
83
+ install-into-venv --venv /opt/venvs/ops --package "runspec-linux==0.13.2" --run-as svc-ops
84
+ ```
85
+
86
+ ## Public Python API
87
+
88
+ The pure logic lives in **[`runspec-linux-core`](../runspec-linux-core)** — no
89
+ `runspec` dependency, no `runspec.toml`, no entry points (so it surfaces no
90
+ runnables). A corporate wrapper package that only wants a helper should depend
91
+ on the core alone:
92
+
93
+ ```python
94
+ from runspec_linux_core import nc_send, system_info, install_into_venv
95
+ ```
96
+
97
+ The helpers are also re-exported from `runspec_linux` for back-compat. Core
98
+ helpers return plain data and raise (`ToolNotFoundError` / `CommandError`) on
99
+ failure; the runnable wrappers catch these to render the CLI/agent behaviour.
100
+
101
+ ## Development
102
+
103
+ ```
104
+ python -m venv .venv && . .venv/bin/activate
105
+ pip install -e ".[dev]"
106
+ ruff check . && ruff format --check .
107
+ pytest
108
+ ```
@@ -0,0 +1,88 @@
1
+ # runspec-linux
2
+
3
+ Linux system-administration runnables (plus Python-venv management, crontab,
4
+ filesystem, and the cross-platform web/TLS/API probes) for
5
+ [runspec](https://pypi.org/project/runspec/). `pip install` it into a venv and
6
+ the runnables are discoverable by `runspec local`, `runspec serve` (MCP), and
7
+ runspec-console.
8
+
9
+ All runnables emit JSON on stdout. Read-only runnables are `autonomy =
10
+ "autonomous"`; state-changing ones are `autonomy = "confirm"`. The privileged
11
+ runnables declare `run_as = "root"`, so runspec-console escalates them via
12
+ `sudo` — run `enable-passwordless-sudo` once to install a `visudo`-validated
13
+ `/etc/sudoers.d` drop-in so they run without a password prompt.
14
+
15
+ ## Install
16
+
17
+ ```
18
+ pip install runspec-linux
19
+ ```
20
+
21
+ ## Runnables
22
+
23
+ | Group | Runnables |
24
+ |---|---|
25
+ | System | `system-info`, `disk-usage`, `check-memory`, `cpu-info`, `pressure` |
26
+ | Processes | `list-processes` |
27
+ | Services | `list-services`, `check-service`, `restart-service`, `service-detail`, `failed-units` |
28
+ | Logs | `tail-log`, `search-log`, `journalctl` |
29
+ | Network | `ping-host`, `check-port`, `show-connections`, `trace-route`, `route-table`, `socket-stats`, `dns-config`, `open-ports` |
30
+ | Kernel params | `get-sysctl`, `set-sysctl` |
31
+ | Files | `find-large-files`, `backup-files`, `owning-package` |
32
+ | Sessions | `last-logins`, `who` |
33
+ | Containers | `list-containers`, `container-logs`, `restart-container` |
34
+ | Packages | `list-packages`, `list-upgrades`, `upgrade-packages`, `install-package`, `remove-package` |
35
+ | Power | `reboot-host` |
36
+ | Sudo bootstrap | `enable-passwordless-sudo` |
37
+ | Python venvs | `create-venv`, `install-into-venv`, `configure-pip` |
38
+ | TCP | `nc-command` |
39
+ | Commands | `which` |
40
+ | Cron | `cron` (multi-verb: `list`/`add`/`remove`/`clear`) |
41
+ | Filesystem | `filesystem` (multi-verb, backed by `runspec-fs-core`) |
42
+ | Web / TLS / API | `cert-check`, `cert-chain`, `tls-info`, `http-check`, `http-headers`, `redirect-trace`, `dns-lookup`, `api-spec` |
43
+
44
+ The package-management runnables auto-detect apt / dnf / yum / zypper / pacman.
45
+ The web/TLS/API probes are pure HTTP (shared with `runspec-windows` via
46
+ `runspec-webops-core`) and run anywhere.
47
+
48
+ ```
49
+ system-info
50
+ list-upgrades
51
+ check-port --host db-01 --port 5432
52
+ cert-check --url https://internal.example.com
53
+ ```
54
+
55
+ ### Python venvs
56
+
57
+ `create-venv`, `install-into-venv` and `configure-pip` take a **per-invocation**
58
+ `--run-as <user>` (+ `--become-method sudo|su`) rather than a declarative
59
+ `run_as`, so the service account that owns a shared venv is chosen per call:
60
+
61
+ ```
62
+ create-venv --python /usr/bin/python3.12 --dest /opt/venvs/ops --run-as svc-ops --group ops
63
+ install-into-venv --venv /opt/venvs/ops --package "runspec-linux==0.13.2" --run-as svc-ops
64
+ ```
65
+
66
+ ## Public Python API
67
+
68
+ The pure logic lives in **[`runspec-linux-core`](../runspec-linux-core)** — no
69
+ `runspec` dependency, no `runspec.toml`, no entry points (so it surfaces no
70
+ runnables). A corporate wrapper package that only wants a helper should depend
71
+ on the core alone:
72
+
73
+ ```python
74
+ from runspec_linux_core import nc_send, system_info, install_into_venv
75
+ ```
76
+
77
+ The helpers are also re-exported from `runspec_linux` for back-compat. Core
78
+ helpers return plain data and raise (`ToolNotFoundError` / `CommandError`) on
79
+ failure; the runnable wrappers catch these to render the CLI/agent behaviour.
80
+
81
+ ## Development
82
+
83
+ ```
84
+ python -m venv .venv && . .venv/bin/activate
85
+ pip install -e ".[dev]"
86
+ ruff check . && ruff format --check .
87
+ pytest
88
+ ```
@@ -4,16 +4,24 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "runspec-linux"
7
- version = "0.13.2"
7
+ version = "0.14.0"
8
8
  requires-python = ">=3.10"
9
9
  description = "Linux system admin runnables for runspec"
10
+ readme = "README.md"
11
+ keywords = ["runspec", "runnable", "linux", "sysadmin", "ops", "ssh", "venv"]
10
12
  dependencies = [
11
13
  "runspec>=0.50.1",
12
- "runspec-linux-core>=0.6.2",
14
+ "runspec-linux-core>=0.7.0",
13
15
  "runspec-webops-core>=0.3.0",
14
16
  "runspec-fs-core>=0.3.0",
15
17
  ]
16
18
 
19
+ [project.urls]
20
+ Documentation = "https://runspec.app/"
21
+ Source = "https://github.com/jasonfinestone/runspec/tree/main/packages/python/runspec-linux"
22
+ Changelog = "https://github.com/jasonfinestone/runspec/blob/main/packages/python/runspec-linux/CHANGELOG.md"
23
+ Issues = "https://github.com/jasonfinestone/runspec/issues"
24
+
17
25
  [project.scripts]
18
26
  system-info = "runspec_linux.system_info:main_system_info"
19
27
  disk-usage = "runspec_linux.system_info:main_disk_usage"
@@ -57,6 +65,7 @@ enable-passwordless-sudo = "runspec_linux.sudoers:main_enable_passwordless_sudo"
57
65
  create-venv = "runspec_linux.venvs:main_create_venv"
58
66
  install-into-venv = "runspec_linux.venvs:main_install_into_venv"
59
67
  configure-pip = "runspec_linux.venvs:main_configure_pip"
68
+ share-venv-logs = "runspec_linux.venvs:main_share_venv_logs"
60
69
  nc-command = "runspec_linux.nc_command:main"
61
70
  which = "runspec_linux.commands:main_which"
62
71
  # Cron / crontab management (backed by runspec-linux-core)
@@ -805,6 +805,42 @@ options = ["sudo", "su"]
805
805
  default = "sudo"
806
806
  description = "How to escalate to run-as: sudo (passwordless, -n) or su"
807
807
 
808
+ [share-venv-logs]
809
+ serve = ["local"]
810
+ description = "Make an existing venv's logs/ dir shared (2775 + setgid, optional chgrp) so the per-venv runs DB and audit logs are writable across a console group — the repair for a venv not built with create-venv --group"
811
+ autonomy = "confirm"
812
+ output = "json"
813
+
814
+ examples = [
815
+ {cmd = "share-venv-logs --venv /opt/venvs/app", description = "Make /opt/venvs/app/logs group-writable + setgid (keeps its current group)"},
816
+ {cmd = "share-venv-logs --venv /opt/venvs/app --group consoles", description = "...and chgrp the logs dir to the shared 'consoles' group"},
817
+ {cmd = "share-venv-logs --venv /opt/venvs/app --group consoles --run-as svc", description = "Run as the service account that owns the venv (via sudo -n -u)"},
818
+ ]
819
+
820
+ [share-venv-logs.args.venv]
821
+ type = "path"
822
+ ui = "directory"
823
+ short = "-v"
824
+ description = "Path to the existing venv whose logs/ dir should be made shared"
825
+
826
+ [share-venv-logs.args.group]
827
+ type = "str"
828
+ short = "-g"
829
+ description = "Optional shared group to chgrp the logs/ dir to (e.g. consoles), so every connected console can read/write. Omit to keep the current group"
830
+ required = false
831
+
832
+ [share-venv-logs.args.run-as]
833
+ type = "str"
834
+ short = "-u"
835
+ description = "Service account that owns the venv (escalates via sudo/su); empty = the SSH login user"
836
+ required = false
837
+
838
+ [share-venv-logs.args.become-method]
839
+ type = "choice"
840
+ options = ["sudo", "su"]
841
+ default = "sudo"
842
+ description = "How to escalate to run-as: sudo (passwordless, -n) or su"
843
+
808
844
  # ── Web / TLS probes (runspec-webops-core; cross-platform, read-only) ──────────
809
845
 
810
846
  [cert-check]
@@ -2,7 +2,7 @@ import json
2
2
  import sys
3
3
 
4
4
  import runspec as rs
5
- from runspec_linux_core import configure_pip, create_venv, install_into_venv
5
+ from runspec_linux_core import configure_pip, create_venv, install_into_venv, share_venv_logs
6
6
  from runspec_linux_core.errors import CommandError
7
7
 
8
8
 
@@ -54,6 +54,25 @@ def main_install_into_venv() -> None:
54
54
  sys.exit(1)
55
55
 
56
56
 
57
+ def main_share_venv_logs() -> None:
58
+ spec = rs.parse("share-venv-logs")
59
+ try:
60
+ result = share_venv_logs(
61
+ str(spec.venv.value),
62
+ group=spec.group.value or None,
63
+ run_as=spec.run_as.value or None,
64
+ become_method=spec.become_method.value,
65
+ )
66
+ print(json.dumps(result))
67
+ except CommandError as e:
68
+ print(json.dumps({"venv": str(spec.venv.value), "shared": False, "error": str(e)}))
69
+ sys.exit(1)
70
+ except Exception as e:
71
+ # Includes ValueError (bad venv path / group name).
72
+ print(json.dumps({"error": str(e)}))
73
+ sys.exit(1)
74
+
75
+
57
76
  def main_configure_pip() -> None:
58
77
  spec = rs.parse("configure-pip")
59
78
  try:
@@ -1,13 +0,0 @@
1
- Metadata-Version: 2.5
2
- Name: runspec-linux
3
- Version: 0.13.2
4
- Summary: Linux system admin runnables for runspec
5
- Requires-Python: >=3.10
6
- Requires-Dist: runspec-fs-core>=0.3.0
7
- Requires-Dist: runspec-linux-core>=0.6.2
8
- Requires-Dist: runspec-webops-core>=0.3.0
9
- Requires-Dist: runspec>=0.50.1
10
- Provides-Extra: dev
11
- Requires-Dist: mypy; extra == 'dev'
12
- Requires-Dist: pytest>=8.0; extra == 'dev'
13
- Requires-Dist: ruff==0.15.20; extra == 'dev'