Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6862409

Browse files
authored
feat(agent/reconnectingpty): allow selecting backend type (#17011)
agent/reconnectingpty: allow specifying backend typecli: exp rpty: automatically select backend based on command
1 parent0cd254f commit6862409

File tree

7 files changed

+78
-21
lines changed

7 files changed

+78
-21
lines changed

‎agent/reconnectingpty/reconnectingpty.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ type Options struct {
3232
Timeout time.Duration
3333
// Metrics tracks various error counters.
3434
Metrics*prometheus.CounterVec
35+
// BackendType specifies the ReconnectingPTY backend to use.
36+
BackendTypestring
3537
}
3638

3739
// ReconnectingPTY is a pty that can be reconnected within a timeout and to
@@ -64,13 +66,20 @@ func New(ctx context.Context, logger slog.Logger, execer agentexec.Execer, cmd *
6466
// runs) but in CI screen often incorrectly claims the session name does not
6567
// exist even though screen -list shows it. For now, restrict screen to
6668
// Linux.
67-
backendType:="buffered"
69+
autoBackendType:="buffered"
6870
ifruntime.GOOS=="linux" {
6971
_,err:=exec.LookPath("screen")
7072
iferr==nil {
71-
backendType="screen"
73+
autoBackendType="screen"
7274
}
7375
}
76+
varbackendTypestring
77+
switchoptions.BackendType {
78+
case"":
79+
backendType=autoBackendType
80+
default:
81+
backendType=options.BackendType
82+
}
7483

7584
logger.Info(ctx,"start reconnecting pty",slog.F("backend_type",backendType))
7685

‎agent/reconnectingpty/server.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,9 @@ func (s *Server) handleConn(ctx context.Context, logger slog.Logger, conn net.Co
207207
s.commandCreator.Execer,
208208
cmd,
209209
&Options{
210-
Timeout:s.timeout,
211-
Metrics:s.errorsTotal,
210+
Timeout:s.timeout,
211+
Metrics:s.errorsTotal,
212+
BackendType:msg.BackendType,
212213
},
213214
)
214215

‎cli/exp_rpty.go

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bufio"
55
"context"
66
"encoding/json"
7-
"fmt"
87
"io"
98
"os"
109
"strings"
@@ -15,6 +14,7 @@ import (
1514
"golang.org/x/xerrors"
1615

1716
"github.com/coder/coder/v2/cli/cliui"
17+
"github.com/coder/coder/v2/coderd/util/slice"
1818
"github.com/coder/coder/v2/codersdk"
1919
"github.com/coder/coder/v2/codersdk/workspacesdk"
2020
"github.com/coder/coder/v2/pty"
@@ -96,6 +96,7 @@ func handleRPTY(inv *serpent.Invocation, client *codersdk.Client, args handleRPT
9696
}else {
9797
reconnectID=uuid.New()
9898
}
99+
99100
ws,agt,err:=getWorkspaceAndAgent(ctx,inv,client,true,args.NamedWorkspace)
100101
iferr!=nil {
101102
returnerr
@@ -118,14 +119,6 @@ func handleRPTY(inv *serpent.Invocation, client *codersdk.Client, args handleRPT
118119
}
119120
}
120121

121-
iferr:=cliui.Agent(ctx,inv.Stderr,agt.ID, cliui.AgentOptions{
122-
FetchInterval:0,
123-
Fetch:client.WorkspaceAgent,
124-
Wait:false,
125-
});err!=nil {
126-
returnerr
127-
}
128-
129122
// Get the width and height of the terminal.
130123
vartermWidth,termHeightuint16
131124
stdoutFile,validOut:=inv.Stdout.(*os.File)
@@ -149,6 +142,15 @@ func handleRPTY(inv *serpent.Invocation, client *codersdk.Client, args handleRPT
149142
}()
150143
}
151144

145+
// If a user does not specify a command, we'll assume they intend to open an
146+
// interactive shell.
147+
varbackendstring
148+
ifisOneShotCommand(args.Command) {
149+
// If the user specified a command, we'll prefer to use the buffered method.
150+
// The screen backend is not well suited for one-shot commands.
151+
backend="buffered"
152+
}
153+
152154
conn,err:=workspacesdk.New(client).AgentReconnectingPTY(ctx, workspacesdk.WorkspaceAgentReconnectingPTYOpts{
153155
AgentID:agt.ID,
154156
Reconnect:reconnectID,
@@ -157,14 +159,13 @@ func handleRPTY(inv *serpent.Invocation, client *codersdk.Client, args handleRPT
157159
ContainerUser:args.ContainerUser,
158160
Width:termWidth,
159161
Height:termHeight,
162+
BackendType:backend,
160163
})
161164
iferr!=nil {
162165
returnxerrors.Errorf("open reconnecting PTY: %w",err)
163166
}
164167
deferconn.Close()
165168

166-
cliui.Infof(inv.Stderr,"Connected to %s (agent id: %s)",args.NamedWorkspace,agt.ID)
167-
cliui.Infof(inv.Stderr,"Reconnect ID: %s",reconnectID)
168169
closeUsage:=client.UpdateWorkspaceUsageWithBodyContext(ctx,ws.ID, codersdk.PostWorkspaceUsageRequest{
169170
AgentID:agt.ID,
170171
AppName:codersdk.UsageAppNameReconnectingPty,
@@ -210,7 +211,21 @@ func handleRPTY(inv *serpent.Invocation, client *codersdk.Client, args handleRPT
210211
_,_=io.Copy(inv.Stdout,conn)
211212
cancel()
212213
_=conn.Close()
213-
_,_=fmt.Fprintf(inv.Stderr,"Connection closed\n")
214214

215215
returnnil
216216
}
217+
218+
varknownShells= []string{"ash","bash","csh","dash","fish","ksh","powershell","pwsh","zsh"}
219+
220+
funcisOneShotCommand(cmd []string)bool {
221+
// If the command is empty, we'll assume the user wants to open a shell.
222+
iflen(cmd)==0 {
223+
returnfalse
224+
}
225+
// If the command is a single word, and that word is a known shell, we'll
226+
// assume the user wants to open a shell.
227+
iflen(cmd)==1&&slice.Contains(knownShells,cmd[0]) {
228+
returnfalse
229+
}
230+
returntrue
231+
}

‎cli/exp_rpty_test.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package cli_test
22

33
import (
4-
"fmt"
54
"runtime"
65
"testing"
76

7+
"github.com/google/uuid"
88
"github.com/ory/dockertest/v3"
99
"github.com/ory/dockertest/v3/docker"
1010

@@ -23,7 +23,7 @@ import (
2323
funcTestExpRpty(t*testing.T) {
2424
t.Parallel()
2525

26-
t.Run("OK",func(t*testing.T) {
26+
t.Run("DefaultCommand",func(t*testing.T) {
2727
t.Parallel()
2828

2929
client,workspace,agentToken:=setupWorkspaceForAgent(t)
@@ -41,11 +41,33 @@ func TestExpRpty(t *testing.T) {
4141
_=agenttest.New(t,client.URL,agentToken)
4242
_=coderdtest.NewWorkspaceAgentWaiter(t,client,workspace.ID).Wait()
4343

44-
pty.ExpectMatch(fmt.Sprintf("Connected to %s",workspace.Name))
4544
pty.WriteLine("exit")
4645
<-cmdDone
4746
})
4847

48+
t.Run("Command",func(t*testing.T) {
49+
t.Parallel()
50+
51+
client,workspace,agentToken:=setupWorkspaceForAgent(t)
52+
randStr:=uuid.NewString()
53+
inv,root:=clitest.New(t,"exp","rpty",workspace.Name,"echo",randStr)
54+
clitest.SetupConfig(t,client,root)
55+
pty:=ptytest.New(t).Attach(inv)
56+
57+
ctx:=testutil.Context(t,testutil.WaitLong)
58+
59+
cmdDone:=tGo(t,func() {
60+
err:=inv.WithContext(ctx).Run()
61+
assert.NoError(t,err)
62+
})
63+
64+
_=agenttest.New(t,client.URL,agentToken)
65+
_=coderdtest.NewWorkspaceAgentWaiter(t,client,workspace.ID).Wait()
66+
67+
pty.ExpectMatch(randStr)
68+
<-cmdDone
69+
})
70+
4971
t.Run("NotFound",func(t*testing.T) {
5072
t.Parallel()
5173

@@ -103,8 +125,6 @@ func TestExpRpty(t *testing.T) {
103125
assert.NoError(t,err)
104126
})
105127

106-
pty.ExpectMatch(fmt.Sprintf("Connected to %s",workspace.Name))
107-
pty.ExpectMatch("Reconnect ID: ")
108128
pty.ExpectMatch(" #")
109129
pty.WriteLine("hostname")
110130
pty.ExpectMatch(ct.Container.Config.Hostname)

‎coderd/workspaceapps/proxy.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ func (s *Server) workspaceAgentPTY(rw http.ResponseWriter, r *http.Request) {
655655
width:=parser.UInt(values,80,"width")
656656
container:=parser.String(values,"","container")
657657
containerUser:=parser.String(values,"","container_user")
658+
backendType:=parser.String(values,"","backend_type")
658659
iflen(parser.Errors)>0 {
659660
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
660661
Message:"Invalid query parameters.",
@@ -695,6 +696,7 @@ func (s *Server) workspaceAgentPTY(rw http.ResponseWriter, r *http.Request) {
695696
ptNetConn,err:=agentConn.ReconnectingPTY(ctx,reconnect,uint16(height),uint16(width),r.URL.Query().Get("command"),func(arp*workspacesdk.AgentReconnectingPTYInit) {
696697
arp.Container=container
697698
arp.ContainerUser=containerUser
699+
arp.BackendType=backendType
698700
})
699701
iferr!=nil {
700702
log.Debug(ctx,"dial reconnecting pty server in workspace agent",slog.Error(err))

‎codersdk/workspacesdk/agentconn.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ type AgentReconnectingPTYInit struct {
100100
// This can be a username or UID, depending on the underlying implementation.
101101
// This is ignored if Container is not set.
102102
ContainerUserstring
103+
104+
BackendTypestring
103105
}
104106

105107
// AgentReconnectingPTYInitOption is a functional option for AgentReconnectingPTYInit.

‎codersdk/workspacesdk/workspacesdk.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,11 @@ type WorkspaceAgentReconnectingPTYOpts struct {
318318
// CODER_AGENT_DEVCONTAINERS_ENABLE set to "true".
319319
Containerstring
320320
ContainerUserstring
321+
322+
// BackendType is the type of backend to use for the PTY. If not set, the
323+
// workspace agent will attempt to determine the preferred backend type.
324+
// Supported values are "screen" and "buffered".
325+
BackendTypestring
321326
}
322327

323328
// AgentReconnectingPTY spawns a PTY that reconnects using the token provided.
@@ -339,6 +344,9 @@ func (c *Client) AgentReconnectingPTY(ctx context.Context, opts WorkspaceAgentRe
339344
ifopts.ContainerUser!="" {
340345
q.Set("container_user",opts.ContainerUser)
341346
}
347+
ifopts.BackendType!="" {
348+
q.Set("backend_type",opts.BackendType)
349+
}
342350
// If we're using a signed token, set the query parameter.
343351
ifopts.SignedToken!="" {
344352
q.Set(codersdk.SignedAppTokenQueryParameter,opts.SignedToken)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp