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.
- package/.prettierignore +2 -0
- package/LICENSE +21 -0
- package/README.md +107 -0
- package/dist/containers.d.ts +16 -0
- package/dist/containers.d.ts.map +1 -0
- package/dist/containers.js +205 -0
- package/dist/containers.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +233 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +3 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +75 -0
- package/dist/jobs.js.map +1 -0
- package/dist/runtime.d.ts +13 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +113 -0
- package/dist/runtime.js.map +1 -0
- package/dist/test/runtime.test.d.ts +2 -0
- package/dist/test/runtime.test.d.ts.map +1 -0
- package/dist/test/runtime.test.js +30 -0
- package/dist/test/runtime.test.js.map +1 -0
- package/dist/test/types.test.d.ts +2 -0
- package/dist/test/types.test.d.ts.map +1 -0
- package/dist/test/types.test.js +58 -0
- package/dist/test/types.test.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/doc/plugin-developer-guide.md +441 -0
- package/package.json +53 -0
- package/public/540.js +2 -0
- package/public/540.js.LICENSE.txt +9 -0
- package/public/805.js +1 -0
- package/public/main.js +1 -0
- package/public/remoteEntry.js +1 -0
- package/webpack.config.js +43 -0
package/.prettierignore
ADDED
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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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"}
|