feat(project): introduce cache manager for project (#16740)

Implement cached manager for resource project and migrate project.Mgr
to pkg.ProjectMgr.

Signed-off-by: chlins <chenyuzh@vmware.com>
This commit is contained in:
chlins 2022-05-05 16:36:49 +08:00
parent 6ca3665207
commit 0fd0c84446
18 changed files with 413 additions and 47 deletions

View File

@ -1,11 +1,12 @@
package immutable
import (
"testing"
"github.com/goharbor/harbor/src/lib/orm"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg"
proModels "github.com/goharbor/harbor/src/pkg/project/models"
"testing"
"github.com/goharbor/harbor/src/common/utils/test"
"github.com/goharbor/harbor/src/pkg/immutable/model"
@ -39,12 +40,12 @@ func (s *ControllerTestSuite) TestImmutableRule() {
var err error
ctx := s.Context()
projectID, err := project.Mgr.Create(ctx, &proModels.Project{
projectID, err := pkg.ProjectMgr.Create(ctx, &proModels.Project{
Name: "testimmutablerule",
OwnerID: 1,
})
if s.Nil(err) {
defer project.Mgr.Delete(ctx, projectID)
defer pkg.ProjectMgr.Delete(ctx, projectID)
}
rule := &model.Metadata{

View File

@ -22,6 +22,7 @@ import (
"github.com/goharbor/harbor/src/core/auth"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/member"
"github.com/goharbor/harbor/src/pkg/member/models"
"github.com/goharbor/harbor/src/pkg/project"
@ -81,7 +82,7 @@ type controller struct {
// NewController ...
func NewController() Controller {
return &controller{mgr: member.Mgr, projectMgr: project.Mgr, userManager: user.New()}
return &controller{mgr: member.Mgr, projectMgr: pkg.ProjectMgr, userManager: user.New()}
}
func (c *controller) Count(ctx context.Context, projectNameOrID interface{}, query *q.Query) (int, error) {

View File

@ -24,6 +24,7 @@ import (
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/orm"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/allowlist"
"github.com/goharbor/harbor/src/pkg/notification"
"github.com/goharbor/harbor/src/pkg/project"
@ -68,7 +69,7 @@ type Controller interface {
// NewController creates an instance of the default project controller
func NewController() Controller {
return &controller{
projectMgr: project.Mgr,
projectMgr: pkg.ProjectMgr,
metaMgr: metadata.Mgr,
allowlistMgr: allowlist.NewDefaultManager(),
userMgr: user.Mgr,

View File

@ -16,13 +16,14 @@ package project
import (
"context"
proModels "github.com/goharbor/harbor/src/pkg/project/models"
"strconv"
"github.com/goharbor/harbor/src/pkg"
proModels "github.com/goharbor/harbor/src/pkg/project/models"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/user"
"github.com/graph-gophers/dataloader"
)
@ -45,7 +46,7 @@ func getProjectsBatchFn(ctx context.Context, keys dataloader.Keys) []*dataloader
projectIDs = append(projectIDs, id)
}
projects, err := project.Mgr.List(ctx, q.New(q.KeyWords{"project_id__in": projectIDs}))
projects, err := pkg.ProjectMgr.List(ctx, q.New(q.KeyWords{"project_id__in": projectIDs}))
if err != nil {
return handleError(err)
}

View File

@ -23,6 +23,7 @@ import (
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/reg"
"github.com/goharbor/harbor/src/pkg/reg/model"
@ -64,7 +65,7 @@ func NewController() Controller {
return &controller{
regMgr: reg.Mgr,
repMgr: replication.Mgr,
proMgr: project.Mgr,
proMgr: pkg.ProjectMgr,
}
}

View File

@ -60,7 +60,7 @@ type Controller interface {
// NewController creates an instance of the default repository controller
func NewController() Controller {
return &controller{
proMgr: project.Mgr,
proMgr: pkg.ProjectMgr,
repoMgr: repository.Mgr,
artMgr: pkg.ArtifactMgr,
artCtl: artifact.Ctl,

View File

@ -22,6 +22,7 @@ import (
"github.com/goharbor/harbor/src/jobservice/job"
"github.com/goharbor/harbor/src/jobservice/logger"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/repository"
"github.com/goharbor/harbor/src/pkg/retention"
@ -390,13 +391,13 @@ func (r *defaultController) UpdateTaskInfo(ctx context.Context, taskID int64, to
// NewController ...
func NewController() Controller {
retentionMgr := retention.NewManager()
retentionLauncher := retention.NewLauncher(project.Mgr, repository.Mgr, retentionMgr, task.ExecMgr, task.Mgr)
retentionLauncher := retention.NewLauncher(pkg.ProjectMgr, repository.Mgr, retentionMgr, task.ExecMgr, task.Mgr)
return &defaultController{
manager: retentionMgr,
execMgr: task.ExecMgr,
taskMgr: task.Mgr,
launcher: retentionLauncher,
projectManager: project.Mgr,
projectManager: pkg.ProjectMgr,
repositoryMgr: repository.Mgr,
scheduler: scheduler.Sched,
}

View File

@ -12,6 +12,7 @@ import (
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/permission/types"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/rbac"
@ -57,7 +58,7 @@ type controller struct {
func NewController() Controller {
return &controller{
robotMgr: robot.Mgr,
proMgr: project.Mgr,
proMgr: pkg.ProjectMgr,
rbacMgr: rbac.Mgr,
}
}

View File

@ -25,11 +25,11 @@ import (
"github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/orm"
"github.com/goharbor/harbor/src/pkg"
_ "github.com/goharbor/harbor/src/pkg/config/db"
_ "github.com/goharbor/harbor/src/pkg/config/inmemory"
"github.com/goharbor/harbor/src/pkg/member"
memberModels "github.com/goharbor/harbor/src/pkg/member/models"
"github.com/goharbor/harbor/src/pkg/project"
userpkg "github.com/goharbor/harbor/src/pkg/user"
userDao "github.com/goharbor/harbor/src/pkg/user/dao"
"github.com/goharbor/harbor/src/pkg/usergroup"
@ -382,7 +382,7 @@ func TestSearchAndOnBoardUser(t *testing.T) {
func TestAddProjectMemberWithLdapUser(t *testing.T) {
memberMgr := member.Mgr
ctx := orm.Context()
currentProject, err := project.Mgr.Get(ctx, "member_test_01")
currentProject, err := pkg.ProjectMgr.Get(ctx, "member_test_01")
if err != nil {
t.Errorf("Error occurred when GetProjectByName: %v", err)
}
@ -402,7 +402,7 @@ func TestAddProjectMemberWithLdapUser(t *testing.T) {
t.Errorf("Error occurred in AddOrUpdateProjectMember: pmid:%v", pmid)
}
currentProject, err = project.Mgr.Get(ctx, "member_test_02")
currentProject, err = pkg.ProjectMgr.Get(ctx, "member_test_02")
if err != nil {
t.Errorf("Error occurred when GetProjectByName: %v", err)
}
@ -424,7 +424,7 @@ func TestAddProjectMemberWithLdapUser(t *testing.T) {
func TestAddProjectMemberWithLdapGroup(t *testing.T) {
memberMgr := member.Mgr
ctx := orm.Context()
currentProject, err := project.Mgr.Get(ctx, "member_test_01")
currentProject, err := pkg.ProjectMgr.Get(ctx, "member_test_01")
if err != nil {
t.Errorf("Error occurred when GetProjectByName: %v", err)
}

View File

@ -22,13 +22,12 @@ import (
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/repository"
)
func abstractArtData(ctx context.Context) error {
abstractor := art.NewAbstractor()
pros, err := project.Mgr.List(ctx, nil)
pros, err := pkg.ProjectMgr.List(ctx, nil)
if err != nil {
return err
}

View File

@ -25,6 +25,8 @@ const (
// Resource type definitions
// ResourceTypeArtifact defines artifact type.
ResourceTypeArtifact = "artifact"
// ResourceTypeProject defines project type.
ResourceTypeProject = "project"
)
// Manager is the interface for resource cache manager.

View File

@ -0,0 +1,202 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package redis
import (
"context"
"time"
"github.com/goharbor/harbor/src/common/utils"
libcache "github.com/goharbor/harbor/src/lib/cache"
"github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/lib/retry"
"github.com/goharbor/harbor/src/pkg/cached"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/project/models"
)
var _ CachedManager = &manager{}
// CachedManager is the interface combines raw resource manager and cached manager for better extension.
type CachedManager interface {
// Manager is the raw resource manager.
project.Manager
// Manager is the common interface for resource cache.
cached.Manager
}
// manager is the cached manager implemented by redis.
type manager struct {
// delegator delegates the raw crud to DAO.
delegator project.Manager
// client returns the redis cache client.
client func() libcache.Cache
// keyBuilder builds cache object key.
keyBuilder *cached.ObjectKey
// lifetime is the cache life time.
lifetime time.Duration
}
// NewManager returns the redis cache manager.
func NewManager(m project.Manager) *manager {
return &manager{
delegator: m,
client: func() libcache.Cache { return libcache.Default() },
keyBuilder: cached.NewObjectKey(cached.ResourceTypeProject),
lifetime: time.Duration(config.CacheExpireHours()) * time.Hour,
}
}
func (m *manager) Create(ctx context.Context, project *models.Project) (int64, error) {
return m.delegator.Create(ctx, project)
}
func (m *manager) Count(ctx context.Context, query *q.Query) (total int64, err error) {
return m.delegator.Count(ctx, query)
}
func (m *manager) List(ctx context.Context, query *q.Query) ([]*models.Project, error) {
return m.delegator.List(ctx, query)
}
func (m *manager) ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error) {
return m.delegator.ListRoles(ctx, projectID, userID, groupIDs...)
}
func (m *manager) Delete(ctx context.Context, id int64) error {
p, err := m.Get(ctx, id)
if err != nil {
return err
}
// pass on delete operation
if err := m.delegator.Delete(ctx, id); err != nil {
return err
}
// clean cache
m.cleanUp(ctx, p)
return nil
}
func (m *manager) Get(ctx context.Context, idOrName interface{}) (*models.Project, error) {
var (
key string
err error
)
id, name, err := utils.ParseProjectIDOrName(idOrName)
if err != nil {
return nil, err
}
if id != 0 {
key, err = m.keyBuilder.Format("id", id)
if err != nil {
return nil, err
}
}
if name != "" {
key, err = m.keyBuilder.Format("name", name)
if err != nil {
return nil, err
}
}
p := &models.Project{}
if err = m.client().Fetch(ctx, key, p); err == nil {
return p, nil
}
log.Debugf("get project %v from cache error: %v, will query from database.", idOrName, err)
p, err = m.delegator.Get(ctx, idOrName)
if err != nil {
return nil, err
}
if err = m.client().Save(ctx, key, p, m.lifetime); err != nil {
// log error if save to cache failed
log.Debugf("save project %s to cache error: %v", p.Name, err)
}
return p, nil
}
// cleanUp cleans up data in cache.
func (m *manager) cleanUp(ctx context.Context, p *models.Project) {
// clean index by id
idIdx, err := m.keyBuilder.Format("id", p.ProjectID)
if err != nil {
log.Errorf("format project id key error: %v", err)
} else {
// retry to avoid dirty data
if err = retry.Retry(func() error { return m.client().Delete(ctx, idIdx) }); err != nil {
log.Errorf("delete project cache key %s error: %v", idIdx, err)
}
}
// clean index by name
nameIdx, err := m.keyBuilder.Format("name", p.Name)
if err != nil {
log.Errorf("format project name key error: %v", err)
} else {
if err = retry.Retry(func() error { return m.client().Delete(ctx, nameIdx) }); err != nil {
log.Errorf("delete project cache key %s error: %v", nameIdx, err)
}
}
}
func (m *manager) ResourceType(ctx context.Context) string {
return cached.ResourceTypeProject
}
func (m *manager) CountCache(ctx context.Context) (int64, error) {
// prefix is resource type
keys, err := m.client().Keys(ctx, m.ResourceType(ctx))
if err != nil {
return 0, err
}
return int64(len(keys)), nil
}
func (m *manager) DeleteCache(ctx context.Context, key string) error {
return m.client().Delete(ctx, key)
}
func (m *manager) FlushAll(ctx context.Context) error {
// prefix is resource type
keys, err := m.client().Keys(ctx, m.ResourceType(ctx))
if err != nil {
return err
}
var errs errors.Errors
for _, key := range keys {
if err = m.client().Delete(ctx, key); err != nil {
errs = append(errs, err)
}
}
if errs.Len() > 0 {
return errs
}
return nil
}

View File

@ -0,0 +1,139 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package redis
import (
"context"
"errors"
"testing"
"github.com/goharbor/harbor/src/lib/cache"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg/project/models"
testcache "github.com/goharbor/harbor/src/testing/lib/cache"
"github.com/goharbor/harbor/src/testing/mock"
testProject "github.com/goharbor/harbor/src/testing/pkg/project"
"github.com/stretchr/testify/suite"
)
type managerTestSuite struct {
suite.Suite
cachedManager CachedManager
projectMgr *testProject.Manager
cache *testcache.Cache
ctx context.Context
}
func (m *managerTestSuite) SetupTest() {
m.projectMgr = &testProject.Manager{}
m.cache = &testcache.Cache{}
m.cachedManager = NewManager(
m.projectMgr,
)
m.cachedManager.(*manager).client = func() cache.Cache { return m.cache }
m.ctx = context.TODO()
}
func (m *managerTestSuite) TestCreate() {
m.projectMgr.On("Create", mock.Anything, mock.Anything).Return(int64(1), nil)
id, err := m.cachedManager.Create(m.ctx, &models.Project{})
m.NoError(err)
m.Equal(int64(1), id)
}
func (m *managerTestSuite) TestCount() {
m.projectMgr.On("Count", mock.Anything, mock.Anything).Return(int64(100), nil)
c, err := m.cachedManager.Count(m.ctx, q.New(q.KeyWords{}))
m.NoError(err)
m.Equal(int64(100), c)
}
func (m *managerTestSuite) List() {
m.projectMgr.On("List", mock.Anything, mock.Anything).Return([]*models.Project{}, nil)
ps, err := m.cachedManager.List(m.ctx, q.New(q.KeyWords{}))
m.NoError(err)
m.ElementsMatch([]*models.Project{}, ps)
}
func (m *managerTestSuite) ListRoles() {
m.projectMgr.On("ListRoles", mock.Anything, mock.Anything, mock.Anything).Return([]int{1}, nil)
rs, err := m.cachedManager.ListRoles(m.ctx, 1, 1)
m.NoError(err)
m.Equal([]int{1}, rs)
}
func (m *managerTestSuite) TestGet() {
// get from cache directly
m.cache.On("Fetch", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
_, err := m.cachedManager.Get(m.ctx, 100)
m.NoError(err, "should get from cache")
m.projectMgr.AssertNotCalled(m.T(), "Get", mock.Anything, mock.Anything)
// not found in cache, read from dao
m.cache.On("Fetch", mock.Anything, mock.Anything, mock.Anything).Return(cache.ErrNotFound).Once()
m.cache.On("Save", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
m.projectMgr.On("Get", mock.Anything, mock.Anything).Return(&models.Project{}, nil).Once()
_, err = m.cachedManager.Get(m.ctx, 100)
m.NoError(err, "should get from projectMgr")
m.projectMgr.AssertCalled(m.T(), "Get", mock.Anything, mock.Anything)
}
func (m *managerTestSuite) TestDelete() {
// delete from projectMgr error
errDelete := errors.New("delete failed")
m.projectMgr.On("Delete", mock.Anything, mock.Anything).Return(errDelete).Once()
m.cache.On("Fetch", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
err := m.cachedManager.Delete(m.ctx, 100)
m.ErrorIs(err, errDelete, "delete should error")
m.cache.AssertNotCalled(m.T(), "Delete", mock.Anything, mock.Anything)
// delete from projectMgr success
m.projectMgr.On("Delete", mock.Anything, mock.Anything).Return(nil).Once()
m.cache.On("Fetch", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
m.cache.On("Delete", mock.Anything, mock.Anything).Return(nil).Twice()
err = m.cachedManager.Delete(m.ctx, 100)
m.NoError(err, "delete should success")
m.cache.AssertCalled(m.T(), "Delete", mock.Anything, mock.Anything)
}
func (m *managerTestSuite) TestResourceType() {
t := m.cachedManager.ResourceType(m.ctx)
m.Equal("project", t)
}
func (m *managerTestSuite) TestCountCache() {
m.cache.On("Keys", mock.Anything, mock.Anything).Return([]string{"1"}, nil).Once()
c, err := m.cachedManager.CountCache(m.ctx)
m.NoError(err)
m.Equal(int64(1), c)
}
func (m *managerTestSuite) TestDeleteCache() {
m.cache.On("Delete", mock.Anything, mock.Anything).Return(nil).Once()
err := m.cachedManager.DeleteCache(m.ctx, "key")
m.NoError(err)
}
func (m *managerTestSuite) TestFlushAll() {
m.cache.On("Keys", mock.Anything, mock.Anything).Return([]string{"1"}, nil).Once()
m.cache.On("Delete", mock.Anything, mock.Anything).Return(nil).Once()
err := m.cachedManager.FlushAll(m.ctx)
m.NoError(err)
}
func TestManager(t *testing.T) {
suite.Run(t, &managerTestSuite{})
}

View File

@ -15,35 +15,45 @@
package pkg
import (
"sync"
"github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/cached/artifact/redis"
cachedArtifact "github.com/goharbor/harbor/src/pkg/cached/artifact/redis"
cachedProject "github.com/goharbor/harbor/src/pkg/cached/project/redis"
"github.com/goharbor/harbor/src/pkg/project"
)
// Define global resource manager.
var (
// once for only init one time.
once sync.Once
// ArtifactMgr is the manager for artifact.
ArtifactMgr artifact.Manager
// ProjectMgr is the manager for project.
ProjectMgr project.Manager
)
// init initialize mananger for resources
func init() {
once.Do(func() {
cacheEnabled := config.CacheEnabled()
initArtifactManager(cacheEnabled)
})
initArtifactMgr(cacheEnabled)
initProjectMgr(cacheEnabled)
}
func initArtifactManager(cacheEnabled bool) {
func initArtifactMgr(cacheEnabled bool) {
artMgr := artifact.NewManager()
// check cache enable
if cacheEnabled {
ArtifactMgr = redis.NewManager(artMgr)
ArtifactMgr = cachedArtifact.NewManager(artMgr)
} else {
ArtifactMgr = artMgr
}
}
func initProjectMgr(cacheEnabled bool) {
projectMgr := project.New()
// check cache enable
if cacheEnabled {
ProjectMgr = cachedProject.NewManager(projectMgr)
} else {
ProjectMgr = projectMgr
}
}

View File

@ -18,19 +18,30 @@ import (
"testing"
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/cached/artifact/redis"
cachedArtifact "github.com/goharbor/harbor/src/pkg/cached/artifact/redis"
cachedProject "github.com/goharbor/harbor/src/pkg/cached/project/redis"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/stretchr/testify/assert"
)
func TestInit(t *testing.T) {
func TestInitArtifactMgr(t *testing.T) {
// cache not enable
// artifact
assert.NotNil(t, ArtifactMgr)
assert.IsType(t, artifact.NewManager(), ArtifactMgr)
// cache enable
initArtifactManager(true)
// artifact
initArtifactMgr(true)
assert.NotNil(t, ArtifactMgr)
assert.IsType(t, redis.NewManager(artifact.NewManager()), ArtifactMgr)
assert.IsType(t, cachedArtifact.NewManager(artifact.NewManager()), ArtifactMgr)
}
func TestInitProjectMgr(t *testing.T) {
// cache not enable
assert.NotNil(t, ProjectMgr)
assert.IsType(t, project.New(), ProjectMgr)
// cache enable
initProjectMgr(true)
assert.NotNil(t, ProjectMgr)
assert.IsType(t, cachedProject.NewManager(project.New()), ProjectMgr)
}

View File

@ -16,10 +16,13 @@ package dao
import (
"database/sql"
"testing"
"github.com/goharbor/harbor/src/common"
_ "github.com/goharbor/harbor/src/common/dao"
testDao "github.com/goharbor/harbor/src/common/dao"
"github.com/goharbor/harbor/src/lib/orm"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/member/models"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/user"
@ -28,7 +31,6 @@ import (
ugModel "github.com/goharbor/harbor/src/pkg/usergroup/model"
htesting "github.com/goharbor/harbor/src/testing"
"github.com/stretchr/testify/suite"
"testing"
)
type DaoTestSuite struct {
@ -67,7 +69,7 @@ func (s *DaoTestSuite) SetupSuite() {
"delete from project_member where id > 1",
}
testDao.PrepareTestData(clearSqls, initSqls)
s.projectMgr = project.Mgr
s.projectMgr = pkg.ProjectMgr
s.userMgr = user.Mgr
ctx := s.Context()
proj, err := s.projectMgr.Get(ctx, "member_test_01")

View File

@ -26,11 +26,6 @@ import (
"github.com/goharbor/harbor/src/pkg/project/models"
)
var (
// Mgr is the global project manager
Mgr = New()
)
// Manager is used for project management
type Manager interface {
// Create create project instance

View File

@ -12,7 +12,6 @@ import (
"github.com/goharbor/harbor/src/controller/immutable"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/project"
proModels "github.com/goharbor/harbor/src/pkg/project/models"
"github.com/goharbor/harbor/src/common/dao"
@ -75,7 +74,7 @@ func randomString(n int) string {
}
func (suite *HandlerSuite) addProject(ctx context.Context, projectName string) int64 {
projectID, err := project.Mgr.Create(ctx, &proModels.Project{
projectID, err := pkg.ProjectMgr.Create(ctx, &proModels.Project{
Name: projectName,
OwnerID: 1,
})
@ -163,7 +162,7 @@ func (suite *HandlerSuite) TestPutDeleteManifestCreated() {
tagID := suite.addTags(ctx, repoID, afID, "release-1.10")
defer func() {
project.Mgr.Delete(ctx, projectID)
pkg.ProjectMgr.Delete(ctx, projectID)
pkg.ArtifactMgr.Delete(ctx, afID)
repository.Mgr.Delete(ctx, repoID)
tag.Mgr.Delete(ctx, tagID)