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

Commit5b59f28

Browse files
authored
fix: fix workspacesdk to return error on API mismatch (#13683)
1 parentc4f1676 commit5b59f28

File tree

4 files changed

+66
-3
lines changed

4 files changed

+66
-3
lines changed

‎codersdk/workspacesdk/connector.go‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package workspacesdk
33
import (
44
"context"
55
"errors"
6+
"fmt"
67
"io"
78
"net/http"
9+
"slices"
810
"sync"
911
"time"
1012

@@ -14,6 +16,7 @@ import (
1416
"tailscale.com/tailcfg"
1517

1618
"cdr.dev/slog"
19+
"github.com/coder/coder/v2/buildinfo"
1720
"github.com/coder/coder/v2/codersdk"
1821
"github.com/coder/coder/v2/tailnet"
1922
"github.com/coder/coder/v2/tailnet/proto"
@@ -101,6 +104,9 @@ func (tac *tailnetAPIConnector) run() {
101104
deferclose(tac.closed)
102105
forretrier:=retry.New(50*time.Millisecond,10*time.Second);retrier.Wait(tac.ctx); {
103106
tailnetClient,err:=tac.dial()
107+
ifxerrors.Is(err,&codersdk.Error{}) {
108+
return
109+
}
104110
iferr!=nil {
105111
continue
106112
}
@@ -110,13 +116,29 @@ func (tac *tailnetAPIConnector) run() {
110116
}
111117
}
112118

119+
varpermanentErrorStatuses= []int{
120+
http.StatusConflict,// returned if client/agent connections disabled (browser only)
121+
http.StatusBadRequest,// returned if API mismatch
122+
http.StatusNotFound,// returned if user doesn't have permission or agent doesn't exist
123+
}
124+
113125
func (tac*tailnetAPIConnector)dial() (proto.DRPCTailnetClient,error) {
114126
tac.logger.Debug(tac.ctx,"dialing Coder tailnet v2+ API")
115127
// nolint:bodyclose
116128
ws,res,err:=websocket.Dial(tac.ctx,tac.coordinateURL,tac.dialOptions)
117129
iftac.isFirst {
118-
ifres!=nil&&res.StatusCode==http.StatusConflict {
130+
ifres!=nil&&slices.Contains(permanentErrorStatuses,res.StatusCode) {
119131
err=codersdk.ReadBodyAsError(res)
132+
// A bit more human-readable help in the case the API version was rejected
133+
varsdkErr*codersdk.Error
134+
ifxerrors.As(err,&sdkErr) {
135+
ifsdkErr.Message==AgentAPIMismatchMessage&&
136+
sdkErr.StatusCode()==http.StatusBadRequest {
137+
sdkErr.Helper=fmt.Sprintf(
138+
"Ensure your client release version (%s, different than the API version) matches the server release version",
139+
buildinfo.Version())
140+
}
141+
}
120142
tac.connected<-err
121143
returnnil,err
122144
}

‎codersdk/workspacesdk/connector_internal_test.go‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818

1919
"cdr.dev/slog"
2020
"cdr.dev/slog/sloggers/slogtest"
21+
"github.com/coder/coder/v2/apiversion"
22+
"github.com/coder/coder/v2/coderd/httpapi"
2123
"github.com/coder/coder/v2/codersdk"
2224
"github.com/coder/coder/v2/tailnet"
2325
"github.com/coder/coder/v2/tailnet/proto"
@@ -97,6 +99,41 @@ func TestTailnetAPIConnector_Disconnects(t *testing.T) {
9799
require.NotNil(t,reqDisc.Disconnect)
98100
}
99101

102+
funcTestTailnetAPIConnector_UplevelVersion(t*testing.T) {
103+
t.Parallel()
104+
ctx:=testutil.Context(t,testutil.WaitShort)
105+
logger:=slogtest.Make(t,nil).Leveled(slog.LevelDebug)
106+
agentID:= uuid.UUID{0x55}
107+
108+
svr:=httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter,r*http.Request) {
109+
sVer:=apiversion.New(proto.CurrentMajor,proto.CurrentMinor-1)
110+
111+
// the following matches what Coderd does;
112+
// c.f. coderd/workspaceagents.go: workspaceAgentClientCoordinate
113+
cVer:=r.URL.Query().Get("version")
114+
iferr:=sVer.Validate(cVer);err!=nil {
115+
httpapi.Write(ctx,w,http.StatusBadRequest, codersdk.Response{
116+
Message:AgentAPIMismatchMessage,
117+
Validations: []codersdk.ValidationError{
118+
{Field:"version",Detail:err.Error()},
119+
},
120+
})
121+
return
122+
}
123+
}))
124+
125+
fConn:=newFakeTailnetConn()
126+
127+
uut:=runTailnetAPIConnector(ctx,logger,agentID,svr.URL,&websocket.DialOptions{},fConn)
128+
129+
err:=testutil.RequireRecvCtx(ctx,t,uut.connected)
130+
varsdkErr*codersdk.Error
131+
require.ErrorAs(t,err,&sdkErr)
132+
require.Equal(t,http.StatusBadRequest,sdkErr.StatusCode())
133+
require.Equal(t,AgentAPIMismatchMessage,sdkErr.Message)
134+
require.NotEmpty(t,sdkErr.Helper)
135+
}
136+
100137
typefakeTailnetConnstruct{}
101138

102139
func (*fakeTailnetConn)UpdatePeers([]*proto.CoordinateResponse_PeerUpdate)error {

‎codersdk/workspacesdk/workspacesdk.go‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ const (
5555
AgentMinimumListeningPort=9
5656
)
5757

58+
constAgentAPIMismatchMessage="Unknown or unsupported API version"
59+
5860
// AgentIgnoredListeningPorts contains a list of ports to ignore when looking for
5961
// running applications inside a workspace. We want to ignore non-HTTP servers,
6062
// so we pre-populate this list with common ports that are not HTTP servers.

‎enterprise/coderd/workspaceagents_test.go‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ func TestBlockNonBrowser(t *testing.T) {
4646
},
4747
})
4848
r:=setupWorkspaceAgent(t,client,user,0)
49+
ctx:=testutil.Context(t,testutil.WaitShort)
4950
//nolint:gocritic // Testing that even the owner gets blocked.
50-
_,err:=workspacesdk.New(client).DialAgent(context.Background(),r.sdkAgent.ID,nil)
51+
_,err:=workspacesdk.New(client).DialAgent(ctx,r.sdkAgent.ID,nil)
5152
varapiErr*codersdk.Error
5253
require.ErrorAs(t,err,&apiErr)
5354
require.Equal(t,http.StatusConflict,apiErr.StatusCode())
@@ -65,8 +66,9 @@ func TestBlockNonBrowser(t *testing.T) {
6566
},
6667
})
6768
r:=setupWorkspaceAgent(t,client,user,0)
69+
ctx:=testutil.Context(t,testutil.WaitShort)
6870
//nolint:gocritic // Testing RBAC is not the point of this test.
69-
conn,err:=workspacesdk.New(client).DialAgent(context.Background(),r.sdkAgent.ID,nil)
71+
conn,err:=workspacesdk.New(client).DialAgent(ctx,r.sdkAgent.ID,nil)
7072
require.NoError(t,err)
7173
_=conn.Close()
7274
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp