From d7ff14777f610c93301b17e7ff0b1301df19c0e8 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Tue, 19 Jun 2018 13:15:10 +0200 Subject: [PATCH] refactor(api): restructure bolt package (#1981) * refactor(api): bolt package refactor * refactor(api): refactor bolt package --- api/bolt/datastore.go | 231 +++++++++++------- api/bolt/dockerhub/dockerhub.go | 48 ++++ api/bolt/dockerhub_service.go | 61 ----- api/bolt/endpoint/endpoint.go | 138 +++++++++++ api/bolt/endpoint_group_service.go | 114 --------- api/bolt/endpoint_service.go | 154 ------------ api/bolt/endpointgroup/endpointgroup.go | 95 +++++++ api/bolt/internal/db.go | 94 +++++++ api/bolt/internal/{internal.go => json.go} | 10 - api/bolt/migrate_dbversion4.go | 16 -- api/bolt/migrate_dbversion5.go | 16 -- api/bolt/migrate_dbversion6.go | 16 -- api/bolt/migrator.go | 152 ------------ api/bolt/{ => migrator}/migrate_dbversion0.go | 19 +- api/bolt/{ => migrator}/migrate_dbversion1.go | 12 +- .../{ => migrator}/migrate_dbversion10.go | 6 +- .../{ => migrator}/migrate_dbversion11.go | 36 ++- api/bolt/{ => migrator}/migrate_dbversion2.go | 11 +- api/bolt/{ => migrator}/migrate_dbversion3.go | 7 +- api/bolt/migrator/migrate_dbversion4.go | 11 + api/bolt/migrator/migrate_dbversion5.go | 11 + api/bolt/migrator/migrate_dbversion6.go | 11 + api/bolt/{ => migrator}/migrate_dbversion7.go | 6 +- api/bolt/{ => migrator}/migrate_dbversion8.go | 6 +- api/bolt/{ => migrator}/migrate_dbversion9.go | 6 +- api/bolt/migrator/migrator.go | 174 +++++++++++++ api/bolt/registry/registry.go | 95 +++++++ api/bolt/registry_service.go | 114 --------- api/bolt/resource_control_service.go | 148 ----------- api/bolt/resourcecontrol/resourcecontrol.go | 134 ++++++++++ api/bolt/settings/settings.go | 48 ++++ api/bolt/settings_service.go | 61 ----- api/bolt/stack/stack.go | 134 ++++++++++ api/bolt/stack_service.go | 159 ------------ api/bolt/tag/tag.go | 76 ++++++ api/bolt/tag_service.go | 71 ------ api/bolt/team/team.go | 126 ++++++++++ api/bolt/team_service.go | 144 ----------- .../teammembership.go} | 142 +++++------ api/bolt/user/user.go | 149 +++++++++++ api/bolt/user_service.go | 170 ------------- api/bolt/version/version.go | 66 +++++ api/bolt/version_service.go | 58 ----- api/cmd/portainer/main.go | 8 +- api/errors.go | 26 +- api/filesystem/filesystem.go | 25 +- api/http/handler/auth/authenticate.go | 2 +- .../handler/dockerhub/dockerhub_update.go | 2 +- .../endpointgroups/endpointgroup_delete.go | 2 +- .../endpointgroups/endpointgroup_inspect.go | 2 +- .../endpointgroups/endpointgroup_update.go | 2 +- .../endpointgroup_update_access.go | 2 +- api/http/handler/endpointproxy/proxy_azure.go | 2 +- .../handler/endpointproxy/proxy_docker.go | 2 +- .../handler/endpointproxy/proxy_storidge.go | 2 +- api/http/handler/endpoints/endpoint_delete.go | 2 +- .../endpoints/endpoint_extension_add.go | 2 +- .../endpoints/endpoint_extension_remove.go | 2 +- .../handler/endpoints/endpoint_inspect.go | 2 +- api/http/handler/endpoints/endpoint_update.go | 2 +- .../endpoints/endpoint_update_access.go | 2 +- .../handler/registries/registry_delete.go | 2 +- .../handler/registries/registry_inspect.go | 2 +- .../handler/registries/registry_update.go | 2 +- .../registries/registry_update_access.go | 2 +- .../resourcecontrol_create.go | 2 +- .../resourcecontrol_delete.go | 2 +- .../resourcecontrol_update.go | 2 +- api/http/handler/settings/settings_update.go | 2 +- api/http/handler/stacks/stack_create.go | 2 +- api/http/handler/stacks/stack_delete.go | 10 +- api/http/handler/stacks/stack_file.go | 4 +- api/http/handler/stacks/stack_inspect.go | 4 +- api/http/handler/stacks/stack_update.go | 6 +- .../teammemberships/teammembership_delete.go | 2 +- .../teammemberships/teammembership_update.go | 2 +- api/http/handler/teams/team_create.go | 2 +- api/http/handler/teams/team_delete.go | 2 +- api/http/handler/teams/team_inspect.go | 2 +- api/http/handler/teams/team_update.go | 2 +- api/http/handler/users/admin_check.go | 2 +- api/http/handler/users/user_create.go | 2 +- api/http/handler/users/user_delete.go | 2 +- api/http/handler/users/user_inspect.go | 2 +- api/http/handler/users/user_password.go | 2 +- api/http/handler/users/user_update.go | 2 +- api/http/handler/websocket/websocket_exec.go | 2 +- api/http/security/bouncer.go | 2 +- api/portainer.go | 5 +- 89 files changed, 1729 insertions(+), 1791 deletions(-) create mode 100644 api/bolt/dockerhub/dockerhub.go delete mode 100644 api/bolt/dockerhub_service.go create mode 100644 api/bolt/endpoint/endpoint.go delete mode 100644 api/bolt/endpoint_group_service.go delete mode 100644 api/bolt/endpoint_service.go create mode 100644 api/bolt/endpointgroup/endpointgroup.go create mode 100644 api/bolt/internal/db.go rename api/bolt/internal/{internal.go => json.go} (53%) delete mode 100644 api/bolt/migrate_dbversion4.go delete mode 100644 api/bolt/migrate_dbversion5.go delete mode 100644 api/bolt/migrate_dbversion6.go delete mode 100644 api/bolt/migrator.go rename api/bolt/{ => migrator}/migrate_dbversion0.go (56%) rename api/bolt/{ => migrator}/migrate_dbversion1.go (89%) rename api/bolt/{ => migrator}/migrate_dbversion10.go (78%) rename api/bolt/{ => migrator}/migrate_dbversion11.go (73%) rename api/bolt/{ => migrator}/migrate_dbversion2.go (70%) rename api/bolt/{ => migrator}/migrate_dbversion3.go (80%) create mode 100644 api/bolt/migrator/migrate_dbversion4.go create mode 100644 api/bolt/migrator/migrate_dbversion5.go create mode 100644 api/bolt/migrator/migrate_dbversion6.go rename api/bolt/{ => migrator}/migrate_dbversion7.go (67%) rename api/bolt/{ => migrator}/migrate_dbversion8.go (67%) rename api/bolt/{ => migrator}/migrate_dbversion9.go (67%) create mode 100644 api/bolt/migrator/migrator.go create mode 100644 api/bolt/registry/registry.go delete mode 100644 api/bolt/registry_service.go delete mode 100644 api/bolt/resource_control_service.go create mode 100644 api/bolt/resourcecontrol/resourcecontrol.go create mode 100644 api/bolt/settings/settings.go delete mode 100644 api/bolt/settings_service.go create mode 100644 api/bolt/stack/stack.go delete mode 100644 api/bolt/stack_service.go create mode 100644 api/bolt/tag/tag.go delete mode 100644 api/bolt/tag_service.go create mode 100644 api/bolt/team/team.go delete mode 100644 api/bolt/team_service.go rename api/bolt/{team_membership_service.go => teammembership/teammembership.go} (51%) create mode 100644 api/bolt/user/user.go delete mode 100644 api/bolt/user_service.go create mode 100644 api/bolt/version/version.go delete mode 100644 api/bolt/version_service.go diff --git a/api/bolt/datastore.go b/api/bolt/datastore.go index d5002a413..e898d4ec2 100644 --- a/api/bolt/datastore.go +++ b/api/bolt/datastore.go @@ -2,90 +2,66 @@ package bolt import ( "log" - "os" + "path" "time" "github.com/boltdb/bolt" "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/dockerhub" + "github.com/portainer/portainer/bolt/endpoint" + "github.com/portainer/portainer/bolt/endpointgroup" + "github.com/portainer/portainer/bolt/migrator" + "github.com/portainer/portainer/bolt/registry" + "github.com/portainer/portainer/bolt/resourcecontrol" + "github.com/portainer/portainer/bolt/settings" + "github.com/portainer/portainer/bolt/stack" + "github.com/portainer/portainer/bolt/tag" + "github.com/portainer/portainer/bolt/team" + "github.com/portainer/portainer/bolt/teammembership" + "github.com/portainer/portainer/bolt/user" + "github.com/portainer/portainer/bolt/version" +) + +const ( + databaseFileName = "portainer.db" ) // Store defines the implementation of portainer.DataStore using // BoltDB as the storage system. type Store struct { - // Path where is stored the BoltDB database. - Path string - - // Services - UserService *UserService - TeamService *TeamService - TeamMembershipService *TeamMembershipService - EndpointService *EndpointService - EndpointGroupService *EndpointGroupService - ResourceControlService *ResourceControlService - VersionService *VersionService - SettingsService *SettingsService - RegistryService *RegistryService - DockerHubService *DockerHubService - StackService *StackService - TagService *TagService - - db *bolt.DB - checkForDataMigration bool - FileService portainer.FileService + path string + db *bolt.DB + checkForDataMigration bool + fileService portainer.FileService + DockerHubService *dockerhub.Service + EndpointGroupService *endpointgroup.Service + EndpointService *endpoint.Service + RegistryService *registry.Service + ResourceControlService *resourcecontrol.Service + SettingsService *settings.Service + StackService *stack.Service + TagService *tag.Service + TeamMembershipService *teammembership.Service + TeamService *team.Service + UserService *user.Service + VersionService *version.Service } -const ( - databaseFileName = "portainer.db" - versionBucketName = "version" - userBucketName = "users" - teamBucketName = "teams" - teamMembershipBucketName = "team_membership" - endpointBucketName = "endpoints" - endpointGroupBucketName = "endpoint_groups" - resourceControlBucketName = "resource_control" - settingsBucketName = "settings" - registryBucketName = "registries" - dockerhubBucketName = "dockerhub" - stackBucketName = "stacks" - tagBucketName = "tags" -) - // NewStore initializes a new Store and the associated services func NewStore(storePath string, fileService portainer.FileService) (*Store, error) { store := &Store{ - Path: storePath, - UserService: &UserService{}, - TeamService: &TeamService{}, - TeamMembershipService: &TeamMembershipService{}, - EndpointService: &EndpointService{}, - EndpointGroupService: &EndpointGroupService{}, - ResourceControlService: &ResourceControlService{}, - VersionService: &VersionService{}, - SettingsService: &SettingsService{}, - RegistryService: &RegistryService{}, - DockerHubService: &DockerHubService{}, - StackService: &StackService{}, - TagService: &TagService{}, - FileService: fileService, + path: storePath, + fileService: fileService, } - store.UserService.store = store - store.TeamService.store = store - store.TeamMembershipService.store = store - store.EndpointService.store = store - store.EndpointGroupService.store = store - store.ResourceControlService.store = store - store.VersionService.store = store - store.SettingsService.store = store - store.RegistryService.store = store - store.DockerHubService.store = store - store.StackService.store = store - store.TagService.store = store - _, err := os.Stat(storePath + "/" + databaseFileName) - if err != nil && os.IsNotExist(err) { - store.checkForDataMigration = false - } else if err != nil { + databasePath := path.Join(storePath, databaseFileName) + databaseFileExists, err := fileService.FileExists(databasePath) + if err != nil { return nil, err + } + + if !databaseFileExists { + store.checkForDataMigration = false } else { store.checkForDataMigration = true } @@ -95,29 +71,14 @@ func NewStore(storePath string, fileService portainer.FileService) (*Store, erro // Open opens and initializes the BoltDB database. func (store *Store) Open() error { - path := store.Path + "/" + databaseFileName - - db, err := bolt.Open(path, 0600, &bolt.Options{Timeout: 1 * time.Second}) + databasePath := path.Join(store.path, databaseFileName) + db, err := bolt.Open(databasePath, 0600, &bolt.Options{Timeout: 1 * time.Second}) if err != nil { return err } store.db = db - bucketsToCreate := []string{versionBucketName, userBucketName, teamBucketName, endpointBucketName, - endpointGroupBucketName, resourceControlBucketName, teamMembershipBucketName, settingsBucketName, - registryBucketName, dockerhubBucketName, stackBucketName, tagBucketName} - - return db.Update(func(tx *bolt.Tx) error { - - for _, bucket := range bucketsToCreate { - _, err := tx.CreateBucketIfNotExists([]byte(bucket)) - if err != nil { - return err - } - } - - return nil - }) + return store.initServices() } // Init creates the default data set. @@ -154,28 +115,114 @@ func (store *Store) Close() error { // MigrateData automatically migrate the data based on the DBVersion. func (store *Store) MigrateData() error { if !store.checkForDataMigration { - err := store.VersionService.StoreDBVersion(portainer.DBVersion) - if err != nil { - return err - } - return nil + return store.VersionService.StoreDBVersion(portainer.DBVersion) } version, err := store.VersionService.DBVersion() - if err == portainer.ErrDBVersionNotFound { + if err == portainer.ErrObjectNotFound { version = 0 } else if err != nil { return err } if version < portainer.DBVersion { + migratorParams := &migrator.Parameters{ + DB: store.db, + DatabaseVersion: version, + EndpointGroupService: store.EndpointGroupService, + EndpointService: store.EndpointService, + ResourceControlService: store.ResourceControlService, + SettingsService: store.SettingsService, + StackService: store.StackService, + UserService: store.UserService, + VersionService: store.VersionService, + FileService: store.fileService, + } + migrator := migrator.NewMigrator(migratorParams) + log.Printf("Migrating database from version %v to %v.\n", version, portainer.DBVersion) - migrator := NewMigrator(store, version) err = migrator.Migrate() if err != nil { + log.Printf("An error occurred during database migration: %s\n", err) return err } } return nil } + +func (store *Store) initServices() error { + dockerhubService, err := dockerhub.NewService(store.db) + if err != nil { + return err + } + store.DockerHubService = dockerhubService + + endpointgroupService, err := endpointgroup.NewService(store.db) + if err != nil { + return err + } + store.EndpointGroupService = endpointgroupService + + endpointService, err := endpoint.NewService(store.db) + if err != nil { + return err + } + store.EndpointService = endpointService + + registryService, err := registry.NewService(store.db) + if err != nil { + return err + } + store.RegistryService = registryService + + resourcecontrolService, err := resourcecontrol.NewService(store.db) + if err != nil { + return err + } + store.ResourceControlService = resourcecontrolService + + settingsService, err := settings.NewService(store.db) + if err != nil { + return err + } + store.SettingsService = settingsService + + stackService, err := stack.NewService(store.db) + if err != nil { + return err + } + store.StackService = stackService + + tagService, err := tag.NewService(store.db) + if err != nil { + return err + } + store.TagService = tagService + + teammembershipService, err := teammembership.NewService(store.db) + if err != nil { + return err + } + store.TeamMembershipService = teammembershipService + + teamService, err := team.NewService(store.db) + if err != nil { + return err + } + store.TeamService = teamService + + userService, err := user.NewService(store.db) + if err != nil { + return err + } + store.UserService = userService + + versionService, err := version.NewService(store.db) + if err != nil { + return err + } + store.VersionService = versionService + + return nil +} diff --git a/api/bolt/dockerhub/dockerhub.go b/api/bolt/dockerhub/dockerhub.go new file mode 100644 index 000000000..0e4b4858c --- /dev/null +++ b/api/bolt/dockerhub/dockerhub.go @@ -0,0 +1,48 @@ +package dockerhub + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "dockerhub" + dockerHubKey = "DOCKERHUB" +) + +// Service represents a service for managing Dockerhub data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// DockerHub returns the DockerHub object. +func (service *Service) DockerHub() (*portainer.DockerHub, error) { + var dockerhub portainer.DockerHub + + err := internal.GetObject(service.db, BucketName, []byte(dockerHubKey), &dockerhub) + if err != nil { + return nil, err + } + + return &dockerhub, nil +} + +// UpdateDockerHub updates a DockerHub object. +func (service *Service) UpdateDockerHub(dockerhub *portainer.DockerHub) error { + return internal.UpdateObject(service.db, BucketName, []byte(dockerHubKey), dockerhub) +} diff --git a/api/bolt/dockerhub_service.go b/api/bolt/dockerhub_service.go deleted file mode 100644 index d28aa6fb2..000000000 --- a/api/bolt/dockerhub_service.go +++ /dev/null @@ -1,61 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// DockerHubService represents a service for managing registries. -type DockerHubService struct { - store *Store -} - -const ( - dbDockerHubKey = "DOCKERHUB" -) - -// DockerHub returns the DockerHub object. -func (service *DockerHubService) DockerHub() (*portainer.DockerHub, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(dockerhubBucketName)) - value := bucket.Get([]byte(dbDockerHubKey)) - if value == nil { - return portainer.ErrDockerHubNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var dockerhub portainer.DockerHub - err = internal.UnmarshalObject(data, &dockerhub) - if err != nil { - return nil, err - } - return &dockerhub, nil -} - -// StoreDockerHub persists a DockerHub object. -func (service *DockerHubService) StoreDockerHub(dockerhub *portainer.DockerHub) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(dockerhubBucketName)) - - data, err := internal.MarshalObject(dockerhub) - if err != nil { - return err - } - - err = bucket.Put([]byte(dbDockerHubKey), data) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/endpoint/endpoint.go b/api/bolt/endpoint/endpoint.go new file mode 100644 index 000000000..79672eb36 --- /dev/null +++ b/api/bolt/endpoint/endpoint.go @@ -0,0 +1,138 @@ +package endpoint + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "endpoints" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// Endpoint returns an endpoint by ID. +func (service *Service) Endpoint(ID portainer.EndpointID) (*portainer.Endpoint, error) { + var endpoint portainer.Endpoint + identifier := internal.Itob(int(ID)) + + err := internal.GetObject(service.db, BucketName, identifier, &endpoint) + if err != nil { + return nil, err + } + + return &endpoint, nil +} + +// UpdateEndpoint updates an endpoint. +func (service *Service) UpdateEndpoint(ID portainer.EndpointID, endpoint *portainer.Endpoint) error { + identifier := internal.Itob(int(ID)) + return internal.UpdateObject(service.db, BucketName, identifier, endpoint) +} + +// DeleteEndpoint deletes an endpoint. +func (service *Service) DeleteEndpoint(ID portainer.EndpointID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) +} + +// Endpoints return an array containing all the endpoints. +func (service *Service) Endpoints() ([]portainer.Endpoint, error) { + var endpoints = make([]portainer.Endpoint, 0) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var endpoint portainer.Endpoint + err := internal.UnmarshalObject(v, &endpoint) + if err != nil { + return err + } + endpoints = append(endpoints, endpoint) + } + + return nil + }) + + return endpoints, err +} + +// CreateEndpoint assign an ID to a new endpoint and saves it. +func (service *Service) CreateEndpoint(endpoint *portainer.Endpoint) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + id, _ := bucket.NextSequence() + endpoint.ID = portainer.EndpointID(id) + + data, err := internal.MarshalObject(endpoint) + if err != nil { + return err + } + + return bucket.Put(internal.Itob(int(endpoint.ID)), data) + }) +} + +// Synchronize creates, updates and deletes endpoints inside a single transaction. +func (service *Service) Synchronize(toCreate, toUpdate, toDelete []*portainer.Endpoint) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + for _, endpoint := range toCreate { + id, _ := bucket.NextSequence() + endpoint.ID = portainer.EndpointID(id) + + data, err := internal.MarshalObject(endpoint) + if err != nil { + return err + } + + err = bucket.Put(internal.Itob(int(endpoint.ID)), data) + if err != nil { + return err + } + } + + for _, endpoint := range toUpdate { + data, err := internal.MarshalObject(endpoint) + if err != nil { + return err + } + + err = bucket.Put(internal.Itob(int(endpoint.ID)), data) + if err != nil { + return err + } + } + + for _, endpoint := range toDelete { + err := bucket.Delete(internal.Itob(int(endpoint.ID))) + if err != nil { + return err + } + } + + return nil + }) +} diff --git a/api/bolt/endpoint_group_service.go b/api/bolt/endpoint_group_service.go deleted file mode 100644 index 9a539ee83..000000000 --- a/api/bolt/endpoint_group_service.go +++ /dev/null @@ -1,114 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// EndpointGroupService represents a service for managing endpoint groups. -type EndpointGroupService struct { - store *Store -} - -// EndpointGroup returns an endpoint group by ID. -func (service *EndpointGroupService) EndpointGroup(ID portainer.EndpointGroupID) (*portainer.EndpointGroup, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointGroupBucketName)) - value := bucket.Get(internal.Itob(int(ID))) - if value == nil { - return portainer.ErrEndpointGroupNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var endpointGroup portainer.EndpointGroup - err = internal.UnmarshalObject(data, &endpointGroup) - if err != nil { - return nil, err - } - return &endpointGroup, nil -} - -// EndpointGroups return an array containing all the endpoint groups. -func (service *EndpointGroupService) EndpointGroups() ([]portainer.EndpointGroup, error) { - var endpointGroups = make([]portainer.EndpointGroup, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointGroupBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var endpointGroup portainer.EndpointGroup - err := internal.UnmarshalObject(v, &endpointGroup) - if err != nil { - return err - } - endpointGroups = append(endpointGroups, endpointGroup) - } - - return nil - }) - if err != nil { - return nil, err - } - - return endpointGroups, nil -} - -// CreateEndpointGroup assign an ID to a new endpoint group and saves it. -func (service *EndpointGroupService) CreateEndpointGroup(endpointGroup *portainer.EndpointGroup) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointGroupBucketName)) - - id, _ := bucket.NextSequence() - endpointGroup.ID = portainer.EndpointGroupID(id) - - data, err := internal.MarshalObject(endpointGroup) - if err != nil { - return err - } - - err = bucket.Put(internal.Itob(int(endpointGroup.ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// UpdateEndpointGroup updates an endpoint group. -func (service *EndpointGroupService) UpdateEndpointGroup(ID portainer.EndpointGroupID, endpointGroup *portainer.EndpointGroup) error { - data, err := internal.MarshalObject(endpointGroup) - if err != nil { - return err - } - - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointGroupBucketName)) - err = bucket.Put(internal.Itob(int(ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// DeleteEndpointGroup deletes an endpoint group. -func (service *EndpointGroupService) DeleteEndpointGroup(ID portainer.EndpointGroupID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointGroupBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/endpoint_service.go b/api/bolt/endpoint_service.go deleted file mode 100644 index e685a9b72..000000000 --- a/api/bolt/endpoint_service.go +++ /dev/null @@ -1,154 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// EndpointService represents a service for managing endpoints. -type EndpointService struct { - store *Store -} - -// Endpoint returns an endpoint by ID. -func (service *EndpointService) Endpoint(ID portainer.EndpointID) (*portainer.Endpoint, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointBucketName)) - value := bucket.Get(internal.Itob(int(ID))) - if value == nil { - return portainer.ErrEndpointNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var endpoint portainer.Endpoint - err = internal.UnmarshalObject(data, &endpoint) - if err != nil { - return nil, err - } - return &endpoint, nil -} - -// Endpoints return an array containing all the endpoints. -func (service *EndpointService) Endpoints() ([]portainer.Endpoint, error) { - var endpoints = make([]portainer.Endpoint, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var endpoint portainer.Endpoint - err := internal.UnmarshalObject(v, &endpoint) - if err != nil { - return err - } - endpoints = append(endpoints, endpoint) - } - - return nil - }) - if err != nil { - return nil, err - } - - return endpoints, nil -} - -// Synchronize creates, updates and deletes endpoints inside a single transaction. -func (service *EndpointService) Synchronize(toCreate, toUpdate, toDelete []*portainer.Endpoint) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointBucketName)) - - for _, endpoint := range toCreate { - err := storeNewEndpoint(endpoint, bucket) - if err != nil { - return err - } - } - - for _, endpoint := range toUpdate { - err := marshalAndStoreEndpoint(endpoint, bucket) - if err != nil { - return err - } - } - - for _, endpoint := range toDelete { - err := bucket.Delete(internal.Itob(int(endpoint.ID))) - if err != nil { - return err - } - } - - return nil - }) -} - -// CreateEndpoint assign an ID to a new endpoint and saves it. -func (service *EndpointService) CreateEndpoint(endpoint *portainer.Endpoint) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointBucketName)) - err := storeNewEndpoint(endpoint, bucket) - if err != nil { - return err - } - return nil - }) -} - -// UpdateEndpoint updates an endpoint. -func (service *EndpointService) UpdateEndpoint(ID portainer.EndpointID, endpoint *portainer.Endpoint) error { - data, err := internal.MarshalObject(endpoint) - if err != nil { - return err - } - - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointBucketName)) - err = bucket.Put(internal.Itob(int(ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// DeleteEndpoint deletes an endpoint. -func (service *EndpointService) DeleteEndpoint(ID portainer.EndpointID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(endpointBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) -} - -func marshalAndStoreEndpoint(endpoint *portainer.Endpoint, bucket *bolt.Bucket) error { - data, err := internal.MarshalObject(endpoint) - if err != nil { - return err - } - - err = bucket.Put(internal.Itob(int(endpoint.ID)), data) - if err != nil { - return err - } - return nil -} - -func storeNewEndpoint(endpoint *portainer.Endpoint, bucket *bolt.Bucket) error { - id, _ := bucket.NextSequence() - endpoint.ID = portainer.EndpointID(id) - return marshalAndStoreEndpoint(endpoint, bucket) -} diff --git a/api/bolt/endpointgroup/endpointgroup.go b/api/bolt/endpointgroup/endpointgroup.go new file mode 100644 index 000000000..89398dbd5 --- /dev/null +++ b/api/bolt/endpointgroup/endpointgroup.go @@ -0,0 +1,95 @@ +package endpointgroup + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "endpoint_groups" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// EndpointGroup returns an endpoint group by ID. +func (service *Service) EndpointGroup(ID portainer.EndpointGroupID) (*portainer.EndpointGroup, error) { + var endpointGroup portainer.EndpointGroup + identifier := internal.Itob(int(ID)) + + err := internal.GetObject(service.db, BucketName, identifier, &endpointGroup) + if err != nil { + return nil, err + } + + return &endpointGroup, nil +} + +// UpdateEndpointGroup updates an endpoint group. +func (service *Service) UpdateEndpointGroup(ID portainer.EndpointGroupID, endpointGroup *portainer.EndpointGroup) error { + identifier := internal.Itob(int(ID)) + return internal.UpdateObject(service.db, BucketName, identifier, endpointGroup) +} + +// DeleteEndpointGroup deletes an endpoint group. +func (service *Service) DeleteEndpointGroup(ID portainer.EndpointGroupID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) +} + +// EndpointGroups return an array containing all the endpoint groups. +func (service *Service) EndpointGroups() ([]portainer.EndpointGroup, error) { + var endpointGroups = make([]portainer.EndpointGroup, 0) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var endpointGroup portainer.EndpointGroup + err := internal.UnmarshalObject(v, &endpointGroup) + if err != nil { + return err + } + endpointGroups = append(endpointGroups, endpointGroup) + } + + return nil + }) + + return endpointGroups, err +} + +// CreateEndpointGroup assign an ID to a new endpoint group and saves it. +func (service *Service) CreateEndpointGroup(endpointGroup *portainer.EndpointGroup) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + id, _ := bucket.NextSequence() + endpointGroup.ID = portainer.EndpointGroupID(id) + + data, err := internal.MarshalObject(endpointGroup) + if err != nil { + return err + } + + return bucket.Put(internal.Itob(int(endpointGroup.ID)), data) + }) +} diff --git a/api/bolt/internal/db.go b/api/bolt/internal/db.go new file mode 100644 index 000000000..59ca7c87d --- /dev/null +++ b/api/bolt/internal/db.go @@ -0,0 +1,94 @@ +package internal + +import ( + "encoding/binary" + + "github.com/boltdb/bolt" + "github.com/portainer/portainer" +) + +// Itob returns an 8-byte big endian representation of v. +// This function is typically used for encoding integer IDs to byte slices +// so that they can be used as BoltDB keys. +func Itob(v int) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(v)) + return b +} + +// CreateBucket is a generic function used to create a bucket inside a bolt database. +func CreateBucket(db *bolt.DB, bucketName string) error { + return db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucketIfNotExists([]byte(bucketName)) + if err != nil { + return err + } + return nil + }) +} + +// GetObject is a generic function used to retrieve an unmarshalled object from a bolt database. +func GetObject(db *bolt.DB, bucketName string, key []byte, object interface{}) error { + var data []byte + + err := db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(bucketName)) + + value := bucket.Get(key) + if value == nil { + return portainer.ErrObjectNotFound + } + + data = make([]byte, len(value)) + copy(data, value) + + return nil + }) + if err != nil { + return err + } + + return UnmarshalObject(data, object) +} + +// UpdateObject is a generic function used to update an object inside a bolt database. +func UpdateObject(db *bolt.DB, bucketName string, key []byte, object interface{}) error { + return db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(bucketName)) + + data, err := MarshalObject(object) + if err != nil { + return err + } + + err = bucket.Put(key, data) + if err != nil { + return err + } + + return nil + }) +} + +// DeleteObject is a generic function used to delete an object inside a bolt database. +func DeleteObject(db *bolt.DB, bucketName string, key []byte) error { + return db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(bucketName)) + return bucket.Delete(key) + }) +} + +// GetNextIdentifier is a generic function that returns the specified bucket identifier incremented by 1. +func GetNextIdentifier(db *bolt.DB, bucketName string) int { + var identifier int + + db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(bucketName)) + id := bucket.Sequence() + identifier = int(id) + return nil + }) + + identifier++ + return identifier +} diff --git a/api/bolt/internal/internal.go b/api/bolt/internal/json.go similarity index 53% rename from api/bolt/internal/internal.go rename to api/bolt/internal/json.go index 4c45524b6..9f69f06ee 100644 --- a/api/bolt/internal/internal.go +++ b/api/bolt/internal/json.go @@ -1,7 +1,6 @@ package internal import ( - "encoding/binary" "encoding/json" ) @@ -14,12 +13,3 @@ func MarshalObject(object interface{}) ([]byte, error) { func UnmarshalObject(data []byte, object interface{}) error { return json.Unmarshal(data, object) } - -// Itob returns an 8-byte big endian representation of v. -// This function is typically used for encoding integer IDs to byte slices -// so that they can be used as BoltDB keys. -func Itob(v int) []byte { - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, uint64(v)) - return b -} diff --git a/api/bolt/migrate_dbversion4.go b/api/bolt/migrate_dbversion4.go deleted file mode 100644 index ace64f51e..000000000 --- a/api/bolt/migrate_dbversion4.go +++ /dev/null @@ -1,16 +0,0 @@ -package bolt - -func (m *Migrator) updateSettingsToVersion5() error { - legacySettings, err := m.SettingsService.Settings() - if err != nil { - return err - } - legacySettings.AllowBindMountsForRegularUsers = true - - err = m.SettingsService.StoreSettings(legacySettings) - if err != nil { - return err - } - - return nil -} diff --git a/api/bolt/migrate_dbversion5.go b/api/bolt/migrate_dbversion5.go deleted file mode 100644 index ef1bfd3ad..000000000 --- a/api/bolt/migrate_dbversion5.go +++ /dev/null @@ -1,16 +0,0 @@ -package bolt - -func (m *Migrator) updateSettingsToVersion6() error { - legacySettings, err := m.SettingsService.Settings() - if err != nil { - return err - } - legacySettings.AllowPrivilegedModeForRegularUsers = true - - err = m.SettingsService.StoreSettings(legacySettings) - if err != nil { - return err - } - - return nil -} diff --git a/api/bolt/migrate_dbversion6.go b/api/bolt/migrate_dbversion6.go deleted file mode 100644 index 95d53af61..000000000 --- a/api/bolt/migrate_dbversion6.go +++ /dev/null @@ -1,16 +0,0 @@ -package bolt - -func (m *Migrator) updateSettingsToVersion7() error { - legacySettings, err := m.SettingsService.Settings() - if err != nil { - return err - } - legacySettings.DisplayDonationHeader = true - - err = m.SettingsService.StoreSettings(legacySettings) - if err != nil { - return err - } - - return nil -} diff --git a/api/bolt/migrator.go b/api/bolt/migrator.go deleted file mode 100644 index 84ede8156..000000000 --- a/api/bolt/migrator.go +++ /dev/null @@ -1,152 +0,0 @@ -package bolt - -import "github.com/portainer/portainer" - -// Migrator defines a service to migrate data after a Portainer version update. -type Migrator struct { - CurrentDBVersion int - store *Store - - EndpointGroupService *EndpointGroupService - EndpointService *EndpointService - ResourceControlService *ResourceControlService - SettingsService *SettingsService - StackService *StackService - UserService *UserService - VersionService *VersionService - FileService portainer.FileService -} - -// NewMigrator creates a new Migrator. -func NewMigrator(store *Store, version int) *Migrator { - return &Migrator{ - CurrentDBVersion: version, - store: store, - EndpointGroupService: store.EndpointGroupService, - EndpointService: store.EndpointService, - ResourceControlService: store.ResourceControlService, - SettingsService: store.SettingsService, - StackService: store.StackService, - UserService: store.UserService, - VersionService: store.VersionService, - } -} - -// Migrate checks the database version and migrate the existing data to the most recent data model. -func (m *Migrator) Migrate() error { - - // Portainer < 1.12 - if m.CurrentDBVersion < 1 { - err := m.updateAdminUserToDBVersion1() - if err != nil { - return err - } - } - - // Portainer 1.12.x - if m.CurrentDBVersion < 2 { - err := m.updateResourceControlsToDBVersion2() - if err != nil { - return err - } - err = m.updateEndpointsToDBVersion2() - if err != nil { - return err - } - } - - // Portainer 1.13.x - if m.CurrentDBVersion < 3 { - err := m.updateSettingsToDBVersion3() - if err != nil { - return err - } - } - - // Portainer 1.14.0 - if m.CurrentDBVersion < 4 { - err := m.updateEndpointsToDBVersion4() - if err != nil { - return err - } - } - - // https://github.com/portainer/portainer/issues/1235 - if m.CurrentDBVersion < 5 { - err := m.updateSettingsToVersion5() - if err != nil { - return err - } - } - - // https://github.com/portainer/portainer/issues/1236 - if m.CurrentDBVersion < 6 { - err := m.updateSettingsToVersion6() - if err != nil { - return err - } - } - - // https://github.com/portainer/portainer/issues/1449 - if m.CurrentDBVersion < 7 { - err := m.updateSettingsToVersion7() - if err != nil { - return err - } - } - - if m.CurrentDBVersion < 8 { - err := m.updateEndpointsToVersion8() - if err != nil { - return err - } - } - - // https: //github.com/portainer/portainer/issues/1396 - if m.CurrentDBVersion < 9 { - err := m.updateEndpointsToVersion9() - if err != nil { - return err - } - } - - // https://github.com/portainer/portainer/issues/461 - if m.CurrentDBVersion < 10 { - err := m.updateEndpointsToVersion10() - if err != nil { - return err - } - } - - // https://github.com/portainer/portainer/issues/1906 - if m.CurrentDBVersion < 11 { - err := m.updateEndpointsToVersion11() - if err != nil { - return err - } - } - - // Portainer 1.17.1-dev - if m.CurrentDBVersion < 12 { - err := m.updateEndpointsToVersion12() - if err != nil { - return err - } - - err = m.updateEndpointGroupsToVersion12() - if err != nil { - return err - } - - err = m.updateStacksToVersion12() - if err != nil { - return err - } - } - - err := m.VersionService.StoreDBVersion(portainer.DBVersion) - if err != nil { - return err - } - return nil -} diff --git a/api/bolt/migrate_dbversion0.go b/api/bolt/migrator/migrate_dbversion0.go similarity index 56% rename from api/bolt/migrate_dbversion0.go rename to api/bolt/migrator/migrate_dbversion0.go index f0223ee9e..4c2bdff12 100644 --- a/api/bolt/migrate_dbversion0.go +++ b/api/bolt/migrator/migrate_dbversion0.go @@ -1,19 +1,20 @@ -package bolt +package migrator import ( "github.com/boltdb/bolt" "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/user" ) func (m *Migrator) updateAdminUserToDBVersion1() error { - u, err := m.UserService.UserByUsername("admin") + u, err := m.userService.UserByUsername("admin") if err == nil { admin := &portainer.User{ Username: "admin", Password: u.Password, Role: portainer.AdministratorRole, } - err = m.UserService.CreateUser(admin) + err = m.userService.CreateUser(admin) if err != nil { return err } @@ -21,19 +22,15 @@ func (m *Migrator) updateAdminUserToDBVersion1() error { if err != nil { return err } - } else if err != nil && err != portainer.ErrUserNotFound { + } else if err != nil && err != portainer.ErrObjectNotFound { return err } return nil } func (m *Migrator) removeLegacyAdminUser() error { - return m.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(userBucketName)) - err := bucket.Delete([]byte("admin")) - if err != nil { - return err - } - return nil + return m.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(user.BucketName)) + return bucket.Delete([]byte("admin")) }) } diff --git a/api/bolt/migrate_dbversion1.go b/api/bolt/migrator/migrate_dbversion1.go similarity index 89% rename from api/bolt/migrate_dbversion1.go rename to api/bolt/migrator/migrate_dbversion1.go index 0b255cd68..063f58dc7 100644 --- a/api/bolt/migrate_dbversion1.go +++ b/api/bolt/migrator/migrate_dbversion1.go @@ -1,4 +1,4 @@ -package bolt +package migrator import ( "github.com/boltdb/bolt" @@ -16,7 +16,7 @@ func (m *Migrator) updateResourceControlsToDBVersion2() error { resourceControl.SubResourceIDs = []string{} resourceControl.TeamAccesses = []portainer.TeamResourceAccess{} - owner, err := m.UserService.User(resourceControl.OwnerID) + owner, err := m.userService.User(resourceControl.OwnerID) if err != nil { return err } @@ -33,7 +33,7 @@ func (m *Migrator) updateResourceControlsToDBVersion2() error { resourceControl.UserAccesses = []portainer.UserResourceAccess{userAccess} } - err = m.ResourceControlService.CreateResourceControl(&resourceControl) + err = m.resourceControlService.CreateResourceControl(&resourceControl) if err != nil { return err } @@ -43,14 +43,14 @@ func (m *Migrator) updateResourceControlsToDBVersion2() error { } func (m *Migrator) updateEndpointsToDBVersion2() error { - legacyEndpoints, err := m.EndpointService.Endpoints() + legacyEndpoints, err := m.endpointService.Endpoints() if err != nil { return err } for _, endpoint := range legacyEndpoints { endpoint.AuthorizedTeams = []portainer.TeamID{} - err = m.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint) + err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint) if err != nil { return err } @@ -61,7 +61,7 @@ func (m *Migrator) updateEndpointsToDBVersion2() error { func (m *Migrator) retrieveLegacyResourceControls() ([]portainer.ResourceControl, error) { legacyResourceControls := make([]portainer.ResourceControl, 0) - err := m.store.db.View(func(tx *bolt.Tx) error { + err := m.db.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte("containerResourceControl")) cursor := bucket.Cursor() for k, v := cursor.First(); k != nil; k, v = cursor.Next() { diff --git a/api/bolt/migrate_dbversion10.go b/api/bolt/migrator/migrate_dbversion10.go similarity index 78% rename from api/bolt/migrate_dbversion10.go rename to api/bolt/migrator/migrate_dbversion10.go index 211d2497a..da55e3962 100644 --- a/api/bolt/migrate_dbversion10.go +++ b/api/bolt/migrator/migrate_dbversion10.go @@ -1,9 +1,9 @@ -package bolt +package migrator import "github.com/portainer/portainer" func (m *Migrator) updateEndpointsToVersion11() error { - legacyEndpoints, err := m.EndpointService.Endpoints() + legacyEndpoints, err := m.endpointService.Endpoints() if err != nil { return err } @@ -18,7 +18,7 @@ func (m *Migrator) updateEndpointsToVersion11() error { } } - err = m.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint) + err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint) if err != nil { return err } diff --git a/api/bolt/migrate_dbversion11.go b/api/bolt/migrator/migrate_dbversion11.go similarity index 73% rename from api/bolt/migrate_dbversion11.go rename to api/bolt/migrator/migrate_dbversion11.go index b53e3fcbf..168d23984 100644 --- a/api/bolt/migrate_dbversion11.go +++ b/api/bolt/migrator/migrate_dbversion11.go @@ -1,4 +1,4 @@ -package bolt +package migrator import ( "strconv" @@ -7,10 +7,11 @@ import ( "github.com/boltdb/bolt" "github.com/portainer/portainer" "github.com/portainer/portainer/bolt/internal" + "github.com/portainer/portainer/bolt/stack" ) func (m *Migrator) updateEndpointsToVersion12() error { - legacyEndpoints, err := m.EndpointService.Endpoints() + legacyEndpoints, err := m.endpointService.Endpoints() if err != nil { return err } @@ -18,7 +19,7 @@ func (m *Migrator) updateEndpointsToVersion12() error { for _, endpoint := range legacyEndpoints { endpoint.Tags = []string{} - err = m.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint) + err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint) if err != nil { return err } @@ -28,7 +29,7 @@ func (m *Migrator) updateEndpointsToVersion12() error { } func (m *Migrator) updateEndpointGroupsToVersion12() error { - legacyEndpointGroups, err := m.EndpointGroupService.EndpointGroups() + legacyEndpointGroups, err := m.endpointGroupService.EndpointGroups() if err != nil { return err } @@ -36,7 +37,7 @@ func (m *Migrator) updateEndpointGroupsToVersion12() error { for _, group := range legacyEndpointGroups { group.Tags = []string{} - err = m.EndpointGroupService.UpdateEndpointGroup(group.ID, &group) + err = m.endpointGroupService.UpdateEndpointGroup(group.ID, &group) if err != nil { return err } @@ -72,7 +73,7 @@ func (m *Migrator) updateStacksToVersion12() error { } func (m *Migrator) convertLegacyStack(s *legacyStack) error { - stackID := m.StackService.GetNextIdentifier() + stackID := m.stackService.GetNextIdentifier() stack := &portainer.Stack{ ID: portainer.StackID(stackID), Name: s.Name, @@ -84,7 +85,7 @@ func (m *Migrator) convertLegacyStack(s *legacyStack) error { } stack.ProjectPath = strings.Replace(s.ProjectPath, s.ID, strconv.Itoa(stackID), 1) - err := m.store.FileService.Rename(s.ProjectPath, stack.ProjectPath) + err := m.fileService.Rename(s.ProjectPath, stack.ProjectPath) if err != nil { return err } @@ -94,24 +95,20 @@ func (m *Migrator) convertLegacyStack(s *legacyStack) error { return err } - return m.StackService.CreateStack(stack) + return m.stackService.CreateStack(stack) } func (m *Migrator) deleteLegacyStack(legacyID string) error { - return m.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) - err := bucket.Delete([]byte(legacyID)) - if err != nil { - return err - } - return nil + return m.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(stack.BucketName)) + return bucket.Delete([]byte(legacyID)) }) } func (m *Migrator) retrieveLegacyStacks() ([]legacyStack, error) { var legacyStacks = make([]legacyStack, 0) - err := m.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) + err := m.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(stack.BucketName)) cursor := bucket.Cursor() for k, v := cursor.First(); k != nil; k, v = cursor.Next() { @@ -125,9 +122,6 @@ func (m *Migrator) retrieveLegacyStacks() ([]legacyStack, error) { return nil }) - if err != nil { - return nil, err - } - return legacyStacks, nil + return legacyStacks, err } diff --git a/api/bolt/migrate_dbversion2.go b/api/bolt/migrator/migrate_dbversion2.go similarity index 70% rename from api/bolt/migrate_dbversion2.go rename to api/bolt/migrator/migrate_dbversion2.go index 38a3e4b50..9488f50f9 100644 --- a/api/bolt/migrate_dbversion2.go +++ b/api/bolt/migrator/migrate_dbversion2.go @@ -1,9 +1,9 @@ -package bolt +package migrator import "github.com/portainer/portainer" func (m *Migrator) updateSettingsToDBVersion3() error { - legacySettings, err := m.SettingsService.Settings() + legacySettings, err := m.settingsService.Settings() if err != nil { return err } @@ -16,10 +16,5 @@ func (m *Migrator) updateSettingsToDBVersion3() error { }, } - err = m.SettingsService.StoreSettings(legacySettings) - if err != nil { - return err - } - - return nil + return m.settingsService.UpdateSettings(legacySettings) } diff --git a/api/bolt/migrate_dbversion3.go b/api/bolt/migrator/migrate_dbversion3.go similarity index 80% rename from api/bolt/migrate_dbversion3.go rename to api/bolt/migrator/migrate_dbversion3.go index d8679ca68..75636dc97 100644 --- a/api/bolt/migrate_dbversion3.go +++ b/api/bolt/migrator/migrate_dbversion3.go @@ -1,9 +1,9 @@ -package bolt +package migrator import "github.com/portainer/portainer" func (m *Migrator) updateEndpointsToDBVersion4() error { - legacyEndpoints, err := m.EndpointService.Endpoints() + legacyEndpoints, err := m.endpointService.Endpoints() if err != nil { return err } @@ -17,7 +17,8 @@ func (m *Migrator) updateEndpointsToDBVersion4() error { endpoint.TLSConfig.TLSCertPath = endpoint.TLSCertPath endpoint.TLSConfig.TLSKeyPath = endpoint.TLSKeyPath } - err = m.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint) + + err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint) if err != nil { return err } diff --git a/api/bolt/migrator/migrate_dbversion4.go b/api/bolt/migrator/migrate_dbversion4.go new file mode 100644 index 000000000..0bc7c84e4 --- /dev/null +++ b/api/bolt/migrator/migrate_dbversion4.go @@ -0,0 +1,11 @@ +package migrator + +func (m *Migrator) updateSettingsToVersion5() error { + legacySettings, err := m.settingsService.Settings() + if err != nil { + return err + } + + legacySettings.AllowBindMountsForRegularUsers = true + return m.settingsService.UpdateSettings(legacySettings) +} diff --git a/api/bolt/migrator/migrate_dbversion5.go b/api/bolt/migrator/migrate_dbversion5.go new file mode 100644 index 000000000..f1ccb5734 --- /dev/null +++ b/api/bolt/migrator/migrate_dbversion5.go @@ -0,0 +1,11 @@ +package migrator + +func (m *Migrator) updateSettingsToVersion6() error { + legacySettings, err := m.settingsService.Settings() + if err != nil { + return err + } + + legacySettings.AllowPrivilegedModeForRegularUsers = true + return m.settingsService.UpdateSettings(legacySettings) +} diff --git a/api/bolt/migrator/migrate_dbversion6.go b/api/bolt/migrator/migrate_dbversion6.go new file mode 100644 index 000000000..860a56ff0 --- /dev/null +++ b/api/bolt/migrator/migrate_dbversion6.go @@ -0,0 +1,11 @@ +package migrator + +func (m *Migrator) updateSettingsToVersion7() error { + legacySettings, err := m.settingsService.Settings() + if err != nil { + return err + } + legacySettings.DisplayDonationHeader = true + + return m.settingsService.UpdateSettings(legacySettings) +} diff --git a/api/bolt/migrate_dbversion7.go b/api/bolt/migrator/migrate_dbversion7.go similarity index 67% rename from api/bolt/migrate_dbversion7.go rename to api/bolt/migrator/migrate_dbversion7.go index bcdd199f2..b248e9e42 100644 --- a/api/bolt/migrate_dbversion7.go +++ b/api/bolt/migrator/migrate_dbversion7.go @@ -1,16 +1,16 @@ -package bolt +package migrator import "github.com/portainer/portainer" func (m *Migrator) updateEndpointsToVersion8() error { - legacyEndpoints, err := m.EndpointService.Endpoints() + legacyEndpoints, err := m.endpointService.Endpoints() if err != nil { return err } for _, endpoint := range legacyEndpoints { endpoint.Extensions = []portainer.EndpointExtension{} - err = m.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint) + err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint) if err != nil { return err } diff --git a/api/bolt/migrate_dbversion8.go b/api/bolt/migrator/migrate_dbversion8.go similarity index 67% rename from api/bolt/migrate_dbversion8.go rename to api/bolt/migrator/migrate_dbversion8.go index 7ef77806d..99a73bf11 100644 --- a/api/bolt/migrate_dbversion8.go +++ b/api/bolt/migrator/migrate_dbversion8.go @@ -1,16 +1,16 @@ -package bolt +package migrator import "github.com/portainer/portainer" func (m *Migrator) updateEndpointsToVersion9() error { - legacyEndpoints, err := m.EndpointService.Endpoints() + legacyEndpoints, err := m.endpointService.Endpoints() if err != nil { return err } for _, endpoint := range legacyEndpoints { endpoint.GroupID = portainer.EndpointGroupID(1) - err = m.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint) + err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint) if err != nil { return err } diff --git a/api/bolt/migrate_dbversion9.go b/api/bolt/migrator/migrate_dbversion9.go similarity index 67% rename from api/bolt/migrate_dbversion9.go rename to api/bolt/migrator/migrate_dbversion9.go index 1882f55c7..f4a52d398 100644 --- a/api/bolt/migrate_dbversion9.go +++ b/api/bolt/migrator/migrate_dbversion9.go @@ -1,16 +1,16 @@ -package bolt +package migrator import "github.com/portainer/portainer" func (m *Migrator) updateEndpointsToVersion10() error { - legacyEndpoints, err := m.EndpointService.Endpoints() + legacyEndpoints, err := m.endpointService.Endpoints() if err != nil { return err } for _, endpoint := range legacyEndpoints { endpoint.Type = portainer.DockerEnvironment - err = m.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint) + err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint) if err != nil { return err } diff --git a/api/bolt/migrator/migrator.go b/api/bolt/migrator/migrator.go new file mode 100644 index 000000000..0455aafd1 --- /dev/null +++ b/api/bolt/migrator/migrator.go @@ -0,0 +1,174 @@ +package migrator + +import ( + "github.com/boltdb/bolt" + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/endpoint" + "github.com/portainer/portainer/bolt/endpointgroup" + "github.com/portainer/portainer/bolt/resourcecontrol" + "github.com/portainer/portainer/bolt/settings" + "github.com/portainer/portainer/bolt/stack" + "github.com/portainer/portainer/bolt/user" + "github.com/portainer/portainer/bolt/version" +) + +type ( + // Migrator defines a service to migrate data after a Portainer version update. + Migrator struct { + currentDBVersion int + db *bolt.DB + endpointGroupService *endpointgroup.Service + endpointService *endpoint.Service + resourceControlService *resourcecontrol.Service + settingsService *settings.Service + stackService *stack.Service + userService *user.Service + versionService *version.Service + fileService portainer.FileService + } + + // Parameters represents the required parameters to create a new Migrator instance. + Parameters struct { + DB *bolt.DB + DatabaseVersion int + EndpointGroupService *endpointgroup.Service + EndpointService *endpoint.Service + ResourceControlService *resourcecontrol.Service + SettingsService *settings.Service + StackService *stack.Service + UserService *user.Service + VersionService *version.Service + FileService portainer.FileService + } +) + +// NewMigrator creates a new Migrator. +func NewMigrator(parameters *Parameters) *Migrator { + return &Migrator{ + db: parameters.DB, + currentDBVersion: parameters.DatabaseVersion, + endpointGroupService: parameters.EndpointGroupService, + endpointService: parameters.EndpointService, + resourceControlService: parameters.ResourceControlService, + settingsService: parameters.SettingsService, + stackService: parameters.StackService, + userService: parameters.UserService, + versionService: parameters.VersionService, + fileService: parameters.FileService, + } +} + +// Migrate checks the database version and migrate the existing data to the most recent data model. +func (m *Migrator) Migrate() error { + + // Portainer < 1.12 + if m.currentDBVersion < 1 { + err := m.updateAdminUserToDBVersion1() + if err != nil { + return err + } + } + + // Portainer 1.12.x + if m.currentDBVersion < 2 { + err := m.updateResourceControlsToDBVersion2() + if err != nil { + return err + } + err = m.updateEndpointsToDBVersion2() + if err != nil { + return err + } + } + + // Portainer 1.13.x + if m.currentDBVersion < 3 { + err := m.updateSettingsToDBVersion3() + if err != nil { + return err + } + } + + // Portainer 1.14.0 + if m.currentDBVersion < 4 { + err := m.updateEndpointsToDBVersion4() + if err != nil { + return err + } + } + + // https://github.com/portainer/portainer/issues/1235 + if m.currentDBVersion < 5 { + err := m.updateSettingsToVersion5() + if err != nil { + return err + } + } + + // https://github.com/portainer/portainer/issues/1236 + if m.currentDBVersion < 6 { + err := m.updateSettingsToVersion6() + if err != nil { + return err + } + } + + // https://github.com/portainer/portainer/issues/1449 + if m.currentDBVersion < 7 { + err := m.updateSettingsToVersion7() + if err != nil { + return err + } + } + + if m.currentDBVersion < 8 { + err := m.updateEndpointsToVersion8() + if err != nil { + return err + } + } + + // https: //github.com/portainer/portainer/issues/1396 + if m.currentDBVersion < 9 { + err := m.updateEndpointsToVersion9() + if err != nil { + return err + } + } + + // https://github.com/portainer/portainer/issues/461 + if m.currentDBVersion < 10 { + err := m.updateEndpointsToVersion10() + if err != nil { + return err + } + } + + // https://github.com/portainer/portainer/issues/1906 + if m.currentDBVersion < 11 { + err := m.updateEndpointsToVersion11() + if err != nil { + return err + } + } + + // Portainer 1.17.1-dev + if m.currentDBVersion < 12 { + err := m.updateEndpointsToVersion12() + if err != nil { + return err + } + + err = m.updateEndpointGroupsToVersion12() + if err != nil { + return err + } + + err = m.updateStacksToVersion12() + if err != nil { + return err + } + } + + return m.versionService.StoreDBVersion(portainer.DBVersion) +} diff --git a/api/bolt/registry/registry.go b/api/bolt/registry/registry.go new file mode 100644 index 000000000..2fbfbeb90 --- /dev/null +++ b/api/bolt/registry/registry.go @@ -0,0 +1,95 @@ +package registry + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "registries" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// Registry returns an registry by ID. +func (service *Service) Registry(ID portainer.RegistryID) (*portainer.Registry, error) { + var registry portainer.Registry + identifier := internal.Itob(int(ID)) + + err := internal.GetObject(service.db, BucketName, identifier, ®istry) + if err != nil { + return nil, err + } + + return ®istry, nil +} + +// Registries returns an array containing all the registries. +func (service *Service) Registries() ([]portainer.Registry, error) { + var registries = make([]portainer.Registry, 0) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var registry portainer.Registry + err := internal.UnmarshalObject(v, ®istry) + if err != nil { + return err + } + registries = append(registries, registry) + } + + return nil + }) + + return registries, err +} + +// CreateRegistry creates a new registry. +func (service *Service) CreateRegistry(registry *portainer.Registry) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + id, _ := bucket.NextSequence() + registry.ID = portainer.RegistryID(id) + + data, err := internal.MarshalObject(registry) + if err != nil { + return err + } + + return bucket.Put(internal.Itob(int(registry.ID)), data) + }) +} + +// UpdateRegistry updates an registry. +func (service *Service) UpdateRegistry(ID portainer.RegistryID, registry *portainer.Registry) error { + identifier := internal.Itob(int(ID)) + return internal.UpdateObject(service.db, BucketName, identifier, registry) +} + +// DeleteRegistry deletes an registry. +func (service *Service) DeleteRegistry(ID portainer.RegistryID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) +} diff --git a/api/bolt/registry_service.go b/api/bolt/registry_service.go deleted file mode 100644 index a7cabb313..000000000 --- a/api/bolt/registry_service.go +++ /dev/null @@ -1,114 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// RegistryService represents a service for managing registries. -type RegistryService struct { - store *Store -} - -// Registry returns an registry by ID. -func (service *RegistryService) Registry(ID portainer.RegistryID) (*portainer.Registry, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(registryBucketName)) - value := bucket.Get(internal.Itob(int(ID))) - if value == nil { - return portainer.ErrRegistryNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var registry portainer.Registry - err = internal.UnmarshalObject(data, ®istry) - if err != nil { - return nil, err - } - return ®istry, nil -} - -// Registries returns an array containing all the registries. -func (service *RegistryService) Registries() ([]portainer.Registry, error) { - var registries = make([]portainer.Registry, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(registryBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var registry portainer.Registry - err := internal.UnmarshalObject(v, ®istry) - if err != nil { - return err - } - registries = append(registries, registry) - } - - return nil - }) - if err != nil { - return nil, err - } - - return registries, nil -} - -// CreateRegistry creates a new registry. -func (service *RegistryService) CreateRegistry(registry *portainer.Registry) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(registryBucketName)) - - id, _ := bucket.NextSequence() - registry.ID = portainer.RegistryID(id) - - data, err := internal.MarshalObject(registry) - if err != nil { - return err - } - - err = bucket.Put(internal.Itob(int(registry.ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// UpdateRegistry updates an registry. -func (service *RegistryService) UpdateRegistry(ID portainer.RegistryID, registry *portainer.Registry) error { - data, err := internal.MarshalObject(registry) - if err != nil { - return err - } - - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(registryBucketName)) - err = bucket.Put(internal.Itob(int(ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// DeleteRegistry deletes an registry. -func (service *RegistryService) DeleteRegistry(ID portainer.RegistryID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(registryBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/resource_control_service.go b/api/bolt/resource_control_service.go deleted file mode 100644 index cbd13fa4a..000000000 --- a/api/bolt/resource_control_service.go +++ /dev/null @@ -1,148 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// ResourceControlService represents a service for managing resource controls. -type ResourceControlService struct { - store *Store -} - -// ResourceControl returns a ResourceControl object by ID -func (service *ResourceControlService) ResourceControl(ID portainer.ResourceControlID) (*portainer.ResourceControl, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(resourceControlBucketName)) - value := bucket.Get(internal.Itob(int(ID))) - if value == nil { - return portainer.ErrResourceControlNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var resourceControl portainer.ResourceControl - err = internal.UnmarshalObject(data, &resourceControl) - if err != nil { - return nil, err - } - return &resourceControl, nil -} - -// ResourceControlByResourceID returns a ResourceControl object by checking if the resourceID is equal -// to the main ResourceID or in SubResourceIDs -func (service *ResourceControlService) ResourceControlByResourceID(resourceID string) (*portainer.ResourceControl, error) { - var resourceControl *portainer.ResourceControl - - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(resourceControlBucketName)) - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var rc portainer.ResourceControl - err := internal.UnmarshalObject(v, &rc) - if err != nil { - return err - } - if rc.ResourceID == resourceID { - resourceControl = &rc - } - for _, subResourceID := range rc.SubResourceIDs { - if subResourceID == resourceID { - resourceControl = &rc - } - } - } - - if resourceControl == nil { - return portainer.ErrResourceControlNotFound - } - return nil - }) - if err != nil { - return nil, err - } - return resourceControl, nil -} - -// ResourceControls returns all the ResourceControl objects -func (service *ResourceControlService) ResourceControls() ([]portainer.ResourceControl, error) { - var rcs = make([]portainer.ResourceControl, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(resourceControlBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var resourceControl portainer.ResourceControl - err := internal.UnmarshalObject(v, &resourceControl) - if err != nil { - return err - } - rcs = append(rcs, resourceControl) - } - - return nil - }) - if err != nil { - return nil, err - } - - return rcs, nil -} - -// CreateResourceControl creates a new ResourceControl object -func (service *ResourceControlService) CreateResourceControl(resourceControl *portainer.ResourceControl) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(resourceControlBucketName)) - id, _ := bucket.NextSequence() - resourceControl.ID = portainer.ResourceControlID(id) - data, err := internal.MarshalObject(resourceControl) - if err != nil { - return err - } - - err = bucket.Put(internal.Itob(int(resourceControl.ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// UpdateResourceControl saves a ResourceControl object. -func (service *ResourceControlService) UpdateResourceControl(ID portainer.ResourceControlID, resourceControl *portainer.ResourceControl) error { - data, err := internal.MarshalObject(resourceControl) - if err != nil { - return err - } - - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(resourceControlBucketName)) - err = bucket.Put(internal.Itob(int(ID)), data) - - if err != nil { - return err - } - return nil - }) -} - -// DeleteResourceControl deletes a ResourceControl object by ID -func (service *ResourceControlService) DeleteResourceControl(ID portainer.ResourceControlID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(resourceControlBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/resourcecontrol/resourcecontrol.go b/api/bolt/resourcecontrol/resourcecontrol.go new file mode 100644 index 000000000..222bafd79 --- /dev/null +++ b/api/bolt/resourcecontrol/resourcecontrol.go @@ -0,0 +1,134 @@ +package resourcecontrol + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "resource_control" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// ResourceControl returns a ResourceControl object by ID +func (service *Service) ResourceControl(ID portainer.ResourceControlID) (*portainer.ResourceControl, error) { + var resourceControl portainer.ResourceControl + identifier := internal.Itob(int(ID)) + + err := internal.GetObject(service.db, BucketName, identifier, &resourceControl) + if err != nil { + return nil, err + } + + return &resourceControl, nil +} + +// ResourceControlByResourceID returns a ResourceControl object by checking if the resourceID is equal +// to the main ResourceID or in SubResourceIDs +func (service *Service) ResourceControlByResourceID(resourceID string) (*portainer.ResourceControl, error) { + var resourceControl *portainer.ResourceControl + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + cursor := bucket.Cursor() + + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var rc portainer.ResourceControl + err := internal.UnmarshalObject(v, &rc) + if err != nil { + return err + } + + if rc.ResourceID == resourceID { + resourceControl = &rc + break + } + + for _, subResourceID := range rc.SubResourceIDs { + if subResourceID == resourceID { + resourceControl = &rc + break + } + } + } + + if resourceControl == nil { + return portainer.ErrObjectNotFound + } + + return nil + }) + + return resourceControl, err +} + +// ResourceControls returns all the ResourceControl objects +func (service *Service) ResourceControls() ([]portainer.ResourceControl, error) { + var rcs = make([]portainer.ResourceControl, 0) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var resourceControl portainer.ResourceControl + err := internal.UnmarshalObject(v, &resourceControl) + if err != nil { + return err + } + rcs = append(rcs, resourceControl) + } + + return nil + }) + + return rcs, err +} + +// CreateResourceControl creates a new ResourceControl object +func (service *Service) CreateResourceControl(resourceControl *portainer.ResourceControl) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + id, _ := bucket.NextSequence() + resourceControl.ID = portainer.ResourceControlID(id) + + data, err := internal.MarshalObject(resourceControl) + if err != nil { + return err + } + + return bucket.Put(internal.Itob(int(resourceControl.ID)), data) + }) +} + +// UpdateResourceControl saves a ResourceControl object. +func (service *Service) UpdateResourceControl(ID portainer.ResourceControlID, resourceControl *portainer.ResourceControl) error { + identifier := internal.Itob(int(ID)) + return internal.UpdateObject(service.db, BucketName, identifier, resourceControl) +} + +// DeleteResourceControl deletes a ResourceControl object by ID +func (service *Service) DeleteResourceControl(ID portainer.ResourceControlID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) +} diff --git a/api/bolt/settings/settings.go b/api/bolt/settings/settings.go new file mode 100644 index 000000000..6e1d4bc82 --- /dev/null +++ b/api/bolt/settings/settings.go @@ -0,0 +1,48 @@ +package settings + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "settings" + settingsKey = "SETTINGS" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// Settings retrieve the settings object. +func (service *Service) Settings() (*portainer.Settings, error) { + var settings portainer.Settings + + err := internal.GetObject(service.db, BucketName, []byte(settingsKey), &settings) + if err != nil { + return nil, err + } + + return &settings, nil +} + +// UpdateSettings persists a Settings object. +func (service *Service) UpdateSettings(settings *portainer.Settings) error { + return internal.UpdateObject(service.db, BucketName, []byte(settingsKey), settings) +} diff --git a/api/bolt/settings_service.go b/api/bolt/settings_service.go deleted file mode 100644 index 2053feac9..000000000 --- a/api/bolt/settings_service.go +++ /dev/null @@ -1,61 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// SettingsService represents a service to manage application settings. -type SettingsService struct { - store *Store -} - -const ( - dbSettingsKey = "SETTINGS" -) - -// Settings retrieve the settings object. -func (service *SettingsService) Settings() (*portainer.Settings, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(settingsBucketName)) - value := bucket.Get([]byte(dbSettingsKey)) - if value == nil { - return portainer.ErrSettingsNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var settings portainer.Settings - err = internal.UnmarshalObject(data, &settings) - if err != nil { - return nil, err - } - return &settings, nil -} - -// StoreSettings persists a Settings object. -func (service *SettingsService) StoreSettings(settings *portainer.Settings) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(settingsBucketName)) - - data, err := internal.MarshalObject(settings) - if err != nil { - return err - } - - err = bucket.Put([]byte(dbSettingsKey), data) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/stack/stack.go b/api/bolt/stack/stack.go new file mode 100644 index 000000000..1bd8e159b --- /dev/null +++ b/api/bolt/stack/stack.go @@ -0,0 +1,134 @@ +package stack + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "stacks" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// Stack returns a stack object by ID. +func (service *Service) Stack(ID portainer.StackID) (*portainer.Stack, error) { + var stack portainer.Stack + identifier := internal.Itob(int(ID)) + + err := internal.GetObject(service.db, BucketName, identifier, &stack) + if err != nil { + return nil, err + } + + return &stack, nil +} + +// StackByName returns a stack object by name. +func (service *Service) StackByName(name string) (*portainer.Stack, error) { + var stack *portainer.Stack + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + cursor := bucket.Cursor() + + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var t portainer.Stack + err := internal.UnmarshalObject(v, &t) + if err != nil { + return err + } + + if t.Name == name { + stack = &t + break + } + } + + if stack == nil { + return portainer.ErrObjectNotFound + } + + return nil + }) + + return stack, err +} + +// Stacks returns an array containing all the stacks. +func (service *Service) Stacks() ([]portainer.Stack, error) { + var stacks = make([]portainer.Stack, 0) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var stack portainer.Stack + err := internal.UnmarshalObject(v, &stack) + if err != nil { + return err + } + stacks = append(stacks, stack) + } + + return nil + }) + + return stacks, err +} + +// GetNextIdentifier returns the next identifier for a stack. +func (service *Service) GetNextIdentifier() int { + return internal.GetNextIdentifier(service.db, BucketName) +} + +// CreateStack creates a new stack. +func (service *Service) CreateStack(stack *portainer.Stack) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + // We manually manage sequences for stacks + err := bucket.SetSequence(uint64(stack.ID)) + if err != nil { + return err + } + + data, err := internal.MarshalObject(stack) + if err != nil { + return err + } + + return bucket.Put(internal.Itob(int(stack.ID)), data) + }) +} + +// UpdateStack updates a stack. +func (service *Service) UpdateStack(ID portainer.StackID, stack *portainer.Stack) error { + identifier := internal.Itob(int(ID)) + return internal.UpdateObject(service.db, BucketName, identifier, stack) +} + +// DeleteStack deletes a stack. +func (service *Service) DeleteStack(ID portainer.StackID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) +} diff --git a/api/bolt/stack_service.go b/api/bolt/stack_service.go deleted file mode 100644 index 34855e59f..000000000 --- a/api/bolt/stack_service.go +++ /dev/null @@ -1,159 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// StackService represents a service for managing stacks. -type StackService struct { - store *Store -} - -// Stack returns a stack object by ID. -func (service *StackService) Stack(ID portainer.StackID) (*portainer.Stack, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) - value := bucket.Get(internal.Itob(int(ID))) - if value == nil { - return portainer.ErrStackNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var stack portainer.Stack - err = internal.UnmarshalObject(data, &stack) - if err != nil { - return nil, err - } - return &stack, nil -} - -// StackByName returns a stack object by name. -func (service *StackService) StackByName(name string) (*portainer.Stack, error) { - var stack *portainer.Stack - - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var t portainer.Stack - err := internal.UnmarshalObject(v, &t) - if err != nil { - return err - } - if t.Name == name { - stack = &t - } - } - - if stack == nil { - return portainer.ErrStackNotFound - } - return nil - }) - if err != nil { - return nil, err - } - return stack, nil -} - -// Stacks returns an array containing all the stacks. -func (service *StackService) Stacks() ([]portainer.Stack, error) { - var stacks = make([]portainer.Stack, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var stack portainer.Stack - err := internal.UnmarshalObject(v, &stack) - if err != nil { - return err - } - stacks = append(stacks, stack) - } - - return nil - }) - if err != nil { - return nil, err - } - - return stacks, nil -} - -// GetNextIdentifier returns the current bucket identifier incremented by 1. -func (service *StackService) GetNextIdentifier() int { - var identifier int - - service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) - id := bucket.Sequence() - identifier = int(id) - return nil - }) - - identifier++ - return identifier -} - -// CreateStack creates a new stack. -func (service *StackService) CreateStack(stack *portainer.Stack) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) - err := bucket.SetSequence(uint64(stack.ID)) - if err != nil { - return err - } - - data, err := internal.MarshalObject(stack) - if err != nil { - return err - } - - err = bucket.Put(internal.Itob(int(stack.ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// UpdateStack updates an stack. -func (service *StackService) UpdateStack(ID portainer.StackID, stack *portainer.Stack) error { - data, err := internal.MarshalObject(stack) - if err != nil { - return err - } - - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) - err = bucket.Put(internal.Itob(int(ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// DeleteStack deletes an stack. -func (service *StackService) DeleteStack(ID portainer.StackID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(stackBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/tag/tag.go b/api/bolt/tag/tag.go new file mode 100644 index 000000000..796b463dd --- /dev/null +++ b/api/bolt/tag/tag.go @@ -0,0 +1,76 @@ +package tag + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "tags" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// Tags return an array containing all the tags. +func (service *Service) Tags() ([]portainer.Tag, error) { + var tags = make([]portainer.Tag, 0) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var tag portainer.Tag + err := internal.UnmarshalObject(v, &tag) + if err != nil { + return err + } + tags = append(tags, tag) + } + + return nil + }) + + return tags, err +} + +// CreateTag creates a new tag. +func (service *Service) CreateTag(tag *portainer.Tag) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + id, _ := bucket.NextSequence() + tag.ID = portainer.TagID(id) + + data, err := internal.MarshalObject(tag) + if err != nil { + return err + } + + return bucket.Put(internal.Itob(int(tag.ID)), data) + }) +} + +// DeleteTag deletes a tag. +func (service *Service) DeleteTag(ID portainer.TagID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) +} diff --git a/api/bolt/tag_service.go b/api/bolt/tag_service.go deleted file mode 100644 index 9ff0fb244..000000000 --- a/api/bolt/tag_service.go +++ /dev/null @@ -1,71 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// TagService represents a service for managing tags. -type TagService struct { - store *Store -} - -// Tags return an array containing all the tags. -func (service *TagService) Tags() ([]portainer.Tag, error) { - var tags = make([]portainer.Tag, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(tagBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var tag portainer.Tag - err := internal.UnmarshalObject(v, &tag) - if err != nil { - return err - } - tags = append(tags, tag) - } - - return nil - }) - if err != nil { - return nil, err - } - - return tags, nil -} - -// CreateTag creates a new tag. -func (service *TagService) CreateTag(tag *portainer.Tag) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(tagBucketName)) - - id, _ := bucket.NextSequence() - tag.ID = portainer.TagID(id) - - data, err := internal.MarshalObject(tag) - if err != nil { - return err - } - - err = bucket.Put(internal.Itob(int(tag.ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// DeleteTag deletes a tag. -func (service *TagService) DeleteTag(ID portainer.TagID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(tagBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/team/team.go b/api/bolt/team/team.go new file mode 100644 index 000000000..189a16a8a --- /dev/null +++ b/api/bolt/team/team.go @@ -0,0 +1,126 @@ +package team + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "teams" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// Team returns a Team by ID +func (service *Service) Team(ID portainer.TeamID) (*portainer.Team, error) { + var team portainer.Team + identifier := internal.Itob(int(ID)) + + err := internal.GetObject(service.db, BucketName, identifier, &team) + if err != nil { + return nil, err + } + + return &team, nil +} + +// TeamByName returns a team by name. +func (service *Service) TeamByName(name string) (*portainer.Team, error) { + var team *portainer.Team + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var t portainer.Team + err := internal.UnmarshalObject(v, &t) + if err != nil { + return err + } + + if t.Name == name { + team = &t + break + } + } + + if team == nil { + return portainer.ErrObjectNotFound + } + + return nil + }) + + return team, err +} + +// Teams return an array containing all the teams. +func (service *Service) Teams() ([]portainer.Team, error) { + var teams = make([]portainer.Team, 0) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var team portainer.Team + err := internal.UnmarshalObject(v, &team) + if err != nil { + return err + } + teams = append(teams, team) + } + + return nil + }) + + return teams, err +} + +// UpdateTeam saves a Team. +func (service *Service) UpdateTeam(ID portainer.TeamID, team *portainer.Team) error { + identifier := internal.Itob(int(ID)) + return internal.UpdateObject(service.db, BucketName, identifier, team) +} + +// CreateTeam creates a new Team. +func (service *Service) CreateTeam(team *portainer.Team) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + id, _ := bucket.NextSequence() + team.ID = portainer.TeamID(id) + + data, err := internal.MarshalObject(team) + if err != nil { + return err + } + + return bucket.Put(internal.Itob(int(team.ID)), data) + }) +} + +// DeleteTeam deletes a Team. +func (service *Service) DeleteTeam(ID portainer.TeamID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) +} diff --git a/api/bolt/team_service.go b/api/bolt/team_service.go deleted file mode 100644 index 61ba23207..000000000 --- a/api/bolt/team_service.go +++ /dev/null @@ -1,144 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// TeamService represents a service for managing teams. -type TeamService struct { - store *Store -} - -// Team returns a Team by ID -func (service *TeamService) Team(ID portainer.TeamID) (*portainer.Team, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamBucketName)) - value := bucket.Get(internal.Itob(int(ID))) - if value == nil { - return portainer.ErrTeamNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var team portainer.Team - err = internal.UnmarshalObject(data, &team) - if err != nil { - return nil, err - } - return &team, nil -} - -// TeamByName returns a team by name. -func (service *TeamService) TeamByName(name string) (*portainer.Team, error) { - var team *portainer.Team - - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamBucketName)) - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var t portainer.Team - err := internal.UnmarshalObject(v, &t) - if err != nil { - return err - } - if t.Name == name { - team = &t - } - } - - if team == nil { - return portainer.ErrTeamNotFound - } - return nil - }) - if err != nil { - return nil, err - } - return team, nil -} - -// Teams return an array containing all the teams. -func (service *TeamService) Teams() ([]portainer.Team, error) { - var teams = make([]portainer.Team, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var team portainer.Team - err := internal.UnmarshalObject(v, &team) - if err != nil { - return err - } - teams = append(teams, team) - } - - return nil - }) - if err != nil { - return nil, err - } - - return teams, nil -} - -// UpdateTeam saves a Team. -func (service *TeamService) UpdateTeam(ID portainer.TeamID, team *portainer.Team) error { - data, err := internal.MarshalObject(team) - if err != nil { - return err - } - - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamBucketName)) - err = bucket.Put(internal.Itob(int(ID)), data) - - if err != nil { - return err - } - return nil - }) -} - -// CreateTeam creates a new Team. -func (service *TeamService) CreateTeam(team *portainer.Team) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamBucketName)) - - id, _ := bucket.NextSequence() - team.ID = portainer.TeamID(id) - - data, err := internal.MarshalObject(team) - if err != nil { - return err - } - - err = bucket.Put(internal.Itob(int(team.ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// DeleteTeam deletes a Team. -func (service *TeamService) DeleteTeam(ID portainer.TeamID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/team_membership_service.go b/api/bolt/teammembership/teammembership.go similarity index 51% rename from api/bolt/team_membership_service.go rename to api/bolt/teammembership/teammembership.go index b56a4bed7..2f09e0ad7 100644 --- a/api/bolt/team_membership_service.go +++ b/api/bolt/teammembership/teammembership.go @@ -1,4 +1,4 @@ -package bolt +package teammembership import ( "github.com/portainer/portainer" @@ -7,42 +7,47 @@ import ( "github.com/boltdb/bolt" ) -// TeamMembershipService represents a service for managing TeamMembership objects. -type TeamMembershipService struct { - store *Store +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "team_membership" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil } // TeamMembership returns a TeamMembership object by ID -func (service *TeamMembershipService) TeamMembership(ID portainer.TeamMembershipID) (*portainer.TeamMembership, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) - value := bucket.Get(internal.Itob(int(ID))) - if value == nil { - return portainer.ErrTeamMembershipNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - +func (service *Service) TeamMembership(ID portainer.TeamMembershipID) (*portainer.TeamMembership, error) { var membership portainer.TeamMembership - err = internal.UnmarshalObject(data, &membership) + identifier := internal.Itob(int(ID)) + + err := internal.GetObject(service.db, BucketName, identifier, &membership) if err != nil { return nil, err } + return &membership, nil } // TeamMemberships return an array containing all the TeamMembership objects. -func (service *TeamMembershipService) TeamMemberships() ([]portainer.TeamMembership, error) { +func (service *Service) TeamMemberships() ([]portainer.TeamMembership, error) { var memberships = make([]portainer.TeamMembership, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) cursor := bucket.Cursor() for k, v := cursor.First(); k != nil; k, v = cursor.Next() { @@ -56,18 +61,16 @@ func (service *TeamMembershipService) TeamMemberships() ([]portainer.TeamMembers return nil }) - if err != nil { - return nil, err - } - return memberships, nil + return memberships, err } // TeamMembershipsByUserID return an array containing all the TeamMembership objects where the specified userID is present. -func (service *TeamMembershipService) TeamMembershipsByUserID(userID portainer.UserID) ([]portainer.TeamMembership, error) { +func (service *Service) TeamMembershipsByUserID(userID portainer.UserID) ([]portainer.TeamMembership, error) { var memberships = make([]portainer.TeamMembership, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) cursor := bucket.Cursor() for k, v := cursor.First(); k != nil; k, v = cursor.Next() { @@ -76,6 +79,7 @@ func (service *TeamMembershipService) TeamMembershipsByUserID(userID portainer.U if err != nil { return err } + if membership.UserID == userID { memberships = append(memberships, membership) } @@ -83,18 +87,16 @@ func (service *TeamMembershipService) TeamMembershipsByUserID(userID portainer.U return nil }) - if err != nil { - return nil, err - } - return memberships, nil + return memberships, err } // TeamMembershipsByTeamID return an array containing all the TeamMembership objects where the specified teamID is present. -func (service *TeamMembershipService) TeamMembershipsByTeamID(teamID portainer.TeamID) ([]portainer.TeamMembership, error) { +func (service *Service) TeamMembershipsByTeamID(teamID portainer.TeamID) ([]portainer.TeamMembership, error) { var memberships = make([]portainer.TeamMembership, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) cursor := bucket.Cursor() for k, v := cursor.First(); k != nil; k, v = cursor.Next() { @@ -103,6 +105,7 @@ func (service *TeamMembershipService) TeamMembershipsByTeamID(teamID portainer.T if err != nil { return err } + if membership.TeamID == teamID { memberships = append(memberships, membership) } @@ -110,35 +113,20 @@ func (service *TeamMembershipService) TeamMembershipsByTeamID(teamID portainer.T return nil }) - if err != nil { - return nil, err - } - return memberships, nil + return memberships, err } // UpdateTeamMembership saves a TeamMembership object. -func (service *TeamMembershipService) UpdateTeamMembership(ID portainer.TeamMembershipID, membership *portainer.TeamMembership) error { - data, err := internal.MarshalObject(membership) - if err != nil { - return err - } - - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) - err = bucket.Put(internal.Itob(int(ID)), data) - - if err != nil { - return err - } - return nil - }) +func (service *Service) UpdateTeamMembership(ID portainer.TeamMembershipID, membership *portainer.TeamMembership) error { + identifier := internal.Itob(int(ID)) + return internal.UpdateObject(service.db, BucketName, identifier, membership) } // CreateTeamMembership creates a new TeamMembership object. -func (service *TeamMembershipService) CreateTeamMembership(membership *portainer.TeamMembership) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) +func (service *Service) CreateTeamMembership(membership *portainer.TeamMembership) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) id, _ := bucket.NextSequence() membership.ID = portainer.TeamMembershipID(id) @@ -148,30 +136,20 @@ func (service *TeamMembershipService) CreateTeamMembership(membership *portainer return err } - err = bucket.Put(internal.Itob(int(membership.ID)), data) - if err != nil { - return err - } - return nil + return bucket.Put(internal.Itob(int(membership.ID)), data) }) } // DeleteTeamMembership deletes a TeamMembership object. -func (service *TeamMembershipService) DeleteTeamMembership(ID portainer.TeamMembershipID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) +func (service *Service) DeleteTeamMembership(ID portainer.TeamMembershipID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) } // DeleteTeamMembershipByUserID deletes all the TeamMembership object associated to a UserID. -func (service *TeamMembershipService) DeleteTeamMembershipByUserID(userID portainer.UserID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) +func (service *Service) DeleteTeamMembershipByUserID(userID portainer.UserID) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) cursor := bucket.Cursor() for k, v := cursor.First(); k != nil; k, v = cursor.Next() { @@ -180,6 +158,7 @@ func (service *TeamMembershipService) DeleteTeamMembershipByUserID(userID portai if err != nil { return err } + if membership.UserID == userID { err := bucket.Delete(internal.Itob(int(membership.ID))) if err != nil { @@ -193,9 +172,9 @@ func (service *TeamMembershipService) DeleteTeamMembershipByUserID(userID portai } // DeleteTeamMembershipByTeamID deletes all the TeamMembership object associated to a TeamID. -func (service *TeamMembershipService) DeleteTeamMembershipByTeamID(teamID portainer.TeamID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(teamMembershipBucketName)) +func (service *Service) DeleteTeamMembershipByTeamID(teamID portainer.TeamID) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) cursor := bucket.Cursor() for k, v := cursor.First(); k != nil; k, v = cursor.Next() { @@ -204,6 +183,7 @@ func (service *TeamMembershipService) DeleteTeamMembershipByTeamID(teamID portai if err != nil { return err } + if membership.TeamID == teamID { err := bucket.Delete(internal.Itob(int(membership.ID))) if err != nil { diff --git a/api/bolt/user/user.go b/api/bolt/user/user.go new file mode 100644 index 000000000..03a3a8d88 --- /dev/null +++ b/api/bolt/user/user.go @@ -0,0 +1,149 @@ +package user + +import ( + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" + + "github.com/boltdb/bolt" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "users" +) + +// Service represents a service for managing endpoint data. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// User returns a user by ID +func (service *Service) User(ID portainer.UserID) (*portainer.User, error) { + var user portainer.User + identifier := internal.Itob(int(ID)) + + err := internal.GetObject(service.db, BucketName, identifier, &user) + if err != nil { + return nil, err + } + + return &user, nil +} + +// UserByUsername returns a user by username. +func (service *Service) UserByUsername(username string) (*portainer.User, error) { + var user *portainer.User + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + cursor := bucket.Cursor() + + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var u portainer.User + err := internal.UnmarshalObject(v, &u) + if err != nil { + return err + } + + if u.Username == username { + user = &u + break + } + } + + if user == nil { + return portainer.ErrObjectNotFound + } + return nil + }) + + return user, err +} + +// Users return an array containing all the users. +func (service *Service) Users() ([]portainer.User, error) { + var users = make([]portainer.User, 0) + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var user portainer.User + err := internal.UnmarshalObject(v, &user) + if err != nil { + return err + } + users = append(users, user) + } + + return nil + }) + + return users, err +} + +// UsersByRole return an array containing all the users with the specified role. +func (service *Service) UsersByRole(role portainer.UserRole) ([]portainer.User, error) { + var users = make([]portainer.User, 0) + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + cursor := bucket.Cursor() + for k, v := cursor.First(); k != nil; k, v = cursor.Next() { + var user portainer.User + err := internal.UnmarshalObject(v, &user) + if err != nil { + return err + } + + if user.Role == role { + users = append(users, user) + } + } + return nil + }) + + return users, err +} + +// UpdateUser saves a user. +func (service *Service) UpdateUser(ID portainer.UserID, user *portainer.User) error { + identifier := internal.Itob(int(ID)) + return internal.UpdateObject(service.db, BucketName, identifier, user) +} + +// CreateUser creates a new user. +func (service *Service) CreateUser(user *portainer.User) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + id, _ := bucket.NextSequence() + user.ID = portainer.UserID(id) + + data, err := internal.MarshalObject(user) + if err != nil { + return err + } + + return bucket.Put(internal.Itob(int(user.ID)), data) + }) +} + +// DeleteUser deletes a user. +func (service *Service) DeleteUser(ID portainer.UserID) error { + identifier := internal.Itob(int(ID)) + return internal.DeleteObject(service.db, BucketName, identifier) +} diff --git a/api/bolt/user_service.go b/api/bolt/user_service.go deleted file mode 100644 index 55723f321..000000000 --- a/api/bolt/user_service.go +++ /dev/null @@ -1,170 +0,0 @@ -package bolt - -import ( - "github.com/portainer/portainer" - "github.com/portainer/portainer/bolt/internal" - - "github.com/boltdb/bolt" -) - -// UserService represents a service for managing users. -type UserService struct { - store *Store -} - -// User returns a user by ID -func (service *UserService) User(ID portainer.UserID) (*portainer.User, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(userBucketName)) - value := bucket.Get(internal.Itob(int(ID))) - if value == nil { - return portainer.ErrUserNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return nil, err - } - - var user portainer.User - err = internal.UnmarshalObject(data, &user) - if err != nil { - return nil, err - } - return &user, nil -} - -// UserByUsername returns a user by username. -func (service *UserService) UserByUsername(username string) (*portainer.User, error) { - var user *portainer.User - - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(userBucketName)) - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var u portainer.User - err := internal.UnmarshalObject(v, &u) - if err != nil { - return err - } - if u.Username == username { - user = &u - } - } - - if user == nil { - return portainer.ErrUserNotFound - } - return nil - }) - if err != nil { - return nil, err - } - return user, nil -} - -// Users return an array containing all the users. -func (service *UserService) Users() ([]portainer.User, error) { - var users = make([]portainer.User, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(userBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var user portainer.User - err := internal.UnmarshalObject(v, &user) - if err != nil { - return err - } - users = append(users, user) - } - - return nil - }) - if err != nil { - return nil, err - } - - return users, nil -} - -// UsersByRole return an array containing all the users with the specified role. -func (service *UserService) UsersByRole(role portainer.UserRole) ([]portainer.User, error) { - var users = make([]portainer.User, 0) - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(userBucketName)) - - cursor := bucket.Cursor() - for k, v := cursor.First(); k != nil; k, v = cursor.Next() { - var user portainer.User - err := internal.UnmarshalObject(v, &user) - if err != nil { - return err - } - if user.Role == role { - users = append(users, user) - } - } - return nil - }) - if err != nil { - return nil, err - } - - return users, nil -} - -// UpdateUser saves a user. -func (service *UserService) UpdateUser(ID portainer.UserID, user *portainer.User) error { - data, err := internal.MarshalObject(user) - if err != nil { - return err - } - - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(userBucketName)) - err = bucket.Put(internal.Itob(int(ID)), data) - - if err != nil { - return err - } - return nil - }) -} - -// CreateUser creates a new user. -func (service *UserService) CreateUser(user *portainer.User) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(userBucketName)) - - id, _ := bucket.NextSequence() - user.ID = portainer.UserID(id) - - data, err := internal.MarshalObject(user) - if err != nil { - return err - } - - err = bucket.Put(internal.Itob(int(user.ID)), data) - if err != nil { - return err - } - return nil - }) -} - -// DeleteUser deletes a user. -func (service *UserService) DeleteUser(ID portainer.UserID) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(userBucketName)) - err := bucket.Delete(internal.Itob(int(ID))) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/bolt/version/version.go b/api/bolt/version/version.go new file mode 100644 index 000000000..52a7b4be4 --- /dev/null +++ b/api/bolt/version/version.go @@ -0,0 +1,66 @@ +package version + +import ( + "strconv" + + "github.com/boltdb/bolt" + "github.com/portainer/portainer" + "github.com/portainer/portainer/bolt/internal" +) + +const ( + // BucketName represents the name of the bucket where this service stores data. + BucketName = "version" + versionKey = "DB_VERSION" +) + +// Service represents a service to manage stored versions. +type Service struct { + db *bolt.DB +} + +// NewService creates a new instance of a service. +func NewService(db *bolt.DB) (*Service, error) { + err := internal.CreateBucket(db, BucketName) + if err != nil { + return nil, err + } + + return &Service{ + db: db, + }, nil +} + +// DBVersion retrieves the stored database version. +func (service *Service) DBVersion() (int, error) { + var data []byte + + err := service.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + value := bucket.Get([]byte(versionKey)) + if value == nil { + return portainer.ErrObjectNotFound + } + + data = make([]byte, len(value)) + copy(data, value) + + return nil + }) + if err != nil { + return 0, err + } + + return strconv.Atoi(string(data)) +} + +// StoreDBVersion store the database version. +func (service *Service) StoreDBVersion(version int) error { + return service.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(BucketName)) + + data := []byte(strconv.Itoa(version)) + return bucket.Put([]byte(versionKey), data) + }) +} diff --git a/api/bolt/version_service.go b/api/bolt/version_service.go deleted file mode 100644 index 1f35cfc40..000000000 --- a/api/bolt/version_service.go +++ /dev/null @@ -1,58 +0,0 @@ -package bolt - -import ( - "strconv" - - "github.com/portainer/portainer" - - "github.com/boltdb/bolt" -) - -// VersionService represents a service to manage stored versions. -type VersionService struct { - store *Store -} - -const ( - dBVersionKey = "DB_VERSION" -) - -// DBVersion retrieves the stored database version. -func (service *VersionService) DBVersion() (int, error) { - var data []byte - err := service.store.db.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(versionBucketName)) - value := bucket.Get([]byte(dBVersionKey)) - if value == nil { - return portainer.ErrDBVersionNotFound - } - - data = make([]byte, len(value)) - copy(data, value) - return nil - }) - if err != nil { - return 0, err - } - - dbVersion, err := strconv.Atoi(string(data)) - if err != nil { - return 0, err - } - - return dbVersion, nil -} - -// StoreDBVersion store the database version. -func (service *VersionService) StoreDBVersion(version int) error { - return service.store.db.Update(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(versionBucketName)) - - data := []byte(strconv.Itoa(version)) - err := bucket.Put([]byte(dBVersionKey), data) - if err != nil { - return err - } - return nil - }) -} diff --git a/api/cmd/portainer/main.go b/api/cmd/portainer/main.go index cd4921590..54b7ebb5b 100644 --- a/api/cmd/portainer/main.go +++ b/api/cmd/portainer/main.go @@ -125,13 +125,13 @@ func initStatus(authorizeEndpointMgmt bool, flags *portainer.CLIFlags) *portaine func initDockerHub(dockerHubService portainer.DockerHubService) error { _, err := dockerHubService.DockerHub() - if err == portainer.ErrDockerHubNotFound { + if err == portainer.ErrObjectNotFound { dockerhub := &portainer.DockerHub{ Authentication: false, Username: "", Password: "", } - return dockerHubService.StoreDockerHub(dockerhub) + return dockerHubService.UpdateDockerHub(dockerhub) } else if err != nil { return err } @@ -141,7 +141,7 @@ func initDockerHub(dockerHubService portainer.DockerHubService) error { func initSettings(settingsService portainer.SettingsService, flags *portainer.CLIFlags) error { _, err := settingsService.Settings() - if err == portainer.ErrSettingsNotFound { + if err == portainer.ErrObjectNotFound { settings := &portainer.Settings{ LogoURL: *flags.Logo, DisplayExternalContributors: false, @@ -168,7 +168,7 @@ func initSettings(settingsService portainer.SettingsService, flags *portainer.CL settings.BlackListedLabels = make([]portainer.Pair, 0) } - return settingsService.StoreSettings(settings) + return settingsService.UpdateSettings(settings) } else if err != nil { return err } diff --git a/api/errors.go b/api/errors.go index 4c8823891..9e4eb70e7 100644 --- a/api/errors.go +++ b/api/errors.go @@ -4,14 +4,12 @@ package portainer const ( ErrUnauthorized = Error("Unauthorized") ErrResourceAccessDenied = Error("Access denied to resource") - ErrResourceNotFound = Error("Unable to find resource") - ErrUnsupportedDockerAPI = Error("Unsupported Docker API response") + ErrObjectNotFound = Error("Object not found inside the database") ErrMissingSecurityContext = Error("Unable to find security details in request context") ) // User errors. const ( - ErrUserNotFound = Error("User not found") ErrUserAlreadyExists = Error("User already exists") ErrInvalidUsername = Error("Invalid username. White spaces are not allowed") ErrAdminAlreadyInitialized = Error("An administrator user already exists") @@ -20,26 +18,22 @@ const ( // Team errors. const ( - ErrTeamNotFound = Error("Team not found") ErrTeamAlreadyExists = Error("Team already exists") ) // TeamMembership errors. const ( - ErrTeamMembershipNotFound = Error("Team membership not found") ErrTeamMembershipAlreadyExists = Error("Team membership already exists for this user and team") ) // ResourceControl errors. const ( - ErrResourceControlNotFound = Error("Resource control not found") ErrResourceControlAlreadyExists = Error("A resource control is already applied on this resource") ErrInvalidResourceControlType = Error("Unsupported resource control type") ) // Endpoint errors. const ( - ErrEndpointNotFound = Error("Endpoint not found") ErrEndpointAccessDenied = Error("Access denied to endpoint") ) @@ -50,19 +44,16 @@ const ( // Endpoint group errors. const ( - ErrEndpointGroupNotFound = Error("Endpoint group not found") ErrCannotRemoveDefaultGroup = Error("Cannot remove the default endpoint group") ) // Registry errors. const ( - ErrRegistryNotFound = Error("Registry not found") ErrRegistryAlreadyExists = Error("A registry is already defined for this URL") ) // Stack errors const ( - ErrStackNotFound = Error("Stack not found") ErrStackAlreadyExists = Error("A stack already exists with this name") ErrComposeFileNotFoundInRepository = Error("Unable to find a Compose file in the repository") ErrStackNotExternal = Error("Not an external stack") @@ -79,21 +70,6 @@ const ( ErrEndpointExtensionAlreadyAssociated = Error("This extension is already associated to the endpoint") ) -// Version errors. -const ( - ErrDBVersionNotFound = Error("DB version not found") -) - -// Settings errors. -const ( - ErrSettingsNotFound = Error("Settings not found") -) - -// DockerHub errors. -const ( - ErrDockerHubNotFound = Error("Dockerhub not found") -) - // Crypto errors. const ( ErrCryptoHashFailure = Error("Unable to hash data") diff --git a/api/filesystem/filesystem.go b/api/filesystem/filesystem.go index b0efbfe8f..5bff04852 100644 --- a/api/filesystem/filesystem.go +++ b/api/filesystem/filesystem.go @@ -201,10 +201,21 @@ func (service *Service) WriteJSONToFile(path string, content interface{}) error return ioutil.WriteFile(path, jsonContent, 0644) } +// FileExists checks for the existence of the specified file. +func (service *Service) FileExists(filePath string) (bool, error) { + if _, err := os.Stat(filePath); err != nil { + if os.IsNotExist(err) { + return false, nil + } + return false, err + } + return true, nil +} + // KeyPairFilesExist checks for the existence of the key files. func (service *Service) KeyPairFilesExist() (bool, error) { privateKeyPath := path.Join(service.dataStorePath, PrivateKeyFile) - exists, err := fileExists(privateKeyPath) + exists, err := service.FileExists(privateKeyPath) if err != nil { return false, err } @@ -213,7 +224,7 @@ func (service *Service) KeyPairFilesExist() (bool, error) { } publicKeyPath := path.Join(service.dataStorePath, PublicKeyFile) - exists, err = fileExists(publicKeyPath) + exists, err = service.FileExists(publicKeyPath) if err != nil { return false, err } @@ -307,13 +318,3 @@ func (service *Service) getContentFromPEMFile(filePath string) ([]byte, error) { block, _ := pem.Decode(fileContent) return block.Bytes, nil } - -func fileExists(filePath string) (bool, error) { - if _, err := os.Stat(filePath); err != nil { - if os.IsNotExist(err) { - return false, nil - } - return false, err - } - return true, nil -} diff --git a/api/http/handler/auth/authenticate.go b/api/http/handler/auth/authenticate.go index a5200f7d3..b146352a8 100644 --- a/api/http/handler/auth/authenticate.go +++ b/api/http/handler/auth/authenticate.go @@ -41,7 +41,7 @@ func (handler *Handler) authenticate(w http.ResponseWriter, r *http.Request) *ht } u, err := handler.UserService.UserByUsername(payload.Username) - if err == portainer.ErrUserNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusBadRequest, "Invalid credentials", ErrInvalidCredentials} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a user with the specified username from the database", err} diff --git a/api/http/handler/dockerhub/dockerhub_update.go b/api/http/handler/dockerhub/dockerhub_update.go index 9f8f8d201..7bd37bce5 100644 --- a/api/http/handler/dockerhub/dockerhub_update.go +++ b/api/http/handler/dockerhub/dockerhub_update.go @@ -43,7 +43,7 @@ func (handler *Handler) dockerhubUpdate(w http.ResponseWriter, r *http.Request) dockerhub.Password = payload.Password } - err = handler.DockerHubService.StoreDockerHub(dockerhub) + err = handler.DockerHubService.UpdateDockerHub(dockerhub) if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist the Dockerhub changes inside the database", err} } diff --git a/api/http/handler/endpointgroups/endpointgroup_delete.go b/api/http/handler/endpointgroups/endpointgroup_delete.go index 87c34f94d..01123d850 100644 --- a/api/http/handler/endpointgroups/endpointgroup_delete.go +++ b/api/http/handler/endpointgroups/endpointgroup_delete.go @@ -21,7 +21,7 @@ func (handler *Handler) endpointGroupDelete(w http.ResponseWriter, r *http.Reque } _, err = handler.EndpointGroupService.EndpointGroup(portainer.EndpointGroupID(endpointGroupID)) - if err == portainer.ErrEndpointGroupNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint group with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint group with the specified identifier inside the database", err} diff --git a/api/http/handler/endpointgroups/endpointgroup_inspect.go b/api/http/handler/endpointgroups/endpointgroup_inspect.go index 8ff26b28f..168d8cb8b 100644 --- a/api/http/handler/endpointgroups/endpointgroup_inspect.go +++ b/api/http/handler/endpointgroups/endpointgroup_inspect.go @@ -17,7 +17,7 @@ func (handler *Handler) endpointGroupInspect(w http.ResponseWriter, r *http.Requ } endpointGroup, err := handler.EndpointGroupService.EndpointGroup(portainer.EndpointGroupID(endpointGroupID)) - if err == portainer.ErrEndpointGroupNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint group with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint group with the specified identifier inside the database", err} diff --git a/api/http/handler/endpointgroups/endpointgroup_update.go b/api/http/handler/endpointgroups/endpointgroup_update.go index 237e5d9a6..ee31e3066 100644 --- a/api/http/handler/endpointgroups/endpointgroup_update.go +++ b/api/http/handler/endpointgroups/endpointgroup_update.go @@ -34,7 +34,7 @@ func (handler *Handler) endpointGroupUpdate(w http.ResponseWriter, r *http.Reque } endpointGroup, err := handler.EndpointGroupService.EndpointGroup(portainer.EndpointGroupID(endpointGroupID)) - if err == portainer.ErrEndpointGroupNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint group with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint group with the specified identifier inside the database", err} diff --git a/api/http/handler/endpointgroups/endpointgroup_update_access.go b/api/http/handler/endpointgroups/endpointgroup_update_access.go index a39dbea94..7a3b3038e 100644 --- a/api/http/handler/endpointgroups/endpointgroup_update_access.go +++ b/api/http/handler/endpointgroups/endpointgroup_update_access.go @@ -32,7 +32,7 @@ func (handler *Handler) endpointGroupUpdateAccess(w http.ResponseWriter, r *http } endpointGroup, err := handler.EndpointGroupService.EndpointGroup(portainer.EndpointGroupID(endpointGroupID)) - if err == portainer.ErrEndpointGroupNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint group with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint group with the specified identifier inside the database", err} diff --git a/api/http/handler/endpointproxy/proxy_azure.go b/api/http/handler/endpointproxy/proxy_azure.go index a9b550da4..dc46bfb3f 100644 --- a/api/http/handler/endpointproxy/proxy_azure.go +++ b/api/http/handler/endpointproxy/proxy_azure.go @@ -17,7 +17,7 @@ func (handler *Handler) proxyRequestsToAzureAPI(w http.ResponseWriter, r *http.R } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/endpointproxy/proxy_docker.go b/api/http/handler/endpointproxy/proxy_docker.go index 352652fc4..01a56e017 100644 --- a/api/http/handler/endpointproxy/proxy_docker.go +++ b/api/http/handler/endpointproxy/proxy_docker.go @@ -17,7 +17,7 @@ func (handler *Handler) proxyRequestsToDockerAPI(w http.ResponseWriter, r *http. } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/endpointproxy/proxy_storidge.go b/api/http/handler/endpointproxy/proxy_storidge.go index 30e85dfda..a582b561d 100644 --- a/api/http/handler/endpointproxy/proxy_storidge.go +++ b/api/http/handler/endpointproxy/proxy_storidge.go @@ -17,7 +17,7 @@ func (handler *Handler) proxyRequestsToStoridgeAPI(w http.ResponseWriter, r *htt } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/endpoints/endpoint_delete.go b/api/http/handler/endpoints/endpoint_delete.go index 4bcb4f14c..40f18f348 100644 --- a/api/http/handler/endpoints/endpoint_delete.go +++ b/api/http/handler/endpoints/endpoint_delete.go @@ -22,7 +22,7 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) * } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/endpoints/endpoint_extension_add.go b/api/http/handler/endpoints/endpoint_extension_add.go index e46ba06ce..009083190 100644 --- a/api/http/handler/endpoints/endpoint_extension_add.go +++ b/api/http/handler/endpoints/endpoint_extension_add.go @@ -33,7 +33,7 @@ func (handler *Handler) endpointExtensionAdd(w http.ResponseWriter, r *http.Requ } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/endpoints/endpoint_extension_remove.go b/api/http/handler/endpoints/endpoint_extension_remove.go index bce4fc478..2e238a89e 100644 --- a/api/http/handler/endpoints/endpoint_extension_remove.go +++ b/api/http/handler/endpoints/endpoint_extension_remove.go @@ -17,7 +17,7 @@ func (handler *Handler) endpointExtensionRemove(w http.ResponseWriter, r *http.R } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/endpoints/endpoint_inspect.go b/api/http/handler/endpoints/endpoint_inspect.go index 80b5703a9..82d2cb7b9 100644 --- a/api/http/handler/endpoints/endpoint_inspect.go +++ b/api/http/handler/endpoints/endpoint_inspect.go @@ -17,7 +17,7 @@ func (handler *Handler) endpointInspect(w http.ResponseWriter, r *http.Request) } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/endpoints/endpoint_update.go b/api/http/handler/endpoints/endpoint_update.go index 7532c0450..769267449 100644 --- a/api/http/handler/endpoints/endpoint_update.go +++ b/api/http/handler/endpoints/endpoint_update.go @@ -47,7 +47,7 @@ func (handler *Handler) endpointUpdate(w http.ResponseWriter, r *http.Request) * } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/endpoints/endpoint_update_access.go b/api/http/handler/endpoints/endpoint_update_access.go index 6fb72ba5f..bedf559ff 100644 --- a/api/http/handler/endpoints/endpoint_update_access.go +++ b/api/http/handler/endpoints/endpoint_update_access.go @@ -36,7 +36,7 @@ func (handler *Handler) endpointUpdateAccess(w http.ResponseWriter, r *http.Requ } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/registries/registry_delete.go b/api/http/handler/registries/registry_delete.go index 1fbe5bc04..2e968539b 100644 --- a/api/http/handler/registries/registry_delete.go +++ b/api/http/handler/registries/registry_delete.go @@ -17,7 +17,7 @@ func (handler *Handler) registryDelete(w http.ResponseWriter, r *http.Request) * } _, err = handler.RegistryService.Registry(portainer.RegistryID(registryID)) - if err == portainer.ErrEndpointGroupNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a registry with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a registry with the specified identifier inside the database", err} diff --git a/api/http/handler/registries/registry_inspect.go b/api/http/handler/registries/registry_inspect.go index d78d1969b..a60f24288 100644 --- a/api/http/handler/registries/registry_inspect.go +++ b/api/http/handler/registries/registry_inspect.go @@ -17,7 +17,7 @@ func (handler *Handler) registryInspect(w http.ResponseWriter, r *http.Request) } registry, err := handler.RegistryService.Registry(portainer.RegistryID(registryID)) - if err == portainer.ErrEndpointGroupNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a registry with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a registry with the specified identifier inside the database", err} diff --git a/api/http/handler/registries/registry_update.go b/api/http/handler/registries/registry_update.go index b1a0167bb..1a3743fb5 100644 --- a/api/http/handler/registries/registry_update.go +++ b/api/http/handler/registries/registry_update.go @@ -39,7 +39,7 @@ func (handler *Handler) registryUpdate(w http.ResponseWriter, r *http.Request) * } registry, err := handler.RegistryService.Registry(portainer.RegistryID(registryID)) - if err == portainer.ErrEndpointGroupNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a registry with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a registry with the specified identifier inside the database", err} diff --git a/api/http/handler/registries/registry_update_access.go b/api/http/handler/registries/registry_update_access.go index a8234e95c..a43ccb2f9 100644 --- a/api/http/handler/registries/registry_update_access.go +++ b/api/http/handler/registries/registry_update_access.go @@ -32,7 +32,7 @@ func (handler *Handler) registryUpdateAccess(w http.ResponseWriter, r *http.Requ } registry, err := handler.RegistryService.Registry(portainer.RegistryID(registryID)) - if err == portainer.ErrEndpointGroupNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a registry with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a registry with the specified identifier inside the database", err} diff --git a/api/http/handler/resourcecontrols/resourcecontrol_create.go b/api/http/handler/resourcecontrols/resourcecontrol_create.go index 4dc41e406..baaee3360 100644 --- a/api/http/handler/resourcecontrols/resourcecontrol_create.go +++ b/api/http/handler/resourcecontrols/resourcecontrol_create.go @@ -64,7 +64,7 @@ func (handler *Handler) resourceControlCreate(w http.ResponseWriter, r *http.Req } rc, err := handler.ResourceControlService.ResourceControlByResourceID(payload.ResourceID) - if err != nil && err != portainer.ErrResourceControlNotFound { + if err != nil && err != portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve resource controls from the database", err} } if rc != nil { diff --git a/api/http/handler/resourcecontrols/resourcecontrol_delete.go b/api/http/handler/resourcecontrols/resourcecontrol_delete.go index 47a507e9d..48fd8a972 100644 --- a/api/http/handler/resourcecontrols/resourcecontrol_delete.go +++ b/api/http/handler/resourcecontrols/resourcecontrol_delete.go @@ -18,7 +18,7 @@ func (handler *Handler) resourceControlDelete(w http.ResponseWriter, r *http.Req } resourceControl, err := handler.ResourceControlService.ResourceControl(portainer.ResourceControlID(resourceControlID)) - if err == portainer.ErrResourceControlNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a resource control with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a resource control with with the specified identifier inside the database", err} diff --git a/api/http/handler/resourcecontrols/resourcecontrol_update.go b/api/http/handler/resourcecontrols/resourcecontrol_update.go index c2a580cb0..3f3b25799 100644 --- a/api/http/handler/resourcecontrols/resourcecontrol_update.go +++ b/api/http/handler/resourcecontrols/resourcecontrol_update.go @@ -37,7 +37,7 @@ func (handler *Handler) resourceControlUpdate(w http.ResponseWriter, r *http.Req } resourceControl, err := handler.ResourceControlService.ResourceControl(portainer.ResourceControlID(resourceControlID)) - if err == portainer.ErrResourceControlNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a resource control with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a resource control with with the specified identifier inside the database", err} diff --git a/api/http/handler/settings/settings_update.go b/api/http/handler/settings/settings_update.go index defe9cd6b..1e854ec7f 100644 --- a/api/http/handler/settings/settings_update.go +++ b/api/http/handler/settings/settings_update.go @@ -62,7 +62,7 @@ func (handler *Handler) settingsUpdate(w http.ResponseWriter, r *http.Request) * return tlsError } - err = handler.SettingsService.StoreSettings(settings) + err = handler.SettingsService.UpdateSettings(settings) if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist settings changes inside the database", err} } diff --git a/api/http/handler/stacks/stack_create.go b/api/http/handler/stacks/stack_create.go index 9a4c37c52..c0b9d9ce0 100644 --- a/api/http/handler/stacks/stack_create.go +++ b/api/http/handler/stacks/stack_create.go @@ -39,7 +39,7 @@ func (handler *Handler) stackCreate(w http.ResponseWriter, r *http.Request) *htt } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err} diff --git a/api/http/handler/stacks/stack_delete.go b/api/http/handler/stacks/stack_delete.go index c46905585..3844a4d7e 100644 --- a/api/http/handler/stacks/stack_delete.go +++ b/api/http/handler/stacks/stack_delete.go @@ -32,14 +32,14 @@ func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *htt } stack, err := handler.StackService.Stack(portainer.StackID(id)) - if err == portainer.ErrStackNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a stack with the specified identifier inside the database", err} } resourceControl, err := handler.ResourceControlService.ResourceControlByResourceID(stack.Name) - if err != nil && err != portainer.ErrResourceControlNotFound { + if err != nil && err != portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a resource control associated to the stack", err} } @@ -68,7 +68,7 @@ func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *htt } endpoint, err := handler.EndpointService.Endpoint(endpointIdentifier) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find the endpoint associated to the stack inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find the endpoint associated to the stack inside the database", err} @@ -94,7 +94,7 @@ func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *htt func (handler *Handler) deleteExternalStack(r *http.Request, w http.ResponseWriter, stackName string) *httperror.HandlerError { stack, err := handler.StackService.StackByName(stackName) - if err != nil && err != portainer.ErrStackNotFound { + if err != nil && err != portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to check for stack existence inside the database", err} } if stack != nil { @@ -107,7 +107,7 @@ func (handler *Handler) deleteExternalStack(r *http.Request, w http.ResponseWrit } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find the endpoint associated to the stack inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find the endpoint associated to the stack inside the database", err} diff --git a/api/http/handler/stacks/stack_file.go b/api/http/handler/stacks/stack_file.go index 0875ae8e1..a0b644ba0 100644 --- a/api/http/handler/stacks/stack_file.go +++ b/api/http/handler/stacks/stack_file.go @@ -24,14 +24,14 @@ func (handler *Handler) stackFile(w http.ResponseWriter, r *http.Request) *httpe } stack, err := handler.StackService.Stack(portainer.StackID(stackID)) - if err == portainer.ErrStackNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a stack with the specified identifier inside the database", err} } resourceControl, err := handler.ResourceControlService.ResourceControlByResourceID(stack.Name) - if err != nil && err != portainer.ErrResourceControlNotFound { + if err != nil && err != portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a resource control associated to the stack", err} } diff --git a/api/http/handler/stacks/stack_inspect.go b/api/http/handler/stacks/stack_inspect.go index ec6d99509..28d5030ac 100644 --- a/api/http/handler/stacks/stack_inspect.go +++ b/api/http/handler/stacks/stack_inspect.go @@ -19,14 +19,14 @@ func (handler *Handler) stackInspect(w http.ResponseWriter, r *http.Request) *ht } stack, err := handler.StackService.Stack(portainer.StackID(stackID)) - if err == portainer.ErrStackNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a stack with the specified identifier inside the database", err} } resourceControl, err := handler.ResourceControlService.ResourceControlByResourceID(stack.Name) - if err != nil && err != portainer.ErrResourceControlNotFound { + if err != nil && err != portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a resource control associated to the stack", err} } diff --git a/api/http/handler/stacks/stack_update.go b/api/http/handler/stacks/stack_update.go index f20f92957..66b2b7f73 100644 --- a/api/http/handler/stacks/stack_update.go +++ b/api/http/handler/stacks/stack_update.go @@ -44,14 +44,14 @@ func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *htt } stack, err := handler.StackService.Stack(portainer.StackID(stackID)) - if err == portainer.ErrStackNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a stack with the specified identifier inside the database", err} } resourceControl, err := handler.ResourceControlService.ResourceControlByResourceID(stack.Name) - if err != nil && err != portainer.ErrResourceControlNotFound { + if err != nil && err != portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a resource control associated to the stack", err} } @@ -78,7 +78,7 @@ func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *htt } endpoint, err := handler.EndpointService.Endpoint(stack.EndpointID) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find the endpoint associated to the stack inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find the endpoint associated to the stack inside the database", err} diff --git a/api/http/handler/teammemberships/teammembership_delete.go b/api/http/handler/teammemberships/teammembership_delete.go index 577f3be7d..a1263745f 100644 --- a/api/http/handler/teammemberships/teammembership_delete.go +++ b/api/http/handler/teammemberships/teammembership_delete.go @@ -18,7 +18,7 @@ func (handler *Handler) teamMembershipDelete(w http.ResponseWriter, r *http.Requ } membership, err := handler.TeamMembershipService.TeamMembership(portainer.TeamMembershipID(membershipID)) - if err == portainer.ErrTeamMembershipNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a team membership with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a team membership with the specified identifier inside the database", err} diff --git a/api/http/handler/teammemberships/teammembership_update.go b/api/http/handler/teammemberships/teammembership_update.go index 953ca5618..6d08bc90a 100644 --- a/api/http/handler/teammemberships/teammembership_update.go +++ b/api/http/handler/teammemberships/teammembership_update.go @@ -52,7 +52,7 @@ func (handler *Handler) teamMembershipUpdate(w http.ResponseWriter, r *http.Requ } membership, err := handler.TeamMembershipService.TeamMembership(portainer.TeamMembershipID(membershipID)) - if err == portainer.ErrTeamMembershipNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a team membership with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a team membership with the specified identifier inside the database", err} diff --git a/api/http/handler/teams/team_create.go b/api/http/handler/teams/team_create.go index 49dc6f093..d865e56c5 100644 --- a/api/http/handler/teams/team_create.go +++ b/api/http/handler/teams/team_create.go @@ -29,7 +29,7 @@ func (handler *Handler) teamCreate(w http.ResponseWriter, r *http.Request) *http } team, err := handler.TeamService.TeamByName(payload.Name) - if err != nil && err != portainer.ErrTeamNotFound { + if err != nil && err != portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve teams from the database", err} } if team != nil { diff --git a/api/http/handler/teams/team_delete.go b/api/http/handler/teams/team_delete.go index ab805248b..623c29c4c 100644 --- a/api/http/handler/teams/team_delete.go +++ b/api/http/handler/teams/team_delete.go @@ -17,7 +17,7 @@ func (handler *Handler) teamDelete(w http.ResponseWriter, r *http.Request) *http } _, err = handler.TeamService.Team(portainer.TeamID(teamID)) - if err == portainer.ErrTeamNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a team with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a team with the specified identifier inside the database", err} diff --git a/api/http/handler/teams/team_inspect.go b/api/http/handler/teams/team_inspect.go index b6c6ab1a6..4030a391e 100644 --- a/api/http/handler/teams/team_inspect.go +++ b/api/http/handler/teams/team_inspect.go @@ -27,7 +27,7 @@ func (handler *Handler) teamInspect(w http.ResponseWriter, r *http.Request) *htt } team, err := handler.TeamService.Team(portainer.TeamID(teamID)) - if err == portainer.ErrTeamNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a team with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a team with the specified identifier inside the database", err} diff --git a/api/http/handler/teams/team_update.go b/api/http/handler/teams/team_update.go index ea80f0dd5..8c0961c31 100644 --- a/api/http/handler/teams/team_update.go +++ b/api/http/handler/teams/team_update.go @@ -31,7 +31,7 @@ func (handler *Handler) teamUpdate(w http.ResponseWriter, r *http.Request) *http } team, err := handler.TeamService.Team(portainer.TeamID(teamID)) - if err == portainer.ErrTeamNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a team with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a team with the specified identifier inside the database", err} diff --git a/api/http/handler/users/admin_check.go b/api/http/handler/users/admin_check.go index 1120c957a..4d7ba233a 100644 --- a/api/http/handler/users/admin_check.go +++ b/api/http/handler/users/admin_check.go @@ -16,7 +16,7 @@ func (handler *Handler) adminCheck(w http.ResponseWriter, r *http.Request) *http } if len(users) == 0 { - return &httperror.HandlerError{http.StatusNotFound, "No administrator account found inside the database", portainer.ErrUserNotFound} + return &httperror.HandlerError{http.StatusNotFound, "No administrator account found inside the database", portainer.ErrObjectNotFound} } return response.Empty(w) diff --git a/api/http/handler/users/user_create.go b/api/http/handler/users/user_create.go index 7efba6d25..9fb4cddda 100644 --- a/api/http/handler/users/user_create.go +++ b/api/http/handler/users/user_create.go @@ -50,7 +50,7 @@ func (handler *Handler) userCreate(w http.ResponseWriter, r *http.Request) *http } user, err := handler.UserService.UserByUsername(payload.Username) - if err != nil && err != portainer.ErrUserNotFound { + if err != nil && err != portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve users from the database", err} } if user != nil { diff --git a/api/http/handler/users/user_delete.go b/api/http/handler/users/user_delete.go index 5723bf387..c183df7a7 100644 --- a/api/http/handler/users/user_delete.go +++ b/api/http/handler/users/user_delete.go @@ -27,7 +27,7 @@ func (handler *Handler) userDelete(w http.ResponseWriter, r *http.Request) *http } _, err = handler.UserService.User(portainer.UserID(userID)) - if err == portainer.ErrUserNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a user with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a user with the specified identifier inside the database", err} diff --git a/api/http/handler/users/user_inspect.go b/api/http/handler/users/user_inspect.go index c74d170d6..9583c833c 100644 --- a/api/http/handler/users/user_inspect.go +++ b/api/http/handler/users/user_inspect.go @@ -17,7 +17,7 @@ func (handler *Handler) userInspect(w http.ResponseWriter, r *http.Request) *htt } user, err := handler.UserService.User(portainer.UserID(userID)) - if err == portainer.ErrUserNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a user with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a user with the specified identifier inside the database", err} diff --git a/api/http/handler/users/user_password.go b/api/http/handler/users/user_password.go index 073c10360..d50f88879 100644 --- a/api/http/handler/users/user_password.go +++ b/api/http/handler/users/user_password.go @@ -41,7 +41,7 @@ func (handler *Handler) userPassword(w http.ResponseWriter, r *http.Request) *ht var password = payload.Password u, err := handler.UserService.User(portainer.UserID(userID)) - if err == portainer.ErrUserNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a user with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a user with the specified identifier inside the database", err} diff --git a/api/http/handler/users/user_update.go b/api/http/handler/users/user_update.go index 4a01d0e37..a8b6c8b1a 100644 --- a/api/http/handler/users/user_update.go +++ b/api/http/handler/users/user_update.go @@ -49,7 +49,7 @@ func (handler *Handler) userUpdate(w http.ResponseWriter, r *http.Request) *http } user, err := handler.UserService.User(portainer.UserID(userID)) - if err == portainer.ErrUserNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find a user with the specified identifier inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a user with the specified identifier inside the database", err} diff --git a/api/http/handler/websocket/websocket_exec.go b/api/http/handler/websocket/websocket_exec.go index cbb9fbbf4..6e46084a6 100644 --- a/api/http/handler/websocket/websocket_exec.go +++ b/api/http/handler/websocket/websocket_exec.go @@ -52,7 +52,7 @@ func (handler *Handler) websocketExec(w http.ResponseWriter, r *http.Request) *h } endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID)) - if err == portainer.ErrEndpointNotFound { + if err == portainer.ErrObjectNotFound { return &httperror.HandlerError{http.StatusNotFound, "Unable to find the endpoint associated to the stack inside the database", err} } else if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find the endpoint associated to the stack inside the database", err} diff --git a/api/http/security/bouncer.go b/api/http/security/bouncer.go index 1327503eb..798d37f7b 100644 --- a/api/http/security/bouncer.go +++ b/api/http/security/bouncer.go @@ -185,7 +185,7 @@ func (bouncer *RequestBouncer) mwCheckAuthentication(next http.Handler) http.Han } _, err = bouncer.userService.User(tokenData.ID) - if err != nil && err == portainer.ErrUserNotFound { + if err != nil && err == portainer.ErrObjectNotFound { httperror.WriteError(w, http.StatusUnauthorized, "Unauthorized", portainer.ErrUnauthorized) return } else if err != nil { diff --git a/api/portainer.go b/api/portainer.go index 37f1e5e19..38cea152f 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -379,13 +379,13 @@ type ( // DockerHubService represents a service for managing the DockerHub object. DockerHubService interface { DockerHub() (*DockerHub, error) - StoreDockerHub(registry *DockerHub) error + UpdateDockerHub(registry *DockerHub) error } // SettingsService represents a service for managing application settings. SettingsService interface { Settings() (*Settings, error) - StoreSettings(settings *Settings) error + UpdateSettings(settings *Settings) error } // VersionService represents a service for managing version data. @@ -447,6 +447,7 @@ type ( StoreKeyPair(private, public []byte, privatePEMHeader, publicPEMHeader string) error LoadKeyPair() ([]byte, []byte, error) WriteJSONToFile(path string, content interface{}) error + FileExists(path string) (bool, error) } // GitService represents a service for managing Git.