chore: Linter rule for properly formatted api errors (#2123)

* chore: Linter rule for properly formatted api errors
* Add omitempty to 'Detail' field
This commit is contained in:
Steven Masley
2022-06-07 14:33:06 +00:00
committed by GitHub
parent 3f1e885d21
commit af401e3fe1
37 changed files with 351 additions and 302 deletions
+38 -37
View File
@@ -46,7 +46,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
showDeleted, err = strconv.ParseBool(deletedStr)
if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
Message: fmt.Sprintf("Invalid boolean value %q for \"deleted\" query param", deletedStr),
Message: fmt.Sprintf("Invalid boolean value %q for \"deleted\" query param.", deletedStr),
Validations: []httpapi.Error{
{Field: "deleted", Detail: "Must be a valid boolean"},
},
@@ -56,7 +56,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
}
if workspace.Deleted && !showDeleted {
httpapi.Write(rw, http.StatusGone, httpapi.Response{
Message: fmt.Sprintf("Workspace %q was deleted, you can view this workspace by specifying '?deleted=true' and trying again", workspace.ID.String()),
Message: fmt.Sprintf("Workspace %q was deleted, you can view this workspace by specifying '?deleted=true' and trying again.", workspace.ID.String()),
})
return
}
@@ -64,7 +64,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching workspace build",
Message: "Internal error fetching workspace build.",
Detail: err.Error(),
})
return
@@ -90,7 +90,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
err = group.Wait()
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching resource",
Message: "Internal error fetching resource.",
Detail: err.Error(),
})
return
@@ -141,7 +141,7 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
workspaces, err := api.Database.GetWorkspacesWithFilter(r.Context(), filter)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching workspaces",
Message: "Internal error fetching workspaces.",
Detail: err.Error(),
})
return
@@ -153,7 +153,8 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
apiWorkspaces, err := convertWorkspaces(r.Context(), api.Database, workspaces)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("convert workspaces: %s", err),
Message: "Internal error reading workspace.",
Detail: err.Error(),
})
return
}
@@ -175,7 +176,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
}
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching workspace by name",
Message: "Internal error fetching workspace by name.",
Detail: err.Error(),
})
return
@@ -187,7 +188,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching workspace build",
Message: "Internal error fetching workspace build.",
Detail: err.Error(),
})
return
@@ -195,7 +196,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
job, err := api.Database.GetProvisionerJobByID(r.Context(), build.JobID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching provisioner job",
Message: "Internal error fetching provisioner job.",
Detail: err.Error(),
})
return
@@ -203,7 +204,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching template",
Message: "Internal error fetching template.",
Detail: err.Error(),
})
return
@@ -229,7 +230,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
template, err := api.Database.GetTemplateByID(r.Context(), createWorkspace.TemplateID)
if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
Message: fmt.Sprintf("Template %q doesn't exist", createWorkspace.TemplateID.String()),
Message: fmt.Sprintf("Template %q doesn't exist.", createWorkspace.TemplateID.String()),
Validations: []httpapi.Error{{
Field: "template_id",
Detail: "template not found",
@@ -239,7 +240,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
}
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching template",
Message: "Internal error fetching template.",
Detail: err.Error(),
})
return
@@ -247,7 +248,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
if organization.ID != template.OrganizationID {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
Message: fmt.Sprintf("Template is not in organization %q", organization.Name),
Message: fmt.Sprintf("Template is not in organization %q.", organization.Name),
})
return
}
@@ -257,13 +258,13 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
})
if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
Message: "You aren't allowed to access templates in that organization",
Message: "You aren't allowed to access templates in that organization.",
})
return
}
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching organization member",
Message: "Internal error fetching organization member.",
Detail: err.Error(),
})
return
@@ -272,7 +273,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, httpapi.Response{
Message: "Invalid Autostart Schedule",
Message: "Invalid Autostart Schedule.",
Validations: []httpapi.Error{{Field: "schedule", Detail: err.Error()}},
})
return
@@ -281,7 +282,7 @@ 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, httpapi.Response{
Message: "Invalid Workspace TTL",
Message: "Invalid Workspace TTL.",
Validations: []httpapi.Error{{Field: "ttl_ms", Detail: err.Error()}},
})
return
@@ -301,14 +302,14 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("Find template for conflicting workspace name %q", createWorkspace.Name),
Message: fmt.Sprintf("Find template for conflicting workspace name %q.", createWorkspace.Name),
Detail: err.Error(),
})
return
}
// The template is fetched for clarity to the user on where the conflicting name may be.
httpapi.Write(rw, http.StatusConflict, httpapi.Response{
Message: fmt.Sprintf("Workspace %q already exists in the %q template", createWorkspace.Name, template.Name),
Message: fmt.Sprintf("Workspace %q already exists in the %q template.", createWorkspace.Name, template.Name),
Validations: []httpapi.Error{{
Field: "name",
Detail: "this value is already in use and should be unique",
@@ -318,7 +319,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
}
if !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("Internal error fetching workspace by name %q", createWorkspace.Name),
Message: fmt.Sprintf("Internal error fetching workspace by name %q.", createWorkspace.Name),
Detail: err.Error(),
})
return
@@ -327,7 +328,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), template.ActiveVersionID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching template version",
Message: "Internal error fetching template version.",
Detail: err.Error(),
})
return
@@ -335,7 +336,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
templateVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching template version job",
Message: "Internal error fetching template version job.",
Detail: err.Error(),
})
return
@@ -437,7 +438,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
})
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error creating workspace",
Message: "Internal error creating workspace.",
Detail: err.Error(),
})
return
@@ -445,7 +446,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
user, err := api.Database.GetUserByID(r.Context(), apiKey.UserID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error fetching user",
Message: "Internal error fetching user.",
Detail: err.Error(),
})
return
@@ -470,7 +471,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
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, httpapi.Response{
Message: "Error fetching workspace template",
Message: "Error fetching workspace template.",
})
return
}
@@ -478,7 +479,7 @@ 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, httpapi.Response{
Message: "Invalid autostart schedule",
Message: "Invalid autostart schedule.",
Validations: []httpapi.Error{{Field: "schedule", Detail: err.Error()}},
})
return
@@ -490,7 +491,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
})
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error updating workspace autostart schedule",
Message: "Internal error updating workspace autostart schedule.",
Detail: err.Error(),
})
return
@@ -520,7 +521,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
dbTTL, err := validWorkspaceTTLMillis(req.TTLMillis, time.Duration(template.MaxTtl))
if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
Message: "Invalid workspace TTL",
Message: "Invalid workspace TTL.",
Detail: err.Error(),
Validations: []httpapi.Error{
{
@@ -538,7 +539,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
})
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Internal error updating workspace TTL",
Message: "Internal error updating workspace TTL.",
Detail: err.Error(),
})
return
@@ -564,20 +565,20 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
build, err := s.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil {
code = http.StatusInternalServerError
resp.Message = "workspace not found"
resp.Message = "Workspace not found."
return xerrors.Errorf("get latest workspace build: %w", err)
}
if build.Transition != database.WorkspaceTransitionStart {
code = http.StatusConflict
resp.Message = "workspace must be started, current status: " + string(build.Transition)
resp.Message = "Workspace must be started, current status: " + string(build.Transition)
return xerrors.Errorf("workspace must be started, current status: %s", build.Transition)
}
newDeadline := req.Deadline.UTC()
if err := validWorkspaceDeadline(build.Deadline, newDeadline); err != nil {
code = http.StatusBadRequest
resp.Message = "bad extend workspace request"
resp.Message = "Bad extend workspace request."
resp.Validations = append(resp.Validations, httpapi.Error{Field: "deadline", Detail: err.Error()})
return err
}
@@ -589,10 +590,10 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
Deadline: newDeadline,
}); err != nil {
code = http.StatusInternalServerError
resp.Message = "failed to extend workspace deadline"
resp.Message = "Failed to extend workspace deadline."
return xerrors.Errorf("update workspace build: %w", err)
}
resp.Message = "deadline updated to " + newDeadline.Format(time.RFC3339)
resp.Message = "Deadline updated to " + newDeadline.Format(time.RFC3339) + "."
return nil
})
@@ -651,7 +652,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspace.ID)
if err != nil {
_ = wsjson.Write(ctx, c, httpapi.Response{
Message: "Internal error fetching workspace",
Message: "Internal error fetching workspace.",
Detail: err.Error(),
})
return
@@ -659,7 +660,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil {
_ = wsjson.Write(ctx, c, httpapi.Response{
Message: "Internal error fetching workspace build",
Message: "Internal error fetching workspace build.",
Detail: err.Error(),
})
return
@@ -685,7 +686,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
err = group.Wait()
if err != nil {
_ = wsjson.Write(ctx, c, httpapi.Response{
Message: "Internal error fetching resource",
Message: "Internal error fetching resource.",
Detail: err.Error(),
})
return