From 56d6dfe02e4f859f9ed2498609a2e805f6e37f93 Mon Sep 17 00:00:00 2001 From: andres-portainer <91705312+andres-portainer@users.noreply.github.com> Date: Thu, 20 Apr 2023 18:42:52 -0300 Subject: [PATCH] feat(transactions): add transaction support for Registries EE-5382 (#8825) --- api/dataservices/registry/registry.go | 21 +++++--- api/dataservices/registry/tx.go | 75 +++++++++++++++++++++++++++ api/datastore/services_tx.go | 14 +++-- 3 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 api/dataservices/registry/tx.go diff --git a/api/dataservices/registry/registry.go b/api/dataservices/registry/registry.go index 1d1da685c..cc11c72f6 100644 --- a/api/dataservices/registry/registry.go +++ b/api/dataservices/registry/registry.go @@ -8,10 +8,8 @@ import ( "github.com/rs/zerolog/log" ) -const ( - // BucketName represents the name of the bucket where this service stores data. - BucketName = "registries" -) +// BucketName represents the name of the bucket where this service stores data. +const BucketName = "registries" // Service represents a service for managing environment(endpoint) data. type Service struct { @@ -34,7 +32,14 @@ func NewService(connection portainer.Connection) (*Service, error) { }, nil } -// Registry returns an registry by ID. +func (service *Service) Tx(tx portainer.Transaction) ServiceTx { + return ServiceTx{ + service: service, + tx: tx, + } +} + +// Registry returns a registry by ID. func (service *Service) Registry(ID portainer.RegistryID) (*portainer.Registry, error) { var registry portainer.Registry identifier := service.connection.ConvertToKey(int(ID)) @@ -69,7 +74,7 @@ func (service *Service) Registries() ([]portainer.Registry, error) { return registries, err } -// CreateRegistry creates a new registry. +// Create creates a new registry. func (service *Service) Create(registry *portainer.Registry) error { return service.connection.CreateObject( BucketName, @@ -80,13 +85,13 @@ func (service *Service) Create(registry *portainer.Registry) error { ) } -// UpdateRegistry updates an registry. +// UpdateRegistry updates a registry. func (service *Service) UpdateRegistry(ID portainer.RegistryID, registry *portainer.Registry) error { identifier := service.connection.ConvertToKey(int(ID)) return service.connection.UpdateObject(BucketName, identifier, registry) } -// DeleteRegistry deletes an registry. +// DeleteRegistry deletes a registry. func (service *Service) DeleteRegistry(ID portainer.RegistryID) error { identifier := service.connection.ConvertToKey(int(ID)) return service.connection.DeleteObject(BucketName, identifier) diff --git a/api/dataservices/registry/tx.go b/api/dataservices/registry/tx.go new file mode 100644 index 000000000..ce1cc444c --- /dev/null +++ b/api/dataservices/registry/tx.go @@ -0,0 +1,75 @@ +package registry + +import ( + "fmt" + + portainer "github.com/portainer/portainer/api" + "github.com/rs/zerolog/log" +) + +type ServiceTx struct { + service *Service + tx portainer.Transaction +} + +func (service ServiceTx) BucketName() string { + return BucketName +} + +// Registry returns a registry by ID. +func (service ServiceTx) Registry(ID portainer.RegistryID) (*portainer.Registry, error) { + var registry portainer.Registry + identifier := service.service.connection.ConvertToKey(int(ID)) + + err := service.tx.GetObject(BucketName, identifier, ®istry) + if err != nil { + return nil, err + } + + return ®istry, nil +} + +// Registries returns an array containing all the registries. +func (service ServiceTx) Registries() ([]portainer.Registry, error) { + var registries = make([]portainer.Registry, 0) + + err := service.tx.GetAll( + BucketName, + &portainer.Registry{}, + func(obj interface{}) (interface{}, error) { + registry, ok := obj.(*portainer.Registry) + if !ok { + log.Debug().Str("obj", fmt.Sprintf("%#v", obj)).Msg("failed to convert to Registry object") + return nil, fmt.Errorf("Failed to convert to Registry object: %s", obj) + } + + registries = append(registries, *registry) + + return &portainer.Registry{}, nil + }) + + return registries, err +} + +// Create creates a new registry. +func (service ServiceTx) Create(registry *portainer.Registry) error { + return service.tx.CreateObject( + BucketName, + func(id uint64) (int, interface{}) { + registry.ID = portainer.RegistryID(id) + return int(registry.ID), registry + }, + ) +} + +// UpdateRegistry updates a registry. +func (service ServiceTx) UpdateRegistry(ID portainer.RegistryID, registry *portainer.Registry) error { + identifier := service.service.connection.ConvertToKey(int(ID)) + return service.tx.UpdateObject(BucketName, identifier, registry) +} + +// DeleteRegistry deletes a registry. +func (service ServiceTx) DeleteRegistry(ID portainer.RegistryID) error { + identifier := service.service.connection.ConvertToKey(int(ID)) + return service.tx.DeleteObject(BucketName, identifier) +} diff --git a/api/datastore/services_tx.go b/api/datastore/services_tx.go index ae44946cf..d027ef6d6 100644 --- a/api/datastore/services_tx.go +++ b/api/datastore/services_tx.go @@ -42,11 +42,15 @@ func (tx *StoreTx) EndpointRelation() dataservices.EndpointRelationService { func (tx *StoreTx) FDOProfile() dataservices.FDOProfileService { return nil } func (tx *StoreTx) HelmUserRepository() dataservices.HelmUserRepositoryService { return nil } -func (tx *StoreTx) Registry() dataservices.RegistryService { return nil } -func (tx *StoreTx) ResourceControl() dataservices.ResourceControlService { return nil } -func (tx *StoreTx) Role() dataservices.RoleService { return nil } -func (tx *StoreTx) APIKeyRepository() dataservices.APIKeyRepository { return nil } -func (tx *StoreTx) Settings() dataservices.SettingsService { return nil } + +func (tx *StoreTx) Registry() dataservices.RegistryService { + return nil +} + +func (tx *StoreTx) ResourceControl() dataservices.ResourceControlService { return nil } +func (tx *StoreTx) Role() dataservices.RoleService { return nil } +func (tx *StoreTx) APIKeyRepository() dataservices.APIKeyRepository { return nil } +func (tx *StoreTx) Settings() dataservices.SettingsService { return nil } func (tx *StoreTx) Snapshot() dataservices.SnapshotService { return tx.store.SnapshotService.Tx(tx.tx)