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

Commit86b67ff

Browse files
committed
feat: add WorkspaceUpdates rpc
1 parentb5f7529 commit86b67ff

20 files changed

+1476
-232
lines changed

‎coderd/apidoc/docs.go

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,7 @@ func New(options *Options) *API {
10101010
r.Route("/roles",func(r chi.Router) {
10111011
r.Get("/",api.AssignableSiteRoles)
10121012
})
1013+
r.Get("/me/tailnet",api.tailnet)
10131014
r.Route("/{user}",func(r chi.Router) {
10141015
r.Use(httpmw.ExtractUserParam(options.Database))
10151016
r.Post("/convert-login",api.postConvertLoginType)

‎coderd/workspaceagents.go

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -856,26 +856,10 @@ func (api *API) workspaceAgentClientCoordinate(rw http.ResponseWriter, r *http.R
856856
return
857857
}
858858

859-
// Accept a resume_token query parameter to use the same peer ID.
860-
var (
861-
peerID=uuid.New()
862-
resumeToken=r.URL.Query().Get("resume_token")
863-
)
864-
ifresumeToken!="" {
865-
varerrerror
866-
peerID,err=api.Options.CoordinatorResumeTokenProvider.VerifyResumeToken(resumeToken)
867-
iferr!=nil {
868-
httpapi.Write(ctx,rw,http.StatusUnauthorized, codersdk.Response{
869-
Message:workspacesdk.CoordinateAPIInvalidResumeToken,
870-
Detail:err.Error(),
871-
Validations: []codersdk.ValidationError{
872-
{Field:"resume_token",Detail:workspacesdk.CoordinateAPIInvalidResumeToken},
873-
},
874-
})
875-
return
876-
}
877-
api.Logger.Debug(ctx,"accepted coordinate resume token for peer",
878-
slog.F("peer_id",peerID.String()))
859+
peerID,err:=api.handleResumeToken(ctx,rw,r)
860+
iferr!=nil {
861+
// handleResumeToken has already written the response.
862+
return
879863
}
880864

881865
api.WebsocketWaitMutex.Lock()
@@ -905,6 +889,28 @@ func (api *API) workspaceAgentClientCoordinate(rw http.ResponseWriter, r *http.R
905889
}
906890
}
907891

892+
// handleResumeToken accepts a resume_token query parameter to use the same peer ID
893+
func (api*API)handleResumeToken(ctx context.Context,rw http.ResponseWriter,r*http.Request) (peerID uuid.UUID,errerror) {
894+
peerID=uuid.New()
895+
resumeToken:=r.URL.Query().Get("resume_token")
896+
ifresumeToken!="" {
897+
peerID,err=api.Options.CoordinatorResumeTokenProvider.VerifyResumeToken(resumeToken)
898+
iferr!=nil {
899+
httpapi.Write(ctx,rw,http.StatusUnauthorized, codersdk.Response{
900+
Message:workspacesdk.CoordinateAPIInvalidResumeToken,
901+
Detail:err.Error(),
902+
Validations: []codersdk.ValidationError{
903+
{Field:"resume_token",Detail:workspacesdk.CoordinateAPIInvalidResumeToken},
904+
},
905+
})
906+
returnpeerID,err
907+
}
908+
api.Logger.Debug(ctx,"accepted coordinate resume token for peer",
909+
slog.F("peer_id",peerID.String()))
910+
}
911+
returnpeerID,err
912+
}
913+
908914
// @Summary Post workspace agent log source
909915
// @ID post-workspace-agent-log-source
910916
// @Security CoderSessionToken

‎coderd/workspacebuilds.go

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ func (api *API) convertWorkspaceBuild(
961961
MaxDeadline:codersdk.NewNullTime(build.MaxDeadline,!build.MaxDeadline.IsZero()),
962962
Reason:codersdk.BuildReason(build.Reason),
963963
Resources:apiResources,
964-
Status:convertWorkspaceStatus(apiJob.Status,transition),
964+
Status:codersdk.ConvertWorkspaceStatus(apiJob.Status,transition),
965965
DailyCost:build.DailyCost,
966966
},nil
967967
}
@@ -990,37 +990,3 @@ func convertWorkspaceResource(resource database.WorkspaceResource, agents []code
990990
DailyCost:resource.DailyCost,
991991
}
992992
}
993-
994-
funcconvertWorkspaceStatus(jobStatus codersdk.ProvisionerJobStatus,transition codersdk.WorkspaceTransition) codersdk.WorkspaceStatus {
995-
switchjobStatus {
996-
casecodersdk.ProvisionerJobPending:
997-
returncodersdk.WorkspaceStatusPending
998-
casecodersdk.ProvisionerJobRunning:
999-
switchtransition {
1000-
casecodersdk.WorkspaceTransitionStart:
1001-
returncodersdk.WorkspaceStatusStarting
1002-
casecodersdk.WorkspaceTransitionStop:
1003-
returncodersdk.WorkspaceStatusStopping
1004-
casecodersdk.WorkspaceTransitionDelete:
1005-
returncodersdk.WorkspaceStatusDeleting
1006-
}
1007-
casecodersdk.ProvisionerJobSucceeded:
1008-
switchtransition {
1009-
casecodersdk.WorkspaceTransitionStart:
1010-
returncodersdk.WorkspaceStatusRunning
1011-
casecodersdk.WorkspaceTransitionStop:
1012-
returncodersdk.WorkspaceStatusStopped
1013-
casecodersdk.WorkspaceTransitionDelete:
1014-
returncodersdk.WorkspaceStatusDeleted
1015-
}
1016-
casecodersdk.ProvisionerJobCanceling:
1017-
returncodersdk.WorkspaceStatusCanceling
1018-
casecodersdk.ProvisionerJobCanceled:
1019-
returncodersdk.WorkspaceStatusCanceled
1020-
casecodersdk.ProvisionerJobFailed:
1021-
returncodersdk.WorkspaceStatusFailed
1022-
}
1023-
1024-
// return error status since we should never get here
1025-
returncodersdk.WorkspaceStatusFailed
1026-
}

‎coderd/workspaces.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/json"
77
"errors"
88
"fmt"
9+
"io"
910
"net/http"
1011
"slices"
1112
"strconv"
@@ -15,6 +16,7 @@ import (
1516
"github.com/go-chi/chi/v5"
1617
"github.com/google/uuid"
1718
"golang.org/x/xerrors"
19+
"nhooyr.io/websocket"
1820

1921
"cdr.dev/slog"
2022
"github.com/coder/coder/v2/agent/proto"
@@ -37,6 +39,7 @@ import (
3739
"github.com/coder/coder/v2/coderd/wspubsub"
3840
"github.com/coder/coder/v2/codersdk"
3941
"github.com/coder/coder/v2/codersdk/agentsdk"
42+
"github.com/coder/coder/v2/tailnet"
4043
)
4144

4245
var (
@@ -2090,6 +2093,11 @@ func (api *API) publishWorkspaceUpdate(ctx context.Context, ownerID uuid.UUID, e
20902093
api.Logger.Warn(ctx,"failed to publish workspace update",
20912094
slog.F("workspace_id",event.WorkspaceID),slog.Error(err))
20922095
}
2096+
err=api.Pubsub.Publish(codersdk.AllWorkspacesNotifyChannel, []byte(workspaceID.String()))
2097+
iferr!=nil {
2098+
api.Logger.Warn(ctx,"failed to publish all workspaces update",
2099+
slog.F("workspace_id",workspaceID),slog.Error(err))
2100+
}
20932101
}
20942102

20952103
func (api*API)publishWorkspaceAgentLogsUpdate(ctx context.Context,workspaceAgentID uuid.UUID,m agentsdk.LogsNotifyMessage) {
@@ -2102,3 +2110,72 @@ func (api *API) publishWorkspaceAgentLogsUpdate(ctx context.Context, workspaceAg
21022110
api.Logger.Warn(ctx,"failed to publish workspace agent logs update",slog.F("workspace_agent_id",workspaceAgentID),slog.Error(err))
21032111
}
21042112
}
2113+
2114+
// @Summary Coordinate multiple workspace agents
2115+
// @ID coordinate-multiple-workspace-agents
2116+
// @Security CoderSessionToken
2117+
// @Tags Workspaces
2118+
// @Success 101
2119+
// @Router /users/me/tailnet [get]
2120+
func (api*API)tailnet(rw http.ResponseWriter,r*http.Request) {
2121+
ctx:=r.Context()
2122+
owner:=httpmw.UserParam(r)
2123+
ownerRoles:=httpmw.UserAuthorization(r)
2124+
2125+
// Check if the actor is allowed to access any workspace owned by the user.
2126+
if!api.Authorize(r,policy.ActionSSH,rbac.ResourceWorkspace.WithOwner(owner.ID.String())) {
2127+
httpapi.ResourceNotFound(rw)
2128+
return
2129+
}
2130+
2131+
version:="1.0"
2132+
qv:=r.URL.Query().Get("version")
2133+
ifqv!="" {
2134+
version=qv
2135+
}
2136+
iferr:=proto.CurrentVersion.Validate(version);err!=nil {
2137+
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
2138+
Message:"Unknown or unsupported API version",
2139+
Validations: []codersdk.ValidationError{
2140+
{Field:"version",Detail:err.Error()},
2141+
},
2142+
})
2143+
return
2144+
}
2145+
2146+
peerID,err:=api.handleResumeToken(ctx,rw,r)
2147+
iferr!=nil {
2148+
// handleResumeToken has already written the response.
2149+
return
2150+
}
2151+
2152+
api.WebsocketWaitMutex.Lock()
2153+
api.WebsocketWaitGroup.Add(1)
2154+
api.WebsocketWaitMutex.Unlock()
2155+
deferapi.WebsocketWaitGroup.Done()
2156+
2157+
conn,err:=websocket.Accept(rw,r,nil)
2158+
iferr!=nil {
2159+
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
2160+
Message:"Failed to accept websocket.",
2161+
Detail:err.Error(),
2162+
})
2163+
return
2164+
}
2165+
ctx,wsNetConn:=codersdk.WebsocketNetConn(ctx,conn,websocket.MessageBinary)
2166+
deferwsNetConn.Close()
2167+
deferconn.Close(websocket.StatusNormalClosure,"")
2168+
2169+
gohttpapi.Heartbeat(ctx,conn)
2170+
err=api.TailnetClientService.ServeUserClient(ctx,version,wsNetConn, tailnet.ServeUserClientOptions{
2171+
PeerID:peerID,
2172+
UserID:owner.ID,
2173+
Subject:&ownerRoles,
2174+
Authz:api.Authorizer,
2175+
Database:api.Database,
2176+
})
2177+
iferr!=nil&&!xerrors.Is(err,io.EOF)&&!xerrors.Is(err,context.Canceled) {
2178+
_=conn.Close(websocket.StatusInternalError,err.Error())
2179+
return
2180+
}
2181+
}

‎codersdk/provisionerdaemons.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,37 @@ func (c *Client) DeleteProvisionerKey(ctx context.Context, organizationID uuid.U
402402
}
403403
returnnil
404404
}
405+
406+
funcConvertWorkspaceStatus(jobStatusProvisionerJobStatus,transitionWorkspaceTransition)WorkspaceStatus {
407+
switchjobStatus {
408+
caseProvisionerJobPending:
409+
returnWorkspaceStatusPending
410+
caseProvisionerJobRunning:
411+
switchtransition {
412+
caseWorkspaceTransitionStart:
413+
returnWorkspaceStatusStarting
414+
caseWorkspaceTransitionStop:
415+
returnWorkspaceStatusStopping
416+
caseWorkspaceTransitionDelete:
417+
returnWorkspaceStatusDeleting
418+
}
419+
caseProvisionerJobSucceeded:
420+
switchtransition {
421+
caseWorkspaceTransitionStart:
422+
returnWorkspaceStatusRunning
423+
caseWorkspaceTransitionStop:
424+
returnWorkspaceStatusStopped
425+
caseWorkspaceTransitionDelete:
426+
returnWorkspaceStatusDeleted
427+
}
428+
caseProvisionerJobCanceling:
429+
returnWorkspaceStatusCanceling
430+
caseProvisionerJobCanceled:
431+
returnWorkspaceStatusCanceled
432+
caseProvisionerJobFailed:
433+
returnWorkspaceStatusFailed
434+
}
435+
436+
// return error status since we should never get here
437+
returnWorkspaceStatusFailed
438+
}

‎codersdk/workspacesdk/connector_internal_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,11 @@ func (f *fakeDRPCClient) RefreshResumeToken(_ context.Context, _ *proto.RefreshR
571571
},nil
572572
}
573573

574+
// WorkspaceUpdates implements proto.DRPCTailnetClient.
575+
func (*fakeDRPCClient)WorkspaceUpdates(context.Context,*proto.WorkspaceUpdatesRequest) (proto.DRPCTailnet_WorkspaceUpdatesClient,error) {
576+
panic("unimplemented")
577+
}
578+
574579
typefakeDRPCConnstruct{}
575580

576581
var_ drpc.Conn=&fakeDRPCConn{}

‎docs/reference/api/workspaces.md

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎enterprise/tailnet/connio.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ var errDisconnect = xerrors.New("graceful disconnect")
133133

134134
func (c*connIO)handleRequest(req*proto.CoordinateRequest)error {
135135
c.logger.Debug(c.peerCtx,"got request")
136-
err:=c.auth.Authorize(req)
136+
err:=c.auth.Authorize(c.coordCtx,req)
137137
iferr!=nil {
138138
c.logger.Warn(c.peerCtx,"unauthorized request",slog.Error(err))
139139
returnxerrors.Errorf("authorize request: %w",err)

‎tailnet/convert.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"tailscale.com/tailcfg"
1010
"tailscale.com/types/key"
1111

12+
"github.com/coder/coder/v2/codersdk"
1213
"github.com/coder/coder/v2/tailnet/proto"
1314
)
1415

@@ -270,3 +271,30 @@ func DERPNodeFromProto(node *proto.DERPMap_Region_Node) *tailcfg.DERPNode {
270271
CanPort80:node.CanPort_80,
271272
}
272273
}
274+
275+
funcWorkspaceStatusToProto(status codersdk.WorkspaceStatus) proto.Workspace_Status {
276+
switchstatus {
277+
casecodersdk.WorkspaceStatusCanceled:
278+
returnproto.Workspace_CANCELED
279+
casecodersdk.WorkspaceStatusCanceling:
280+
returnproto.Workspace_CANCELING
281+
casecodersdk.WorkspaceStatusDeleted:
282+
returnproto.Workspace_DELETED
283+
casecodersdk.WorkspaceStatusDeleting:
284+
returnproto.Workspace_DELETING
285+
casecodersdk.WorkspaceStatusFailed:
286+
returnproto.Workspace_FAILED
287+
casecodersdk.WorkspaceStatusPending:
288+
returnproto.Workspace_PENDING
289+
casecodersdk.WorkspaceStatusRunning:
290+
returnproto.Workspace_RUNNING
291+
casecodersdk.WorkspaceStatusStarting:
292+
returnproto.Workspace_STARTING
293+
casecodersdk.WorkspaceStatusStopped:
294+
returnproto.Workspace_STOPPED
295+
casecodersdk.WorkspaceStatusStopping:
296+
returnproto.Workspace_STOPPING
297+
default:
298+
returnproto.Workspace_UNKNOWN
299+
}
300+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp