mirror of
https://github.com/cirruslabs/orchard.git
synced 2026-10-07 23:41:33 +02:00
/exec API: drop session reconnection support (#487)
This commit is contained in:
@@ -365,176 +365,6 @@ func TestVMExecKeepsSharedSSHClientAfterSessionRejection(t *testing.T) {
|
||||
require.EqualValues(t, 1, sshServer.SuccessfulConnections())
|
||||
}
|
||||
|
||||
func TestVMExecSessionReconnectHistory(t *testing.T) {
|
||||
devClient, vmName := prepareForExec(t)
|
||||
sessionID := uuid.NewString()
|
||||
|
||||
wsConn, err := devClient.VMs().ExecSession(t.Context(), vmName, client.ExecSessionOptions{
|
||||
Command: "sh -c 'echo first; sleep 1; echo second'",
|
||||
WaitSeconds: 30,
|
||||
Session: sessionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
firstFrame := readFrame(t, wsConn)
|
||||
require.Equal(t, execstream.FrameTypeStdout, firstFrame.Type)
|
||||
require.Equal(t, "first\n", string(firstFrame.Data))
|
||||
require.EqualValues(t, 1, firstFrame.Watermark)
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{Type: execstream.FrameTypeDetach})
|
||||
require.NoError(t, err)
|
||||
_ = wsConn.CloseNow()
|
||||
|
||||
// Let the detached process finish so this test verifies partial replay
|
||||
// without relying on live-output timing.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
wsConn, err = devClient.VMs().ExecSession(t.Context(), vmName, client.ExecSessionOptions{
|
||||
WaitSeconds: 30,
|
||||
Session: sessionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer wsConn.CloseNow()
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{
|
||||
Type: execstream.FrameTypeHistory,
|
||||
Watermark: firstFrame.Watermark,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
frames := readFramesUntilExit(t, wsConn)
|
||||
require.Len(t, framesByType(frames, execstream.FrameTypeStdout), 1)
|
||||
require.Equal(t, "second\n", string(framesByType(frames, execstream.FrameTypeStdout)[0].Data))
|
||||
require.EqualValues(t, 0, framesByType(frames, execstream.FrameTypeExit)[0].Exit.Code)
|
||||
}
|
||||
|
||||
func TestVMExecSessionReconnectAfterExit(t *testing.T) {
|
||||
devClient, vmName := prepareForExec(t)
|
||||
sessionID := uuid.NewString()
|
||||
|
||||
wsConn, err := devClient.VMs().ExecSession(t.Context(), vmName, client.ExecSessionOptions{
|
||||
Command: "sh -c 'echo replay-me'",
|
||||
WaitSeconds: 30,
|
||||
Session: sessionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{Type: execstream.FrameTypeDetach})
|
||||
require.NoError(t, err)
|
||||
_ = wsConn.CloseNow()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
wsConn, err = devClient.VMs().ExecSession(t.Context(), vmName, client.ExecSessionOptions{
|
||||
WaitSeconds: 30,
|
||||
Session: sessionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer wsConn.CloseNow()
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{Type: execstream.FrameTypeHistory})
|
||||
require.NoError(t, err)
|
||||
|
||||
frames := readFramesUntilExit(t, wsConn)
|
||||
require.Equal(t, "replay-me\n", string(framesByType(frames, execstream.FrameTypeStdout)[0].Data))
|
||||
require.EqualValues(t, 0, framesByType(frames, execstream.FrameTypeExit)[0].Exit.Code)
|
||||
}
|
||||
|
||||
func TestVMExecSessionReplayPreservesStreams(t *testing.T) {
|
||||
devClient, vmName := prepareForExec(t)
|
||||
sessionID := uuid.NewString()
|
||||
|
||||
wsConn, err := devClient.VMs().ExecSession(t.Context(), vmName, client.ExecSessionOptions{
|
||||
Command: "sh -c 'echo out1; sleep 1; echo err1 >&2; sleep 1; echo out2; sleep 1; echo err2 >&2'",
|
||||
WaitSeconds: 30,
|
||||
Session: sessionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{Type: execstream.FrameTypeDetach})
|
||||
require.NoError(t, err)
|
||||
_ = wsConn.CloseNow()
|
||||
|
||||
time.Sleep(4 * time.Second)
|
||||
|
||||
wsConn, err = devClient.VMs().ExecSession(t.Context(), vmName, client.ExecSessionOptions{
|
||||
WaitSeconds: 30,
|
||||
Session: sessionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer wsConn.CloseNow()
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{Type: execstream.FrameTypeHistory})
|
||||
require.NoError(t, err)
|
||||
|
||||
frames := readFramesUntilExit(t, wsConn)
|
||||
require.Equal(t, []execstream.FrameType{
|
||||
execstream.FrameTypeStdout,
|
||||
execstream.FrameTypeStderr,
|
||||
execstream.FrameTypeStdout,
|
||||
execstream.FrameTypeStderr,
|
||||
execstream.FrameTypeExit,
|
||||
}, frameTypes(frames))
|
||||
require.Equal(t, "out1\n", string(frames[0].Data))
|
||||
require.Equal(t, "err1\n", string(frames[1].Data))
|
||||
require.Equal(t, "out2\n", string(frames[2].Data))
|
||||
require.Equal(t, "err2\n", string(frames[3].Data))
|
||||
}
|
||||
|
||||
func TestVMExecSessionStdinSurvivesReconnect(t *testing.T) {
|
||||
devClient, vmName := prepareForExec(t)
|
||||
sessionID := uuid.NewString()
|
||||
|
||||
wsConn, err := devClient.VMs().ExecSession(t.Context(), vmName, client.ExecSessionOptions{
|
||||
Command: "/bin/cat",
|
||||
Interactive: true,
|
||||
WaitSeconds: 30,
|
||||
Session: sessionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{
|
||||
Type: execstream.FrameTypeStdin,
|
||||
Data: []byte("one\n"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
frame := readFrame(t, wsConn)
|
||||
require.Equal(t, execstream.FrameTypeStdout, frame.Type)
|
||||
require.Equal(t, "one\n", string(frame.Data))
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{Type: execstream.FrameTypeDetach})
|
||||
require.NoError(t, err)
|
||||
_ = wsConn.CloseNow()
|
||||
|
||||
wsConn, err = devClient.VMs().ExecSession(t.Context(), vmName, client.ExecSessionOptions{
|
||||
WaitSeconds: 30,
|
||||
Session: sessionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer wsConn.CloseNow()
|
||||
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{
|
||||
Type: execstream.FrameTypeStdin,
|
||||
Data: []byte("two\n"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{
|
||||
Type: execstream.FrameTypeStdin,
|
||||
Data: []byte{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
err = execstream.WriteFrame(t.Context(), wsConn, &execstream.Frame{Type: execstream.FrameTypeHistory})
|
||||
require.NoError(t, err)
|
||||
|
||||
frames := readFramesUntilExit(t, wsConn)
|
||||
stdoutFrames := framesByType(frames, execstream.FrameTypeStdout)
|
||||
require.Len(t, stdoutFrames, 2)
|
||||
require.Equal(t, "one\n", string(stdoutFrames[0].Data))
|
||||
require.Equal(t, "two\n", string(stdoutFrames[1].Data))
|
||||
require.EqualValues(t, 0, framesByType(frames, execstream.FrameTypeExit)[0].Exit.Code)
|
||||
}
|
||||
|
||||
func prepareForExec(t *testing.T) (*client.Client, string) {
|
||||
devClient, _, _ := devcontroller.StartIntegrationTestEnvironment(t)
|
||||
|
||||
@@ -635,43 +465,3 @@ func readFrameErr(ctx context.Context, wsConn *websocket.Conn) (*execstream.Fram
|
||||
|
||||
return &frame, nil
|
||||
}
|
||||
|
||||
func readFramesUntilExit(t *testing.T, wsConn *websocket.Conn) []*execstream.Frame {
|
||||
t.Helper()
|
||||
|
||||
var frames []*execstream.Frame
|
||||
|
||||
for {
|
||||
frame := readFrame(t, wsConn)
|
||||
if frame.Type == execstream.FrameTypeNoMoreHistory {
|
||||
continue
|
||||
}
|
||||
|
||||
frames = append(frames, frame)
|
||||
if frame.Type == execstream.FrameTypeExit {
|
||||
return frames
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func framesByType(frames []*execstream.Frame, frameType execstream.FrameType) []*execstream.Frame {
|
||||
var result []*execstream.Frame
|
||||
|
||||
for _, frame := range frames {
|
||||
if frame.Type == frameType {
|
||||
result = append(result, frame)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func frameTypes(frames []*execstream.Frame) []execstream.FrameType {
|
||||
var result []execstream.FrameType
|
||||
|
||||
for _, frame := range frames {
|
||||
result = append(result, frame.Type)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user