fix: honor trans backend config for ssh
This commit is contained in:
+61
-5
@@ -23,6 +23,7 @@ import {
|
||||
type SshRemoteCommandStreamHandlers,
|
||||
} from "./ssh-file-transfer";
|
||||
import { readTransHostProxyEnvRule, type TransHostProxyEnvRule } from "./trans-host-proxy";
|
||||
import { readTransSshBackendConfig, type TransSshBackendConfig } from "./trans-config";
|
||||
|
||||
export interface ParsedSshArgs {
|
||||
remoteCommand: string | null;
|
||||
@@ -74,6 +75,7 @@ export interface SshCaptureBackendPlan {
|
||||
dockerExecutable: boolean;
|
||||
backendCoreContainer: boolean;
|
||||
error: string | null;
|
||||
source?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -196,6 +198,8 @@ const windowsCmdExeNativePath = "C:\\Windows\\System32\\cmd.exe";
|
||||
const defaultSshSlowWarningMs = 10_000;
|
||||
const defaultSshRuntimeTimeoutMs = 60_000;
|
||||
const maxSshRuntimeTimeoutMs = 60_000;
|
||||
const defaultSshBackendCoreDetectTimeoutMs = 15_000;
|
||||
const maxSshBackendCoreDetectTimeoutMs = 60_000;
|
||||
const defaultSshStdoutStreamMaxBytes = 256 * 1024;
|
||||
const minSshStdoutStreamMaxBytes = 4 * 1024;
|
||||
const maxSshStdoutStreamMaxBytes = 16 * 1024 * 1024;
|
||||
@@ -3551,14 +3555,46 @@ async function runRemoteSshCapture(config: UniDeskConfig, host: string, target:
|
||||
}
|
||||
|
||||
export function sshCaptureBackendPlan(config: UniDeskConfig, env: NodeJS.ProcessEnv = process.env): SshCaptureBackendPlan {
|
||||
const localBackendCore = detectLocalBackendCoreStatus();
|
||||
const configuredBackend = readTransSshBackendConfig(env);
|
||||
const remoteHost = sshCaptureRemoteHost(config, env);
|
||||
if (configuredBackend !== null) return configuredSshCaptureBackendPlan(configuredBackend, remoteHost);
|
||||
const localBackendCore = detectLocalBackendCoreStatus(env);
|
||||
const runnerEnv = isRunnerEnvironment(env);
|
||||
if (runnerEnv && remoteHost !== null) return { backend: "remote-frontend-websocket", remoteHost, reason: "runner-environment", localBackendCore };
|
||||
if (!localBackendCore.backendCoreContainer && remoteHost !== null) return { backend: "remote-frontend-websocket", remoteHost, reason: "local-backend-core-unavailable", localBackendCore };
|
||||
return { backend: "local-backend-core-broker", remoteHost: null, reason: "main-server-local-backend-core", localBackendCore };
|
||||
}
|
||||
|
||||
function configuredSshCaptureBackendPlan(configuredBackend: TransSshBackendConfig, remoteHost: string | null): SshCaptureBackendPlan {
|
||||
if (configuredBackend.backend === "local-backend-core-broker") {
|
||||
return {
|
||||
backend: "local-backend-core-broker",
|
||||
remoteHost: null,
|
||||
reason: `configured:${configuredBackend.sourceRef}`,
|
||||
localBackendCore: {
|
||||
dockerExecutable: true,
|
||||
backendCoreContainer: true,
|
||||
error: null,
|
||||
source: configuredBackend.sourceRef,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (remoteHost === null) {
|
||||
throw new Error(`${configuredBackend.sourceRef} selects ${configuredBackend.raw}, but no remote host is configured for frontend websocket SSH`);
|
||||
}
|
||||
return {
|
||||
backend: "remote-frontend-websocket",
|
||||
remoteHost,
|
||||
reason: `configured:${configuredBackend.sourceRef}`,
|
||||
localBackendCore: {
|
||||
dockerExecutable: false,
|
||||
backendCoreContainer: false,
|
||||
error: null,
|
||||
source: configuredBackend.sourceRef,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function sshCaptureRemoteHost(config: UniDeskConfig, env: NodeJS.ProcessEnv): string | null {
|
||||
return normalizeRemoteHost(env.UNIDESK_MAIN_SERVER_IP)
|
||||
?? normalizeRemoteHost(env.UNIDESK_MAIN_SERVER_HOST)
|
||||
@@ -3583,17 +3619,37 @@ function isRunnerEnvironment(env: NodeJS.ProcessEnv): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function detectLocalBackendCoreStatus(): SshCaptureBackendPlan["localBackendCore"] {
|
||||
const result = spawnSync("docker", ["ps", "--format", "{{.Names}}"], { encoding: "utf8", timeout: 2000 });
|
||||
if (result.error !== undefined) return { dockerExecutable: false, backendCoreContainer: false, error: result.error.message };
|
||||
function detectLocalBackendCoreStatus(env: NodeJS.ProcessEnv = process.env): SshCaptureBackendPlan["localBackendCore"] {
|
||||
const timeout = sshBackendCoreDetectTimeoutMs(env);
|
||||
const inspect = spawnSync("docker", ["inspect", "unidesk-backend-core", "--format", "{{.State.Running}}"], { encoding: "utf8", timeout });
|
||||
if (inspect.error !== undefined) return { dockerExecutable: false, backendCoreContainer: false, error: inspect.error.message, source: "docker-inspect" };
|
||||
const inspectOutput = `${inspect.stdout ?? ""}\n${inspect.stderr ?? ""}`.trim();
|
||||
if (inspect.status === 0) {
|
||||
const running = String(inspect.stdout ?? "").trim() === "true";
|
||||
return {
|
||||
dockerExecutable: true,
|
||||
backendCoreContainer: running,
|
||||
error: running ? null : inspectOutput || "docker inspect unidesk-backend-core reported not running",
|
||||
source: "docker-inspect",
|
||||
};
|
||||
}
|
||||
const result = spawnSync("docker", ["ps", "--format", "{{.Names}}"], { encoding: "utf8", timeout });
|
||||
if (result.error !== undefined) return { dockerExecutable: false, backendCoreContainer: false, error: result.error.message, source: "docker-ps" };
|
||||
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`.trim();
|
||||
return {
|
||||
dockerExecutable: result.status === 0,
|
||||
backendCoreContainer: result.status === 0 && String(result.stdout ?? "").split(/\r?\n/u).includes("unidesk-backend-core"),
|
||||
error: result.status === 0 ? null : output || `docker ps exited ${result.status ?? "unknown"}`,
|
||||
error: result.status === 0 ? null : inspectOutput || output || `docker ps exited ${result.status ?? "unknown"}`,
|
||||
source: "docker-ps",
|
||||
};
|
||||
}
|
||||
|
||||
function sshBackendCoreDetectTimeoutMs(env: NodeJS.ProcessEnv = process.env): number {
|
||||
const parsed = Number(env.UNIDESK_SSH_BACKEND_CORE_DETECT_TIMEOUT_MS);
|
||||
if (!Number.isFinite(parsed) || parsed <= 0) return defaultSshBackendCoreDetectTimeoutMs;
|
||||
return Math.min(maxSshBackendCoreDetectTimeoutMs, Math.max(2000, Math.trunc(parsed)));
|
||||
}
|
||||
|
||||
function isLocalSshCaptureBackendUnavailable(result: SshCaptureResult): boolean {
|
||||
return /No such container: unidesk-backend-core|failed to start broker|Executable not found.*"docker"|docker: not found|Cannot connect to the Docker daemon/iu.test(result.stderr);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user