workspaceAgentClientCoordinate accepts a WebSocket that reads node network updates. After accept a PubSub starts listening for new connection node updates which are written to the WebSocket. @Summary Coordinate workspace agent @ID coordinate-workspace-agent @Security CoderSessionToken @Tags Agents
(rw http.ResponseWriter, r *http.Request)
| 1305 | // @Success 101 |
| 1306 | // @Router /api/v2/workspaceagents/{workspaceagent}/coordinate [get] |
| 1307 | func (api *API) workspaceAgentClientCoordinate(rw http.ResponseWriter, r *http.Request) { |
| 1308 | ctx := r.Context() |
| 1309 | |
| 1310 | // Ensure the database is reachable before proceeding. |
| 1311 | _, err := api.Database.Ping(ctx) |
| 1312 | if err != nil { |
| 1313 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 1314 | Message: codersdk.DatabaseNotReachable, |
| 1315 | Detail: err.Error(), |
| 1316 | }) |
| 1317 | return |
| 1318 | } |
| 1319 | |
| 1320 | // This route accepts user API key auth and workspace proxy auth. The moon actor has |
| 1321 | // full permissions so should be able to pass this authz check. |
| 1322 | waws := httpmw.WorkspaceAgentAndWorkspaceParam(r) |
| 1323 | if !api.Authorize(r, policy.ActionSSH, waws) { |
| 1324 | httpapi.ResourceNotFound(rw) |
| 1325 | return |
| 1326 | } |
| 1327 | |
| 1328 | // This is used by Enterprise code to control the functionality of this route. |
| 1329 | // Namely, disabling the route using `CODER_BROWSER_ONLY`. |
| 1330 | override := api.WorkspaceClientCoordinateOverride.Load() |
| 1331 | if override != nil { |
| 1332 | overrideFunc := *override |
| 1333 | if overrideFunc != nil && overrideFunc(rw) { |
| 1334 | return |
| 1335 | } |
| 1336 | } |
| 1337 | |
| 1338 | version := "1.0" |
| 1339 | qv := r.URL.Query().Get("version") |
| 1340 | if qv != "" { |
| 1341 | version = qv |
| 1342 | } |
| 1343 | if err := proto.CurrentVersion.Validate(version); err != nil { |
| 1344 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 1345 | Message: "Unknown or unsupported API version", |
| 1346 | Validations: []codersdk.ValidationError{ |
| 1347 | {Field: "version", Detail: err.Error()}, |
| 1348 | }, |
| 1349 | }) |
| 1350 | return |
| 1351 | } |
| 1352 | |
| 1353 | peerID, err := api.handleResumeToken(ctx, rw, r) |
| 1354 | if err != nil { |
| 1355 | // handleResumeToken has already written the response. |
| 1356 | return |
| 1357 | } |
| 1358 | |
| 1359 | api.WebsocketWaitMutex.Lock() |
| 1360 | api.WebsocketWaitGroup.Add(1) |
| 1361 | api.WebsocketWaitMutex.Unlock() |
| 1362 | defer api.WebsocketWaitGroup.Done() |
| 1363 | |
| 1364 | conn, err := websocket.Accept(rw, r, nil) |
nothing calls this directly
no test coverage detected