From b14438fd990add9ee6337361547a15dfee25573a Mon Sep 17 00:00:00 2001 From: Oscar Zhou <100548325+oscarzhou-portainer@users.noreply.github.com> Date: Tue, 8 Oct 2024 19:17:09 +1300 Subject: [PATCH] fix(edge): add agent id/name into edge api response [BE-10988] (#12256) --- .../edgestacks/edgestack_status_update.go | 11 +++++----- .../endpointedge/endpointedge_job_logs.go | 21 +++++++++---------- .../endpointedge_stack_inspect.go | 21 +++++++++---------- .../endpointedge_status_inspect.go | 11 +++++----- .../EnvironmentsDatatable/columns.tsx | 2 +- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/api/http/handler/edgestacks/edgestack_status_update.go b/api/http/handler/edgestacks/edgestack_status_update.go index ab12aa09b..08bd8bdf1 100644 --- a/api/http/handler/edgestacks/edgestack_status_update.go +++ b/api/http/handler/edgestacks/edgestack_status_update.go @@ -2,6 +2,7 @@ package edgestacks import ( "errors" + "fmt" "net/http" "time" @@ -63,7 +64,7 @@ func (handler *Handler) edgeStackStatusUpdate(w http.ResponseWriter, r *http.Req var payload updateStatusPayload if err := request.DecodeAndValidateJSONPayload(r, &payload); err != nil { - return httperror.BadRequest("Invalid request payload", err) + return httperror.BadRequest("Invalid request payload", fmt.Errorf("edge polling error: %w. Environment ID: %d", err, payload.EndpointID)) } var stack *portainer.EdgeStack @@ -95,16 +96,16 @@ func (handler *Handler) updateEdgeStackStatus(tx dataservices.DataStoreTx, r *ht return nil, nil } - return nil, err + return nil, fmt.Errorf("unable to retrieve Edge stack from the database: %w. Environment ID: %d", err, payload.EndpointID) } endpoint, err := tx.Endpoint().Endpoint(payload.EndpointID) if err != nil { - return nil, handler.handlerDBErr(err, "Unable to find an environment with the specified identifier inside the database") + return nil, handler.handlerDBErr(fmt.Errorf("unable to find the environment from the database: %w. Environment ID: %d", err, payload.EndpointID), "unable to find the environment") } if err := handler.requestBouncer.AuthorizedEdgeEndpointOperation(r, endpoint); err != nil { - return nil, httperror.Forbidden("Permission denied to access environment", err) + return nil, httperror.Forbidden("Permission denied to access environment", fmt.Errorf("unauthorized edge endpoint operation: %w. Environment name: %s", err, endpoint.Name)) } status := *payload.Status @@ -123,7 +124,7 @@ func (handler *Handler) updateEdgeStackStatus(tx dataservices.DataStoreTx, r *ht updateEnvStatus(payload.EndpointID, stack, deploymentStatus) if err := tx.EdgeStack().UpdateEdgeStack(stackID, stack); err != nil { - return nil, handler.handlerDBErr(err, "Unable to persist the stack changes inside the database") + return nil, handler.handlerDBErr(fmt.Errorf("unable to update Edge stack to the database: %w. Environment name: %s", err, endpoint.Name), "unable to update Edge stack") } return stack, nil diff --git a/api/http/handler/endpointedge/endpointedge_job_logs.go b/api/http/handler/endpointedge/endpointedge_job_logs.go index 971b5a996..c6cf3de96 100644 --- a/api/http/handler/endpointedge/endpointedge_job_logs.go +++ b/api/http/handler/endpointedge/endpointedge_job_logs.go @@ -2,6 +2,7 @@ package endpointedge import ( "errors" + "fmt" "net/http" "strconv" @@ -39,32 +40,30 @@ func (handler *Handler) endpointEdgeJobsLogs(w http.ResponseWriter, r *http.Requ return httperror.BadRequest("Unable to find an environment on request context", err) } - err = handler.requestBouncer.AuthorizedEdgeEndpointOperation(r, endpoint) - if err != nil { - return httperror.Forbidden("Permission denied to access environment", err) + if err := handler.requestBouncer.AuthorizedEdgeEndpointOperation(r, endpoint); err != nil { + return httperror.Forbidden("Permission denied to access environment", fmt.Errorf("unauthorized edge endpoint operation: %w. Environment name: %s", err, endpoint.Name)) } edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "jobID") if err != nil { - return httperror.BadRequest("Invalid edge job identifier route variable", err) + return httperror.BadRequest("Invalid edge job identifier route variable", fmt.Errorf("invalid Edge job route variable: %w. Environment name: %s", err, endpoint.Name)) } var payload logsPayload - err = request.DecodeAndValidateJSONPayload(r, &payload) - if err != nil { - return httperror.BadRequest("Invalid request payload", err) + if err := request.DecodeAndValidateJSONPayload(r, &payload); err != nil { + return httperror.BadRequest("Invalid request payload", fmt.Errorf("invalid Edge job request payload: %w. Environment name: %s", err, endpoint.Name)) } - err = handler.DataStore.UpdateTx(func(tx dataservices.DataStoreTx) error { + if err := handler.DataStore.UpdateTx(func(tx dataservices.DataStoreTx) error { return handler.getEdgeJobLobs(tx, endpoint.ID, portainer.EdgeJobID(edgeJobID), payload) - }) - if err != nil { + }); err != nil { var httpErr *httperror.HandlerError if errors.As(err, &httpErr) { + httpErr.Err = fmt.Errorf("edge polling error: %w. Environment name: %s", httpErr.Err, endpoint.Name) return httpErr } - return httperror.InternalServerError("Unexpected error", err) + return httperror.InternalServerError("Unexpected error", fmt.Errorf("edge polling error: %w. Environment name: %s", err, endpoint.Name)) } return response.JSON(w, nil) diff --git a/api/http/handler/endpointedge/endpointedge_stack_inspect.go b/api/http/handler/endpointedge/endpointedge_stack_inspect.go index fc9f208b0..ef146c7e6 100644 --- a/api/http/handler/endpointedge/endpointedge_stack_inspect.go +++ b/api/http/handler/endpointedge/endpointedge_stack_inspect.go @@ -1,7 +1,7 @@ package endpointedge import ( - "errors" + "fmt" "net/http" portainer "github.com/portainer/portainer/api" @@ -33,27 +33,26 @@ func (handler *Handler) endpointEdgeStackInspect(w http.ResponseWriter, r *http. return httperror.BadRequest("Unable to find an environment on request context", err) } - err = handler.requestBouncer.AuthorizedEdgeEndpointOperation(r, endpoint) - if err != nil { - return httperror.Forbidden("Permission denied to access environment", err) + if err := handler.requestBouncer.AuthorizedEdgeEndpointOperation(r, endpoint); err != nil { + return httperror.Forbidden("Permission denied to access environment", fmt.Errorf("unauthorized edge endpoint operation: %w. Environment name: %s", err, endpoint.Name)) } edgeStackID, err := request.RetrieveNumericRouteVariableValue(r, "stackId") if err != nil { - return httperror.BadRequest("Invalid edge stack identifier route variable", err) + return httperror.BadRequest("Invalid edge stack identifier route variable", fmt.Errorf("invalid Edge stack route variable: %w. Environment name: %s", err, endpoint.Name)) } edgeStack, err := handler.DataStore.EdgeStack().EdgeStack(portainer.EdgeStackID(edgeStackID)) if handler.DataStore.IsErrObjectNotFound(err) { - return httperror.NotFound("Unable to find an edge stack with the specified identifier inside the database", err) + return httperror.NotFound("Unable to find an edge stack with the specified identifier inside the database", fmt.Errorf("unable to find the Edge stack from database: %w. Environment name: %s", err, endpoint.Name)) } else if err != nil { - return httperror.InternalServerError("Unable to find an edge stack with the specified identifier inside the database", err) + return httperror.InternalServerError("Unable to find an edge stack with the specified identifier inside the database", fmt.Errorf("failed to find the Edge stack from database: %w. Environment name: %s", err, endpoint.Name)) } fileName := edgeStack.EntryPoint if endpointutils.IsDockerEndpoint(endpoint) { if fileName == "" { - return httperror.BadRequest("Docker is not supported by this stack", errors.New("Docker is not supported by this stack")) + return httperror.BadRequest("Docker is not supported by this stack", fmt.Errorf("no filename is provided for the Docker endpoint. Environment name: %s", endpoint.Name)) } } @@ -66,18 +65,18 @@ func (handler *Handler) endpointEdgeStackInspect(w http.ResponseWriter, r *http. fileName = edgeStack.ManifestPath if fileName == "" { - return httperror.BadRequest("Kubernetes is not supported by this stack", errors.New("Kubernetes is not supported by this stack")) + return httperror.BadRequest("Kubernetes is not supported by this stack", fmt.Errorf("no filename is provided for the Kubernetes endpoint. Environment name: %s", endpoint.Name)) } } dirEntries, err := filesystem.LoadDir(edgeStack.ProjectPath) if err != nil { - return httperror.InternalServerError("Unable to load repository", err) + return httperror.InternalServerError("Unable to load repository", fmt.Errorf("failed to load project directory: %w. Environment name: %s", err, endpoint.Name)) } fileContent, err := filesystem.FilterDirForCompatibility(dirEntries, fileName, endpoint.Agent.Version) if err != nil { - return httperror.InternalServerError("File not found", err) + return httperror.InternalServerError("File not found", fmt.Errorf("unable to find file: %w. Environment name: %s", err, endpoint.Name)) } dirEntries = filesystem.FilterDirForEntryFile(dirEntries, fileName) diff --git a/api/http/handler/endpointedge/endpointedge_status_inspect.go b/api/http/handler/endpointedge/endpointedge_status_inspect.go index 12d84aae7..de22b195f 100644 --- a/api/http/handler/endpointedge/endpointedge_status_inspect.go +++ b/api/http/handler/endpointedge/endpointedge_status_inspect.go @@ -85,25 +85,25 @@ func (handler *Handler) endpointEdgeStatusInspect(w http.ResponseWriter, r *http if _, ok := handler.DataStore.Endpoint().Heartbeat(portainer.EndpointID(endpointID)); !ok { // EE-5190 - return httperror.Forbidden("Permission denied to access environment", errors.New("the device has not been trusted yet")) + return httperror.Forbidden("Permission denied to access environment. The device has not been trusted yet", fmt.Errorf("unable to retrieve endpoint heartbeat. Environment ID: %d", endpointID)) } endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID)) if err != nil { // EE-5190 - return httperror.Forbidden("Permission denied to access environment", errors.New("the device has not been trusted yet")) + return httperror.Forbidden("Permission denied to access environment. The device has not been trusted yet", fmt.Errorf("unable to retrieve endpoint from database: %w. Environment ID: %d", err, endpointID)) } firstConn := endpoint.LastCheckInDate == 0 if err := handler.requestBouncer.AuthorizedEdgeEndpointOperation(r, endpoint); err != nil { - return httperror.Forbidden("Permission denied to access environment", err) + return httperror.Forbidden("Permission denied to access environment. The device has not been trusted yet", fmt.Errorf("unauthorized Edge endpoint operation: %w. Environment name: %s", err, endpoint.Name)) } handler.DataStore.Endpoint().UpdateHeartbeat(endpoint.ID) if err := handler.requestBouncer.TrustedEdgeEnvironmentAccess(handler.DataStore, endpoint); err != nil { - return httperror.Forbidden("Permission denied to access environment", err) + return httperror.Forbidden("Permission denied to access environment. The device has not been trusted yet", fmt.Errorf("untrusted Edge environment access: %w. Environment name: %s", err, endpoint.Name)) } var statusResponse *endpointEdgeStatusInspectResponse @@ -113,10 +113,11 @@ func (handler *Handler) endpointEdgeStatusInspect(w http.ResponseWriter, r *http }); err != nil { var httpErr *httperror.HandlerError if errors.As(err, &httpErr) { + httpErr.Err = fmt.Errorf("edge polling error: %w. Environment name: %s", httpErr.Err, endpoint.Name) return httpErr } - return httperror.InternalServerError("Unexpected error", err) + return httperror.InternalServerError("Unexpected error", fmt.Errorf("edge polling error: %w. Environment name: %s", err, endpoint.Name)) } return cacheResponse(w, endpoint.ID, *statusResponse) diff --git a/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/columns.tsx b/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/columns.tsx index 2e6626158..0e6c91336 100644 --- a/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/columns.tsx +++ b/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/columns.tsx @@ -139,7 +139,7 @@ function ErrorCell({