From 6570f1f8eb119a1d04bc45fd3079717c82574c73 Mon Sep 17 00:00:00 2001 From: matias-portainer <104775949+matias-portainer@users.noreply.github.com> Date: Tue, 17 Jan 2023 09:47:23 -0300 Subject: [PATCH] fix(edgejobs): remove endpoint from edge job mapping on endpoint deletion EE-4764 (#8212) --- api/dataservices/edgejob/edgejob.go | 12 +++++++++- api/dataservices/interface.go | 1 + api/http/handler/endpoints/endpoint_delete.go | 23 +++++++++++++++++++ api/internal/testhelpers/datastore.go | 3 +++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/api/dataservices/edgejob/edgejob.go b/api/dataservices/edgejob/edgejob.go index 29f883f1c..48c085fa9 100644 --- a/api/dataservices/edgejob/edgejob.go +++ b/api/dataservices/edgejob/edgejob.go @@ -80,12 +80,22 @@ func (service *Service) Create(ID portainer.EdgeJobID, edgeJob *portainer.EdgeJo ) } -// UpdateEdgeJob updates an Edge job by ID +// Deprecated: use UpdateEdgeJobFunc instead func (service *Service) UpdateEdgeJob(ID portainer.EdgeJobID, edgeJob *portainer.EdgeJob) error { identifier := service.connection.ConvertToKey(int(ID)) return service.connection.UpdateObject(BucketName, identifier, edgeJob) } +// UpdateEdgeJobFunc updates an edge job inside a transaction avoiding data races. +func (service *Service) UpdateEdgeJobFunc(ID portainer.EdgeJobID, updateFunc func(edgeJob *portainer.EdgeJob)) error { + id := service.connection.ConvertToKey(int(ID)) + edgeJob := &portainer.EdgeJob{} + + return service.connection.UpdateObjectFunc(BucketName, id, edgeJob, func() { + updateFunc(edgeJob) + }) +} + // DeleteEdgeJob deletes an Edge job func (service *Service) DeleteEdgeJob(ID portainer.EdgeJobID) error { identifier := service.connection.ConvertToKey(int(ID)) diff --git a/api/dataservices/interface.go b/api/dataservices/interface.go index 452993ad0..220e27e6e 100644 --- a/api/dataservices/interface.go +++ b/api/dataservices/interface.go @@ -78,6 +78,7 @@ type ( EdgeJob(ID portainer.EdgeJobID) (*portainer.EdgeJob, error) Create(ID portainer.EdgeJobID, edgeJob *portainer.EdgeJob) error UpdateEdgeJob(ID portainer.EdgeJobID, edgeJob *portainer.EdgeJob) error + UpdateEdgeJobFunc(ID portainer.EdgeJobID, updateFunc func(edgeJob *portainer.EdgeJob)) error DeleteEdgeJob(ID portainer.EdgeJobID) error GetNextIdentifier() int BucketName() string diff --git a/api/http/handler/endpoints/endpoint_delete.go b/api/http/handler/endpoints/endpoint_delete.go index ab9d92d6d..68c91e484 100644 --- a/api/http/handler/endpoints/endpoint_delete.go +++ b/api/http/handler/endpoints/endpoint_delete.go @@ -9,6 +9,7 @@ import ( "github.com/portainer/libhttp/response" portainer "github.com/portainer/portainer/api" httperrors "github.com/portainer/portainer/api/http/errors" + "github.com/portainer/portainer/api/internal/endpointutils" ) // @id EndpointDelete @@ -124,6 +125,28 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) * } } + if !endpointutils.IsEdgeEndpoint(endpoint) { + return response.Empty(w) + } + + edgeJobs, err := handler.DataStore.EdgeJob().EdgeJobs() + if err != nil { + return httperror.InternalServerError("Unable to retrieve edge jobs from the database", err) + } + + for idx := range edgeJobs { + edgeJob := &edgeJobs[idx] + if _, ok := edgeJob.Endpoints[endpoint.ID]; ok { + err = handler.DataStore.EdgeJob().UpdateEdgeJobFunc(edgeJob.ID, func(j *portainer.EdgeJob) { + delete(j.Endpoints, endpoint.ID) + }) + + if err != nil { + return httperror.InternalServerError("Unable to update edge job", err) + } + } + } + return response.Empty(w) } diff --git a/api/internal/testhelpers/datastore.go b/api/internal/testhelpers/datastore.go index d283853ff..0394667bc 100644 --- a/api/internal/testhelpers/datastore.go +++ b/api/internal/testhelpers/datastore.go @@ -163,6 +163,9 @@ func (s *stubEdgeJobService) Create(ID portainer.EdgeJobID, edgeJob *portainer.E func (s *stubEdgeJobService) UpdateEdgeJob(ID portainer.EdgeJobID, edgeJob *portainer.EdgeJob) error { return nil } +func (s *stubEdgeJobService) UpdateEdgeJobFunc(ID portainer.EdgeJobID, updateFunc func(edgeJob *portainer.EdgeJob)) error { + return nil +} func (s *stubEdgeJobService) DeleteEdgeJob(ID portainer.EdgeJobID) error { return nil } func (s *stubEdgeJobService) GetNextIdentifier() int { return 0 }