signalk-container 1.18.0 → 1.19.1
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.
- package/README.md +87 -1
- package/dist/containers.d.ts +61 -0
- package/dist/containers.d.ts.map +1 -1
- package/dist/containers.js +159 -5
- package/dist/containers.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -11
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts.map +1 -1
- package/dist/jobs.js +6 -0
- package/dist/jobs.js.map +1 -1
- package/dist/types.d.ts +64 -0
- package/dist/types.d.ts.map +1 -1
- package/doc/plugin-developer-guide.md +22 -1
- package/package.json +1 -1
- package/public/chunks/_virtual_mf-localSharedImportMap___mfe_internal__signalk_container-B0qftSeN.js +1 -0
- package/public/chunks/hostInit-Co9yD_J1.js +1 -0
- package/public/chunks/{virtualExposes-BvqLyGjU.js → virtualExposes-B__J5cSP.js} +1 -1
- package/public/chunks/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__signalk_container__remoteEntry_js-D6gSy08Y.js +4 -0
- package/public/chunks/{virtual_mf-exposes-ssr___mfe_internal__signalk_container__remoteEntry_js-BM72a-CN.js → virtual_mf-exposes-ssr___mfe_internal__signalk_container__remoteEntry_js-eOfXLU2V.js} +1 -1
- package/public/chunks/vite-preload-helper-L5lOfJxi.js +1 -0
- package/public/configpanel-entry.js +1 -1
- package/public/remoteEntry.js +1 -1
- package/public/remoteEntry.ssr.js +1 -1
- package/public/chunks/_virtual_mf-localSharedImportMap___mfe_internal__signalk_container-BEsDhqjG.js +0 -1
- package/public/chunks/dist-B5XYILWI.js +0 -4
- package/public/chunks/hostInit-B3-ZMCBI.js +0 -1
- package/public/chunks/vite-preload-helper-2rxlSZO5.js +0 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Instead of each plugin implementing its own container orchestration, they delega
|
|
|
14
14
|
- **Update detection** -- centralized "is there a newer image?" service for all consumer plugins. Auto-detects semver vs floating tags (`:latest`, `:main`), offline-tolerant with persistent cache, emits Signal K notifications, visible inline in the config panel. See the [developer guide](doc/plugin-developer-guide.md#update-detection).
|
|
15
15
|
- **Resource limits editor** -- interactive UI in the config panel for setting CPU/memory/PID caps per container. Values are applied live via `podman update` when possible (no downtime), falls back to recreate when needed. Stored overrides are minimized against the consumer plugin's defaults so a future default bump flows through automatically. See the [developer guide](doc/plugin-developer-guide.md#resource-limits).
|
|
16
16
|
- **Reset to plugin default** -- one-click restore of a container's original resource limits, clearing any user override.
|
|
17
|
-
- **Per-process ulimits** -- `ContainerConfig.ulimits` pins per-process limits (`nofile`, `nproc`, …) on a container. A containerized process inherits these from the runtime, not the host sysctl, so raising the host `fs.file-max` alone does not lift a database's open-files limit; setting `ulimits` does. See the [developer guide](doc/plugin-developer-guide.md#per-process-ulimits-nofile-).
|
|
17
|
+
- **Per-process ulimits** -- `ContainerConfig.ulimits` pins per-process limits (`nofile`, `nproc`, …) on a container. A containerized process inherits these from the runtime, not the host sysctl, so raising the host `fs.file-max` alone does not lift a database's open-files limit; setting `ulimits` does. A `nofile` request over the host ceiling is clamped (not rejected) so the container still starts. See the [developer guide](doc/plugin-developer-guide.md#per-process-ulimits-nofile-) and, for raising the host limit, [Raising the open-files limit](#raising-the-open-files-limit-nofile).
|
|
18
18
|
- **Image management** -- scheduled pruning of dangling images (weekly/monthly)
|
|
19
19
|
- **Zero-config data dir sharing** -- `signalkDataMount` mounts the SignalK data directory into any managed container automatically, whether Signal K runs bare-metal, in Docker (named volume), or in Podman (named volume or bind mount). No host paths to configure.
|
|
20
20
|
- **Zero-config config root sharing** -- `signalkConfigRootMount` mounts the entire SignalK installation config (`~/.signalk/`) — for backup, audit, or config-sync tools that need the whole tree, not the per-plugin subdirectory.
|
|
@@ -23,6 +23,7 @@ Instead of each plugin implementing its own container orchestration, they delega
|
|
|
23
23
|
- **Per-volume host-source policy** -- volumes accept `{ source, ifMissing: "skip" | "abort" }` for user-managed (USB drives, NFS) or deployment-required (TLS certs) mounts. Plugins subscribe to `onVolumeIssue` events for `'skipped'`, `'aborted'`, and `'recovered'` actions; signalk-container auto-recreates the container when a previously-missing source reappears. See the [developer guide](doc/plugin-developer-guide.md#optional-and-required-volumes).
|
|
24
24
|
- **Container log streaming** -- click **Logs** on any managed-container card to open a live-streaming popup of the container's stdout+stderr (combined, the same shape `podman logs <name>` produces). Plugin authors can also wire `onContainerLog` in `ensureRunning` options to forward the same stream into their plugin's `app.debug` channel — visible in the Signal K server log when debug is enabled. Multiple subscribers share a single underlying log stream. See the [developer guide](doc/plugin-developer-guide.md#streaming-container-logs-into-your-plugins-debug-channel).
|
|
25
25
|
- **Host-UID ownership alignment** -- managed containers run by default under the Signal K host user's UID/GID (via `--user host:host` on Docker/rootful Podman, `--userns=keep-id` on rootless Podman). Files created on bind mounts are owned by the same identity that runs Signal K, with no `chmod` sweeps. Override per container via `ContainerConfig.user` for images with a non-root `USER` directive, or `user: false` to opt out. See the [developer guide](doc/plugin-developer-guide.md#host-uid-ownership).
|
|
26
|
+
- **Data-directory teardown** -- `containers.removeManagedData(name, hostPath)` removes a managed container _and_ deletes its bind-mount data, even on rootless Podman where a container process running as a non-root in-container UID writes files owned by a host **subuid** the Signal K user can't `rm`. The host-side delete is tried first (docker / rootful); on EACCES it falls back to an in-userns wipe using the container's own image (no extra pull). Use it for plugin uninstall cleanup. See the [developer guide](doc/plugin-developer-guide.md#removemanageddataname-hostpath-options-promisevoid).
|
|
26
27
|
- **Image compliance probes** -- `containers.doctor.imageRunsAsUser(image, user?)` runs the image under the live UID mapping and verifies it can write `/tmp` as the host caller. Surfaces UID-compatibility problems _before_ a container wedges in a restart loop. See the [developer guide](doc/plugin-developer-guide.md#containersdoctorimagerunsasuserimage-user-promiseimageproberesult).
|
|
27
28
|
- **Podman image qualification** -- automatically prefixes `docker.io/` for short image names
|
|
28
29
|
- **Docker `host.containers.internal` parity** -- signalk-container adds the `host-gateway` mapping for Docker automatically (Podman has it natively). User-supplied `extraHosts` overrides are respected.
|
|
@@ -272,6 +273,91 @@ The deployment doctor at `/api/doctor/deployment` also detects this
|
|
|
272
273
|
scenario and surfaces the same kernel-cmdline fix in its `remediation`
|
|
273
274
|
array, so you don't have to guess which layer is broken first.
|
|
274
275
|
|
|
276
|
+
### Raising the open-files limit (`nofile`)
|
|
277
|
+
|
|
278
|
+
Some managed containers ask for a high per-process open-files limit
|
|
279
|
+
(`RLIMIT_NOFILE`). QuestDB is the common case — it recommends
|
|
280
|
+
`nofile=1048576` and otherwise logs an open-files warning and risks WAL
|
|
281
|
+
corruption under heavy ingestion.
|
|
282
|
+
|
|
283
|
+
A containerized process inherits `nofile` from the **container runtime**,
|
|
284
|
+
not from the host's `fs.file-max` sysctl — so raising `fs.file-max` does
|
|
285
|
+
**not** help here. And under **rootless Podman** a container can never
|
|
286
|
+
raise its hard limit above the limit of the user that runs the runtime.
|
|
287
|
+
When a plugin requests more than the host allows, signalk-container clamps
|
|
288
|
+
the request to the host ceiling so the container still starts (you'll see
|
|
289
|
+
an advisory in the requesting plugin's config panel, e.g. QuestDB's
|
|
290
|
+
"open-files limit capped by the host"). To grant the full value, raise the
|
|
291
|
+
host limit.
|
|
292
|
+
|
|
293
|
+
**Check the limit the container actually got:**
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# podman, or `docker exec` on Docker
|
|
297
|
+
podman exec <sk-container> cat /proc/1/limits | grep -i "open files"
|
|
298
|
+
# Max open files 524288 524288 ← the per-process cap in effect
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**Rootless Podman** runs under the systemd user session, so the lever is the
|
|
302
|
+
user manager's open-files limit, which a rootless container can never exceed.
|
|
303
|
+
There are two places to set it; on stock Debian / Raspberry Pi OS you usually
|
|
304
|
+
need the **second**. Editing `/etc/security/limits.conf` does **not** help —
|
|
305
|
+
`pam_limits` only touches login shells, not the user manager that parents the
|
|
306
|
+
podman socket. `LimitNOFILE` takes a `soft:hard` form; a single number sets
|
|
307
|
+
soft = hard, and the container's hard ceiling is the user manager's _hard_
|
|
308
|
+
limit.
|
|
309
|
+
|
|
310
|
+
**1. Per-user-manager drop-in.** One-time, requires sudo:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
sudo mkdir -p /etc/systemd/system/user@.service.d
|
|
314
|
+
sudo tee /etc/systemd/system/user@.service.d/nofile.conf <<'EOF'
|
|
315
|
+
[Service]
|
|
316
|
+
LimitNOFILE=1048576
|
|
317
|
+
EOF
|
|
318
|
+
sudo systemctl daemon-reload
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
The new limit only applies once the **user manager itself restarts** — and
|
|
322
|
+
`daemon-reload` does **not** restart an already-running `user@<uid>.service`.
|
|
323
|
+
On a headless boat the SK user has linger enabled (`loginctl enable-linger`),
|
|
324
|
+
so logging out and back in does not tear it down. Force a fresh user manager,
|
|
325
|
+
then restart the container:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
sudo systemctl restart user@$(id -u <sk-user>).service # or just reboot
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**2. System-wide default (Raspberry Pi OS / openplotter, and the reliable
|
|
332
|
+
fallback).** Stock Debian / Pi OS ships `/etc/systemd/system.conf` with a
|
|
333
|
+
commented `#DefaultLimitNOFILE=1024:524288` — that 524288 _hard_ default is
|
|
334
|
+
what bounds the per-unit request when step 1 doesn't take. Raise the system
|
|
335
|
+
(PID 1) manager's default directly:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
sudo sed -i 's/^#\?DefaultLimitNOFILE=.*/DefaultLimitNOFILE=1048576:1048576/' /etc/systemd/system.conf
|
|
339
|
+
sudo systemctl daemon-reexec # NOT daemon-reload — manager-global defaults
|
|
340
|
+
# are only re-read when PID 1 re-executes itself
|
|
341
|
+
sudo reboot # respawns the lingering user@.service + podman
|
|
342
|
+
# under the raised default
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Rootful Podman / Docker** read the limit from the daemon's own service.
|
|
346
|
+
For Docker, set `LimitNOFILE=1048576` in a `docker.service` drop-in
|
|
347
|
+
(`/etc/systemd/system/docker.service.d/nofile.conf`), `daemon-reload`, and
|
|
348
|
+
restart the daemon.
|
|
349
|
+
|
|
350
|
+
The value cannot exceed the kernel's absolute per-process cap, `fs.nr_open`
|
|
351
|
+
(`cat /proc/sys/fs/nr_open` — typically ~1 billion, so not a practical limit).
|
|
352
|
+
Verify (either path):
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
systemctl show user@$(id -u <sk-user>).service -p LimitNOFILE
|
|
356
|
+
# LimitNOFILE=1048576 ← the user manager now allows it
|
|
357
|
+
<runtime> exec <sk-container> cat /proc/1/limits | grep -i "open files"
|
|
358
|
+
# Max open files 1048576 1048576 ← the container actually got it
|
|
359
|
+
```
|
|
360
|
+
|
|
275
361
|
### Watch out for systemd auto-restart (Quadlet / `Restart=always`)
|
|
276
362
|
|
|
277
363
|
If you run Signal K via a podman Quadlet (`*.container` in
|
package/dist/containers.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type Docker from "dockerode";
|
|
|
2
2
|
import { ContainerConfig, ContainerInfo, ContainerRuntimeInfo, ContainerState, EnsureRunningOptions, UlimitClamp, VolumeIssue, VolumeSpec } from "./types.js";
|
|
3
3
|
import { StreamingProcessHandle } from "./runtime.js";
|
|
4
4
|
import { type ContainerClient } from "./client.js";
|
|
5
|
+
import type { ErrorKind } from "./errors.js";
|
|
5
6
|
/**
|
|
6
7
|
* Build the value for a `-v <source>:<dest>[:flags]` argument with the
|
|
7
8
|
* correct SELinux relabel suffix for the runtime.
|
|
@@ -464,6 +465,66 @@ prior?: ContainerConfig, _postRecreate?: boolean, _pull?: PullFn): Promise<void>
|
|
|
464
465
|
export declare function startContainer(runtime: ContainerRuntimeInfo, name: string, client?: ContainerClient): Promise<void>;
|
|
465
466
|
export declare function stopContainer(runtime: ContainerRuntimeInfo, name: string, client?: ContainerClient): Promise<void>;
|
|
466
467
|
export declare function removeContainer(runtime: ContainerRuntimeInfo, name: string, client?: ContainerClient): Promise<void>;
|
|
468
|
+
/**
|
|
469
|
+
* Thrown by `removeContainer` when the runtime refuses to remove a container.
|
|
470
|
+
* Carries the classified `kind` so callers can distinguish a `permission`
|
|
471
|
+
* failure (a rootless container wedged unkillable in `Stopping`) — where
|
|
472
|
+
* keeping a healthy existing container beats failing startup — from other
|
|
473
|
+
* removal failures that should propagate.
|
|
474
|
+
*/
|
|
475
|
+
export declare class ContainerRemovalError extends Error {
|
|
476
|
+
readonly kind: ErrorKind;
|
|
477
|
+
constructor(message: string, kind: ErrorKind);
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Reject host paths that must never be recursively wiped. The guard is the
|
|
481
|
+
* cheap, always-correct floor (empty / `/` / a non-absolute path); the
|
|
482
|
+
* caller layers any deployment-specific "must be under the Signal K tree"
|
|
483
|
+
* check on top, where it has the data/config roots to compare against.
|
|
484
|
+
*/
|
|
485
|
+
export declare function assertWipablePath(hostPath: string): void;
|
|
486
|
+
/**
|
|
487
|
+
* Result of one wipe-job run, mirroring the bits of `ContainerJobResult`
|
|
488
|
+
* that `removeManagedData` reasons about. Keeps `containers.ts` free of a
|
|
489
|
+
* `jobs.ts` import (jobs.ts already imports from here — the cycle would be
|
|
490
|
+
* real) while staying fully testable via an injected runner.
|
|
491
|
+
*/
|
|
492
|
+
export interface WipeJobOutcome {
|
|
493
|
+
ok: boolean;
|
|
494
|
+
error?: string;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Delete a managed container's bind-mount data, working around the
|
|
498
|
+
* rootless-Podman subuid-ownership trap.
|
|
499
|
+
*
|
|
500
|
+
* Sequence:
|
|
501
|
+
* 1. Remove the container `name` (idempotent — a missing container is fine)
|
|
502
|
+
* so nothing holds the mount.
|
|
503
|
+
* 2. Try a direct host-side `fs.rm(hostPath, {recursive, force})`. On
|
|
504
|
+
* docker / rootful Podman the files are host-owned and this succeeds.
|
|
505
|
+
* 3. On EACCES/EPERM (the rootless-Podman case — files are owned by a
|
|
506
|
+
* subuid the host user can't touch) run `runWipeJob`: a one-shot helper
|
|
507
|
+
* that bind-mounts `hostPath` and `rm -rf`s its CONTENTS from inside the
|
|
508
|
+
* userns as in-container root, then retry the host-side delete to drop
|
|
509
|
+
* the now-empty host-owned parent dir.
|
|
510
|
+
*
|
|
511
|
+
* `runWipeJob(image, hostPath)` is injected so the runtime logic stays out
|
|
512
|
+
* of the `jobs.ts` import cycle and so unit tests can drive every branch
|
|
513
|
+
* without a real runtime. The wrapper in `index.ts` wires it to `runJob`
|
|
514
|
+
* with the container's own (already-present) image.
|
|
515
|
+
*
|
|
516
|
+
* `wipeImage` is the container's own image, captured from `inspect` BEFORE
|
|
517
|
+
* removal so the helper reuses bits already on disk — no registry pull on a
|
|
518
|
+
* possibly-offline boat. `null` when the container was already gone; the
|
|
519
|
+
* fallback then can't run, so a still-undeletable dir surfaces as an error.
|
|
520
|
+
*/
|
|
521
|
+
export declare function removeManagedData(runtime: ContainerRuntimeInfo, name: string, hostPath: string, runWipeJob: (image: string, hostPath: string) => Promise<WipeJobOutcome>, client?: ContainerClient, onRemoved?: () => void): Promise<void>;
|
|
522
|
+
/**
|
|
523
|
+
* Container path the wipe helper mounts the data directory at — re-exported
|
|
524
|
+
* for the wrapper that builds the `runJob` config and for tests asserting the
|
|
525
|
+
* mount/command shape.
|
|
526
|
+
*/
|
|
527
|
+
export declare const WIPE_MOUNT_PATH = "/sk-wipe-target";
|
|
467
528
|
export declare function listContainers(runtime: ContainerRuntimeInfo, client?: ContainerClient): Promise<ContainerInfo[]>;
|
|
468
529
|
export declare function pruneImages(runtime: ContainerRuntimeInfo, client?: ContainerClient): Promise<{
|
|
469
530
|
imagesRemoved: number;
|
package/dist/containers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containers.d.ts","sourceRoot":"","sources":["../src/containers.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"containers.d.ts","sourceRoot":"","sources":["../src/containers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAGpC,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EAEpB,WAAW,EACX,WAAW,EACX,UAAU,EACX,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EAIvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAML,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAa7C;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,GAAE,OAAe,GACxB,MAAM,CAOR;AAcD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACvC,eAAe,EAAE,MAAM,GAAG,SAAS,GAClC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAIpC;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,GAAG,SAAS,EACxD,KAAK,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAoB,GAC5C;IACD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D,CAuCA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EACD;IACE,OAAO,EAAE,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D,GACD,SAAS,EACb,cAAc,EAAE,KAAK,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAChE,cAAc,EAAE,KAAK,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAChE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,KAAK,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBlD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,EACnE,KAAK,EAAE,WAAW,EAClB,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAClC,IAAI,CAUN;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,EAC7D,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAClC,IAAI,CAON;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,EACnE,KAAK,EAAE,WAAW,EAClB,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAClC,IAAI,CAON;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAC9B,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACvC,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B,GACA,sBAAsB,CAuDxB;AAED,kEAAkE;AAClE,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAe9B;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,MAAM,GACZ;IAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAqB/C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3C,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,MAAM,EAAE,CAAC,CAgCnB;AAiBD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,oBAAoB,GAC5B,MAAM,CAwBR;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,OAAO,CAAC,CAKlB;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,oBAAoB,EAC7B,gBAAgB,EAAE,MAAM,EACxB,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAUD;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAqBlC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAUxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,MAAM,EACrB,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAClC,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,cAAc,CAAC,CA4BzB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,OAAO,YAAY,EAAE,uBAAuB,CAAC,CAwEvD;AAmBD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GACxD,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CA2C5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAOrC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;;;;;;;OAUG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CA0HrC;AA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,oBAAoB,EAC7B,KAAK,CAAC,EAAE,eAAe,GACtB;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAoJvB;AAiGD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,oBAAoB,GAC5B,MAAM,GAAG,IAAI,CAyBf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,EACnC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,EAC7B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GACrD,MAAM,CAAC,MAAM,EAAE,GAAG,SAAS,CAsC7B;AAoKD;;;;;GAKG;AACH,KAAK,MAAM,GAAG,CACZ,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,KAC/B,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAE5B,OAAO,CAAC,EAAE,oBAAoB,EAC9B,MAAM,GAAE,eAA6B;AACrC;;;;;;;GAOG;AACH,KAAK,CAAC,EAAE,eAAe,EACvB,aAAa,GAAE,OAAe,EAC9B,KAAK,GAAE,MAAkB,GACxB,OAAO,CAAC,IAAI,CAAC,CA8Mf;AA6CD,wBAAsB,cAAc,CAClC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAEf;AA2CD,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAG5C,QAAQ,CAAC,IAAI,EAAE,SAAS;gBADxB,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,SAAS;CAK3B;AAqBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAiBxD;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,EACxE,MAAM,GAAE,eAA6B,EAKrC,SAAS,GAAE,MAAM,IAAe,GAC/B,OAAO,CAAC,IAAI,CAAC,CAkDf;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,oBAAa,CAAC;AAE1C,wBAAsB,cAAc,CAClC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,aAAa,EAAE,CAAC,CA8B1B;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,oBAAoB,EAC7B,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CAe5D;AAuCD,wBAAsB,eAAe,CACnC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAE/D;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAW7E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,EAAE,CAQzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA2B5E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iCAAiC,IAAI,MAAM,EAAE,CAQ5D;AA8BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,oBAAoB,EAC7B,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe,EACvC,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsDxB;AAuBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,EAC7B,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe,EACvC,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,MAAM,CAAC,CA2DjB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,cAAc,EAAE,GACvB,wBAAwB,GAAG,IAAI,CAgCjC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,EAC7B,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe,EACvC,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAgC1C;AAcD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEtD;AAeD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1E;AASD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEvE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,oBAAoB,EAC7B,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAe,EACvC,MAAM,GAAE,eAA6B,GACpC,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAiC1B;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,MAAc,EACzB,UAAU,GAAE,MAAY,GACvB,OAAO,CAAC,IAAI,CAAC,CAYf"}
|
package/dist/containers.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as net from "node:net";
|
|
2
|
+
import * as path from "node:path";
|
|
2
3
|
import { PassThrough } from "node:stream";
|
|
3
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import { rm } from "node:fs/promises";
|
|
4
6
|
import { isContainerized, makeLineSplitter, userMappingFlags, } from "./runtime.js";
|
|
5
7
|
import { demuxToText, demuxBufferToText, getClient, safe, safeInspect, } from "./client.js";
|
|
6
8
|
import { resourcePayloadForRun } from "./resources.js";
|
|
@@ -1492,7 +1494,29 @@ prior, _postRecreate = false, _pull = pullImage) {
|
|
|
1492
1494
|
if (drifted.length === 0)
|
|
1493
1495
|
return false;
|
|
1494
1496
|
debug(`Container ${fullName} config drift detected (${drifted.join(", ")}); recreating`);
|
|
1495
|
-
|
|
1497
|
+
return recreateUnlessWedged(drifted.join(", "));
|
|
1498
|
+
};
|
|
1499
|
+
// Remove + recreate the container to apply a detected drift — but if removal
|
|
1500
|
+
// fails because the container is wedged unkillable in `Stopping` (the
|
|
1501
|
+
// rootless "sending SIGKILL … operation not permitted" condition) AND it is
|
|
1502
|
+
// still running, keep it and defer the recreate to the next start rather than
|
|
1503
|
+
// failing startup. Returns true if recreated, false if deferred. Shared by
|
|
1504
|
+
// the config-drift and digest-drift paths so both survive the wedge.
|
|
1505
|
+
const recreateUnlessWedged = async (driftDesc) => {
|
|
1506
|
+
try {
|
|
1507
|
+
await removeContainer(runtime, name, client);
|
|
1508
|
+
}
|
|
1509
|
+
catch (err) {
|
|
1510
|
+
if (err instanceof ContainerRemovalError &&
|
|
1511
|
+
err.kind === "permission" &&
|
|
1512
|
+
(await getContainerState(runtime, name, client)) === "running") {
|
|
1513
|
+
debug(`Container ${fullName} could not be removed to apply drift ` +
|
|
1514
|
+
`(${driftDesc}) — it is still running; keeping it and deferring ` +
|
|
1515
|
+
`the recreate. ${err.message}`);
|
|
1516
|
+
return false;
|
|
1517
|
+
}
|
|
1518
|
+
throw err;
|
|
1519
|
+
}
|
|
1496
1520
|
await ensureRunning(runtime, name, config, debug, options, client, prior, true, _pull);
|
|
1497
1521
|
return true;
|
|
1498
1522
|
};
|
|
@@ -1533,9 +1557,7 @@ prior, _postRecreate = false, _pull = pullImage) {
|
|
|
1533
1557
|
return false;
|
|
1534
1558
|
}
|
|
1535
1559
|
debug(`Container ${fullName} floating-tag digest drift detected (${liveId.slice(0, 19)}… → ${remoteId.slice(0, 19)}…); recreating`);
|
|
1536
|
-
|
|
1537
|
-
await ensureRunning(runtime, name, config, debug, options, client, prior, true, _pull);
|
|
1538
|
-
return true;
|
|
1560
|
+
return recreateUnlessWedged(`digest ${liveId.slice(0, 19)}… → ${remoteId.slice(0, 19)}…`);
|
|
1539
1561
|
};
|
|
1540
1562
|
switch (state) {
|
|
1541
1563
|
case "running": {
|
|
@@ -1700,9 +1722,141 @@ export async function removeContainer(runtime, name, client = getClient()) {
|
|
|
1700
1722
|
const result = await safe(() => client.getContainer(fullName).remove({ force: true }));
|
|
1701
1723
|
// 404 = already gone; that's success for a remove.
|
|
1702
1724
|
if (!result.ok && result.error.kind !== "not-found") {
|
|
1703
|
-
|
|
1725
|
+
// Surface the raw runtime error, not just the generic userMessage — a
|
|
1726
|
+
// hidden raw (e.g. podman's "sending SIGKILL … operation not permitted"
|
|
1727
|
+
// when a rootless container wedges in `Stopping`) is undiagnosable from
|
|
1728
|
+
// the report. Carry the kind so callers can react to a permission/wedge
|
|
1729
|
+
// failure (keep a healthy container running) vs hard-fail.
|
|
1730
|
+
throw new ContainerRemovalError(`Failed to remove ${fullName}: ${result.error.userMessage} (${result.error.raw})`, result.error.kind);
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
/**
|
|
1734
|
+
* Thrown by `removeContainer` when the runtime refuses to remove a container.
|
|
1735
|
+
* Carries the classified `kind` so callers can distinguish a `permission`
|
|
1736
|
+
* failure (a rootless container wedged unkillable in `Stopping`) — where
|
|
1737
|
+
* keeping a healthy existing container beats failing startup — from other
|
|
1738
|
+
* removal failures that should propagate.
|
|
1739
|
+
*/
|
|
1740
|
+
export class ContainerRemovalError extends Error {
|
|
1741
|
+
kind;
|
|
1742
|
+
constructor(message, kind) {
|
|
1743
|
+
super(message);
|
|
1744
|
+
this.kind = kind;
|
|
1745
|
+
this.name = "ContainerRemovalError";
|
|
1704
1746
|
}
|
|
1705
1747
|
}
|
|
1748
|
+
/**
|
|
1749
|
+
* Container path the wipe helper mounts the data directory at. Arbitrary —
|
|
1750
|
+
* the only requirement is that it not collide with image-baked paths the
|
|
1751
|
+
* helper's `rm` might depend on; a dedicated top-level dir avoids that.
|
|
1752
|
+
*/
|
|
1753
|
+
const WIPE_MOUNT = "/sk-wipe-target";
|
|
1754
|
+
/** Posix error codes that signal "the host user can't delete this" and so
|
|
1755
|
+
* warrant the in-userns fallback rather than a hard failure. */
|
|
1756
|
+
const OWNERSHIP_ERROR_CODES = new Set(["EACCES", "EPERM"]);
|
|
1757
|
+
/** True for the EACCES/EPERM ownership errors that the in-userns wipe can fix.
|
|
1758
|
+
* Anything else (ENOENT, ENOTEMPTY from a live mount, …) is not an ownership
|
|
1759
|
+
* problem and should surface unchanged. */
|
|
1760
|
+
function isOwnershipError(err) {
|
|
1761
|
+
const code = err?.code;
|
|
1762
|
+
return code !== undefined && OWNERSHIP_ERROR_CODES.has(code);
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* Reject host paths that must never be recursively wiped. The guard is the
|
|
1766
|
+
* cheap, always-correct floor (empty / `/` / a non-absolute path); the
|
|
1767
|
+
* caller layers any deployment-specific "must be under the Signal K tree"
|
|
1768
|
+
* check on top, where it has the data/config roots to compare against.
|
|
1769
|
+
*/
|
|
1770
|
+
export function assertWipablePath(hostPath) {
|
|
1771
|
+
// Require an absolute path: a relative value would `path.resolve` to a
|
|
1772
|
+
// cwd-relative dir and quietly pass the root check, risking an rm -rf of
|
|
1773
|
+
// the wrong tree. The data/config sources signalk-container deals with are
|
|
1774
|
+
// always absolute, so reject anything else outright. Normalize first so a
|
|
1775
|
+
// root-equivalent like `/..` collapses to the root and is rejected too.
|
|
1776
|
+
const normalized = path.normalize(hostPath || "");
|
|
1777
|
+
if (!hostPath ||
|
|
1778
|
+
hostPath.trim() === "" ||
|
|
1779
|
+
!path.isAbsolute(hostPath) ||
|
|
1780
|
+
normalized === path.parse(normalized).root) {
|
|
1781
|
+
throw new Error(`removeManagedData: refusing to delete unsafe path ${JSON.stringify(hostPath)}`);
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
/**
|
|
1785
|
+
* Delete a managed container's bind-mount data, working around the
|
|
1786
|
+
* rootless-Podman subuid-ownership trap.
|
|
1787
|
+
*
|
|
1788
|
+
* Sequence:
|
|
1789
|
+
* 1. Remove the container `name` (idempotent — a missing container is fine)
|
|
1790
|
+
* so nothing holds the mount.
|
|
1791
|
+
* 2. Try a direct host-side `fs.rm(hostPath, {recursive, force})`. On
|
|
1792
|
+
* docker / rootful Podman the files are host-owned and this succeeds.
|
|
1793
|
+
* 3. On EACCES/EPERM (the rootless-Podman case — files are owned by a
|
|
1794
|
+
* subuid the host user can't touch) run `runWipeJob`: a one-shot helper
|
|
1795
|
+
* that bind-mounts `hostPath` and `rm -rf`s its CONTENTS from inside the
|
|
1796
|
+
* userns as in-container root, then retry the host-side delete to drop
|
|
1797
|
+
* the now-empty host-owned parent dir.
|
|
1798
|
+
*
|
|
1799
|
+
* `runWipeJob(image, hostPath)` is injected so the runtime logic stays out
|
|
1800
|
+
* of the `jobs.ts` import cycle and so unit tests can drive every branch
|
|
1801
|
+
* without a real runtime. The wrapper in `index.ts` wires it to `runJob`
|
|
1802
|
+
* with the container's own (already-present) image.
|
|
1803
|
+
*
|
|
1804
|
+
* `wipeImage` is the container's own image, captured from `inspect` BEFORE
|
|
1805
|
+
* removal so the helper reuses bits already on disk — no registry pull on a
|
|
1806
|
+
* possibly-offline boat. `null` when the container was already gone; the
|
|
1807
|
+
* fallback then can't run, so a still-undeletable dir surfaces as an error.
|
|
1808
|
+
*/
|
|
1809
|
+
export async function removeManagedData(runtime, name, hostPath, runWipeJob, client = getClient(),
|
|
1810
|
+
// Invoked exactly once, the instant the container is removed (before the data
|
|
1811
|
+
// delete). Lets the caller tear down container-scoped state (ports, log
|
|
1812
|
+
// broker) only when removal actually happened — not on a pre-removal failure
|
|
1813
|
+
// such as a non-404 inspect error, when the container is still running.
|
|
1814
|
+
onRemoved = () => { }) {
|
|
1815
|
+
assertWipablePath(hostPath);
|
|
1816
|
+
// Capture the image before removal so the in-userns fallback can reuse it
|
|
1817
|
+
// (guaranteed present locally — the container was just running it).
|
|
1818
|
+
const fullName = prefixedName(name);
|
|
1819
|
+
const info = await safeInspect(() => client.getContainer(fullName).inspect());
|
|
1820
|
+
const wipeImage = typeof info?.Config?.Image === "string" ? info.Config.Image : null;
|
|
1821
|
+
await removeContainer(runtime, name, client);
|
|
1822
|
+
onRemoved();
|
|
1823
|
+
// Docker / rootful Podman: bind-mount files are host-owned, plain rm works.
|
|
1824
|
+
try {
|
|
1825
|
+
await rm(hostPath, { recursive: true, force: true });
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1828
|
+
catch (err) {
|
|
1829
|
+
if (!isOwnershipError(err))
|
|
1830
|
+
throw err;
|
|
1831
|
+
}
|
|
1832
|
+
// Rootless-Podman subuid case: the host user can't delete subuid-owned
|
|
1833
|
+
// files. Wipe the dir contents from inside the userns (as in-container
|
|
1834
|
+
// root, which owns them) using the container's own image, then retry the
|
|
1835
|
+
// host-side delete to drop the now-empty host-owned parent.
|
|
1836
|
+
if (!wipeImage) {
|
|
1837
|
+
throw new Error(`removeManagedData: ${hostPath} is not deletable by the Signal K user ` +
|
|
1838
|
+
`and the container's image is unknown (it was already removed), so the ` +
|
|
1839
|
+
`in-userns cleanup helper cannot run. Delete ${hostPath} manually.`);
|
|
1840
|
+
}
|
|
1841
|
+
const wipe = await runWipeJob(wipeImage, hostPath);
|
|
1842
|
+
if (!wipe.ok) {
|
|
1843
|
+
throw new Error(`removeManagedData: in-userns wipe of ${hostPath} failed: ${wipe.error ?? "unknown error"}`);
|
|
1844
|
+
}
|
|
1845
|
+
try {
|
|
1846
|
+
await rm(hostPath, { recursive: true, force: true });
|
|
1847
|
+
}
|
|
1848
|
+
catch (err) {
|
|
1849
|
+
const code = err.code ?? "unknown";
|
|
1850
|
+
throw new Error(`removeManagedData: ${hostPath} still not removable after in-userns wipe (${code}). ` +
|
|
1851
|
+
`Delete it manually.`, { cause: err });
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
/**
|
|
1855
|
+
* Container path the wipe helper mounts the data directory at — re-exported
|
|
1856
|
+
* for the wrapper that builds the `runJob` config and for tests asserting the
|
|
1857
|
+
* mount/command shape.
|
|
1858
|
+
*/
|
|
1859
|
+
export const WIPE_MOUNT_PATH = WIPE_MOUNT;
|
|
1706
1860
|
export async function listContainers(runtime, client = getClient()) {
|
|
1707
1861
|
const result = await safe(() => client.listContainers({
|
|
1708
1862
|
all: true,
|