1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 00:09:40 +02:00

fix(errors): wrap db errors, improve error handling (#8859)

* use error check func, wrap db object not found

* add errorlint and fix all the linting errors

* add exportloopref linter and fix errors

* fix incorrect error details returned on an api

* fix new errors

* increase linter timeout

* increase timeout to 10minutes

* increase timeout to 10minutes

* rebase and fix new lint errors

* make CE match EE

* fix govet issue
This commit is contained in:
Matt Hook 2023-05-05 12:19:47 +12:00 committed by GitHub
parent 550e235d59
commit 334eee0c8c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 158 additions and 115 deletions

View file

@ -1,6 +1,7 @@
package edgegroups
import (
"errors"
"net/http"
httperror "github.com/portainer/libhttp/error"
@ -39,8 +40,9 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
func txResponse(w http.ResponseWriter, r any, err error) *httperror.HandlerError {
if err != nil {
if httpErr, ok := err.(*httperror.HandlerError); ok {
return httpErr
var handlerError *httperror.HandlerError
if errors.As(err, &handlerError) {
return handlerError
}
return httperror.InternalServerError("Unexpected error", err)

View file

@ -1,6 +1,7 @@
package edgejobs
import (
"errors"
"net/http"
"strconv"
@ -42,8 +43,9 @@ func (handler *Handler) edgeJobDelete(w http.ResponseWriter, r *http.Request) *h
}
if err != nil {
if httpErr, ok := err.(*httperror.HandlerError); ok {
return httpErr
var handlerError *httperror.HandlerError
if errors.As(err, &handlerError) {
return handlerError
}
return httperror.InternalServerError("Unexpected error", err)

View file

@ -1,6 +1,7 @@
package edgejobs
import (
"errors"
"net/http"
"strconv"
@ -75,8 +76,9 @@ func (handler *Handler) edgeJobTasksClear(w http.ResponseWriter, r *http.Request
}
if err != nil {
if httpErr, ok := err.(*httperror.HandlerError); ok {
return httpErr
var handlerError *httperror.HandlerError
if errors.As(err, &handlerError) {
return handlerError
}
return httperror.InternalServerError("Unexpected error", err)

View file

@ -1,6 +1,7 @@
package edgejobs
import (
"errors"
"net/http"
httperror "github.com/portainer/libhttp/error"
@ -83,8 +84,9 @@ func (handler *Handler) edgeJobTasksCollect(w http.ResponseWriter, r *http.Reque
})
if err != nil {
if httpErr, ok := err.(*httperror.HandlerError); ok {
return httpErr
var handlerError *httperror.HandlerError
if errors.As(err, &handlerError) {
return handlerError
}
return httperror.InternalServerError("Unexpected error", err)

View file

@ -1,6 +1,7 @@
package edgejobs
import (
"errors"
"net/http"
httperror "github.com/portainer/libhttp/error"
@ -62,8 +63,9 @@ func convertEndpointsToMetaObject(endpoints []portainer.EndpointID) map[portaine
func txResponse(w http.ResponseWriter, r any, err error) *httperror.HandlerError {
if err != nil {
if httpErr, ok := err.(*httperror.HandlerError); ok {
return httpErr
var handlerError *httperror.HandlerError
if errors.As(err, &handlerError) {
return handlerError
}
return httperror.InternalServerError("Unexpected error", err)

View file

@ -153,8 +153,8 @@ func registryAccessPoliciesContainsNamespace(registryAccess portainer.RegistryAc
func (handler *Handler) filterKubernetesRegistriesByUserRole(r *http.Request, registries []portainer.Registry, endpoint *portainer.Endpoint, user *portainer.User) ([]portainer.Registry, *httperror.HandlerError) {
err := handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
if err == security.ErrAuthorizationRequired {
return nil, httperror.Forbidden("User is not authorized", errors.New("missing namespace query parameter"))
if errors.Is(err, security.ErrAuthorizationRequired) {
return nil, httperror.Forbidden("User is not authorized", err)
}
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve info from request context", err)

View file

@ -29,7 +29,7 @@ type repositoryFilePreviewPayload struct {
func (payload *repositoryFilePreviewPayload) Validate(r *http.Request) error {
if govalidator.IsNull(payload.Repository) || !govalidator.IsURL(payload.Repository) {
return errors.New("Invalid repository URL. Must correspond to a valid URL format")
return errors.New("invalid repository URL. Must correspond to a valid URL format")
}
if govalidator.IsNull(payload.Reference) {
@ -37,7 +37,7 @@ func (payload *repositoryFilePreviewPayload) Validate(r *http.Request) error {
}
if govalidator.IsNull(payload.TargetFile) {
return errors.New("Invalid target filename.")
return errors.New("invalid target filename")
}
return nil
@ -70,11 +70,11 @@ func (handler *Handler) gitOperationRepoFilePreview(w http.ResponseWriter, r *ht
err = handler.gitService.CloneRepository(projectPath, payload.Repository, payload.Reference, payload.Username, payload.Password, payload.TLSSkipVerify)
if err != nil {
if err == gittypes.ErrAuthenticationFailure {
if errors.Is(err, gittypes.ErrAuthenticationFailure) {
return httperror.BadRequest("Invalid git credential", err)
}
newErr := fmt.Errorf("unable to clone git repository: %w", err)
newErr := fmt.Errorf("unable to clone git repository, error: %w", err)
return httperror.InternalServerError(newErr.Error(), newErr)
}

View file

@ -9,7 +9,6 @@ import (
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
bolterrors "github.com/portainer/portainer/api/dataservices/errors"
"github.com/portainer/portainer/api/internal/endpointutils"
)
@ -33,7 +32,7 @@ func (handler *Handler) openAMTActivate(w http.ResponseWriter, r *http.Request)
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err == bolterrors.ErrObjectNotFound {
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
} else if err != nil {
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)

View file

@ -8,7 +8,6 @@ import (
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
bolterrors "github.com/portainer/portainer/api/dataservices/errors"
"github.com/rs/zerolog/log"
)
@ -33,7 +32,7 @@ func (handler *Handler) openAMTDevices(w http.ResponseWriter, r *http.Request) *
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err == bolterrors.ErrObjectNotFound {
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
} else if err != nil {
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)

View file

@ -12,7 +12,6 @@ import (
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
bolterrors "github.com/portainer/portainer/api/dataservices/errors"
"github.com/portainer/portainer/api/hostmanagement/openamt"
"github.com/docker/docker/api/types"
@ -63,7 +62,7 @@ func (handler *Handler) openAMTHostInfo(w http.ResponseWriter, r *http.Request)
log.Info().Int("endpointID", endpointID).Msg("OpenAMTHostInfo")
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err == bolterrors.ErrObjectNotFound {
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
} else if err != nil {
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)

View file

@ -7,7 +7,6 @@ import (
"strconv"
portainer "github.com/portainer/portainer/api"
portainerDsErrors "github.com/portainer/portainer/api/dataservices/errors"
"github.com/portainer/portainer/api/kubernetes"
"github.com/gorilla/mux"
@ -121,7 +120,7 @@ func (handler *Handler) kubeClient(next http.Handler) http.Handler {
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err == portainerDsErrors.ErrObjectNotFound {
if handler.DataStore.IsErrObjectNotFound(err) {
httperror.WriteError(
w,
http.StatusNotFound,

View file

@ -8,7 +8,6 @@ import (
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
portainerDsErrors "github.com/portainer/portainer/api/dataservices/errors"
models "github.com/portainer/portainer/api/http/models/kubernetes"
"github.com/portainer/portainer/api/http/security"
)
@ -23,7 +22,7 @@ func (handler *Handler) getKubernetesIngressControllers(w http.ResponseWriter, r
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err == portainerDsErrors.ErrObjectNotFound {
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound(
"Unable to find an environment with the specified identifier inside the database",
err,

View file

@ -1,6 +1,7 @@
package stacks
import (
"errors"
"net/http"
httperror "github.com/portainer/libhttp/error"
@ -38,7 +39,8 @@ func (handler *Handler) webhookInvoke(w http.ResponseWriter, r *http.Request) *h
}
if err = deployments.RedeployWhenChanged(stack.ID, handler.StackDeployer, handler.DataStore, handler.GitService); err != nil {
if _, ok := err.(*deployments.StackAuthorMissingErr); ok {
var StackAuthorMissingErr *deployments.StackAuthorMissingErr
if errors.As(err, &StackAuthorMissingErr) {
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: "Autoupdate for the stack isn't available", Err: err}
}

View file

@ -1,6 +1,7 @@
package tags
import (
"errors"
"net/http"
httperror "github.com/portainer/libhttp/error"
@ -34,8 +35,9 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
func txResponse(w http.ResponseWriter, r any, err error) *httperror.HandlerError {
if err != nil {
if httpErr, ok := err.(*httperror.HandlerError); ok {
return httpErr
var handlerError *httperror.HandlerError
if errors.As(err, &handlerError) {
return handlerError
}
return httperror.InternalServerError("Unexpected error", err)

View file

@ -1,6 +1,7 @@
package tags
import (
"errors"
"net/http"
httperror "github.com/portainer/libhttp/error"
@ -41,8 +42,9 @@ func (handler *Handler) tagDelete(w http.ResponseWriter, r *http.Request) *httpe
}
if err != nil {
if httpErr, ok := err.(*httperror.HandlerError); ok {
return httpErr
var handlerError *httperror.HandlerError
if errors.As(err, &handlerError) {
return handlerError
}
return httperror.InternalServerError("Unexpected error", err)

View file

@ -1,6 +1,7 @@
package users
import (
"errors"
"net/http"
httperror "github.com/portainer/libhttp/error"
@ -66,7 +67,7 @@ func (handler *Handler) userRemoveAccessToken(w http.ResponseWriter, r *http.Req
err = handler.apiKeyService.DeleteAPIKey(portainer.APIKeyID(apiKeyID))
if err != nil {
if err == apikey.ErrInvalidAPIKey {
if errors.Is(err, apikey.ErrInvalidAPIKey) {
return httperror.NotFound("Unable to find an api-key with the specified identifier inside the database", err)
}
return httperror.InternalServerError("Unable to remove the api-key from the user", err)

View file

@ -1,6 +1,7 @@
package websocket
import (
"errors"
"fmt"
"net/http"
"net/http/httputil"
@ -11,7 +12,7 @@ import (
func hijackRequest(websocketConn *websocket.Conn, httpConn *httputil.ClientConn, request *http.Request) error {
// Server hijacks the connection, error 'connection closed' expected
resp, err := httpConn.Do(request)
if err != httputil.ErrPersistEOF {
if !errors.Is(err, httputil.ErrPersistEOF) {
if err != nil {
return err
}