signalk-container 0.1.0

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.
@@ -0,0 +1,2 @@
1
+ dist/
2
+ node_modules/
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dirk Wahrheit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # signalk-container
2
+
3
+ Shared container runtime management (Podman/Docker) for Signal K plugins.
4
+
5
+ Instead of each plugin implementing its own container orchestration, they delegate to this plugin. It detects the available runtime, pulls images, manages container lifecycles, and provides a config panel in the Admin UI.
6
+
7
+ ## Features
8
+
9
+ - **Runtime detection** -- Podman preferred, Docker fallback, podman-shim aware
10
+ - **Container lifecycle** -- pull, create, start, stop, remove with `sk-` prefix naming
11
+ - **One-shot jobs** -- run containers for batch tasks (export, conversion, etc.)
12
+ - **Image management** -- scheduled pruning of dangling images (weekly/monthly)
13
+ - **SELinux support** -- `:Z` volume flags for Podman on Fedora/RHEL
14
+ - **Podman image qualification** -- automatically prefixes `docker.io/` for short image names
15
+ - **Config panel** -- runtime status, managed containers with start/stop/remove controls, prune button
16
+ - **Cross-plugin API** -- other plugins use `globalThis.__signalk_containerManager`
17
+
18
+ ## Config Panel
19
+
20
+ The plugin embeds a React config panel in the Signal K Admin UI (via Module Federation) showing:
21
+
22
+ - Detected runtime with version and status indicator
23
+ - List of managed containers with state (green=running, yellow=stopped)
24
+ - **Start** button for stopped containers
25
+ - **Stop** button for running containers
26
+ - **Remove** button with confirmation dialog when container is running
27
+ - Prune dangling images button
28
+ - Settings for preferred runtime and auto-prune schedule
29
+
30
+ ## How Other Plugins Use It
31
+
32
+ ```typescript
33
+ const containers = (globalThis as any).__signalk_containerManager;
34
+ if (!containers) {
35
+ app.setPluginError("signalk-container plugin required");
36
+ return;
37
+ }
38
+
39
+ // Start a long-running service container
40
+ await containers.ensureRunning("my-service", {
41
+ image: "myorg/myimage",
42
+ tag: "latest",
43
+ ports: { "8080/tcp": "127.0.0.1:8080" },
44
+ volumes: { "/data": app.getDataDirPath() },
45
+ env: { MY_VAR: "value" },
46
+ restart: "unless-stopped",
47
+ });
48
+
49
+ // Run a one-shot job
50
+ const result = await containers.runJob({
51
+ image: "myorg/converter",
52
+ command: ["convert", "--input", "/in/data.csv"],
53
+ inputs: { "/in": "/host/path/input" },
54
+ outputs: { "/out": "/host/path/output" },
55
+ timeout: 120,
56
+ });
57
+ ```
58
+
59
+ See [doc/plugin-developer-guide.md](doc/plugin-developer-guide.md) for the full integration guide with gotchas and patterns.
60
+
61
+ ## API
62
+
63
+ | Method | Description |
64
+ | --------------------------------------- | ------------------------------------------------------------ |
65
+ | `getRuntime()` | Returns `{ runtime, version, isPodmanDockerShim }` or `null` |
66
+ | `pullImage(image, onProgress?)` | Pull a container image (auto-qualifies for Podman) |
67
+ | `imageExists(image)` | Check if image exists locally |
68
+ | `ensureRunning(name, config, options?)` | Create and start container if not running |
69
+ | `start(name)` | Start a stopped container |
70
+ | `stop(name)` | Stop a running container |
71
+ | `remove(name)` | Stop and remove a container |
72
+ | `getState(name)` | Returns `running`, `stopped`, `missing`, or `no-runtime` |
73
+ | `runJob(config)` | Execute a one-shot container job |
74
+ | `prune()` | Remove dangling images |
75
+ | `listContainers()` | List all `sk-` prefixed containers |
76
+
77
+ ## REST Endpoints
78
+
79
+ All mounted at `/plugins/signalk-container/api/`:
80
+
81
+ | Method | Path | Description |
82
+ | ------ | -------------------------- | --------------------------- |
83
+ | GET | `/runtime` | Detected runtime info |
84
+ | GET | `/containers` | List managed containers |
85
+ | GET | `/containers/:name/state` | Container state |
86
+ | POST | `/containers/:name/start` | Start a stopped container |
87
+ | POST | `/containers/:name/stop` | Stop a running container |
88
+ | POST | `/containers/:name/remove` | Stop and remove a container |
89
+ | POST | `/prune` | Prune dangling images |
90
+
91
+ ## Configuration
92
+
93
+ | Setting | Default | Description |
94
+ | ------------------- | -------- | --------------------------------------- |
95
+ | Preferred runtime | `auto` | Auto-detect, or force `podman`/`docker` |
96
+ | Auto-prune images | `weekly` | `off`, `weekly`, or `monthly` |
97
+ | Max concurrent jobs | `2` | Limit parallel one-shot job executions |
98
+
99
+ ## Requirements
100
+
101
+ - Node.js >= 22
102
+ - Podman or Docker installed on the host
103
+ - Signal K server
104
+
105
+ ## License
106
+
107
+ MIT
@@ -0,0 +1,16 @@
1
+ import { ContainerConfig, ContainerInfo, ContainerRuntimeInfo, ContainerState, HealthCheckOptions } from "./types";
2
+ export declare function qualifyImage(image: string, runtime: ContainerRuntimeInfo): string;
3
+ export declare function imageExists(runtime: ContainerRuntimeInfo, image: string): Promise<boolean>;
4
+ export declare function pullImage(runtime: ContainerRuntimeInfo, image: string, onProgress?: (msg: string) => void): Promise<void>;
5
+ export declare function getContainerState(runtime: ContainerRuntimeInfo, name: string): Promise<ContainerState>;
6
+ export declare function ensureRunning(runtime: ContainerRuntimeInfo, name: string, config: ContainerConfig, debug: (msg: string) => void, options?: HealthCheckOptions): Promise<void>;
7
+ export declare function startContainer(runtime: ContainerRuntimeInfo, name: string): Promise<void>;
8
+ export declare function stopContainer(runtime: ContainerRuntimeInfo, name: string): Promise<void>;
9
+ export declare function removeContainer(runtime: ContainerRuntimeInfo, name: string): Promise<void>;
10
+ export declare function listContainers(runtime: ContainerRuntimeInfo): Promise<ContainerInfo[]>;
11
+ export declare function pruneImages(runtime: ContainerRuntimeInfo): Promise<{
12
+ imagesRemoved: number;
13
+ spaceReclaimed: string;
14
+ }>;
15
+ export declare function waitForReady(url: string, timeoutMs?: number, intervalMs?: number): Promise<void>;
16
+ //# sourceMappingURL=containers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containers.d.ts","sourceRoot":"","sources":["../src/containers.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAWjB,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,oBAAoB,GAC5B,MAAM,CAUR;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACjC,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,CAAC,CAczB;AAgDD,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,kBAAkB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC,CA6B1B;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CAY5D;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,MAAc,EACzB,UAAU,GAAE,MAAY,GACvB,OAAO,CAAC,IAAI,CAAC,CAYf"}
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.qualifyImage = qualifyImage;
4
+ exports.imageExists = imageExists;
5
+ exports.pullImage = pullImage;
6
+ exports.getContainerState = getContainerState;
7
+ exports.ensureRunning = ensureRunning;
8
+ exports.startContainer = startContainer;
9
+ exports.stopContainer = stopContainer;
10
+ exports.removeContainer = removeContainer;
11
+ exports.listContainers = listContainers;
12
+ exports.pruneImages = pruneImages;
13
+ exports.waitForReady = waitForReady;
14
+ const runtime_1 = require("./runtime");
15
+ const CONTAINER_PREFIX = "sk-";
16
+ function prefixedName(name) {
17
+ return name.startsWith(CONTAINER_PREFIX)
18
+ ? name
19
+ : `${CONTAINER_PREFIX}${name}`;
20
+ }
21
+ function qualifyImage(image, runtime) {
22
+ // Podman requires fully qualified image names when unqualified-search
23
+ // registries are not configured. Prefix docker.io/ if missing.
24
+ if (runtime.runtime === "podman") {
25
+ const parts = image.split("/");
26
+ if (parts.length <= 2 && !parts[0].includes(".")) {
27
+ return `docker.io/${image}`;
28
+ }
29
+ }
30
+ return image;
31
+ }
32
+ async function imageExists(runtime, image) {
33
+ const result = await (0, runtime_1.execRuntime)(runtime, ["image", "inspect", image]);
34
+ return result.exitCode === 0;
35
+ }
36
+ async function pullImage(runtime, image, onProgress) {
37
+ const { exitCode, log } = await (0, runtime_1.execRuntimeLong)(runtime, ["pull", image], onProgress, 300000);
38
+ if (exitCode !== 0) {
39
+ throw new Error(`Failed to pull ${image}: ${log.slice(-5).join("\n")}`);
40
+ }
41
+ }
42
+ async function getContainerState(runtime, name) {
43
+ const fullName = prefixedName(name);
44
+ const result = await (0, runtime_1.execRuntime)(runtime, [
45
+ "inspect",
46
+ "--format",
47
+ "{{.State.Status}}",
48
+ fullName,
49
+ ]);
50
+ if (result.exitCode !== 0)
51
+ return "missing";
52
+ const status = result.stdout.toLowerCase();
53
+ if (status === "running")
54
+ return "running";
55
+ return "stopped";
56
+ }
57
+ function buildRunArgs(name, config, runtime) {
58
+ const fullName = prefixedName(name);
59
+ const imageRef = qualifyImage(`${config.image}:${config.tag}`, runtime);
60
+ const args = ["run", "-d", "--name", fullName];
61
+ if (config.restart && config.restart !== "no") {
62
+ args.push("--restart", config.restart);
63
+ }
64
+ if (config.networkMode) {
65
+ args.push("--network", config.networkMode);
66
+ }
67
+ if (config.ports && !config.networkMode) {
68
+ for (const [containerPort, hostBind] of Object.entries(config.ports)) {
69
+ const port = containerPort.replace(/\/tcp$/, "");
70
+ args.push("-p", `${hostBind}:${port}`);
71
+ }
72
+ }
73
+ if (config.volumes) {
74
+ for (const [containerPath, hostPath] of Object.entries(config.volumes)) {
75
+ const suffix = runtime.runtime === "podman" ? ":Z" : "";
76
+ args.push("-v", `${hostPath}:${containerPath}${suffix}`);
77
+ }
78
+ }
79
+ if (config.env) {
80
+ for (const [key, value] of Object.entries(config.env)) {
81
+ args.push("-e", `${key}=${value}`);
82
+ }
83
+ }
84
+ args.push(imageRef);
85
+ if (config.command) {
86
+ args.push(...config.command);
87
+ }
88
+ return args;
89
+ }
90
+ async function ensureRunning(runtime, name, config, debug,
91
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
92
+ options) {
93
+ const state = await getContainerState(runtime, name);
94
+ const fullName = prefixedName(name);
95
+ const imageRef = qualifyImage(`${config.image}:${config.tag}`, runtime);
96
+ switch (state) {
97
+ case "running":
98
+ debug(`Container ${fullName} already running`);
99
+ return;
100
+ case "stopped": {
101
+ debug(`Starting stopped container ${fullName}`);
102
+ const startResult = await (0, runtime_1.execRuntime)(runtime, ["start", fullName]);
103
+ if (startResult.exitCode !== 0) {
104
+ throw new Error(`Failed to start ${fullName}: ${startResult.stderr}`);
105
+ }
106
+ return;
107
+ }
108
+ case "missing": {
109
+ const hasImage = await imageExists(runtime, imageRef);
110
+ if (!hasImage) {
111
+ debug(`Pulling ${imageRef}...`);
112
+ await pullImage(runtime, imageRef, debug);
113
+ }
114
+ debug(`Creating container ${fullName}`);
115
+ const runArgs = buildRunArgs(name, config, runtime);
116
+ const runResult = await (0, runtime_1.execRuntime)(runtime, runArgs);
117
+ if (runResult.exitCode !== 0) {
118
+ throw new Error(`Failed to create ${fullName}: ${runResult.stderr}`);
119
+ }
120
+ return;
121
+ }
122
+ }
123
+ }
124
+ async function startContainer(runtime, name) {
125
+ const fullName = prefixedName(name);
126
+ const result = await (0, runtime_1.execRuntime)(runtime, ["start", fullName]);
127
+ if (result.exitCode !== 0) {
128
+ throw new Error(`Failed to start ${fullName}: ${result.stderr}`);
129
+ }
130
+ }
131
+ async function stopContainer(runtime, name) {
132
+ const fullName = prefixedName(name);
133
+ const result = await (0, runtime_1.execRuntime)(runtime, ["stop", fullName]);
134
+ if (result.exitCode !== 0) {
135
+ const state = await getContainerState(runtime, name);
136
+ if (state !== "stopped" && state !== "missing") {
137
+ throw new Error(`Failed to stop ${fullName}: ${result.stderr}`);
138
+ }
139
+ }
140
+ }
141
+ async function removeContainer(runtime, name) {
142
+ const fullName = prefixedName(name);
143
+ await (0, runtime_1.execRuntime)(runtime, ["stop", fullName]);
144
+ const result = await (0, runtime_1.execRuntime)(runtime, ["rm", "-f", fullName]);
145
+ if (result.exitCode !== 0) {
146
+ throw new Error(`Failed to remove ${fullName}: ${result.stderr}`);
147
+ }
148
+ }
149
+ async function listContainers(runtime) {
150
+ const result = await (0, runtime_1.execRuntime)(runtime, [
151
+ "ps",
152
+ "-a",
153
+ "--filter",
154
+ `name=${CONTAINER_PREFIX}`,
155
+ "--format",
156
+ "{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.CreatedAt}}\t{{.Ports}}",
157
+ ]);
158
+ if (result.exitCode !== 0 || !result.stdout)
159
+ return [];
160
+ return result.stdout
161
+ .split("\n")
162
+ .filter(Boolean)
163
+ .map((line) => {
164
+ const [name, image, status, created, ports] = line.split("\t");
165
+ const state = status.toLowerCase().startsWith("up")
166
+ ? "running"
167
+ : "stopped";
168
+ return {
169
+ name,
170
+ image,
171
+ state,
172
+ created: created || "",
173
+ ports: ports ? ports.split(",").map((p) => p.trim()) : [],
174
+ managedBy: "",
175
+ };
176
+ });
177
+ }
178
+ async function pruneImages(runtime) {
179
+ const result = await (0, runtime_1.execRuntime)(runtime, ["image", "prune", "-f"]);
180
+ if (result.exitCode !== 0) {
181
+ throw new Error(`Prune failed: ${result.stderr}`);
182
+ }
183
+ const lines = result.stdout.split("\n").filter(Boolean);
184
+ const reclaimedMatch = result.stdout.match(/reclaimed\s+([\d.]+\s*\w+)/i);
185
+ return {
186
+ imagesRemoved: lines.filter((l) => l.match(/^[a-f0-9]{12,}/i)).length,
187
+ spaceReclaimed: reclaimedMatch?.[1] ?? "0 B",
188
+ };
189
+ }
190
+ async function waitForReady(url, timeoutMs = 30000, intervalMs = 500) {
191
+ const deadline = Date.now() + timeoutMs;
192
+ while (Date.now() < deadline) {
193
+ try {
194
+ const res = await fetch(url, { signal: AbortSignal.timeout(2000) });
195
+ if (res.ok)
196
+ return;
197
+ }
198
+ catch {
199
+ // not ready yet
200
+ }
201
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
202
+ }
203
+ throw new Error(`Timed out waiting for ${url} to become ready`);
204
+ }
205
+ //# sourceMappingURL=containers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containers.js","sourceRoot":"","sources":["../src/containers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const runtime_1 = require("./runtime");
4
+ const containers_1 = require("./containers");
5
+ const jobs_1 = require("./jobs");
6
+ module.exports = (app) => {
7
+ let runtimeInfo = null;
8
+ let pruneTimer = null;
9
+ const healthTimers = new Map();
10
+ const api = {
11
+ getRuntime() {
12
+ return runtimeInfo;
13
+ },
14
+ async pullImage(image, onProgress) {
15
+ if (!runtimeInfo)
16
+ throw new Error("No container runtime available");
17
+ await (0, containers_1.pullImage)(runtimeInfo, (0, containers_1.qualifyImage)(image, runtimeInfo), onProgress);
18
+ },
19
+ async imageExists(image) {
20
+ if (!runtimeInfo)
21
+ return false;
22
+ return (0, containers_1.imageExists)(runtimeInfo, (0, containers_1.qualifyImage)(image, runtimeInfo));
23
+ },
24
+ async ensureRunning(name, config, options) {
25
+ if (!runtimeInfo)
26
+ throw new Error("No container runtime available");
27
+ await (0, containers_1.ensureRunning)(runtimeInfo, name, config, (msg) => app.debug(msg), options);
28
+ if (options?.healthCheck) {
29
+ const existing = healthTimers.get(name);
30
+ if (existing)
31
+ clearInterval(existing);
32
+ const timer = setInterval(async () => {
33
+ try {
34
+ const ok = await options.healthCheck();
35
+ if (!ok) {
36
+ options.onUnhealthy?.(name, "Health check returned false");
37
+ }
38
+ }
39
+ catch (err) {
40
+ options.onUnhealthy?.(name, err instanceof Error ? err.message : String(err));
41
+ }
42
+ }, 60000);
43
+ healthTimers.set(name, timer);
44
+ }
45
+ },
46
+ async start(name) {
47
+ if (!runtimeInfo)
48
+ throw new Error("No container runtime available");
49
+ await (0, containers_1.startContainer)(runtimeInfo, name);
50
+ },
51
+ async stop(name) {
52
+ if (!runtimeInfo)
53
+ throw new Error("No container runtime available");
54
+ await (0, containers_1.stopContainer)(runtimeInfo, name);
55
+ },
56
+ async remove(name) {
57
+ if (!runtimeInfo)
58
+ throw new Error("No container runtime available");
59
+ await (0, containers_1.removeContainer)(runtimeInfo, name);
60
+ },
61
+ async getState(name) {
62
+ if (!runtimeInfo)
63
+ return "no-runtime";
64
+ return (0, containers_1.getContainerState)(runtimeInfo, name);
65
+ },
66
+ async runJob(config) {
67
+ if (!runtimeInfo)
68
+ throw new Error("No container runtime available");
69
+ return (0, jobs_1.runJob)(runtimeInfo, config);
70
+ },
71
+ async prune() {
72
+ if (!runtimeInfo)
73
+ throw new Error("No container runtime available");
74
+ return (0, containers_1.pruneImages)(runtimeInfo);
75
+ },
76
+ async listContainers() {
77
+ if (!runtimeInfo)
78
+ return [];
79
+ return (0, containers_1.listContainers)(runtimeInfo);
80
+ },
81
+ };
82
+ const plugin = {
83
+ id: "signalk-container",
84
+ name: "Container Manager",
85
+ schema: {
86
+ type: "object",
87
+ properties: {
88
+ runtime: {
89
+ type: "string",
90
+ enum: ["auto", "podman", "docker"],
91
+ default: "auto",
92
+ title: "Container runtime",
93
+ description: "Auto-detect (Podman preferred), or force a specific runtime",
94
+ },
95
+ pruneSchedule: {
96
+ type: "string",
97
+ enum: ["off", "weekly", "monthly"],
98
+ default: "weekly",
99
+ title: "Auto-prune dangling images",
100
+ },
101
+ maxConcurrentJobs: {
102
+ type: "number",
103
+ default: 2,
104
+ title: "Max concurrent one-shot jobs",
105
+ description: "Limit parallel container job executions",
106
+ },
107
+ },
108
+ },
109
+ start(config) {
110
+ // Expose API on global so other plugins can find it.
111
+ // Each plugin gets a shallow copy of app (_.assign({}, app)),
112
+ // so setting on app doesn't propagate. Global is the shared bus.
113
+ globalThis.__signalk_containerManager = api;
114
+ // Async init — server does not await start()
115
+ (async () => {
116
+ const preference = config.runtime ?? "auto";
117
+ app.debug("detecting runtime, preference=%s", preference);
118
+ runtimeInfo = await (0, runtime_1.detectRuntime)(preference);
119
+ app.debug("detectRuntime result: %o", runtimeInfo);
120
+ if (!runtimeInfo) {
121
+ app.setPluginError("No container runtime found. Install Podman: sudo apt install podman");
122
+ return;
123
+ }
124
+ app.setPluginStatus(`${runtimeInfo.runtime} ${runtimeInfo.version}${runtimeInfo.isPodmanDockerShim ? " (podman shim)" : ""}`);
125
+ if (config.pruneSchedule && config.pruneSchedule !== "off") {
126
+ const intervalMs = config.pruneSchedule === "weekly"
127
+ ? 7 * 24 * 60 * 60 * 1000
128
+ : 30 * 24 * 60 * 60 * 1000;
129
+ pruneTimer = setInterval(async () => {
130
+ try {
131
+ const result = await (0, containers_1.pruneImages)(runtimeInfo);
132
+ app.debug(`Pruned ${result.imagesRemoved} images, reclaimed ${result.spaceReclaimed}`);
133
+ }
134
+ catch (err) {
135
+ app.error("Auto-prune failed:", err);
136
+ }
137
+ }, intervalMs);
138
+ }
139
+ app.debug("Container manager started");
140
+ })().catch((err) => {
141
+ app.setPluginError(`Startup failed: ${err instanceof Error ? err.message : String(err)}`);
142
+ });
143
+ },
144
+ stop() {
145
+ if (pruneTimer) {
146
+ clearInterval(pruneTimer);
147
+ pruneTimer = null;
148
+ }
149
+ for (const timer of healthTimers.values()) {
150
+ clearInterval(timer);
151
+ }
152
+ healthTimers.clear();
153
+ delete globalThis.__signalk_containerManager;
154
+ },
155
+ registerWithRouter(router) {
156
+ router.get("/api/runtime", (_req, res) => {
157
+ if (!runtimeInfo) {
158
+ res.status(503).json({ error: "No container runtime available" });
159
+ return;
160
+ }
161
+ res.json(runtimeInfo);
162
+ });
163
+ router.get("/api/containers", async (_req, res) => {
164
+ try {
165
+ const containers = await api.listContainers();
166
+ res.json(containers);
167
+ }
168
+ catch (err) {
169
+ res.status(500).json({
170
+ error: err instanceof Error ? err.message : "Unknown error",
171
+ });
172
+ }
173
+ });
174
+ router.get("/api/containers/:name/state", async (req, res) => {
175
+ try {
176
+ const state = await api.getState(req.params.name);
177
+ res.json({ name: req.params.name, state });
178
+ }
179
+ catch (err) {
180
+ res.status(500).json({
181
+ error: err instanceof Error ? err.message : "Unknown error",
182
+ });
183
+ }
184
+ });
185
+ router.post("/api/containers/:name/stop", async (req, res) => {
186
+ try {
187
+ await api.stop(req.params.name);
188
+ res.json({ status: "stopped" });
189
+ }
190
+ catch (err) {
191
+ res.status(500).json({
192
+ error: err instanceof Error ? err.message : "Unknown error",
193
+ });
194
+ }
195
+ });
196
+ router.post("/api/containers/:name/start", async (req, res) => {
197
+ try {
198
+ await api.start(req.params.name);
199
+ res.json({ status: "started" });
200
+ }
201
+ catch (err) {
202
+ res.status(500).json({
203
+ error: err instanceof Error ? err.message : "Unknown error",
204
+ });
205
+ }
206
+ });
207
+ router.post("/api/containers/:name/remove", async (req, res) => {
208
+ try {
209
+ await api.remove(req.params.name);
210
+ res.json({ status: "removed" });
211
+ }
212
+ catch (err) {
213
+ res.status(500).json({
214
+ error: err instanceof Error ? err.message : "Unknown error",
215
+ });
216
+ }
217
+ });
218
+ router.post("/api/prune", async (_req, res) => {
219
+ try {
220
+ const result = await api.prune();
221
+ res.json(result);
222
+ }
223
+ catch (err) {
224
+ res.status(500).json({
225
+ error: err instanceof Error ? err.message : "Unknown error",
226
+ });
227
+ }
228
+ });
229
+ },
230
+ };
231
+ return plugin;
232
+ };
233
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/jobs.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { ContainerJobConfig, ContainerJobResult, ContainerRuntimeInfo } from "./types";
2
+ export declare function runJob(runtime: ContainerRuntimeInfo, config: ContainerJobConfig): Promise<ContainerJobResult>;
3
+ //# sourceMappingURL=jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../src/jobs.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAGjB,wBAAsB,MAAM,CAC1B,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CA0F7B"}