diff --git a/config/platform-infra/webterm.yaml b/config/platform-infra/webterm.yaml index 7848581f..b7c84924 100644 --- a/config/platform-infra/webterm.yaml +++ b/config/platform-infra/webterm.yaml @@ -242,6 +242,14 @@ targets: - source: /root/user_uploads target: /root/user_uploads readOnly: false + networkSpeedTest: + enabled: true + containerName: web-terminal-7683-speed-test + hostPort: 7783 + containerPort: 7781 + publicUrl: "http://{hostname}:7783" + downloadBytes: 16777216 + uploadBytes: 8388608 autoStartSessions: - title: 决策中心 cwd: /root/unidesk diff --git a/scripts/src/platform-infra-webterm.ts b/scripts/src/platform-infra-webterm.ts index 30b7a2a5..a283494b 100644 --- a/scripts/src/platform-infra-webterm.ts +++ b/scripts/src/platform-infra-webterm.ts @@ -79,6 +79,7 @@ interface WebtermTarget { privileged: boolean; pid: "host" | "container"; sourceMounts: Array<{ source: string; target: string; readOnly: boolean }>; + networkSpeedTest: { enabled: boolean; containerName: string; hostPort: number; containerPort: number; publicUrl: string; downloadBytes: number; uploadBytes: number } | null; autoStartSessions: Array<{ title: string; cwd: string; command: string; cols: number; rows: number; resumePrompt: boolean; fallbackShell: boolean }>; sessionStartModes: SessionStartModes; autoResumePrompt: AutoResumePrompt; @@ -351,6 +352,16 @@ function parseTarget( const environment = parseEnvironment(recordField(runtime, "environment", `${path}.runtime`), `${path}.runtime.environment`); const sourceMounts = parseSourceMounts(runtime.sourceMounts, `${path}.runtime.sourceMounts`); const autoStartSessions = parseAutoStartSessions(runtime.autoStartSessions, `${path}.runtime.autoStartSessions`); + const speedRaw = runtime.networkSpeedTest === undefined ? null : recordField(runtime, "networkSpeedTest", `${path}.runtime`); + const networkSpeedTest = speedRaw === null ? null : { + enabled: booleanField(speedRaw, "enabled", `${path}.runtime.networkSpeedTest`), + containerName: stringField(speedRaw, "containerName", `${path}.runtime.networkSpeedTest`), + hostPort: portField(speedRaw, "hostPort", `${path}.runtime.networkSpeedTest`), + containerPort: portField(speedRaw, "containerPort", `${path}.runtime.networkSpeedTest`), + publicUrl: stringField(speedRaw, "publicUrl", `${path}.runtime.networkSpeedTest`), + downloadBytes: integerField(speedRaw, "downloadBytes", `${path}.runtime.networkSpeedTest`), + uploadBytes: integerField(speedRaw, "uploadBytes", `${path}.runtime.networkSpeedTest`), + }; const target: WebtermTarget = { id: stringField(record, "id", path), enabled: booleanField(record, "enabled", path), @@ -368,6 +379,7 @@ function parseTarget( privileged: booleanField(runtime, "privileged", `${path}.runtime`), pid: parsePid(stringField(runtime, "pid", `${path}.runtime`), `${path}.runtime.pid`), sourceMounts, + networkSpeedTest, autoStartSessions, sessionStartModes, autoResumePrompt, @@ -421,6 +433,11 @@ function renderCompose(target: WebtermTarget): string { BROWSER_TERMINAL_HISTORY_JSON: JSON.stringify(target.runtime.browserTerminalHistory), BROWSER_OUTPUT_POLICY_JSON: JSON.stringify(target.runtime.browserOutputPolicy), BROWSER_PERFORMANCE_JSON: JSON.stringify(target.runtime.browserPerformance), + ...(target.runtime.networkSpeedTest?.enabled ? { + NETWORK_SPEED_TEST_PUBLIC_URL: target.runtime.networkSpeedTest.publicUrl, + NETWORK_SPEED_TEST_DOWNLOAD_BYTES: String(target.runtime.networkSpeedTest.downloadBytes), + NETWORK_SPEED_TEST_UPLOAD_BYTES: String(target.runtime.networkSpeedTest.uploadBytes), + } : {}), }; const envLines = Object.entries(environment) .map(([key, value]) => ` ${key}: ${quoteYaml(value)}`) @@ -428,6 +445,21 @@ function renderCompose(target: WebtermTarget): string { const volumeLines = target.runtime.sourceMounts .map((mount) => ` - ${quoteYaml(`${mount.source}:${mount.target}${mount.readOnly ? ":ro" : ""}`)}`) .join("\n"); + const speed = target.runtime.networkSpeedTest; + const speedTestService = speed?.enabled ? ` + network-speed-test: + image: ${target.runtime.image} + container_name: ${speed.containerName} + restart: unless-stopped + command: ["node", "src/speed-server.js"] + ports: + - "${speed.hostPort}:${speed.containerPort}" + volumes: + - "/root/webterm/src:/app/src:ro" + environment: + SPEED_TEST_HOST: "0.0.0.0" + SPEED_TEST_PORT: "${speed.containerPort}" +` : ""; return `name: ${target.runtime.composeProject} services: @@ -445,6 +477,7 @@ services: ${volumeLines} environment: ${envLines} +${speedTestService} `; } @@ -474,6 +507,7 @@ function policyChecks(target: WebtermTarget, compose: string): Array= 3, detail: `mounts=${target.runtime.sourceMounts.length}` }, + { name: "network-speed-test", ok: !target.runtime.networkSpeedTest?.enabled || compose.includes(`container_name: ${target.runtime.networkSpeedTest.containerName}`), detail: target.runtime.networkSpeedTest?.enabled ? `${target.runtime.networkSpeedTest.hostPort}:${target.runtime.networkSpeedTest.containerPort}` : "disabled" }, ]; }