fix: isolate provider egress tunnel diagnostics
This commit is contained in:
@@ -199,6 +199,91 @@ export async function debugSshPool(_config: UniDeskConfig, providerId: string):
|
||||
};
|
||||
}
|
||||
|
||||
export async function debugEgressProxy(_config: UniDeskConfig, providerId: string): Promise<unknown> {
|
||||
const nodesResponse = await coreInternalFetch("/api/nodes");
|
||||
const body = recordValue(recordValue(nodesResponse).body);
|
||||
const nodes = arrayValue(body.nodes);
|
||||
const node = nodes
|
||||
.map((item) => recordValue(item))
|
||||
.find((item) => item.providerId === providerId) ?? null;
|
||||
if (node === null) {
|
||||
return {
|
||||
ok: false,
|
||||
providerId,
|
||||
degradedReason: "provider-not-found",
|
||||
nodesFetch: nodesResponse,
|
||||
next: { fullHealth: "bun scripts/cli.ts debug health" },
|
||||
};
|
||||
}
|
||||
const labels = recordValue(node.labels);
|
||||
const active = Number(labels.providerGatewayEgressProxyActiveTunnels ?? 0);
|
||||
const pending = Number(labels.providerGatewayEgressProxyPendingTunnels ?? 0);
|
||||
const opened = Number(labels.providerGatewayEgressProxyOpenedTunnels ?? 0);
|
||||
const stale = Number(labels.providerGatewayEgressProxyStaleTunnels ?? 0);
|
||||
const enabled = labels.providerGatewayEgressProxy === true;
|
||||
const connected = labels.providerGatewayEgressProxyConnected === true;
|
||||
const sshReady = Number(labels.providerGatewaySshDataPoolReady ?? 0);
|
||||
const activeTunnelDetails = arrayValue(labels.providerGatewayEgressProxyActiveTunnelDetails);
|
||||
const recentClosedTunnels = arrayValue(labels.providerGatewayEgressProxyRecentClosedTunnels);
|
||||
const ok = enabled && connected && stale === 0;
|
||||
return {
|
||||
ok,
|
||||
providerId,
|
||||
node: {
|
||||
providerId: node.providerId,
|
||||
name: node.name,
|
||||
status: node.status,
|
||||
lastHeartbeat: node.lastHeartbeat ?? null,
|
||||
updatedAt: node.updatedAt ?? null,
|
||||
},
|
||||
egressProxy: {
|
||||
enabled,
|
||||
connected,
|
||||
port: labels.providerGatewayEgressProxyPort ?? null,
|
||||
activeTunnels: Number.isFinite(active) ? active : 0,
|
||||
pendingTunnels: Number.isFinite(pending) ? pending : 0,
|
||||
openedTunnels: Number.isFinite(opened) ? opened : 0,
|
||||
staleTunnels: Number.isFinite(stale) ? stale : 0,
|
||||
oldestTunnelAgeMs: labels.providerGatewayEgressProxyOldestTunnelAgeMs ?? null,
|
||||
policy: {
|
||||
openTimeoutMs: labels.providerGatewayEgressProxyOpenTimeoutMs ?? null,
|
||||
idleTimeoutMs: labels.providerGatewayEgressProxyIdleTimeoutMs ?? null,
|
||||
maxTunnelAgeMs: labels.providerGatewayEgressProxyMaxTunnelAgeMs ?? null,
|
||||
staleTunnelIdleMs: labels.providerGatewayEgressProxyStaleTunnelIdleMs ?? null,
|
||||
maxPendingBytes: labels.providerGatewayEgressProxyMaxPendingBytes ?? null,
|
||||
},
|
||||
activeTunnelDetails,
|
||||
activeTunnelDetailsCount: activeTunnelDetails.length,
|
||||
recentClosedTunnels,
|
||||
recentClosedTunnelCount: recentClosedTunnels.length,
|
||||
},
|
||||
controlPlaneSeparation: {
|
||||
sshDataTransport: stringValue(labels.providerGatewaySshDataTransport),
|
||||
sshDataPoolReady: Number.isFinite(sshReady) ? sshReady : 0,
|
||||
sshDataPoolDesired: labels.providerGatewaySshDataPoolDesired ?? null,
|
||||
sshDataPoolClaimed: labels.providerGatewaySshDataPoolClaimed ?? null,
|
||||
note: "SSH/control readiness is reported separately from egress download tunnel activity.",
|
||||
},
|
||||
classification: !enabled
|
||||
? "egress-proxy-disabled"
|
||||
: !connected
|
||||
? "egress-proxy-core-channel-disconnected"
|
||||
: stale > 0
|
||||
? "egress-tunnel-stale"
|
||||
: active > 0
|
||||
? "egress-tunnel-active"
|
||||
: "egress-proxy-ready",
|
||||
outputPolicy: {
|
||||
redaction: "activeTunnelDetails expose target host/port and path/query-key summary only; URL credentials, headers, tokens and query values are not emitted.",
|
||||
boundedRecentClosedTunnels: true,
|
||||
},
|
||||
next: {
|
||||
smoke: `trans ${providerId} argv true`,
|
||||
fullHealth: "bun scripts/cli.ts debug health",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function waitForTask(taskId: string, timeoutMs: number): Promise<unknown> {
|
||||
const started = Date.now();
|
||||
let latest: unknown = null;
|
||||
|
||||
Reference in New Issue
Block a user