@hyzyn/dsh-docker 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/lib/docker.js ADDED
@@ -0,0 +1,515 @@
1
+ import { RemoteExec, runLocal, sshTarget } from './ssh-exec.js';
2
+ /* ------------------------------------------------------------------ *
3
+ * 通用:校验与解析工具
4
+ * ------------------------------------------------------------------ */
5
+ /** 容器名 / ID / 镜像引用白名单(docker 允许字母数字与 _.- ,首字符为字母数字)。 */
6
+ const REF_RE = /^[A-Za-z0-9][A-Za-z0-9_.-]*$/;
7
+ /** 校验一个 docker 引用(容器名 / ID / 镜像)。不合法直接抛错,绝不拼接进命令。 */
8
+ export function assertRef(value, field) {
9
+ if (typeof value !== 'string' || value.trim() === '')
10
+ throw new Error(`${field} 不能为空`);
11
+ const trimmed = value.trim();
12
+ if (trimmed.length > 128)
13
+ throw new Error(`${field} 过长(≤128 字符)`);
14
+ if (!REF_RE.test(trimmed))
15
+ throw new Error(`${field} 含非法字符(仅允许字母、数字、_ . -):${trimmed}`);
16
+ return trimmed;
17
+ }
18
+ /** docker CLI 可执行文件白名单(argv[0],不设默认值以免误用其他程序)。 */
19
+ export function assertBin(value) {
20
+ if (typeof value !== 'string' || value.trim() === '')
21
+ return 'docker';
22
+ const trimmed = value.trim();
23
+ if (!/^[A-Za-z0-9_./-]+$/.test(trimmed))
24
+ throw new Error(`dockerBin 含非法字符:${trimmed}`);
25
+ return trimmed;
26
+ }
27
+ /** 逐行 JSON 解析:兼容 `{{json .}}`(每行一个对象)与整体 JSON 数组。 */
28
+ export function parseJsonLines(text) {
29
+ const trimmed = text.trim();
30
+ if (trimmed === '')
31
+ return [];
32
+ if (trimmed.startsWith('[')) {
33
+ try {
34
+ const parsed = JSON.parse(trimmed);
35
+ if (Array.isArray(parsed))
36
+ return parsed.filter((item) => typeof item === 'object' && item !== null);
37
+ }
38
+ catch {
39
+ /* 落到逐行解析 */
40
+ }
41
+ }
42
+ const rows = [];
43
+ for (const line of trimmed.split(/\r?\n/)) {
44
+ const one = line.trim();
45
+ if (one === '' || !one.startsWith('{'))
46
+ continue;
47
+ try {
48
+ const parsed = JSON.parse(one);
49
+ if (typeof parsed === 'object' && parsed !== null)
50
+ rows.push(parsed);
51
+ }
52
+ catch {
53
+ /* 跳过非 JSON 行(警告文本等) */
54
+ }
55
+ }
56
+ return rows;
57
+ }
58
+ /** 取字符串字段(大小写不敏感,兼容不同版本字段名)。 */
59
+ function str(row, ...keys) {
60
+ for (const key of keys) {
61
+ const direct = row[key];
62
+ if (typeof direct === 'string')
63
+ return direct;
64
+ const lower = row[key.toLowerCase()];
65
+ if (typeof lower === 'string')
66
+ return lower;
67
+ const upper = row[key.toUpperCase()];
68
+ if (typeof upper === 'string')
69
+ return upper;
70
+ }
71
+ return '';
72
+ }
73
+ /** `12.3MiB` / `1.2kB` / `0B` → 字节数(解析失败返回 null)。 */
74
+ export function parseDockerSize(text) {
75
+ const match = /^\s*([0-9]+(?:\.[0-9]+)?)\s*([a-zA-Z]*)\s*$/.exec(text);
76
+ if (match === null)
77
+ return null;
78
+ const value = Number(match[1]);
79
+ const unit = (match[2] ?? '').toLowerCase();
80
+ const scale = {
81
+ '': 1,
82
+ b: 1,
83
+ kb: 1e3,
84
+ kib: 1024,
85
+ mb: 1e6,
86
+ mib: 1024 ** 2,
87
+ gb: 1e9,
88
+ gib: 1024 ** 3,
89
+ tb: 1e12,
90
+ tib: 1024 ** 4,
91
+ pb: 1e15,
92
+ pib: 1024 ** 5,
93
+ };
94
+ const factor = scale[unit];
95
+ if (factor === undefined)
96
+ return null;
97
+ return Math.round(value * factor);
98
+ }
99
+ /** `12.34%` → 12.34(解析失败返回 null)。 */
100
+ export function parsePercent(text) {
101
+ const match = /^\s*([0-9]+(?:\.[0-9]+)?)\s*%\s*$/.exec(text);
102
+ if (match === null)
103
+ return null;
104
+ return Number(match[1]);
105
+ }
106
+ /** `1.2kB / 0B` → { rx, tx }(解析失败一侧为 null)。 */
107
+ export function parseIOPair(text) {
108
+ const [left = '', right = ''] = text.split('/');
109
+ return { rx: parseDockerSize(left), tx: parseDockerSize(right) };
110
+ }
111
+ /** 从 ps 的 `.Status`(`Up 2 hours (healthy)`)推导状态。健康态单独由 deriveHealth 提供。 */
112
+ export function deriveState(status) {
113
+ const lower = status.toLowerCase();
114
+ if (lower.startsWith('up')) {
115
+ if (lower.includes('(paused)'))
116
+ return 'paused';
117
+ if (lower.includes('(restarting)'))
118
+ return 'restarting';
119
+ // Up 但 unhealthy 的容器状态仍是 running,健康态见 health 字段
120
+ return 'running';
121
+ }
122
+ if (lower.startsWith('exited'))
123
+ return 'exited';
124
+ if (lower.startsWith('created'))
125
+ return 'created';
126
+ if (lower.startsWith('restarting'))
127
+ return 'restarting';
128
+ if (lower.startsWith('paused'))
129
+ return 'paused';
130
+ if (lower.startsWith('dead'))
131
+ return 'dead';
132
+ if (lower.startsWith('removal in progress'))
133
+ return 'removing';
134
+ return 'unknown';
135
+ }
136
+ /** 从 ps 的 `.Status` 提取健康态(`Up 2 hours (healthy)` → healthy)。 */
137
+ export function deriveHealth(status) {
138
+ const match = /\((healthy|unhealthy|health: starting)\)/i.exec(status);
139
+ if (match === null)
140
+ return null;
141
+ const value = match[1].toLowerCase();
142
+ return value === 'health: starting' ? 'starting' : value;
143
+ }
144
+ /** 解析 ps 的 `.Ports` 串:`0.0.0.0:8080->80/tcp, [::]:8080->80/tcp, 9000/tcp`。 */
145
+ export function parsePorts(text) {
146
+ const out = [];
147
+ const seen = new Set();
148
+ for (const raw of text.split(',')) {
149
+ const item = raw.trim();
150
+ if (item === '')
151
+ continue;
152
+ const arrow = item.split('->');
153
+ if (arrow.length === 2) {
154
+ const [hostPart = '', containerPart = ''] = arrow;
155
+ const [containerPortText = '', protocol = 'tcp'] = containerPart.split('/');
156
+ const containerPort = Number(containerPortText);
157
+ if (!Number.isInteger(containerPort))
158
+ continue;
159
+ const hostPortText = hostPart.slice(hostPart.lastIndexOf(':') + 1);
160
+ const hostPort = Number(hostPortText);
161
+ const hostIp = hostPart.slice(0, hostPart.lastIndexOf(':'));
162
+ const key = `${hostIp}:${hostPortText}:${containerPortText}/${protocol}`;
163
+ if (seen.has(key))
164
+ continue;
165
+ seen.add(key);
166
+ out.push({
167
+ ...(hostIp === '' ? {} : { hostIp }),
168
+ ...(Number.isInteger(hostPort) ? { hostPort } : {}),
169
+ containerPort,
170
+ protocol,
171
+ });
172
+ continue;
173
+ }
174
+ // 仅暴露容器端口(未映射):`9000/tcp`
175
+ const [containerPortText = '', protocol = 'tcp'] = item.split('/');
176
+ const containerPort = Number(containerPortText);
177
+ if (!Number.isInteger(containerPort))
178
+ continue;
179
+ const key = `-:${containerPortText}/${protocol}`;
180
+ if (seen.has(key))
181
+ continue;
182
+ seen.add(key);
183
+ out.push({ containerPort, protocol });
184
+ }
185
+ return out;
186
+ }
187
+ /** `docker ps --format '{{json .}}'` → ContainerSummary[]。 */
188
+ export function parsePsJson(text) {
189
+ return parseJsonLines(text).map((row) => {
190
+ const id = str(row, 'ID', 'Id');
191
+ const status = str(row, 'Status');
192
+ const labels = parseLabels(str(row, 'Labels'));
193
+ return {
194
+ id,
195
+ shortId: id.slice(0, 12),
196
+ name: str(row, 'Names', 'Name'),
197
+ image: str(row, 'Image'),
198
+ state: str(row, 'State') === '' ? deriveState(status) : str(row, 'State').toLowerCase(),
199
+ status,
200
+ health: deriveHealth(status),
201
+ createdAt: str(row, 'CreatedAt') === '' ? null : str(row, 'CreatedAt'),
202
+ runningFor: str(row, 'RunningFor'),
203
+ ports: parsePorts(str(row, 'Ports')),
204
+ composeProject: labels['com.docker.compose.project'] ?? null,
205
+ composeService: labels['com.docker.compose.service'] ?? null,
206
+ size: str(row, 'Size'),
207
+ };
208
+ });
209
+ }
210
+ /** ps 的 `.Labels` 是 `k=v,k2=v2` 串。 */
211
+ export function parseLabels(text) {
212
+ const out = {};
213
+ if (text.trim() === '')
214
+ return out;
215
+ for (const pair of text.split(',')) {
216
+ const eq = pair.indexOf('=');
217
+ if (eq <= 0)
218
+ continue;
219
+ out[pair.slice(0, eq).trim()] = pair.slice(eq + 1).trim();
220
+ }
221
+ return out;
222
+ }
223
+ /** `docker stats --no-stream --format '{{json .}}'` → ContainerStats[]。 */
224
+ export function parseStatsJson(text) {
225
+ return parseJsonLines(text).map((row) => {
226
+ const id = str(row, 'ID', 'Container', 'ContainerID');
227
+ const mem = str(row, 'MemUsage');
228
+ const [memUsedText = '', memLimitText = ''] = mem.split('/');
229
+ const net = parseIOPair(str(row, 'NetIO'));
230
+ const block = parseIOPair(str(row, 'BlockIO'));
231
+ const pids = Number(str(row, 'PIDs'));
232
+ return {
233
+ id,
234
+ shortId: id.slice(0, 12),
235
+ name: str(row, 'Name'),
236
+ cpuPercent: parsePercent(str(row, 'CPUPerc')),
237
+ memPercent: parsePercent(str(row, 'MemPerc')),
238
+ memUsed: parseDockerSize(memUsedText),
239
+ memLimit: parseDockerSize(memLimitText),
240
+ memUsage: mem.trim(),
241
+ netRx: net.rx,
242
+ netTx: net.tx,
243
+ netIO: str(row, 'NetIO').trim(),
244
+ blockRead: block.rx,
245
+ blockWrite: block.tx,
246
+ blockIO: str(row, 'BlockIO').trim(),
247
+ pids: Number.isInteger(pids) ? pids : null,
248
+ };
249
+ });
250
+ }
251
+ /** `docker images --format '{{json .}}'` → ImageSummary[]。 */
252
+ export function parseImagesJson(text) {
253
+ return parseJsonLines(text).map((row) => {
254
+ const id = str(row, 'ID', 'Id');
255
+ const repository = str(row, 'Repository') || '<none>';
256
+ const tag = str(row, 'Tag') || '<none>';
257
+ const sizeText = str(row, 'Size');
258
+ return {
259
+ id,
260
+ shortId: id.replace(/^sha256:/, '').slice(0, 12),
261
+ repository,
262
+ tag,
263
+ reference: `${repository}:${tag}`,
264
+ size: parseDockerSize(sizeText),
265
+ sizeText,
266
+ createdAt: str(row, 'CreatedAt'),
267
+ createdSince: str(row, 'CreatedSince'),
268
+ dangling: repository === '<none>' && tag === '<none>',
269
+ };
270
+ });
271
+ }
272
+ /** `docker inspect <id…>` 的 JSON 数组 → ContainerDetail[]。 */
273
+ export function parseInspectJson(text) {
274
+ const parsed = parseJsonLines(text);
275
+ return parsed.map((row) => {
276
+ const state = asRecord(row.State);
277
+ const config = asRecord(row.Config);
278
+ const hostConfig = asRecord(row.HostConfig);
279
+ const networkSettings = asRecord(row.NetworkSettings);
280
+ const labels = asRecord(config.Labels);
281
+ const mountsRaw = Array.isArray(row.Mounts) ? row.Mounts : [];
282
+ const networksRaw = asRecord(networkSettings.Networks);
283
+ const health = asRecord(state.Health);
284
+ const healthLog = Array.isArray(health.Log) ? health.Log : [];
285
+ const lastHealth = healthLog.length > 0 ? asRecord(healthLog[healthLog.length - 1]) : {};
286
+ const id = str(row, 'Id', 'ID');
287
+ const name = str(row, 'Name').replace(/^\//, '');
288
+ return {
289
+ id,
290
+ shortId: id.slice(0, 12),
291
+ name,
292
+ image: str(config, 'Image'),
293
+ imageId: str(row, 'Image'),
294
+ state: str(state, 'Status') === '' ? 'unknown' : str(state, 'Status').toLowerCase(),
295
+ status: str(state, 'Status'),
296
+ health: typeof health.Status === 'string' ? health.Status : null,
297
+ healthLogTail: typeof lastHealth.Output === 'string' ? lastHealth.Output.trim() : null,
298
+ created: typeof row.Created === 'string' ? row.Created : null,
299
+ startedAt: typeof state.StartedAt === 'string' ? state.StartedAt : null,
300
+ finishedAt: typeof state.FinishedAt === 'string' ? state.FinishedAt : null,
301
+ exitCode: typeof state.ExitCode === 'number' ? state.ExitCode : null,
302
+ oomKilled: state.OOMKilled === true,
303
+ restartCount: typeof row.RestartCount === 'number' ? row.RestartCount : null,
304
+ restartPolicy: typeof asRecord(hostConfig.RestartPolicy).Name === 'string' ? String(asRecord(hostConfig.RestartPolicy).Name) : null,
305
+ platform: typeof row.Platform === 'string' ? row.Platform : '',
306
+ pid: typeof state.Pid === 'number' ? state.Pid : null,
307
+ ports: parseInspectPorts(networkSettings.Ports),
308
+ mounts: mountsRaw.map((item) => {
309
+ const mount = asRecord(item);
310
+ return {
311
+ type: typeof mount.Type === 'string' ? mount.Type : '',
312
+ source: typeof mount.Source === 'string' ? mount.Source : '',
313
+ destination: typeof mount.Destination === 'string' ? mount.Destination : '',
314
+ mode: typeof mount.Mode === 'string' ? mount.Mode : '',
315
+ readWrite: mount.RW !== false,
316
+ };
317
+ }),
318
+ networks: Object.entries(networksRaw).map(([name, value]) => {
319
+ const net = asRecord(value);
320
+ return { name, ip: typeof net.IPAddress === 'string' && net.IPAddress !== '' ? net.IPAddress : null };
321
+ }),
322
+ command: Array.isArray(config.Cmd) ? config.Cmd.map(String).join(' ') : str(config, 'Cmd'),
323
+ entrypoint: Array.isArray(config.Entrypoint) ? config.Entrypoint.map(String).join(' ') : str(config, 'Entrypoint'),
324
+ workingDir: typeof config.WorkingDir === 'string' ? config.WorkingDir : '',
325
+ user: typeof config.User === 'string' ? config.User : '',
326
+ composeProject: typeof labels['com.docker.compose.project'] === 'string' ? labels['com.docker.compose.project'] : null,
327
+ composeService: typeof labels['com.docker.compose.service'] === 'string' ? labels['com.docker.compose.service'] : null,
328
+ labels: Object.fromEntries(Object.entries(labels).slice(0, 50).map(([k, v]) => [k, String(v)])),
329
+ };
330
+ });
331
+ }
332
+ function asRecord(value) {
333
+ return typeof value === 'object' && value !== null ? value : {};
334
+ }
335
+ /** inspect 的 `NetworkSettings.Ports`:`{ "80/tcp": [{HostIp, HostPort}] }`。 */
336
+ export function parseInspectPorts(value) {
337
+ const ports = asRecord(value);
338
+ const out = [];
339
+ for (const [key, mappings] of Object.entries(ports)) {
340
+ const [containerPortText = '', protocol = 'tcp'] = key.split('/');
341
+ const containerPort = Number(containerPortText);
342
+ if (!Number.isInteger(containerPort))
343
+ continue;
344
+ const list = Array.isArray(mappings) ? mappings : [];
345
+ if (list.length === 0) {
346
+ out.push({ containerPort, protocol });
347
+ continue;
348
+ }
349
+ const seen = new Set();
350
+ for (const item of list) {
351
+ const map = asRecord(item);
352
+ const hostIp = typeof map.HostIp === 'string' ? map.HostIp : '';
353
+ const hostPort = Number(map.HostPort);
354
+ const dedupe = `${hostPort}`;
355
+ if (seen.has(dedupe))
356
+ continue;
357
+ seen.add(dedupe);
358
+ out.push({
359
+ ...(hostIp === '' ? {} : { hostIp }),
360
+ ...(Number.isInteger(hostPort) ? { hostPort } : {}),
361
+ containerPort,
362
+ protocol,
363
+ });
364
+ }
365
+ }
366
+ return out;
367
+ }
368
+ /** 单个目标上的 Docker 操作集合。 */
369
+ export class DockerApi {
370
+ runner;
371
+ bin;
372
+ limits;
373
+ constructor(runner, bin, limits) {
374
+ this.runner = runner;
375
+ this.bin = bin;
376
+ this.limits = limits;
377
+ }
378
+ /** 探测:docker CLI 是否可用 + daemon 是否可达。 */
379
+ async probe() {
380
+ const base = { bin: this.bin, target: this.runner.label };
381
+ try {
382
+ const result = await this.runner.run([this.bin, 'version', '--format', '{{.Server.Version}}'], { timeoutMs: 15_000 });
383
+ if (result.code === 0) {
384
+ return { ok: true, serverVersion: result.stdout.trim() || null, error: null, ...base };
385
+ }
386
+ const message = (result.stderr.trim() || result.stdout.trim() || `退出码 ${String(result.code)}`).split('\n')[0];
387
+ return { ok: false, serverVersion: null, error: message ?? '未知错误', ...base };
388
+ }
389
+ catch (error) {
390
+ return { ok: false, serverVersion: null, error: error instanceof Error ? error.message : String(error), ...base };
391
+ }
392
+ }
393
+ async listContainers(all) {
394
+ const argv = [this.bin, 'ps', ...(all ? ['-a'] : []), '--no-trunc', '--format', '{{json .}}'];
395
+ const result = await this.runner.run(argv, { timeoutMs: this.limits.timeoutMs, maxBytes: this.limits.maxBytes });
396
+ this.assertOk(result, '列出容器');
397
+ return parsePsJson(result.stdout);
398
+ }
399
+ async inspect(ids) {
400
+ const safe = ids.map((id) => assertRef(id, 'container'));
401
+ if (safe.length === 0)
402
+ return [];
403
+ const result = await this.runner.run([this.bin, 'inspect', ...safe], {
404
+ timeoutMs: this.limits.timeoutMs,
405
+ maxBytes: this.limits.maxBytes,
406
+ });
407
+ this.assertOk(result, '读取容器详情');
408
+ return parseInspectJson(result.stdout);
409
+ }
410
+ async stats(ids) {
411
+ const safe = ids.map((id) => assertRef(id, 'container'));
412
+ const result = await this.runner.run([this.bin, 'stats', '--no-stream', '--format', '{{json .}}', ...safe], { timeoutMs: Math.max(this.limits.timeoutMs, 20_000), maxBytes: this.limits.maxBytes });
413
+ this.assertOk(result, '读取容器统计');
414
+ return parseStatsJson(result.stdout);
415
+ }
416
+ async images() {
417
+ const result = await this.runner.run([this.bin, 'images', '--format', '{{json .}}'], {
418
+ timeoutMs: this.limits.timeoutMs,
419
+ maxBytes: this.limits.maxBytes,
420
+ });
421
+ this.assertOk(result, '列出镜像');
422
+ return parseImagesJson(result.stdout);
423
+ }
424
+ /** 日志:stdout / stderr 分别收,再按到达顺序合并(docker logs 两者都有内容)。 */
425
+ async logs(id, options) {
426
+ const safe = assertRef(id, 'container');
427
+ const tail = Math.min(Math.max(Math.trunc(options?.tail ?? 200), 1), 5000);
428
+ const argv = [
429
+ this.bin,
430
+ 'logs',
431
+ '--tail',
432
+ String(tail),
433
+ ...(options?.timestamps === true ? ['--timestamps'] : []),
434
+ ...(typeof options?.since === 'string' && options.since.trim() !== '' ? ['--since', options.since.trim()] : []),
435
+ safe,
436
+ ];
437
+ const result = await this.runner.run(argv, { timeoutMs: this.limits.timeoutMs, maxBytes: this.limits.maxBytes });
438
+ this.assertOk(result, '读取容器日志');
439
+ const text = result.stdout + (result.stderr === '' ? '' : (result.stdout === '' ? '' : '\n') + result.stderr);
440
+ return { id: safe, text, truncated: result.truncated };
441
+ }
442
+ /** 生命周期操作;调用方负责 readOnly / allowMutations 门禁。 */
443
+ async action(request) {
444
+ const safe = assertRef(request.id, 'container');
445
+ const map = {
446
+ start: ['start'],
447
+ stop: ['stop'],
448
+ restart: ['restart'],
449
+ remove: ['rm'],
450
+ };
451
+ const sub = map[request.action];
452
+ const result = await this.runner.run([this.bin, ...sub, safe], {
453
+ // stop / restart 可能要等容器优雅退出(docker 默认 10s 超时)
454
+ timeoutMs: Math.max(this.limits.timeoutMs, 60_000),
455
+ maxBytes: 64 * 1024,
456
+ });
457
+ if (result.code !== 0) {
458
+ const message = (result.stderr.trim() || result.stdout.trim() || `退出码 ${String(result.code)}`).split('\n')[0];
459
+ const hint = request.action === 'remove' && /running/i.test(message) ? '(容器仍在运行:先停止再删除)' : '';
460
+ throw new Error(`${request.action} ${safe} 失败:${message}${hint}`);
461
+ }
462
+ return { id: safe, action: request.action, message: result.stdout.trim() || 'ok' };
463
+ }
464
+ /** 一次性 exec(无 TTY):`docker exec <id> sh -c <command>`。 */
465
+ async exec(id, command, timeoutMs) {
466
+ const safe = assertRef(id, 'container');
467
+ if (typeof command !== 'string' || command.trim() === '')
468
+ throw new Error('command 不能为空');
469
+ if (command.length > 8000)
470
+ throw new Error('command 过长(≤8000 字符)');
471
+ const result = await this.runner.run([this.bin, 'exec', safe, 'sh', '-c', command], {
472
+ timeoutMs: Math.min(Math.max(timeoutMs ?? 30_000, 1_000), 120_000),
473
+ maxBytes: this.limits.maxBytes,
474
+ });
475
+ if (result.timedOut)
476
+ throw new Error(`exec 超时(${String(Math.round(result.durationMs / 1000))}s):${safe}`);
477
+ return {
478
+ id: safe,
479
+ command,
480
+ code: result.code,
481
+ stdout: result.stdout,
482
+ stderr: result.stderr,
483
+ truncated: result.truncated,
484
+ durationMs: result.durationMs,
485
+ };
486
+ }
487
+ assertOk(result, what) {
488
+ if (result.code === 0)
489
+ return;
490
+ const message = (result.stderr.trim() || result.stdout.trim() || `退出码 ${String(result.code)}`).split('\n')[0];
491
+ throw new Error(`${what}失败(${this.runner.label}):${message}`);
492
+ }
493
+ }
494
+ /** 为一个目标构造 Runner。 */
495
+ export function createRunner(options) {
496
+ const { target, remote, logger } = options;
497
+ if (target.kind === 'local') {
498
+ return {
499
+ label: `本机(${target.name})`,
500
+ run: (argv, runOptions) => runLocal(argv, runOptions),
501
+ };
502
+ }
503
+ const spec = target.spec;
504
+ if (spec === undefined)
505
+ throw new Error(`目标 ${target.name} 缺少 SSH 规格`);
506
+ return {
507
+ label: `${sshTarget(spec)}(${target.name})`,
508
+ run: (argv, runOptions) => remote.run(spec, argv, runOptions),
509
+ };
510
+ }
511
+ /** 供宿主半体复用:把 HostKeyStore 与 logger 绑到 RemoteExec。 */
512
+ export function createRemoteExec(logger, store) {
513
+ return new RemoteExec(logger, store);
514
+ }
515
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @hyzyn/dsh-docker — DSH Web GUI 的 Docker 容器面板(host 半体)。
3
+ *
4
+ * 与 dsh-tty 的关系(方案 A:独立插件,tty 零改动):
5
+ * - **连接簿**:只读复用 tty 的 settings 命名空间(`ctx.settings.get('tty')`
6
+ * 的 `sshHosts`)。tty 未安装时退化为「只支持本机 / 内联 SSH 字段」。
7
+ * - **主机指纹**:本插件自持一份 `hostKeys`(TOFU),并优先读取 tty 已记录
8
+ * 的指纹作为种子,避免同一主机在两处重复确认。
9
+ * - **执行通道**:自持池化 SSH exec(src/ssh-exec.ts),与 tty 的 PTY 会话
10
+ * 完全独立;本机目标直接 spawn docker CLI。
11
+ *
12
+ * 信任模型(与 tty 不同,必须强调):
13
+ * docker socket ≈ 该主机的 root 权限。因此**默认只读**:
14
+ * `allowMutations` 未开启时 start/stop/restart/remove 一律拒绝,
15
+ * `allowExec` 未开启时 `docker exec` 一律拒绝;两个开关都需用户在设置卡片
16
+ * 显式打开。agent 工具同样受这两个开关约束(未开启时连工具都不注册)。
17
+ */
18
+ import type { Context } from '@deepseek-ai/cordis';
19
+ import { DockerApi, assertBin, parseInspectJson, parsePsJson, parseStatsJson } from './docker.js';
20
+ import type { DockerTarget, ResolvedTarget } from './docker.js';
21
+ import type { HostKeyRecord, SshSpec } from './ssh-exec.js';
22
+ export type { HostKeyRecord } from './ssh-exec.js';
23
+ export type { ContainerSummary, ContainerDetail, ContainerStats, ImageSummary, DockerTarget } from './docker.js';
24
+ export interface Config {
25
+ /** 关闭整个插件。默认开。 */
26
+ enabled?: boolean;
27
+ /** 是否向 agent 注入插件能力公告。默认开。 */
28
+ announceToAgent?: boolean;
29
+ /** docker CLI 可执行文件名 / 路径(podman 可填 podman)。默认 docker。 */
30
+ dockerBin?: string;
31
+ /** 允许 start/stop/restart/remove(含对应 agent 工具)。默认关。 */
32
+ allowMutations?: boolean;
33
+ /** 允许一次性 docker exec(含对应 agent 工具)。默认关。 */
34
+ allowExec?: boolean;
35
+ /** exec 默认超时秒数(1~120)。默认 30。 */
36
+ execTimeoutSec?: number;
37
+ /** 面板统计刷新间隔秒数(1~60)。默认 5。 */
38
+ pollIntervalSec?: number;
39
+ /** 日志默认尾部行数(1~5000)。默认 200。 */
40
+ logTailDefault?: number;
41
+ /** 单次命令输出上限(KB,1~8192)。默认 512。 */
42
+ maxOutputKb?: number;
43
+ /** 目标列表(本机 / SSH)。 */
44
+ targets?: DockerTarget[];
45
+ /** SSH 主机指纹记录(TOFU,随 settings 落盘)。 */
46
+ hostKeys?: HostKeyRecord[];
47
+ }
48
+ /** 解析后的运行期配置(settings 与 composition 两条来源统一到这一形状)。 */
49
+ interface LiveConfig {
50
+ enabled: boolean;
51
+ announceToAgent: boolean;
52
+ dockerBin: string;
53
+ allowMutations: boolean;
54
+ allowExec: boolean;
55
+ execTimeoutSec: number;
56
+ pollIntervalSec: number;
57
+ logTailDefault: number;
58
+ maxOutputKb: number;
59
+ targets: DockerTarget[];
60
+ hostKeys: HostKeyRecord[];
61
+ }
62
+ /** 清洗一份 targets 输入(settings 存储 / 热更新路径共用)。 */
63
+ export declare function sanitizeTargets(input: unknown): DockerTarget[] | undefined;
64
+ /** 清洗一份 hostKeys 输入。 */
65
+ export declare function sanitizeHostKeys(input: unknown): HostKeyRecord[] | undefined;
66
+ /**
67
+ * 合并凭证:配置卡片从不回显密码 / 口令(只回 passwordSet),因此浏览器提交的
68
+ * targets 里往往**没有** password/passphrase 字段。按目标名把已有值补回来,
69
+ * 避免「改个名字就把密码清了」。(显式传空字符串仍然按清空处理。)
70
+ */
71
+ export declare function mergeTargetSecrets(prev: DockerTarget[], incoming: unknown): unknown;
72
+ /** 把一份任意来源的配置归一成 LiveConfig。 */
73
+ export declare function normalizeConfig(section: Record<string, unknown>): LiveConfig;
74
+ /** 把一个配置目标解析成可连接的规格(连接簿查找在此完成)。 */
75
+ export declare function resolveTarget(target: DockerTarget, books: Map<string, SshSpec>): {
76
+ resolved?: ResolvedTarget;
77
+ error?: string;
78
+ };
79
+ export declare const name: string, inject: string[] | undefined, apply: (ctx: Context, config?: Config | undefined) => void;
80
+ export { parsePsJson, parseStatsJson, parseInspectJson, assertBin, DockerApi };
81
+ export type { Runner } from './docker.js';