Merge pull request #8343 from ywk253100/190717_scheduler

Move the pkg manager/controller declaration to the api package
This commit is contained in:
Steven Zou 2019-07-19 19:16:31 +08:00 committed by GitHub
commit 8894d66b63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 97 additions and 67 deletions

View File

@ -15,9 +15,9 @@
package api package api
import ( import (
"errors"
"net/http" "net/http"
"errors"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/goharbor/harbor/src/common/api" "github.com/goharbor/harbor/src/common/api"
"github.com/goharbor/harbor/src/common/security" "github.com/goharbor/harbor/src/common/security"
@ -25,10 +25,21 @@ import (
"github.com/goharbor/harbor/src/core/config" "github.com/goharbor/harbor/src/core/config"
"github.com/goharbor/harbor/src/core/filter" "github.com/goharbor/harbor/src/core/filter"
"github.com/goharbor/harbor/src/core/promgr" "github.com/goharbor/harbor/src/core/promgr"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/repository"
) )
const ( const (
yamlFileContentType = "application/x-yaml" yamlFileContentType = "application/x-yaml"
// ReplicationJobType ...
ReplicationJobType = "replication"
// ScanJobType ...
ScanJobType = "scan"
)
var (
projectMgr project.Manager
repositoryMgr repository.Manager
) )
// BaseController ... // BaseController ...
@ -41,13 +52,6 @@ type BaseController struct {
ProjectMgr promgr.ProjectManager ProjectMgr promgr.ProjectManager
} }
const (
// ReplicationJobType ...
ReplicationJobType = "replication"
// ScanJobType ...
ScanJobType = "scan"
)
// Prepare inits security context and project manager from request // Prepare inits security context and project manager from request
// context // context
func (b *BaseController) Prepare() { func (b *BaseController) Prepare() {
@ -91,6 +95,22 @@ func (b *BaseController) WriteYamlData(object interface{}) {
// Init related objects/configurations for the API controllers // Init related objects/configurations for the API controllers
func Init() error { func Init() error {
registerHealthCheckers() registerHealthCheckers()
// init chart controller
if err := initChartController(); err != nil {
return err
}
// init project manager
initProjectManager()
// init repository manager
initRepositoryManager()
return nil
}
func initChartController() error {
// If chart repository is not enabled then directly return // If chart repository is not enabled then directly return
if !config.WithChartMuseum() { if !config.WithChartMuseum() {
return nil return nil
@ -102,6 +122,13 @@ func Init() error {
} }
chartController = chartCtl chartController = chartCtl
return nil return nil
} }
func initProjectManager() {
projectMgr = project.New()
}
func initRepositoryManager() {
repositoryMgr = repository.New(projectMgr, chartController)
}

View File

@ -28,7 +28,7 @@ import (
var ( var (
resourceLabelAPIBasePath = "/api/repositories" resourceLabelAPIBasePath = "/api/repositories"
repository = "library/hello-world" repo = "library/hello-world"
tag = "latest" tag = "latest"
proLibraryLabelID int64 proLibraryLabelID int64
) )
@ -63,7 +63,7 @@ func TestAddToImage(t *testing.T) {
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath,
repository, tag), repo, tag),
method: http.MethodPost, method: http.MethodPost,
}, },
code: http.StatusUnauthorized, code: http.StatusUnauthorized,
@ -72,13 +72,13 @@ func TestAddToImage(t *testing.T) {
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath,
repository, tag), repo, tag),
method: http.MethodPost, method: http.MethodPost,
credential: projGuest, credential: projGuest,
}, },
code: http.StatusForbidden, code: http.StatusForbidden,
}, },
// 404 repository doesn't exist // 404 repo doesn't exist
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/library/non-exist-repo/tags/%s/labels", resourceLabelAPIBasePath, tag), url: fmt.Sprintf("%s/library/non-exist-repo/tags/%s/labels", resourceLabelAPIBasePath, tag),
@ -90,7 +90,7 @@ func TestAddToImage(t *testing.T) {
// 404 image doesn't exist // 404 image doesn't exist
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/non-exist-tag/labels", resourceLabelAPIBasePath, repository), url: fmt.Sprintf("%s/%s/tags/non-exist-tag/labels", resourceLabelAPIBasePath, repo),
method: http.MethodPost, method: http.MethodPost,
credential: projDeveloper, credential: projDeveloper,
}, },
@ -99,7 +99,7 @@ func TestAddToImage(t *testing.T) {
// 400 // 400
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, repository, tag), url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, repo, tag),
method: http.MethodPost, method: http.MethodPost,
credential: projDeveloper, credential: projDeveloper,
}, },
@ -109,7 +109,7 @@ func TestAddToImage(t *testing.T) {
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath,
repository, tag), repo, tag),
method: http.MethodPost, method: http.MethodPost,
credential: projDeveloper, credential: projDeveloper,
bodyJSON: struct { bodyJSON: struct {
@ -124,7 +124,7 @@ func TestAddToImage(t *testing.T) {
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath,
repository, tag), repo, tag),
method: http.MethodPost, method: http.MethodPost,
credential: projDeveloper, credential: projDeveloper,
bodyJSON: struct { bodyJSON: struct {
@ -139,7 +139,7 @@ func TestAddToImage(t *testing.T) {
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath,
repository, tag), repo, tag),
method: http.MethodPost, method: http.MethodPost,
credential: projDeveloper, credential: projDeveloper,
bodyJSON: struct { bodyJSON: struct {
@ -154,7 +154,7 @@ func TestAddToImage(t *testing.T) {
{ {
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath,
repository, tag), repo, tag),
method: http.MethodPost, method: http.MethodPost,
credential: projDeveloper, credential: projDeveloper,
bodyJSON: struct { bodyJSON: struct {
@ -172,7 +172,7 @@ func TestAddToImage(t *testing.T) {
func TestGetOfImage(t *testing.T) { func TestGetOfImage(t *testing.T) {
labels := []*models.Label{} labels := []*models.Label{}
err := handleAndParse(&testingRequest{ err := handleAndParse(&testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, repository, tag), url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, repo, tag),
method: http.MethodGet, method: http.MethodGet,
credential: projDeveloper, credential: projDeveloper,
}, &labels) }, &labels)
@ -185,7 +185,7 @@ func TestRemoveFromImage(t *testing.T) {
runCodeCheckingCases(t, &codeCheckingCase{ runCodeCheckingCases(t, &codeCheckingCase{
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels/%d", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/tags/%s/labels/%d", resourceLabelAPIBasePath,
repository, tag, proLibraryLabelID), repo, tag, proLibraryLabelID),
method: http.MethodDelete, method: http.MethodDelete,
credential: projDeveloper, credential: projDeveloper,
}, },
@ -195,7 +195,7 @@ func TestRemoveFromImage(t *testing.T) {
labels := []*models.Label{} labels := []*models.Label{}
err := handleAndParse(&testingRequest{ err := handleAndParse(&testingRequest{
url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/tags/%s/labels", resourceLabelAPIBasePath,
repository, tag), repo, tag),
method: http.MethodGet, method: http.MethodGet,
credential: projDeveloper, credential: projDeveloper,
}, &labels) }, &labels)
@ -206,7 +206,7 @@ func TestRemoveFromImage(t *testing.T) {
func TestAddToRepository(t *testing.T) { func TestAddToRepository(t *testing.T) {
runCodeCheckingCases(t, &codeCheckingCase{ runCodeCheckingCases(t, &codeCheckingCase{
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/labels", resourceLabelAPIBasePath, repository), url: fmt.Sprintf("%s/%s/labels", resourceLabelAPIBasePath, repo),
method: http.MethodPost, method: http.MethodPost,
bodyJSON: struct { bodyJSON: struct {
ID int64 ID int64
@ -222,7 +222,7 @@ func TestAddToRepository(t *testing.T) {
func TestGetOfRepository(t *testing.T) { func TestGetOfRepository(t *testing.T) {
labels := []*models.Label{} labels := []*models.Label{}
err := handleAndParse(&testingRequest{ err := handleAndParse(&testingRequest{
url: fmt.Sprintf("%s/%s/labels", resourceLabelAPIBasePath, repository), url: fmt.Sprintf("%s/%s/labels", resourceLabelAPIBasePath, repo),
method: http.MethodGet, method: http.MethodGet,
credential: projDeveloper, credential: projDeveloper,
}, &labels) }, &labels)
@ -235,7 +235,7 @@ func TestRemoveFromRepository(t *testing.T) {
runCodeCheckingCases(t, &codeCheckingCase{ runCodeCheckingCases(t, &codeCheckingCase{
request: &testingRequest{ request: &testingRequest{
url: fmt.Sprintf("%s/%s/labels/%d", resourceLabelAPIBasePath, url: fmt.Sprintf("%s/%s/labels/%d", resourceLabelAPIBasePath,
repository, proLibraryLabelID), repo, proLibraryLabelID),
method: http.MethodDelete, method: http.MethodDelete,
credential: projDeveloper, credential: projDeveloper,
}, },
@ -244,7 +244,7 @@ func TestRemoveFromRepository(t *testing.T) {
labels := []*models.Label{} labels := []*models.Label{}
err := handleAndParse(&testingRequest{ err := handleAndParse(&testingRequest{
url: fmt.Sprintf("%s/%s/labels", resourceLabelAPIBasePath, repository), url: fmt.Sprintf("%s/%s/labels", resourceLabelAPIBasePath, repo),
method: http.MethodGet, method: http.MethodGet,
credential: projDeveloper, credential: projDeveloper,
}, &labels) }, &labels)

View File

@ -21,11 +21,6 @@ import (
"github.com/goharbor/harbor/src/common/models" "github.com/goharbor/harbor/src/common/models"
) )
var (
// Mgr is an instance of the default project Manager
Mgr = New()
)
// Manager is used for project management // Manager is used for project management
// currently, the interface only defines the methods needed for tag retention // currently, the interface only defines the methods needed for tag retention
// will expand it when doing refactor // will expand it when doing refactor

View File

@ -18,15 +18,9 @@ import (
"github.com/goharbor/harbor/src/chartserver" "github.com/goharbor/harbor/src/chartserver"
"github.com/goharbor/harbor/src/common/dao" "github.com/goharbor/harbor/src/common/dao"
"github.com/goharbor/harbor/src/common/models" "github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/core/api"
"github.com/goharbor/harbor/src/pkg/project" "github.com/goharbor/harbor/src/pkg/project"
) )
var (
// Mgr is an instance of the default repository Manager
Mgr = New()
)
// Manager is used for repository management // Manager is used for repository management
// currently, the interface only defines the methods needed for tag retention // currently, the interface only defines the methods needed for tag retention
// will expand it when doing refactor // will expand it when doing refactor
@ -38,11 +32,17 @@ type Manager interface {
} }
// New returns a default implementation of Manager // New returns a default implementation of Manager
func New() Manager { func New(projectMgr project.Manager, chartCtl *chartserver.Controller) Manager {
return &manager{} return &manager{
projectMgr: projectMgr,
chartCtl: chartCtl,
}
} }
type manager struct{} type manager struct {
projectMgr project.Manager
chartCtl *chartserver.Controller
}
// List image repositories under the project specified by the ID // List image repositories under the project specified by the ID
func (m *manager) ListImageRepositories(projectID int64) ([]*models.RepoRecord, error) { func (m *manager) ListImageRepositories(projectID int64) ([]*models.RepoRecord, error) {
@ -53,9 +53,9 @@ func (m *manager) ListImageRepositories(projectID int64) ([]*models.RepoRecord,
// List chart repositories under the project specified by the ID // List chart repositories under the project specified by the ID
func (m *manager) ListChartRepositories(projectID int64) ([]*chartserver.ChartInfo, error) { func (m *manager) ListChartRepositories(projectID int64) ([]*chartserver.ChartInfo, error) {
project, err := project.Mgr.Get(projectID) project, err := m.projectMgr.Get(projectID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return api.GetChartController().ListCharts(project.Name) return m.chartCtl.ListCharts(project.Name)
} }

View File

@ -27,12 +27,6 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// TODO init the client
var (
client Client
mgr Manager
)
// Launcher provides function to launch the async jobs to run retentions based on the provided policy. // Launcher provides function to launch the async jobs to run retentions based on the provided policy.
type Launcher interface { type Launcher interface {
// Launch async jobs for the retention policy // Launch async jobs for the retention policy
@ -49,11 +43,21 @@ type Launcher interface {
} }
// NewLauncher returns an instance of Launcher // NewLauncher returns an instance of Launcher
func NewLauncher() Launcher { func NewLauncher(projectMgr project.Manager, repositoryMgr repository.Manager,
return &launcher{} retentionMgr Manager, retentionClient Client) Launcher {
return &launcher{
projectMgr: projectMgr,
repositoryMgr: repositoryMgr,
retentionMgr: retentionMgr,
retentionClient: retentionClient,
}
} }
type launcher struct { type launcher struct {
retentionMgr Manager
retentionClient Client
projectMgr project.Manager
repositoryMgr repository.Manager
} }
type jobData struct { type jobData struct {
@ -81,7 +85,7 @@ func (l *launcher) Launch(ply *policy.Metadata, executionID int64) (int64, error
var err error var err error
if level == "system" { if level == "system" {
// get projects // get projects
projectCandidates, err = getProjects() projectCandidates, err = getProjects(l.projectMgr)
if err != nil { if err != nil {
return 0, launcherError(err) return 0, launcherError(err)
} }
@ -111,7 +115,7 @@ func (l *launcher) Launch(ply *policy.Metadata, executionID int64) (int64, error
var repositoryCandidates []*res.Candidate var repositoryCandidates []*res.Candidate
// get repositories of projects // get repositories of projects
for _, projectCandidate := range projectCandidates { for _, projectCandidate := range projectCandidates {
repositories, err := getRepositories(projectCandidate.NamespaceID) repositories, err := getRepositories(l.projectMgr, l.repositoryMgr, projectCandidate.NamespaceID)
if err != nil { if err != nil {
return 0, launcherError(err) return 0, launcherError(err)
} }
@ -152,7 +156,7 @@ func (l *launcher) Launch(ply *policy.Metadata, executionID int64) (int64, error
// create task records // create task records
jobDatas := []*jobData{} jobDatas := []*jobData{}
for repository, policy := range repositoryRules { for repository, policy := range repositoryRules {
taskID, err := mgr.CreateTask(&Task{ taskID, err := l.retentionMgr.CreateTask(&Task{
ExecutionID: executionID, ExecutionID: executionID,
}) })
if err != nil { if err != nil {
@ -167,7 +171,7 @@ func (l *launcher) Launch(ply *policy.Metadata, executionID int64) (int64, error
allFailed := true allFailed := true
for _, jobData := range jobDatas { for _, jobData := range jobDatas {
_, err := client.SubmitTask(jobData.taskID, jobData.repository, jobData.policy) _, err := l.retentionClient.SubmitTask(jobData.taskID, jobData.repository, jobData.policy)
if err != nil { if err != nil {
log.Error(launcherError(fmt.Errorf("failed to submit task %d: %v", jobData.taskID, err))) log.Error(launcherError(fmt.Errorf("failed to submit task %d: %v", jobData.taskID, err)))
continue continue
@ -184,8 +188,8 @@ func launcherError(err error) error {
return errors.Wrap(err, "launcher") return errors.Wrap(err, "launcher")
} }
func getProjects() ([]*res.Candidate, error) { func getProjects(projectMgr project.Manager) ([]*res.Candidate, error) {
projects, err := project.Mgr.List() projects, err := projectMgr.List()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -199,14 +203,14 @@ func getProjects() ([]*res.Candidate, error) {
return candidates, nil return candidates, nil
} }
func getRepositories(projectID int64) ([]*res.Candidate, error) { func getRepositories(projectMgr project.Manager, repositoryMgr repository.Manager, projectID int64) ([]*res.Candidate, error) {
var candidates []*res.Candidate var candidates []*res.Candidate
project, err := project.Mgr.Get(projectID) project, err := projectMgr.Get(projectID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// get image repositories // get image repositories
imageRepositories, err := repository.Mgr.ListImageRepositories(projectID) imageRepositories, err := repositoryMgr.ListImageRepositories(projectID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -219,7 +223,7 @@ func getRepositories(projectID int64) ([]*res.Candidate, error) {
}) })
} }
// get chart repositories // get chart repositories
chartRepositories, err := repository.Mgr.ListChartRepositories(projectID) chartRepositories, err := repositoryMgr.ListChartRepositories(projectID)
for _, repository := range chartRepositories { for _, repository := range chartRepositories {
candidates = append(candidates, &res.Candidate{ candidates = append(candidates, &res.Candidate{
Namespace: project.Name, Namespace: project.Name,

View File

@ -137,6 +137,10 @@ func (f *fakeRetentionManager) ListHistories(executionID int64, query *q.Query)
type launchTestSuite struct { type launchTestSuite struct {
suite.Suite suite.Suite
projectMgr project.Manager
repositoryMgr repository.Manager
retentionMgr Manager
retentionClient Client
} }
func (l *launchTestSuite) SetupTest() { func (l *launchTestSuite) SetupTest() {
@ -144,11 +148,11 @@ func (l *launchTestSuite) SetupTest() {
ProjectID: 1, ProjectID: 1,
Name: "library", Name: "library",
} }
project.Mgr = &fakeProjectManager{ l.projectMgr = &fakeProjectManager{
projects: []*models.Project{ projects: []*models.Project{
pro, pro,
}} }}
repository.Mgr = &fakeRepositoryManager{ l.repositoryMgr = &fakeRepositoryManager{
imageRepositories: []*models.RepoRecord{ imageRepositories: []*models.RepoRecord{
{ {
Name: "library/image", Name: "library/image",
@ -160,12 +164,12 @@ func (l *launchTestSuite) SetupTest() {
}, },
}, },
} }
client = &fakeClient{} l.retentionMgr = &fakeRetentionManager{}
mgr = &fakeRetentionManager{} l.retentionClient = &fakeClient{}
} }
func (l *launchTestSuite) TestGetProjects() { func (l *launchTestSuite) TestGetProjects() {
projects, err := getProjects() projects, err := getProjects(l.projectMgr)
require.Nil(l.T(), err) require.Nil(l.T(), err)
assert.Equal(l.T(), 1, len(projects)) assert.Equal(l.T(), 1, len(projects))
assert.Equal(l.T(), int64(1), projects[0].NamespaceID) assert.Equal(l.T(), int64(1), projects[0].NamespaceID)
@ -173,7 +177,7 @@ func (l *launchTestSuite) TestGetProjects() {
} }
func (l *launchTestSuite) TestGetRepositories() { func (l *launchTestSuite) TestGetRepositories() {
repositories, err := getRepositories(1) repositories, err := getRepositories(l.projectMgr, l.repositoryMgr, 1)
require.Nil(l.T(), err) require.Nil(l.T(), err)
assert.Equal(l.T(), 2, len(repositories)) assert.Equal(l.T(), 2, len(repositories))
assert.Equal(l.T(), "library", repositories[0].Namespace) assert.Equal(l.T(), "library", repositories[0].Namespace)
@ -185,7 +189,7 @@ func (l *launchTestSuite) TestGetRepositories() {
} }
func (l *launchTestSuite) TestLaunch() { func (l *launchTestSuite) TestLaunch() {
launcher := NewLauncher() launcher := NewLauncher(l.projectMgr, l.repositoryMgr, l.retentionMgr, l.retentionClient)
var ply *policy.Metadata var ply *policy.Metadata
// nil policy // nil policy
n, err := launcher.Launch(ply, 1) n, err := launcher.Launch(ply, 1)