@Summary Workspace agent RPC API @ID workspace-agent-rpc-api @Security CoderSessionToken @Tags Agents @Success 101 @Router /api/v2/workspaceagents/me/rpc [get] @x-apidocgen {"skip": true}
(rw http.ResponseWriter, r *http.Request)
| 40 | // @Router /api/v2/workspaceagents/me/rpc [get] |
| 41 | // @x-apidocgen {"skip": true} |
| 42 | func (api *API) workspaceAgentRPC(rw http.ResponseWriter, r *http.Request) { |
| 43 | ctx := r.Context() |
| 44 | logger := api.Logger.Named("agentrpc") |
| 45 | |
| 46 | version := r.URL.Query().Get("version") |
| 47 | if version == "" { |
| 48 | // The initial version on this HTTP endpoint was 2.0, so assume this version if unspecified. |
| 49 | // Coder v2.7.1 (not to be confused with the Agent API version) calls this endpoint without |
| 50 | // a version parameter and wants Agent API version 2.0. |
| 51 | version = "2.0" |
| 52 | } |
| 53 | if err := proto.CurrentVersion.Validate(version); err != nil { |
| 54 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 55 | Message: "Unknown or unsupported API version", |
| 56 | Validations: []codersdk.ValidationError{ |
| 57 | {Field: "version", Detail: err.Error()}, |
| 58 | }, |
| 59 | }) |
| 60 | return |
| 61 | } |
| 62 | |
| 63 | // The role parameter distinguishes the real workspace agent from |
| 64 | // other clients using the same agent token (e.g. coder-logstream-kube). |
| 65 | // Only connections with the "agent" role trigger connection monitoring |
| 66 | // that updates first_connected_at/last_connected_at/disconnected_at. |
| 67 | // For backward compatibility, we default to monitoring when the role |
| 68 | // is omitted, since older agents don't send this parameter. In a |
| 69 | // future release, once all agents include role=agent, we can change |
| 70 | // this default to skip monitoring for unspecified roles. |
| 71 | role := r.URL.Query().Get("role") |
| 72 | monitorConnection := role == "" || role == "agent" |
| 73 | |
| 74 | api.WebsocketWaitMutex.Lock() |
| 75 | api.WebsocketWaitGroup.Add(1) |
| 76 | api.WebsocketWaitMutex.Unlock() |
| 77 | defer api.WebsocketWaitGroup.Done() |
| 78 | workspaceAgent := httpmw.WorkspaceAgent(r) |
| 79 | build := httpmw.LatestBuild(r) |
| 80 | |
| 81 | workspace, err := api.Database.GetWorkspaceByID(ctx, build.WorkspaceID) |
| 82 | if err != nil { |
| 83 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 84 | Message: "Internal error fetching workspace.", |
| 85 | Detail: err.Error(), |
| 86 | }) |
| 87 | return |
| 88 | } |
| 89 | |
| 90 | logger = logger.With( |
| 91 | slog.F("owner", workspace.OwnerUsername), |
| 92 | slog.F("workspace_name", workspace.Name), |
| 93 | slog.F("agent_name", workspaceAgent.Name), |
| 94 | ) |
| 95 | |
| 96 | conn, err := websocket.Accept(rw, r, nil) |
| 97 | if err != nil { |
| 98 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 99 | Message: "Failed to accept websocket.", |
nothing calls this directly
no test coverage detected