mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
feat: trace httpapi.{Read,Write} (#4134)
This commit is contained in:
+87
-78
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user