mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-25 03:35:21 +01:00
deprecate resource label (#19349)
There is no api is using the DAO, remove it from the source code. Signed-off-by: wang yan <wangyan@vmware.com>
This commit is contained in:
parent
97b285168a
commit
ed370a496b
1
make/migrations/postgresql/0130_2.10.0_schema.up.sql
Normal file
1
make/migrations/postgresql/0130_2.10.0_schema.up.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DROP TABLE IF EXISTS harbor_resource_label;
|
@ -1,130 +0,0 @@
|
|||||||
// 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 dao
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/client/orm"
|
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/common/models"
|
|
||||||
"github.com/goharbor/harbor/src/pkg/label/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddResourceLabel add a label to a resource
|
|
||||||
func AddResourceLabel(rl *models.ResourceLabel) (int64, error) {
|
|
||||||
now := time.Now()
|
|
||||||
rl.CreationTime = now
|
|
||||||
rl.UpdateTime = now
|
|
||||||
return GetOrmer().Insert(rl)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResourceLabel specified by resource ID or name
|
|
||||||
// Get the ResourceLabel by ResourceID if rIDOrName is int
|
|
||||||
// Get the ResourceLabel by ResourceName if rIDOrName is string
|
|
||||||
func GetResourceLabel(rType string, rIDOrName interface{}, labelID int64) (*models.ResourceLabel, error) {
|
|
||||||
rl := &models.ResourceLabel{
|
|
||||||
ResourceType: rType,
|
|
||||||
LabelID: labelID,
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
id, ok := rIDOrName.(int64)
|
|
||||||
if ok {
|
|
||||||
rl.ResourceID = id
|
|
||||||
err = GetOrmer().Read(rl, "ResourceType", "ResourceID", "LabelID")
|
|
||||||
} else {
|
|
||||||
rl.ResourceName = rIDOrName.(string)
|
|
||||||
err = GetOrmer().Read(rl, "ResourceType", "ResourceName", "LabelID")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if err == orm.ErrNoRows {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return rl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLabelsOfResource returns the label list of the resource
|
|
||||||
// Get the labels by ResourceID if rIDOrName is int, or get the labels by ResourceName
|
|
||||||
func GetLabelsOfResource(rType string, rIDOrName interface{}) ([]*model.Label, error) {
|
|
||||||
sql := `select l.id, l.name, l.description, l.color, l.scope, l.project_id, l.creation_time, l.update_time
|
|
||||||
from harbor_resource_label rl
|
|
||||||
join harbor_label l on rl.label_id=l.id
|
|
||||||
where rl.resource_type = ? and`
|
|
||||||
if _, ok := rIDOrName.(int64); ok {
|
|
||||||
sql += ` rl.resource_id = ?`
|
|
||||||
} else {
|
|
||||||
sql += ` rl.resource_name = ?`
|
|
||||||
}
|
|
||||||
|
|
||||||
labels := []*model.Label{}
|
|
||||||
_, err := GetOrmer().Raw(sql, rType, rIDOrName).QueryRows(&labels)
|
|
||||||
return labels, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResourceLabel ...
|
|
||||||
func DeleteResourceLabel(id int64) error {
|
|
||||||
_, err := GetOrmer().Delete(&models.ResourceLabel{
|
|
||||||
ID: id,
|
|
||||||
})
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteLabelsOfResource removes all labels of the resource
|
|
||||||
func DeleteLabelsOfResource(rType string, rIDOrName interface{}) error {
|
|
||||||
qs := GetOrmer().QueryTable(&models.ResourceLabel{}).
|
|
||||||
Filter("ResourceType", rType)
|
|
||||||
if _, ok := rIDOrName.(int64); ok {
|
|
||||||
qs = qs.Filter("ResourceID", rIDOrName)
|
|
||||||
} else {
|
|
||||||
qs = qs.Filter("ResourceName", rIDOrName)
|
|
||||||
}
|
|
||||||
_, err := qs.Delete()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListResourceLabels lists ResourceLabel according to the query conditions
|
|
||||||
func ListResourceLabels(query ...*models.ResourceLabelQuery) ([]*models.ResourceLabel, error) {
|
|
||||||
qs := GetOrmer().QueryTable(&models.ResourceLabel{})
|
|
||||||
if len(query) > 0 {
|
|
||||||
q := query[0]
|
|
||||||
if q.LabelID > 0 {
|
|
||||||
qs = qs.Filter("LabelID", q.LabelID)
|
|
||||||
}
|
|
||||||
if len(q.ResourceType) > 0 {
|
|
||||||
qs = qs.Filter("ResourceType", q.ResourceType)
|
|
||||||
}
|
|
||||||
if q.ResourceID > 0 {
|
|
||||||
qs = qs.Filter("ResourceID", q.ResourceID)
|
|
||||||
}
|
|
||||||
if len(q.ResourceName) > 0 {
|
|
||||||
qs = qs.Filter("ResourceName", q.ResourceName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rls := []*models.ResourceLabel{}
|
|
||||||
_, err := qs.All(&rls)
|
|
||||||
return rls, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResourceLabelByLabel delete the mapping relationship by label ID
|
|
||||||
func DeleteResourceLabelByLabel(id int64) error {
|
|
||||||
_, err := GetOrmer().QueryTable(&models.ResourceLabel{}).Filter("LabelID", id).Delete()
|
|
||||||
return err
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
// 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 dao
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/common"
|
|
||||||
"github.com/goharbor/harbor/src/common/models"
|
|
||||||
"github.com/goharbor/harbor/src/lib/orm"
|
|
||||||
"github.com/goharbor/harbor/src/pkg/label/dao"
|
|
||||||
"github.com/goharbor/harbor/src/pkg/label/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMethodsOfResourceLabel(t *testing.T) {
|
|
||||||
labelDao := dao.New()
|
|
||||||
labelID, err := labelDao.Create(orm.Context(), &model.Label{
|
|
||||||
Name: "test_label",
|
|
||||||
Level: common.LabelLevelUser,
|
|
||||||
Scope: common.LabelScopeGlobal,
|
|
||||||
})
|
|
||||||
require.Nil(t, err)
|
|
||||||
defer labelDao.Delete(orm.Context(), labelID)
|
|
||||||
|
|
||||||
var resourceID int64 = 1
|
|
||||||
resourceType := common.ResourceTypeRepository
|
|
||||||
|
|
||||||
// add
|
|
||||||
rl := &models.ResourceLabel{
|
|
||||||
LabelID: labelID,
|
|
||||||
ResourceType: resourceType,
|
|
||||||
ResourceID: resourceID,
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := AddResourceLabel(rl)
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
// get
|
|
||||||
r, err := GetResourceLabel(resourceType, resourceID, labelID)
|
|
||||||
require.Nil(t, err)
|
|
||||||
assert.Equal(t, id, r.ID)
|
|
||||||
|
|
||||||
// get by resource
|
|
||||||
labels, err := GetLabelsOfResource(resourceType, resourceID)
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Equal(t, 1, len(labels))
|
|
||||||
assert.Equal(t, id, r.ID)
|
|
||||||
|
|
||||||
// list
|
|
||||||
rls, err := ListResourceLabels(&models.ResourceLabelQuery{
|
|
||||||
LabelID: labelID,
|
|
||||||
ResourceType: resourceType,
|
|
||||||
ResourceID: resourceID,
|
|
||||||
})
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Equal(t, 1, len(rls))
|
|
||||||
assert.Equal(t, id, rls[0].ID)
|
|
||||||
|
|
||||||
// delete
|
|
||||||
err = DeleteResourceLabel(id)
|
|
||||||
require.Nil(t, err)
|
|
||||||
labels, err = GetLabelsOfResource(resourceType, resourceID)
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Equal(t, 0, len(labels))
|
|
||||||
|
|
||||||
// delete by resource
|
|
||||||
id, err = AddResourceLabel(rl)
|
|
||||||
require.Nil(t, err)
|
|
||||||
err = DeleteLabelsOfResource(resourceType, resourceID)
|
|
||||||
require.Nil(t, err)
|
|
||||||
labels, err = GetLabelsOfResource(resourceType, resourceID)
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Equal(t, 0, len(labels))
|
|
||||||
|
|
||||||
// delete by label ID
|
|
||||||
id, err = AddResourceLabel(rl)
|
|
||||||
require.Nil(t, err)
|
|
||||||
err = DeleteResourceLabelByLabel(labelID)
|
|
||||||
require.Nil(t, err)
|
|
||||||
rls, err = ListResourceLabels(&models.ResourceLabelQuery{
|
|
||||||
LabelID: labelID,
|
|
||||||
})
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Equal(t, 0, len(rls))
|
|
||||||
}
|
|
@ -21,7 +21,6 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
orm.RegisterModel(
|
orm.RegisterModel(
|
||||||
new(Role),
|
new(Role),
|
||||||
new(ResourceLabel),
|
|
||||||
new(OIDCUser),
|
new(OIDCUser),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
// 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 models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ResourceLabel records the relationship between resource and label
|
|
||||||
type ResourceLabel struct {
|
|
||||||
ID int64 `orm:"pk;auto;column(id)"`
|
|
||||||
LabelID int64 `orm:"column(label_id)"`
|
|
||||||
ResourceID int64 `orm:"column(resource_id)"`
|
|
||||||
ResourceName string `orm:"column(resource_name)"`
|
|
||||||
ResourceType string `orm:"column(resource_type)"`
|
|
||||||
CreationTime time.Time `orm:"column(creation_time);auto_now_add"`
|
|
||||||
UpdateTime time.Time `orm:"column(update_time);auto_now"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName ...
|
|
||||||
func (r *ResourceLabel) TableName() string {
|
|
||||||
return "harbor_resource_label"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResourceLabelQuery : query parameters for the mapping relationships of resource and label
|
|
||||||
type ResourceLabelQuery struct {
|
|
||||||
LabelID int64
|
|
||||||
ResourceID int64
|
|
||||||
ResourceName string
|
|
||||||
ResourceType string
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
// 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 models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/pkg/label/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestValidOfLabel(t *testing.T) {
|
|
||||||
cases := []struct {
|
|
||||||
label *model.Label
|
|
||||||
hasError bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
label: &model.Label{
|
|
||||||
Name: "",
|
|
||||||
},
|
|
||||||
hasError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: &model.Label{
|
|
||||||
Name: "test",
|
|
||||||
Scope: "",
|
|
||||||
},
|
|
||||||
hasError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: &model.Label{
|
|
||||||
Name: "test",
|
|
||||||
Scope: "invalid_scope",
|
|
||||||
},
|
|
||||||
hasError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: &model.Label{
|
|
||||||
Name: "test",
|
|
||||||
Scope: "g",
|
|
||||||
},
|
|
||||||
hasError: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: &model.Label{
|
|
||||||
Name: "test",
|
|
||||||
Scope: "p",
|
|
||||||
},
|
|
||||||
hasError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: &model.Label{
|
|
||||||
Name: "test",
|
|
||||||
Scope: "p",
|
|
||||||
ProjectID: -1,
|
|
||||||
},
|
|
||||||
hasError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: &model.Label{
|
|
||||||
Name: "test",
|
|
||||||
Scope: "p",
|
|
||||||
ProjectID: 1,
|
|
||||||
},
|
|
||||||
hasError: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range cases {
|
|
||||||
err := c.label.Valid()
|
|
||||||
if c.hasError {
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
} else {
|
|
||||||
assert.Nil(t, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
// 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 api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/common/models"
|
|
||||||
"github.com/goharbor/harbor/src/core/label"
|
|
||||||
"github.com/goharbor/harbor/src/lib/log"
|
|
||||||
pkg_label "github.com/goharbor/harbor/src/pkg/label"
|
|
||||||
"github.com/goharbor/harbor/src/pkg/label/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LabelResourceAPI provides the related basic functions to handle marking labels to resources
|
|
||||||
type LabelResourceAPI struct {
|
|
||||||
BaseController
|
|
||||||
labelManager label.Manager
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare resources for follow-up actions.
|
|
||||||
func (lra *LabelResourceAPI) Prepare() {
|
|
||||||
lra.BaseController.Prepare()
|
|
||||||
|
|
||||||
// Create label manager
|
|
||||||
lra.labelManager = &label.BaseManager{
|
|
||||||
LabelMgr: pkg_label.Mgr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lra *LabelResourceAPI) getLabelsOfResource(rType string, rIDOrName interface{}) {
|
|
||||||
labels, err := lra.labelManager.GetLabelsOfResource(rType, rIDOrName)
|
|
||||||
if err != nil {
|
|
||||||
lra.handleErrors(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
lra.Data["json"] = labels
|
|
||||||
if err := lra.ServeJSON(); err != nil {
|
|
||||||
log.Errorf("failed to serve json, %v", err)
|
|
||||||
lra.handleErrors(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lra *LabelResourceAPI) markLabelToResource(rl *models.ResourceLabel) {
|
|
||||||
labelID, err := lra.labelManager.MarkLabelToResource(rl)
|
|
||||||
if err != nil {
|
|
||||||
lra.handleErrors(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the ID of label and return status code 200 rather than 201 as the label is not created
|
|
||||||
lra.Redirect(http.StatusOK, strconv.FormatInt(labelID, 10))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lra *LabelResourceAPI) removeLabelFromResource(rType string, rIDOrName interface{}, labelID int64) {
|
|
||||||
if err := lra.labelManager.RemoveLabelFromResource(rType, rIDOrName, labelID); err != nil {
|
|
||||||
lra.handleErrors(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// eat the error of validate method of label manager
|
|
||||||
func (lra *LabelResourceAPI) validate(labelID, projectID int64) (*model.Label, bool) {
|
|
||||||
label, err := lra.labelManager.Validate(labelID, projectID)
|
|
||||||
if err != nil {
|
|
||||||
lra.handleErrors(err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return label, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// eat the error of exists method of label manager
|
|
||||||
func (lra *LabelResourceAPI) exists(labelID int64) (*model.Label, bool) {
|
|
||||||
label, err := lra.labelManager.Exists(labelID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return label, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle different kinds of errors.
|
|
||||||
func (lra *LabelResourceAPI) handleErrors(err error) {
|
|
||||||
switch err.(type) {
|
|
||||||
case *label.ErrLabelBadRequest:
|
|
||||||
lra.SendBadRequestError(err)
|
|
||||||
case *label.ErrLabelConflict:
|
|
||||||
lra.SendConflictError(err)
|
|
||||||
case *label.ErrLabelNotFound:
|
|
||||||
lra.SendNotFoundError(err)
|
|
||||||
default:
|
|
||||||
lra.SendInternalServerError(err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
// 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 label
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrLabelBase contains the basic required info for building the final errors.
|
|
||||||
type ErrLabelBase struct {
|
|
||||||
LabelID int64
|
|
||||||
ResourceType string
|
|
||||||
ResourceIDOrName interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrLabelNotFound defines the error of not found label on the resource
|
|
||||||
// or the specified label is not found.
|
|
||||||
type ErrLabelNotFound struct {
|
|
||||||
ErrLabelBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrLabelConflict defines the error of label conflicts on the resource.
|
|
||||||
type ErrLabelConflict struct {
|
|
||||||
ErrLabelBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrLabelBadRequest defines the error of bad request to the resource.
|
|
||||||
type ErrLabelBadRequest struct {
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrLabelNotFound builds an error with ErrLabelNotFound type
|
|
||||||
func NewErrLabelNotFound(labelID int64, resourceType string, resourceIDOrName interface{}) *ErrLabelNotFound {
|
|
||||||
return &ErrLabelNotFound{
|
|
||||||
ErrLabelBase{
|
|
||||||
LabelID: labelID,
|
|
||||||
ResourceType: resourceType,
|
|
||||||
ResourceIDOrName: resourceIDOrName,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the error message of ErrLabelNotFound.
|
|
||||||
func (nf *ErrLabelNotFound) Error() string {
|
|
||||||
if len(nf.ResourceType) > 0 && nf.ResourceIDOrName != nil {
|
|
||||||
return fmt.Sprintf("not found: label '%d' on %s '%v'", nf.LabelID, nf.ResourceType, nf.ResourceIDOrName)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("not found: label '%d'", nf.LabelID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrLabelConflict builds an error with NewErrLabelConflict type.
|
|
||||||
func NewErrLabelConflict(labelID int64, resourceType string, resourceIDOrName interface{}) *ErrLabelConflict {
|
|
||||||
return &ErrLabelConflict{
|
|
||||||
ErrLabelBase{
|
|
||||||
LabelID: labelID,
|
|
||||||
ResourceType: resourceType,
|
|
||||||
ResourceIDOrName: resourceIDOrName,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the error message of ErrLabelConflict.
|
|
||||||
func (cl *ErrLabelConflict) Error() string {
|
|
||||||
return fmt.Sprintf("conflict: %s '%v' is already marked with label '%d'", cl.ResourceType, cl.ResourceIDOrName, cl.LabelID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrLabelBadRequest builds an error with ErrLabelBadRequest type.
|
|
||||||
func NewErrLabelBadRequest(message string) *ErrLabelBadRequest {
|
|
||||||
return &ErrLabelBadRequest{
|
|
||||||
Message: message,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the error message of ErrLabelBadRequest.
|
|
||||||
func (br *ErrLabelBadRequest) Error() string {
|
|
||||||
return br.Message
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package label
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Test cases for kinds of error definitions.
|
|
||||||
func TestErrorFormats(t *testing.T) {
|
|
||||||
br := NewErrLabelBadRequest("bad requests")
|
|
||||||
if !checkErrorFormat(br, "bad requests") {
|
|
||||||
t.Fatalf("expect an error with ErrLabelBadRequest kind but got incorrect format '%v'", br)
|
|
||||||
}
|
|
||||||
|
|
||||||
cf := NewErrLabelConflict(1, "c", "repo1/mychart:1.0.0")
|
|
||||||
if !checkErrorFormat(cf, fmt.Sprintf("conflict: %s '%v' is already marked with label '%d'", "c", "repo1/mychart:1.0.0", 1)) {
|
|
||||||
t.Fatalf("expect an error with ErrLabelConflict kind but got incorrect format '%v'", cf)
|
|
||||||
}
|
|
||||||
|
|
||||||
nf := NewErrLabelNotFound(1, "c", "repo1/mychart:1.0.0")
|
|
||||||
if !checkErrorFormat(nf, fmt.Sprintf("not found: label '%d' on %s '%v'", 1, "c", "repo1/mychart:1.0.0")) {
|
|
||||||
t.Fatalf("expect an error with ErrLabelNotFound kind but got incorrect format '%v'", nf)
|
|
||||||
}
|
|
||||||
|
|
||||||
nf2 := NewErrLabelNotFound(1, "", "")
|
|
||||||
if !checkErrorFormat(nf2, fmt.Sprintf("not found: label '%d'", 1)) {
|
|
||||||
t.Fatalf("expect an error with ErrLabelNotFound kind but got incorrect format %v", nf2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkErrorFormat(err error, msg string) bool {
|
|
||||||
return err.Error() == msg
|
|
||||||
}
|
|
@ -1,162 +0,0 @@
|
|||||||
// 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 label
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/common"
|
|
||||||
"github.com/goharbor/harbor/src/common/dao"
|
|
||||||
"github.com/goharbor/harbor/src/common/models"
|
|
||||||
"github.com/goharbor/harbor/src/lib/errors"
|
|
||||||
"github.com/goharbor/harbor/src/lib/orm"
|
|
||||||
"github.com/goharbor/harbor/src/pkg/label"
|
|
||||||
"github.com/goharbor/harbor/src/pkg/label/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Manager defines the related operations for label management
|
|
||||||
type Manager interface {
|
|
||||||
// Mark label to the resource.
|
|
||||||
//
|
|
||||||
// If succeed, the relationship ID will be returned.
|
|
||||||
// Otherwise, an non-nil error will be returned.
|
|
||||||
MarkLabelToResource(label *models.ResourceLabel) (int64, error)
|
|
||||||
|
|
||||||
// Remove the label from the resource.
|
|
||||||
// Resource type and ID(/name) should be provided to identify the relationship.
|
|
||||||
//
|
|
||||||
// An non-nil error will be got if meet any issues or nil error returned.
|
|
||||||
RemoveLabelFromResource(resourceType string, resourceIDOrName interface{}, labelID int64) error
|
|
||||||
|
|
||||||
// Get labels for the specified resource.
|
|
||||||
// Resource is identified by the resource type and ID(/name).
|
|
||||||
//
|
|
||||||
// If succeed, a label list is returned.
|
|
||||||
// Otherwise, a non-nil error will be returned.
|
|
||||||
GetLabelsOfResource(resourceType string, resourceIDOrName interface{}) ([]*model.Label, error)
|
|
||||||
|
|
||||||
// Check the existence of the specified label.
|
|
||||||
//
|
|
||||||
// If label existing, a non-nil label object is returned and nil error is set.
|
|
||||||
// A non-nil error will be set if any issues met while checking or label is not found.
|
|
||||||
Exists(labelID int64) (*model.Label, error)
|
|
||||||
|
|
||||||
// Validate if the scope of the input label is correct.
|
|
||||||
// If the scope is project level, the projectID is required then.
|
|
||||||
//
|
|
||||||
// If everything is ok, an validated label reference will be returned.
|
|
||||||
// Otherwise, a non-nil error is returned.
|
|
||||||
Validate(labelID int64, projectID int64) (*model.Label, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BaseManager is the default implementation of the Manager interface.
|
|
||||||
type BaseManager struct {
|
|
||||||
LabelMgr label.Manager
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarkLabelToResource is the implementation of same method in Manager interface.
|
|
||||||
func (bm *BaseManager) MarkLabelToResource(label *models.ResourceLabel) (int64, error) {
|
|
||||||
if label == nil {
|
|
||||||
return -1, errors.New("nil label object")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use ID or name of resource. ID first.
|
|
||||||
var rIDOrName interface{}
|
|
||||||
if label.ResourceID != 0 {
|
|
||||||
rIDOrName = label.ResourceID
|
|
||||||
} else {
|
|
||||||
rIDOrName = label.ResourceName
|
|
||||||
}
|
|
||||||
|
|
||||||
rlabel, err := dao.GetResourceLabel(label.ResourceType, rIDOrName, label.LabelID)
|
|
||||||
if err != nil {
|
|
||||||
return -1, fmt.Errorf("failed to check the existence of label %d for resource %s %v: %v", label.LabelID, label.ResourceType, rIDOrName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rlabel != nil {
|
|
||||||
return -1, NewErrLabelConflict(label.LabelID, label.ResourceType, rIDOrName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := dao.AddResourceLabel(label); err != nil {
|
|
||||||
return -1, fmt.Errorf("failed to add label %d to resource %s %v: %v", label.LabelID, label.ResourceType, rIDOrName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the ID of label
|
|
||||||
return label.LabelID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveLabelFromResource is the implementation of same method in Manager interface.
|
|
||||||
func (bm *BaseManager) RemoveLabelFromResource(resourceType string, resourceIDOrName interface{}, labelID int64) error {
|
|
||||||
rl, err := dao.GetResourceLabel(resourceType, resourceIDOrName, labelID)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to check the existence of label %d for resource %s %v: %v", labelID, resourceType, resourceIDOrName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rl == nil {
|
|
||||||
return NewErrLabelNotFound(labelID, resourceType, resourceIDOrName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = dao.DeleteResourceLabel(rl.ID); err != nil {
|
|
||||||
return fmt.Errorf("failed to delete resource label record %d: %v", rl.ID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLabelsOfResource is the implementation of same method in Manager interface.
|
|
||||||
func (bm *BaseManager) GetLabelsOfResource(resourceType string, resourceIDOrName interface{}) ([]*model.Label, error) {
|
|
||||||
labels, err := dao.GetLabelsOfResource(resourceType, resourceIDOrName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get labels of resource %s %v: %v", resourceType, resourceIDOrName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return labels, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exists is the implementation of same method in Manager interface.
|
|
||||||
func (bm *BaseManager) Exists(labelID int64) (*model.Label, error) {
|
|
||||||
label, err := bm.LabelMgr.Get(orm.Context(), labelID)
|
|
||||||
if err != nil {
|
|
||||||
if errors.IsErr(err, errors.NotFoundCode) {
|
|
||||||
return nil, NewErrLabelNotFound(labelID, "", nil)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed to get label %d: %v", labelID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return label, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate is the implementation of same method in Manager interface.
|
|
||||||
func (bm *BaseManager) Validate(labelID int64, projectID int64) (*model.Label, error) {
|
|
||||||
label, err := bm.LabelMgr.Get(orm.Context(), labelID)
|
|
||||||
if err != nil {
|
|
||||||
if errors.IsErr(err, errors.NotFoundCode) {
|
|
||||||
return nil, NewErrLabelNotFound(labelID, "", nil)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed to get label %d: %v", labelID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if label.Level != common.LabelLevelUser {
|
|
||||||
return nil, NewErrLabelBadRequest("only user level labels can be used")
|
|
||||||
}
|
|
||||||
|
|
||||||
if label.Scope == common.LabelScopeProject {
|
|
||||||
if projectID != label.ProjectID {
|
|
||||||
return nil, NewErrLabelBadRequest("can not add labels which don't belong to the project to the resources under the project")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return label, nil
|
|
||||||
}
|
|
@ -77,19 +77,3 @@ type Reference struct {
|
|||||||
func (r *Reference) TableName() string {
|
func (r *Reference) TableName() string {
|
||||||
return "label_reference"
|
return "label_reference"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResourceLabel records the relationship between resource and label
|
|
||||||
type ResourceLabel struct {
|
|
||||||
ID int64 `orm:"pk;auto;column(id)"`
|
|
||||||
LabelID int64 `orm:"column(label_id)"`
|
|
||||||
ResourceID int64 `orm:"column(resource_id)"`
|
|
||||||
ResourceName string `orm:"column(resource_name)"`
|
|
||||||
ResourceType string `orm:"column(resource_type)"`
|
|
||||||
CreationTime time.Time `orm:"column(creation_time);auto_now_add"`
|
|
||||||
UpdateTime time.Time `orm:"column(update_time);auto_now"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName ...
|
|
||||||
func (r *ResourceLabel) TableName() string {
|
|
||||||
return "harbor_resource_label"
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user