mirror of https://github.com/portainer/portainer
fix(pending-actions): clean pending actions for deleted environment [EE-6545] (#11598)
parent
37bba18c81
commit
d9df58e93a
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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\"}"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue