feat: trace httpapi.{Read,Write} (#4134)

This commit is contained in:
Colin Adler
2022-09-21 17:07:00 -05:00
committed by GitHub
parent 1bf2dc0cc3
commit 5de6f86959
45 changed files with 919 additions and 774 deletions
+87 -78
View File
@@ -42,6 +42,7 @@ var (
)
func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
workspace := httpmw.WorkspaceParam(r)
if !api.Authorize(r, rbac.ActionRead, workspace) {
httpapi.ResourceNotFound(rw)
@@ -56,7 +57,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
var err error
showDeleted, err = strconv.ParseBool(deletedStr)
if err != nil {
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid boolean value %q for \"include_deleted\" query param.", deletedStr),
Validations: []codersdk.ValidationError{
{Field: "deleted", Detail: "Must be a valid boolean"},
@@ -66,22 +67,22 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
}
}
if workspace.Deleted && !showDeleted {
httpapi.Write(rw, http.StatusGone, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusGone, codersdk.Response{
Message: fmt.Sprintf("Workspace %q was deleted, you can view this workspace by specifying '?deleted=true' and trying again.", workspace.ID.String()),
})
return
}
data, err := api.workspaceData(r.Context(), []database.Workspace{workspace})
data, err := api.workspaceData(ctx, []database.Workspace{workspace})
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.",
Detail: err.Error(),
})
return
}
httpapi.Write(rw, http.StatusOK, convertWorkspace(
httpapi.Write(ctx, rw, http.StatusOK, convertWorkspace(
workspace,
data.builds[0],
data.templates[0],
@@ -92,12 +93,13 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
// workspaces returns all workspaces a user can read.
// Optional filters with query params
func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
apiKey := httpmw.APIKey(r)
queryStr := r.URL.Query().Get("q")
filter, errs := workspaceSearchQuery(queryStr)
if len(errs) > 0 {
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid workspace search query.",
Validations: errs,
})
@@ -109,9 +111,9 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
filter.OwnerUsername = ""
}
workspaces, err := api.Database.GetWorkspaces(r.Context(), filter)
workspaces, err := api.Database.GetWorkspaces(ctx, filter)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspaces.",
Detail: err.Error(),
})
@@ -121,16 +123,16 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
// Only return workspaces the user can read
workspaces, err = AuthorizeFilter(api.HTTPAuth, r, rbac.ActionRead, workspaces)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspaces.",
Detail: err.Error(),
})
return
}
data, err := api.workspaceData(r.Context(), workspaces)
data, err := api.workspaceData(ctx, workspaces)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.",
Detail: err.Error(),
})
@@ -139,17 +141,18 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
wss, err := convertWorkspaces(workspaces, data)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error converting workspaces.",
Detail: err.Error(),
})
return
}
httpapi.Write(rw, http.StatusOK, wss)
httpapi.Write(ctx, rw, http.StatusOK, wss)
}
func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
owner := httpmw.UserParam(r)
workspaceName := chi.URLParam(r, "workspacename")
@@ -158,7 +161,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
var err error
includeDeleted, err = strconv.ParseBool(s)
if err != nil {
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid boolean value %q for \"include_deleted\" query param.", s),
Validations: []codersdk.ValidationError{
{Field: "include_deleted", Detail: "Must be a valid boolean"},
@@ -168,12 +171,12 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
}
}
workspace, err := api.Database.GetWorkspaceByOwnerIDAndName(r.Context(), database.GetWorkspaceByOwnerIDAndNameParams{
workspace, err := api.Database.GetWorkspaceByOwnerIDAndName(ctx, database.GetWorkspaceByOwnerIDAndNameParams{
OwnerID: owner.ID,
Name: workspaceName,
})
if includeDeleted && errors.Is(err, sql.ErrNoRows) {
workspace, err = api.Database.GetWorkspaceByOwnerIDAndName(r.Context(), database.GetWorkspaceByOwnerIDAndNameParams{
workspace, err = api.Database.GetWorkspaceByOwnerIDAndName(ctx, database.GetWorkspaceByOwnerIDAndNameParams{
OwnerID: owner.ID,
Name: workspaceName,
Deleted: includeDeleted,
@@ -184,7 +187,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
return
}
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace by name.",
Detail: err.Error(),
})
@@ -195,16 +198,16 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
return
}
data, err := api.workspaceData(r.Context(), []database.Workspace{workspace})
data, err := api.workspaceData(ctx, []database.Workspace{workspace})
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.",
Detail: err.Error(),
})
return
}
httpapi.Write(rw, http.StatusOK, convertWorkspace(
httpapi.Write(ctx, rw, http.StatusOK, convertWorkspace(
workspace,
data.builds[0],
data.templates[0],
@@ -215,6 +218,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
// Create a new workspace for the currently authenticated user.
func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
organization = httpmw.OrganizationParam(r)
apiKey = httpmw.APIKey(r)
auditor = api.Auditor.Load()
@@ -234,13 +238,13 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
}
var createWorkspace codersdk.CreateWorkspaceRequest
if !httpapi.Read(rw, r, &createWorkspace) {
if !httpapi.Read(ctx, rw, r, &createWorkspace) {
return
}
template, err := api.Database.GetTemplateByID(r.Context(), createWorkspace.TemplateID)
template, err := api.Database.GetTemplateByID(ctx, createWorkspace.TemplateID)
if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Template %q doesn't exist.", createWorkspace.TemplateID.String()),
Validations: []codersdk.ValidationError{{
Field: "template_id",
@@ -250,7 +254,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
return
}
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template.",
Detail: err.Error(),
})
@@ -263,7 +267,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
}
if organization.ID != template.OrganizationID {
httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Template is not in organization %q.", organization.Name),
})
return
@@ -271,7 +275,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
dbAutostartSchedule, err := validWorkspaceSchedule(createWorkspace.AutostartSchedule, time.Duration(template.MinAutostartInterval))
if err != nil {
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid Autostart Schedule.",
Validations: []codersdk.ValidationError{{Field: "schedule", Detail: err.Error()}},
})
@@ -280,20 +284,20 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
dbTTL, err := validWorkspaceTTLMillis(createWorkspace.TTLMillis, time.Duration(template.MaxTtl))
if err != nil {
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid Workspace Time to Shutdown.",
Validations: []codersdk.ValidationError{{Field: "ttl_ms", Detail: err.Error()}},
})
return
}
workspace, err := api.Database.GetWorkspaceByOwnerIDAndName(r.Context(), database.GetWorkspaceByOwnerIDAndNameParams{
workspace, err := api.Database.GetWorkspaceByOwnerIDAndName(ctx, database.GetWorkspaceByOwnerIDAndNameParams{
OwnerID: apiKey.UserID,
Name: createWorkspace.Name,
})
if err == nil {
// If the workspace already exists, don't allow creation.
httpapi.Write(rw, http.StatusConflict, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusConflict, codersdk.Response{
Message: fmt.Sprintf("Workspace %q already exists.", createWorkspace.Name),
Validations: []codersdk.ValidationError{{
Field: "name",
@@ -303,24 +307,24 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
return
}
if err != nil && !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Internal error fetching workspace by name %q.", createWorkspace.Name),
Detail: err.Error(),
})
return
}
templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), template.ActiveVersionID)
templateVersion, err := api.Database.GetTemplateVersionByID(ctx, template.ActiveVersionID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version.",
Detail: err.Error(),
})
return
}
templateVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
templateVersionJob, err := api.Database.GetProvisionerJobByID(ctx, templateVersion.JobID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version job.",
Detail: err.Error(),
})
@@ -329,17 +333,17 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
templateVersionJobStatus := convertProvisionerJob(templateVersionJob).Status
switch templateVersionJobStatus {
case codersdk.ProvisionerJobPending, codersdk.ProvisionerJobRunning:
httpapi.Write(rw, http.StatusNotAcceptable, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusNotAcceptable, codersdk.Response{
Message: fmt.Sprintf("The provided template version is %s. Wait for it to complete importing!", templateVersionJobStatus),
})
return
case codersdk.ProvisionerJobFailed:
httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusPreconditionFailed, codersdk.Response{
Message: fmt.Sprintf("The provided template version %q has failed to import. You cannot create workspaces using it!", templateVersion.Name),
})
return
case codersdk.ProvisionerJobCanceled:
httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "The provided template version was canceled during import. You cannot create workspaces using it!",
})
return
@@ -351,7 +355,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
now := database.Now()
workspaceBuildID := uuid.New()
// Workspaces are created without any versions.
workspace, err = db.InsertWorkspace(r.Context(), database.InsertWorkspaceParams{
workspace, err = db.InsertWorkspace(ctx, database.InsertWorkspaceParams{
ID: uuid.New(),
CreatedAt: now,
UpdatedAt: now,
@@ -372,7 +376,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
continue
}
_, err = db.InsertParameterValue(r.Context(), database.InsertParameterValueParams{
_, err = db.InsertParameterValue(ctx, database.InsertParameterValueParams{
ID: uuid.New(),
Name: parameterValue.Name,
CreatedAt: now,
@@ -394,7 +398,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
if err != nil {
return xerrors.Errorf("marshal provision job: %w", err)
}
provisionerJob, err = db.InsertProvisionerJob(r.Context(), database.InsertProvisionerJobParams{
provisionerJob, err = db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
ID: uuid.New(),
CreatedAt: now,
UpdatedAt: now,
@@ -409,7 +413,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
if err != nil {
return xerrors.Errorf("insert provisioner job: %w", err)
}
workspaceBuild, err = db.InsertWorkspaceBuild(r.Context(), database.InsertWorkspaceBuildParams{
workspaceBuild, err = db.InsertWorkspaceBuild(ctx, database.InsertWorkspaceBuildParams{
ID: workspaceBuildID,
CreatedAt: now,
UpdatedAt: now,
@@ -428,7 +432,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
return nil
})
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error creating workspace.",
Detail: err.Error(),
})
@@ -436,11 +440,11 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
}
aReq.New = workspace
users, err := api.Database.GetUsersByIDs(r.Context(), database.GetUsersByIDsParams{
users, err := api.Database.GetUsersByIDs(ctx, database.GetUsersByIDsParams{
IDs: []uuid.UUID{apiKey.UserID, workspaceBuild.InitiatorID},
})
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user.",
Detail: err.Error(),
})
@@ -463,14 +467,14 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
[]database.WorkspaceApp{},
)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error converting workspace build.",
Detail: err.Error(),
})
return
}
httpapi.Write(rw, http.StatusCreated, convertWorkspace(
httpapi.Write(ctx, rw, http.StatusCreated, convertWorkspace(
workspace,
apiBuild,
template,
@@ -480,6 +484,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load()
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
@@ -498,7 +503,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
}
var req codersdk.UpdateWorkspaceRequest
if !httpapi.Read(rw, r, &req) {
if !httpapi.Read(ctx, rw, r, &req) {
return
}
@@ -516,7 +521,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
name = req.Name
}
newWorkspace, err := api.Database.UpdateWorkspace(r.Context(), database.UpdateWorkspaceParams{
newWorkspace, err := api.Database.UpdateWorkspace(ctx, database.UpdateWorkspaceParams{
ID: workspace.ID,
Name: name,
})
@@ -528,14 +533,14 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
// We could do this check earlier but we'd need to start a
// transaction.
if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusMethodNotAllowed, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusMethodNotAllowed, codersdk.Response{
Message: fmt.Sprintf("Workspace %q is deleted and cannot be updated.", workspace.Name),
})
return
}
// Check if the name was already in use.
if database.IsUniqueViolation(err) {
httpapi.Write(rw, http.StatusConflict, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusConflict, codersdk.Response{
Message: fmt.Sprintf("Workspace %q already exists.", req.Name),
Validations: []codersdk.ValidationError{{
Field: "name",
@@ -544,7 +549,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
})
return
}
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating workspace.",
Detail: err.Error(),
})
@@ -557,6 +562,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load()
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
@@ -575,14 +581,14 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
}
var req codersdk.UpdateWorkspaceAutostartRequest
if !httpapi.Read(rw, r, &req) {
if !httpapi.Read(ctx, rw, r, &req) {
return
}
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
template, err := api.Database.GetTemplateByID(ctx, workspace.TemplateID)
if err != nil {
api.Logger.Error(r.Context(), "fetch workspace template", slog.F("workspace_id", workspace.ID), slog.F("template_id", workspace.TemplateID), slog.Error(err))
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
api.Logger.Error(ctx, "fetch workspace template", slog.F("workspace_id", workspace.ID), slog.F("template_id", workspace.TemplateID), slog.Error(err))
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Error fetching workspace template.",
})
return
@@ -590,19 +596,19 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
dbSched, err := validWorkspaceSchedule(req.Schedule, time.Duration(template.MinAutostartInterval))
if err != nil {
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid autostart schedule.",
Validations: []codersdk.ValidationError{{Field: "schedule", Detail: err.Error()}},
})
return
}
err = api.Database.UpdateWorkspaceAutostart(r.Context(), database.UpdateWorkspaceAutostartParams{
err = api.Database.UpdateWorkspaceAutostart(ctx, database.UpdateWorkspaceAutostartParams{
ID: workspace.ID,
AutostartSchedule: dbSched,
})
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating workspace autostart schedule.",
Detail: err.Error(),
})
@@ -618,6 +624,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load()
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
@@ -635,16 +642,16 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
}
var req codersdk.UpdateWorkspaceTTLRequest
if !httpapi.Read(rw, r, &req) {
if !httpapi.Read(ctx, rw, r, &req) {
return
}
var dbTTL sql.NullInt64
err := api.Database.InTx(func(s database.Store) error {
template, err := s.GetTemplateByID(r.Context(), workspace.TemplateID)
template, err := s.GetTemplateByID(ctx, workspace.TemplateID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Error fetching workspace template!",
})
return xerrors.Errorf("fetch workspace template: %w", err)
@@ -654,7 +661,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
if err != nil {
return codersdk.ValidationError{Field: "ttl_ms", Detail: err.Error()}
}
if err := s.UpdateWorkspaceTTL(r.Context(), database.UpdateWorkspaceTTLParams{
if err := s.UpdateWorkspaceTTL(ctx, database.UpdateWorkspaceTTLParams{
ID: workspace.ID,
Ttl: dbTTL,
}); err != nil {
@@ -670,12 +677,12 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
var validErr codersdk.ValidationError
if errors.As(err, &validErr) {
resp.Validations = []codersdk.ValidationError{validErr}
httpapi.Write(rw, http.StatusBadRequest, resp)
httpapi.Write(ctx, rw, http.StatusBadRequest, resp)
return
}
resp.Detail = err.Error()
httpapi.Write(rw, http.StatusInternalServerError, resp)
httpapi.Write(ctx, rw, http.StatusInternalServerError, resp)
return
}
@@ -687,6 +694,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
}
func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
workspace := httpmw.WorkspaceParam(r)
if !api.Authorize(r, rbac.ActionUpdate, workspace) {
@@ -695,7 +703,7 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
}
var req codersdk.PutExtendWorkspaceRequest
if !httpapi.Read(rw, r, &req) {
if !httpapi.Read(ctx, rw, r, &req) {
return
}
@@ -703,21 +711,21 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
resp := codersdk.Response{}
err := api.Database.InTx(func(s database.Store) error {
template, err := s.GetTemplateByID(r.Context(), workspace.TemplateID)
template, err := s.GetTemplateByID(ctx, workspace.TemplateID)
if err != nil {
code = http.StatusInternalServerError
resp.Message = "Error fetching workspace template!"
return xerrors.Errorf("get workspace template: %w", err)
}
build, err := s.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
build, err := s.GetLatestWorkspaceBuildByWorkspaceID(ctx, workspace.ID)
if err != nil {
code = http.StatusInternalServerError
resp.Message = "Error fetching workspace build."
return xerrors.Errorf("get latest workspace build: %w", err)
}
job, err := s.GetProvisionerJobByID(r.Context(), build.JobID)
job, err := s.GetProvisionerJobByID(ctx, build.JobID)
if err != nil {
code = http.StatusInternalServerError
resp.Message = "Error fetching workspace provisioner job."
@@ -752,7 +760,7 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
return err
}
if err := s.UpdateWorkspaceBuildByID(r.Context(), database.UpdateWorkspaceBuildByIDParams{
if err := s.UpdateWorkspaceBuildByID(ctx, database.UpdateWorkspaceBuildByIDParams{
ID: build.ID,
UpdatedAt: build.UpdatedAt,
ProvisionerState: build.ProvisionerState,
@@ -767,12 +775,13 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
return nil
})
if err != nil {
api.Logger.Info(r.Context(), "extending workspace", slog.Error(err))
api.Logger.Info(ctx, "extending workspace", slog.Error(err))
}
httpapi.Write(rw, code, resp)
httpapi.Write(ctx, rw, code, resp)
}
func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
workspace := httpmw.WorkspaceParam(r)
if !api.Authorize(r, rbac.ActionRead, workspace) {
httpapi.ResourceNotFound(rw)
@@ -781,7 +790,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
sendEvent, err := httpapi.ServerSentEventSender(rw, r)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error setting up server-sent events.",
Detail: err.Error(),
})
@@ -792,12 +801,12 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
defer t.Stop()
for {
select {
case <-r.Context().Done():
case <-ctx.Done():
return
case <-t.C:
workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspace.ID)
workspace, err := api.Database.GetWorkspaceByID(ctx, workspace.ID)
if err != nil {
_ = sendEvent(r.Context(), codersdk.ServerSentEvent{
_ = sendEvent(ctx, codersdk.ServerSentEvent{
Type: codersdk.ServerSentEventTypeError,
Data: codersdk.Response{
Message: "Internal error fetching workspace.",
@@ -807,9 +816,9 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
return
}
data, err := api.workspaceData(r.Context(), []database.Workspace{workspace})
data, err := api.workspaceData(ctx, []database.Workspace{workspace})
if err != nil {
_ = sendEvent(r.Context(), codersdk.ServerSentEvent{
_ = sendEvent(ctx, codersdk.ServerSentEvent{
Type: codersdk.ServerSentEventTypeError,
Data: codersdk.Response{
Message: "Internal error fetching workspace data.",
@@ -819,7 +828,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
return
}
_ = sendEvent(r.Context(), codersdk.ServerSentEvent{
_ = sendEvent(ctx, codersdk.ServerSentEvent{
Type: codersdk.ServerSentEventTypeData,
Data: convertWorkspace(
workspace,