fix(plugin): close kubernetes exec timeout edges

This commit is contained in:
Dotta
2026-05-13 14:10:04 -05:00
committed by Chris Farhood
parent 40e8638aa3
commit 3e998bda97
2 changed files with 40 additions and 1 deletions
@@ -153,7 +153,7 @@ export async function execInPod(
websocketPromise
.then((webSocket) => {
ws = webSocket as WebSocketLike;
if (stdinStream && stdinPayload) {
if (!settled && stdinStream && stdinPayload) {
stdinStream.end(stdinPayload);
}
ws.on("close", (code: number, reason: Buffer) => {
@@ -168,6 +168,7 @@ export async function execInPod(
})
.catch((err) => {
if (settled) return;
if (timeout) clearTimeout(timeout);
reject(err);
});
},
@@ -63,6 +63,17 @@ describe("execInPod", () => {
expect(result.stderr).toContain("Kubernetes exec timed out after 5ms");
});
it("clears the timeout when websocket setup rejects", async () => {
const clearTimeoutSpy = vi.spyOn(globalThis, "clearTimeout");
execMock.mockRejectedValue(new Error("network unreachable"));
await expect(
execInPod({} as never, "ns", "pod-1", "agent", ["echo", "ok"], undefined, 1000),
).rejects.toThrow("network unreachable");
expect(clearTimeoutSpy).toHaveBeenCalled();
clearTimeoutSpy.mockRestore();
});
it("wraps stdin commands with a byte-counted head prefix", async () => {
let observedCommand: string[] | undefined;
let observedStdin = "";
@@ -89,4 +100,31 @@ describe("execInPod", () => {
expect(observedStdin).toBe("abc");
expect(observedStdinFinished).toBe(true);
});
it("does not send stdin if the exec timed out before websocket setup completed", async () => {
let resolveWebsocket: ((ws: EventEmitter) => void) | undefined;
let observedStdin = "";
let observedStdinFinished = false;
execMock.mockImplementation((_namespace, _pod, _container, _command, _stdout, _stderr, stdin) => {
stdin?.on("data", (chunk: Buffer) => {
observedStdin += chunk.toString("utf8");
});
stdin?.on("finish", () => {
observedStdinFinished = true;
});
return new Promise<EventEmitter>((resolve) => {
resolveWebsocket = resolve;
});
});
const result = await execInPod({} as never, "ns", "pod-1", "agent", ["base64", "-d"], "abc", 5);
expect(result.timedOut).toBe(true);
resolveWebsocket?.(new EventEmitter());
await Promise.resolve();
expect(observedStdin).toBe("");
expect(observedStdinFinished).toBe(false);
});
});