fix(pending-actions): clean pending actions for deleted environment [EE-6545] (#11598)

pull/11604/head
Prabhat Khera 2024-04-16 15:09:10 +12:00 committed by GitHub
parent 37bba18c81
commit d9df58e93a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 82 additions and 2 deletions

View File

@ -73,6 +73,7 @@ type (
PendingActionsService interface { PendingActionsService interface {
BaseCRUD[portainer.PendingActions, portainer.PendingActionsID] BaseCRUD[portainer.PendingActions, portainer.PendingActionsID]
GetNextIdentifier() int GetNextIdentifier() int
DeleteByEndpointID(ID portainer.EndpointID) error
} }
// EdgeStackService represents a service to manage Edge stacks // EdgeStackService represents a service to manage Edge stacks

View File

@ -1,10 +1,12 @@
package pendingactions package pendingactions
import ( import (
"fmt"
"time" "time"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/dataservices"
"github.com/rs/zerolog/log"
) )
const ( const (
@ -45,6 +47,12 @@ func (s Service) Update(ID portainer.PendingActionsID, config *portainer.Pending
}) })
} }
func (s Service) DeleteByEndpointID(ID portainer.EndpointID) error {
return s.Connection.UpdateTx(func(tx portainer.Transaction) error {
return s.Tx(tx).DeleteByEndpointID(ID)
})
}
func (service *Service) Tx(tx portainer.Transaction) ServiceTx { func (service *Service) Tx(tx portainer.Transaction) ServiceTx {
return ServiceTx{ return ServiceTx{
BaseDataServiceTx: dataservices.BaseDataServiceTx[portainer.PendingActions, portainer.PendingActionsID]{ BaseDataServiceTx: dataservices.BaseDataServiceTx[portainer.PendingActions, portainer.PendingActionsID]{
@ -68,6 +76,29 @@ func (s ServiceTx) Update(ID portainer.PendingActionsID, config *portainer.Pendi
return s.BaseDataServiceTx.Update(ID, config) return s.BaseDataServiceTx.Update(ID, config)
} }
func (s ServiceTx) DeleteByEndpointID(ID portainer.EndpointID) error {
log.Debug().Int("endpointId", int(ID)).Msg("deleting pending actions for endpoint")
pendingActions, err := s.BaseDataServiceTx.ReadAll()
if err != nil {
return fmt.Errorf("failed to retrieve pending-actions for endpoint (%d): %w", ID, err)
}
for _, pendingAction := range pendingActions {
if pendingAction.EndpointID == ID {
err := s.BaseDataServiceTx.Delete(pendingAction.ID)
if err != nil {
log.Debug().Int("endpointId", int(ID)).Msgf("failed to delete pending action: %v", err)
}
}
}
return nil
}
// GetNextIdentifier returns the next identifier for a custom template.
func (service ServiceTx) GetNextIdentifier() int {
return service.Tx.GetNextIdentifier(BucketName)
}
// GetNextIdentifier returns the next identifier for a custom template. // GetNextIdentifier returns the next identifier for a custom template.
func (service *Service) GetNextIdentifier() int { func (service *Service) GetNextIdentifier() int {
return service.Connection.GetNextIdentifier(BucketName) return service.Connection.GetNextIdentifier(BucketName)

View File

@ -86,6 +86,7 @@ func (store *Store) newMigratorParameters(version *models.Version) *migrator.Mig
EdgeStackService: store.EdgeStackService, EdgeStackService: store.EdgeStackService,
EdgeJobService: store.EdgeJobService, EdgeJobService: store.EdgeJobService,
TunnelServerService: store.TunnelServerService, TunnelServerService: store.TunnelServerService,
PendingActionsService: store.PendingActionsService,
} }
} }

View File

@ -0,0 +1,32 @@
package migrator
import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/rs/zerolog/log"
)
func (migrator *Migrator) cleanPendingActionsForDeletedEndpointsForDB111() error {
log.Info().Msg("cleaning up pending actions for deleted endpoints")
pendingActions, err := migrator.pendingActionsService.ReadAll()
if err != nil {
return err
}
endpoints := make(map[portainer.EndpointID]struct{})
for _, action := range pendingActions {
endpoints[action.EndpointID] = struct{}{}
}
for endpointId := range endpoints {
_, err := migrator.endpointService.Endpoint(endpointId)
if dataservices.IsErrObjectNotFound(err) {
err := migrator.pendingActionsService.DeleteByEndpointID(endpointId)
if err != nil {
return err
}
}
}
return nil
}

View File

@ -14,6 +14,7 @@ import (
"github.com/portainer/portainer/api/dataservices/endpointrelation" "github.com/portainer/portainer/api/dataservices/endpointrelation"
"github.com/portainer/portainer/api/dataservices/extension" "github.com/portainer/portainer/api/dataservices/extension"
"github.com/portainer/portainer/api/dataservices/fdoprofile" "github.com/portainer/portainer/api/dataservices/fdoprofile"
"github.com/portainer/portainer/api/dataservices/pendingactions"
"github.com/portainer/portainer/api/dataservices/registry" "github.com/portainer/portainer/api/dataservices/registry"
"github.com/portainer/portainer/api/dataservices/resourcecontrol" "github.com/portainer/portainer/api/dataservices/resourcecontrol"
"github.com/portainer/portainer/api/dataservices/role" "github.com/portainer/portainer/api/dataservices/role"
@ -58,6 +59,7 @@ type (
edgeStackService *edgestack.Service edgeStackService *edgestack.Service
edgeJobService *edgejob.Service edgeJobService *edgejob.Service
TunnelServerService *tunnelserver.Service TunnelServerService *tunnelserver.Service
pendingActionsService *pendingactions.Service
} }
// MigratorParameters represents the required parameters to create a new Migrator instance. // MigratorParameters represents the required parameters to create a new Migrator instance.
@ -85,6 +87,7 @@ type (
EdgeStackService *edgestack.Service EdgeStackService *edgestack.Service
EdgeJobService *edgejob.Service EdgeJobService *edgejob.Service
TunnelServerService *tunnelserver.Service TunnelServerService *tunnelserver.Service
PendingActionsService *pendingactions.Service
} }
) )
@ -114,6 +117,7 @@ func NewMigrator(parameters *MigratorParameters) *Migrator {
edgeStackService: parameters.EdgeStackService, edgeStackService: parameters.EdgeStackService,
edgeJobService: parameters.EdgeJobService, edgeJobService: parameters.EdgeJobService,
TunnelServerService: parameters.TunnelServerService, TunnelServerService: parameters.TunnelServerService,
pendingActionsService: parameters.PendingActionsService,
} }
migrator.initMigrations() migrator.initMigrations()
@ -232,6 +236,9 @@ func (m *Migrator) initMigrations() {
m.updateAppTemplatesVersionForDB110, m.updateAppTemplatesVersionForDB110,
m.updateResourceOverCommitToDB110, m.updateResourceOverCommitToDB110,
) )
m.addMigrations("2.22",
m.cleanPendingActionsForDeletedEndpointsForDB111,
)
// Add new migrations below... // Add new migrations below...
// One function per migration, each versions migration funcs in the same file. // One function per migration, each versions migration funcs in the same file.

View File

@ -16,7 +16,9 @@ func (tx *StoreTx) IsErrObjectNotFound(err error) bool {
func (tx *StoreTx) CustomTemplate() dataservices.CustomTemplateService { return nil } func (tx *StoreTx) CustomTemplate() dataservices.CustomTemplateService { return nil }
func (tx *StoreTx) PendingActions() dataservices.PendingActionsService { return nil } func (tx *StoreTx) PendingActions() dataservices.PendingActionsService {
return tx.store.PendingActionsService.Tx(tx.tx)
}
func (tx *StoreTx) EdgeGroup() dataservices.EdgeGroupService { func (tx *StoreTx) EdgeGroup() dataservices.EdgeGroupService {
return tx.store.EdgeGroupService.Tx(tx.tx) return tx.store.EdgeGroupService.Tx(tx.tx)

View File

@ -940,6 +940,6 @@
} }
], ],
"version": { "version": {
"VERSION": "{\"SchemaVersion\":\"2.22.0\",\"MigratorCount\":0,\"Edition\":1,\"InstanceID\":\"463d5c47-0ea5-4aca-85b1-405ceefee254\"}" "VERSION": "{\"SchemaVersion\":\"2.22.0\",\"MigratorCount\":1,\"Edition\":1,\"InstanceID\":\"463d5c47-0ea5-4aca-85b1-405ceefee254\"}"
} }
} }

View File

@ -179,6 +179,12 @@ func (handler *Handler) deleteEndpoint(tx dataservices.DataStoreTx, endpointID p
} }
} }
// delete the pending actions
err = tx.PendingActions().DeleteByEndpointID(endpoint.ID)
if err != nil {
log.Warn().Err(err).Int("endpointId", int(endpoint.ID)).Msgf("Unable to delete pending actions")
}
err = tx.Endpoint().DeleteEndpoint(portainer.EndpointID(endpointID)) err = tx.Endpoint().DeleteEndpoint(portainer.EndpointID(endpointID))
if err != nil { if err != nil {
return httperror.InternalServerError("Unable to delete the environment from the database", err) return httperror.InternalServerError("Unable to delete the environment from the database", err)