Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 66c8ec3

Browse files
committed
Add coderd endpoints for startup script logs
1 parent 99d510c commit 66c8ec3

File tree

12 files changed

+390
-1
lines changed

12 files changed

+390
-1
lines changed

coderd/apidoc/docs.go

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

coderd/apidoc/swagger.json

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

coderd/coderd.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,10 @@ func New(options *Options) *API {
572572
r.Route("/me", func(r chi.Router) {
573573
r.Use(httpmw.ExtractWorkspaceAgent(options.Database))
574574
r.Get("/metadata", api.workspaceAgentMetadata)
575-
r.Post("/startup", api.postWorkspaceAgentStartup)
575+
r.Route("/startup", func(r chi.Router) {
576+
r.Post("/", api.postWorkspaceAgentStartup)
577+
r.Patch("/logs", api.insertOrUpdateStartupScriptLogs)
578+
})
576579
r.Post("/app-health", api.postWorkspaceAppHealth)
577580
r.Get("/gitauth", api.workspaceAgentsGitAuth)
578581
r.Get("/gitsshkey", api.agentGitSSHKey)
@@ -630,6 +633,7 @@ func New(options *Options) *API {
630633
r.Get("/parameters", api.workspaceBuildParameters)
631634
r.Get("/resources", api.workspaceBuildResources)
632635
r.Get("/state", api.workspaceBuildState)
636+
r.Get("/startup-script-logs", api.startupScriptLogs)
633637
})
634638
r.Route("/authcheck", func(r chi.Router) {
635639
r.Use(apiKeyMiddleware)

coderd/coderdtest/authorize.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
7171
"GET:/api/v2/workspaceagents/me/metadata": {NoAuthorize: true},
7272
"GET:/api/v2/workspaceagents/me/coordinate": {NoAuthorize: true},
7373
"POST:/api/v2/workspaceagents/me/startup": {NoAuthorize: true},
74+
"PATCH:/api/v2/workspaceagents/me/startup/logs": {NoAuthorize: true},
7475
"POST:/api/v2/workspaceagents/me/app-health": {NoAuthorize: true},
7576
"POST:/api/v2/workspaceagents/me/report-stats": {NoAuthorize: true},
7677
"POST:/api/v2/workspaceagents/me/report-lifecycle": {NoAuthorize: true},

coderd/coderdtest/swaggerparser.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ func assertProduce(t *testing.T, comment SwaggerComment) {
345345
} else {
346346
if (comment.router == "/workspaceagents/me/app-health" && comment.method == "post") ||
347347
(comment.router == "/workspaceagents/me/startup" && comment.method == "post") ||
348+
(comment.router == "/workspaceagents/me/startup/logs" && comment.method == "patch") ||
348349
(comment.router == "/licenses/{id}" && comment.method == "delete") ||
349350
(comment.router == "/debug/coordinator" && comment.method == "get") {
350351
return // Exception: HTTP 200 is returned without response entity

coderd/workspaceagents.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,48 @@ func (api *API) postWorkspaceAgentStartup(rw http.ResponseWriter, r *http.Reques
208208
httpapi.Write(ctx, rw, http.StatusOK, nil)
209209
}
210210

211+
// @Summary Submit most recent workspace agent startup logs
212+
// @ID insert-update-startup-script-logs
213+
// @Security CoderSessionToken
214+
// @Accept json
215+
// @Produce json
216+
// @Tags Agents
217+
// @Param request body agentsdk.InsertOrUpdateStartupLogsRequest true "Startup logs"
218+
// @Success 200
219+
// @Router /workspaceagents/me/startup/logs [patch]
220+
// @x-apidocgen {"skip": true}
221+
func (api *API) insertOrUpdateStartupScriptLogs(rw http.ResponseWriter, r *http.Request) {
222+
ctx := r.Context()
223+
workspaceAgent := httpmw.WorkspaceAgent(r)
224+
resource, err := api.Database.GetWorkspaceResourceByID(ctx, workspaceAgent.ResourceID)
225+
if err != nil {
226+
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
227+
Message: "Failed to upload startup logs",
228+
Detail: err.Error(),
229+
})
230+
return
231+
}
232+
233+
var req agentsdk.InsertOrUpdateStartupLogsRequest
234+
if !httpapi.Read(ctx, rw, r, &req) {
235+
return
236+
}
237+
238+
if err := api.Database.InsertOrUpdateStartupScriptLog(ctx, database.InsertOrUpdateStartupScriptLogParams{
239+
AgentID: workspaceAgent.ID,
240+
JobID: resource.JobID,
241+
Output: req.Output,
242+
}); err != nil {
243+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
244+
Message: "Failed to upload startup logs",
245+
Detail: err.Error(),
246+
})
247+
return
248+
}
249+
250+
httpapi.Write(ctx, rw, http.StatusOK, nil)
251+
}
252+
211253
// workspaceAgentPTY spawns a PTY and pipes it over a WebSocket.
212254
// This is used for the web terminal.
213255
//

coderd/workspacebuilds.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,44 @@ func (api *API) workspaceBuildLogs(rw http.ResponseWriter, r *http.Request) {
874874
api.provisionerJobLogs(rw, r, job)
875875
}
876876

877+
// @Summary Stream workspace agent startup logs
878+
// @ID stream-startup-script-logs
879+
// @Security CoderSessionToken
880+
// @Produce json
881+
// @Tags Agents
882+
// @Param workspacebuild path string true "Workspace build ID"
883+
// @Success 200 {object} []codersdk.StartupScriptLog
884+
// @Router /workspaceagents/{workspaceagent}/logs [get]
885+
func (api *API) startupScriptLogs(rw http.ResponseWriter, r *http.Request) {
886+
ctx := r.Context()
887+
workspaceBuild := httpmw.WorkspaceBuildParam(r)
888+
889+
// TODO: Wait until the logs are written or use SSE.
890+
891+
dblogs, err := api.Database.GetStartupScriptLogsByJobID(ctx, workspaceBuild.JobID)
892+
if errors.Is(err, sql.ErrNoRows) {
893+
httpapi.Write(ctx, rw, http.StatusOK, codersdk.StartupScriptLog{})
894+
return
895+
}
896+
if err != nil {
897+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
898+
Message: "Error getting startup logs",
899+
Detail: err.Error(),
900+
})
901+
return
902+
}
903+
904+
logs := []codersdk.StartupScriptLog{}
905+
for _, l := range dblogs {
906+
logs = append(logs, codersdk.StartupScriptLog{
907+
AgentID: l.AgentID,
908+
JobID: l.JobID,
909+
Output: l.Output,
910+
})
911+
}
912+
httpapi.Write(ctx, rw, http.StatusOK, logs)
913+
}
914+
877915
// @Summary Get provisioner state for workspace build
878916
// @ID get-provisioner-state-for-workspace-build
879917
// @Security CoderSessionToken

codersdk/agentsdk/agentsdk.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,22 @@ func (c *Client) PostStartup(ctx context.Context, req PostStartupRequest) error
499499
return nil
500500
}
501501

502+
type InsertOrUpdateStartupLogsRequest struct {
503+
Output string
504+
}
505+
506+
func (c *Client) InsertOrUpdateStartupLogs(ctx context.Context, req InsertOrUpdateStartupLogsRequest) error {
507+
res, err := c.SDK.Request(ctx, http.MethodPatch, "/api/v2/workspaceagents/me/startup/logs", req)
508+
if err != nil {
509+
return err
510+
}
511+
defer res.Body.Close()
512+
if res.StatusCode != http.StatusOK {
513+
return codersdk.ReadBodyAsError(res)
514+
}
515+
return nil
516+
}
517+
502518
type GitAuthResponse struct {
503519
Username string `json:"username"`
504520
Password string `json:"password"`

0 commit comments

Comments
 (0)