mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-17 07:45:24 +01:00
a11a70d941
The logger is the fundamental library, so move it into lib folder Signed-off-by: wang yan <wangyan@vmware.com>
259 lines
6.9 KiB
Go
259 lines
6.9 KiB
Go
// Copyright 2018 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 promgr
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/goharbor/harbor/src/pkg/scan/whitelist"
|
|
"strconv"
|
|
|
|
"github.com/goharbor/harbor/src/common/models"
|
|
"github.com/goharbor/harbor/src/core/promgr/metamgr"
|
|
"github.com/goharbor/harbor/src/core/promgr/pmsdriver"
|
|
"github.com/goharbor/harbor/src/lib/log"
|
|
)
|
|
|
|
// ProjectManager is the project manager which abstracts the operations related
|
|
// to projects
|
|
type ProjectManager interface {
|
|
Get(projectIDOrName interface{}) (*models.Project, error)
|
|
Create(*models.Project) (int64, error)
|
|
Delete(projectIDOrName interface{}) error
|
|
Update(projectIDOrName interface{}, project *models.Project) error
|
|
List(query *models.ProjectQueryParam) (*models.ProjectQueryResult, error)
|
|
IsPublic(projectIDOrName interface{}) (bool, error)
|
|
Exists(projectIDOrName interface{}) (bool, error)
|
|
// get all public project
|
|
GetPublic() ([]*models.Project, error)
|
|
// if the project manager uses a metadata manager, return it, otherwise return nil
|
|
GetMetadataManager() metamgr.ProjectMetadataManager
|
|
}
|
|
|
|
type defaultProjectManager struct {
|
|
pmsDriver pmsdriver.PMSDriver
|
|
metaMgrEnabled bool // if metaMgrEnabled is enabled, metaMgr will be used to CURD metadata
|
|
metaMgr metamgr.ProjectMetadataManager
|
|
whitelistMgr whitelist.Manager
|
|
}
|
|
|
|
// NewDefaultProjectManager returns an instance of defaultProjectManager,
|
|
// if metaMgrEnabled is true, a project metadata manager will be created
|
|
// and used to CURD metadata
|
|
func NewDefaultProjectManager(driver pmsdriver.PMSDriver, metaMgrEnabled bool) ProjectManager {
|
|
mgr := &defaultProjectManager{
|
|
pmsDriver: driver,
|
|
metaMgrEnabled: metaMgrEnabled,
|
|
}
|
|
if metaMgrEnabled {
|
|
mgr.metaMgr = metamgr.NewDefaultProjectMetadataManager()
|
|
mgr.whitelistMgr = whitelist.NewDefaultManager()
|
|
}
|
|
return mgr
|
|
}
|
|
|
|
func (d *defaultProjectManager) Get(projectIDOrName interface{}) (*models.Project, error) {
|
|
project, err := d.pmsDriver.Get(projectIDOrName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if project != nil && d.metaMgrEnabled {
|
|
meta, err := d.metaMgr.Get(project.ProjectID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(project.Metadata) == 0 {
|
|
project.Metadata = make(map[string]string)
|
|
}
|
|
for k, v := range meta {
|
|
project.Metadata[k] = v
|
|
}
|
|
wl, err := d.whitelistMgr.Get(project.ProjectID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
project.CVEWhitelist = *wl
|
|
}
|
|
return project, nil
|
|
}
|
|
func (d *defaultProjectManager) Create(project *models.Project) (int64, error) {
|
|
id, err := d.pmsDriver.Create(project)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if d.metaMgrEnabled {
|
|
d.whitelistMgr.CreateEmpty(id)
|
|
if len(project.Metadata) > 0 {
|
|
if err = d.metaMgr.Add(id, project.Metadata); err != nil {
|
|
log.Errorf("failed to add metadata for project %s: %v", project.Name, err)
|
|
}
|
|
}
|
|
}
|
|
return id, nil
|
|
}
|
|
|
|
func (d *defaultProjectManager) Delete(projectIDOrName interface{}) error {
|
|
project, err := d.Get(projectIDOrName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if project == nil {
|
|
return nil
|
|
}
|
|
if project.Metadata != nil && d.metaMgrEnabled {
|
|
if err = d.metaMgr.Delete(project.ProjectID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return d.pmsDriver.Delete(project.ProjectID)
|
|
}
|
|
|
|
func (d *defaultProjectManager) Update(projectIDOrName interface{}, project *models.Project) error {
|
|
pro, err := d.Get(projectIDOrName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if pro == nil {
|
|
return fmt.Errorf("project %v not found", projectIDOrName)
|
|
}
|
|
// TODO transaction?
|
|
if d.metaMgrEnabled {
|
|
if err := d.whitelistMgr.Set(pro.ProjectID, project.CVEWhitelist); err != nil {
|
|
return err
|
|
}
|
|
if len(project.Metadata) > 0 {
|
|
metaNeedUpdated := map[string]string{}
|
|
metaNeedCreated := map[string]string{}
|
|
if pro.Metadata == nil {
|
|
pro.Metadata = map[string]string{}
|
|
}
|
|
for key, value := range project.Metadata {
|
|
_, exist := pro.Metadata[key]
|
|
if exist {
|
|
metaNeedUpdated[key] = value
|
|
} else {
|
|
metaNeedCreated[key] = value
|
|
}
|
|
}
|
|
if err = d.metaMgr.Add(pro.ProjectID, metaNeedCreated); err != nil {
|
|
return err
|
|
}
|
|
if err = d.metaMgr.Update(pro.ProjectID, metaNeedUpdated); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return d.pmsDriver.Update(projectIDOrName, project)
|
|
}
|
|
|
|
func (d *defaultProjectManager) List(query *models.ProjectQueryParam) (*models.ProjectQueryResult, error) {
|
|
// query by public/private property with ProjectMetadataManager first
|
|
if d.metaMgrEnabled && query != nil && query.Public != nil {
|
|
projectIDs, err := d.filterByPublic(*query.Public)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(projectIDs) == 0 {
|
|
return &models.ProjectQueryResult{}, nil
|
|
}
|
|
|
|
if query.ProjectIDs == nil {
|
|
query.ProjectIDs = projectIDs
|
|
} else {
|
|
query.ProjectIDs = findInBoth(query.ProjectIDs, projectIDs)
|
|
}
|
|
}
|
|
|
|
// query by other properties
|
|
result, err := d.pmsDriver.List(query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// populate metadata
|
|
if d.metaMgrEnabled {
|
|
for _, project := range result.Projects {
|
|
meta, err := d.metaMgr.Get(project.ProjectID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
project.Metadata = meta
|
|
}
|
|
}
|
|
// the whitelist is not populated deliberately
|
|
return result, nil
|
|
}
|
|
|
|
func (d *defaultProjectManager) filterByPublic(public bool) ([]int64, error) {
|
|
metas, err := d.metaMgr.List(models.ProMetaPublic, strconv.FormatBool(public))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
projectIDs := []int64{}
|
|
for _, meta := range metas {
|
|
projectIDs = append(projectIDs, meta.ProjectID)
|
|
}
|
|
return projectIDs, nil
|
|
}
|
|
|
|
func findInBoth(ids1 []int64, ids2 []int64) []int64 {
|
|
m := map[int64]struct{}{}
|
|
for _, id := range ids1 {
|
|
m[id] = struct{}{}
|
|
}
|
|
|
|
ids := []int64{}
|
|
for _, id := range ids2 {
|
|
if _, exist := m[id]; exist {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
|
|
return ids
|
|
}
|
|
|
|
func (d *defaultProjectManager) IsPublic(projectIDOrName interface{}) (bool, error) {
|
|
project, err := d.Get(projectIDOrName)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if project == nil {
|
|
return false, nil
|
|
}
|
|
return project.IsPublic(), nil
|
|
}
|
|
|
|
func (d *defaultProjectManager) Exists(projectIDOrName interface{}) (bool, error) {
|
|
project, err := d.Get(projectIDOrName)
|
|
return project != nil, err
|
|
}
|
|
|
|
func (d *defaultProjectManager) GetPublic() ([]*models.Project, error) {
|
|
value := true
|
|
result, err := d.List(&models.ProjectQueryParam{
|
|
Public: &value,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return result.Projects, nil
|
|
}
|
|
|
|
func (d *defaultProjectManager) GetMetadataManager() metamgr.ProjectMetadataManager {
|
|
return d.metaMgr
|
|
}
|