mirror of
https://github.com/goharbor/harbor.git
synced 2024-08-19 02:22:48 +02:00
Merge pull request #7304 from cd1989/registry-delete-constraint
Use policy controller in registry deletion
This commit is contained in:
commit
f4bf948847
|
@ -12,13 +12,15 @@ import (
|
|||
"github.com/goharbor/harbor/src/replication/ng"
|
||||
"github.com/goharbor/harbor/src/replication/ng/adapter"
|
||||
"github.com/goharbor/harbor/src/replication/ng/model"
|
||||
"github.com/goharbor/harbor/src/replication/ng/policy"
|
||||
"github.com/goharbor/harbor/src/replication/ng/registry"
|
||||
)
|
||||
|
||||
// RegistryAPI handles requests to /api/registries/{}. It manages registries integrated to Harbor.
|
||||
type RegistryAPI struct {
|
||||
BaseController
|
||||
manager registry.Manager
|
||||
manager registry.Manager
|
||||
policyCtl policy.Controller
|
||||
}
|
||||
|
||||
// Prepare validates the user
|
||||
|
@ -35,6 +37,7 @@ func (t *RegistryAPI) Prepare() {
|
|||
}
|
||||
|
||||
t.manager = ng.RegistryMgr
|
||||
t.policyCtl = ng.PolicyCtl
|
||||
}
|
||||
|
||||
// Get gets a registry by id.
|
||||
|
@ -193,21 +196,39 @@ func (t *RegistryAPI) Delete() {
|
|||
}
|
||||
|
||||
if registry == nil {
|
||||
t.HandleNotFound(fmt.Sprintf("registry %d not found", id))
|
||||
t.HandleNotFound(fmt.Sprintf("Registry %d not found", id))
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: filter the policies by registry ID
|
||||
_, policies, err := ng.PolicyCtl.List()
|
||||
// Check whether there are replication policies that use this registry as source registry.
|
||||
total, _, err := t.policyCtl.List([]*model.PolicyQuery{
|
||||
{
|
||||
SrcRegistry: id,
|
||||
},
|
||||
}...)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("Get policies related to registry %d error: %v", id, err)
|
||||
t.HandleInternalServerError(fmt.Sprintf("List replication policies with source registry %d error: %v", id, err))
|
||||
return
|
||||
}
|
||||
if total > 0 {
|
||||
msg := fmt.Sprintf("Can't delete registry %d, %d replication policies use it as source registry", id, total)
|
||||
log.Error(msg)
|
||||
t.HandleInternalServerError(msg)
|
||||
t.HandleStatusPreconditionFailed(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if len(policies) > 0 {
|
||||
msg := fmt.Sprintf("Can't delete registry with replication policies, %d found", len(policies))
|
||||
// Check whether there are replication policies that use this registry as destination registry.
|
||||
total, _, err = t.policyCtl.List([]*model.PolicyQuery{
|
||||
{
|
||||
DestRegistry: id,
|
||||
},
|
||||
}...)
|
||||
if err != nil {
|
||||
t.HandleInternalServerError(fmt.Sprintf("List replication policies with destination registry %d error: %v", id, err))
|
||||
return
|
||||
}
|
||||
if total > 0 {
|
||||
msg := fmt.Sprintf("Can't delete registry %d, %d replication policies use it as destination registry", id, total)
|
||||
log.Error(msg)
|
||||
t.HandleStatusPreconditionFailed(msg)
|
||||
return
|
||||
|
|
|
@ -38,6 +38,7 @@ import (
|
|||
"github.com/goharbor/harbor/src/core/filter"
|
||||
"github.com/goharbor/harbor/src/core/proxy"
|
||||
"github.com/goharbor/harbor/src/core/service/token"
|
||||
"github.com/goharbor/harbor/src/replication/ng"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -129,8 +130,9 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
closing := make(chan struct{})
|
||||
go gracefulShutdown(closing)
|
||||
if err := ng.Init(); err != nil {
|
||||
log.Fatalf("failed to initialize replication: %v", err)
|
||||
}
|
||||
|
||||
filter.Init()
|
||||
beego.InsertFilter("/*", beego.BeforeRouter, filter.SecurityFilter)
|
||||
|
|
|
@ -5,8 +5,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/astaxie/beego/orm"
|
||||
|
||||
common_dao "github.com/goharbor/harbor/src/common/dao"
|
||||
"github.com/goharbor/harbor/src/replication/ng/dao/models"
|
||||
"github.com/goharbor/harbor/src/replication/ng/model"
|
||||
)
|
||||
|
||||
// AddRepPolicy insert new policy to DB.
|
||||
|
@ -19,33 +21,53 @@ func AddRepPolicy(policy *models.RepPolicy) (int64, error) {
|
|||
return o.Insert(policy)
|
||||
}
|
||||
|
||||
func filteredRepPolicyQuerySeter(name, namespace string) orm.QuerySeter {
|
||||
// GetPolicies list polices with given query parameters.
|
||||
func GetPolicies(queries ...*model.PolicyQuery) (int64, []*models.RepPolicy, error) {
|
||||
var qs = common_dao.GetOrmer().QueryTable(new(models.RepPolicy))
|
||||
var policies []*models.RepPolicy
|
||||
|
||||
// TODO: just filter polices by name now, and need consider how to filter namespace.
|
||||
qs = qs.Filter("name__icontains", name)
|
||||
if len(queries) == 0 {
|
||||
total, err := qs.Count()
|
||||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
|
||||
return qs
|
||||
}
|
||||
_, err = qs.All(&policies)
|
||||
if err != nil {
|
||||
return total, nil, err
|
||||
}
|
||||
|
||||
// GetTotalOfRepPolicies returns the total count of replication policies
|
||||
func GetTotalOfRepPolicies(name, namespace string) (int64, error) {
|
||||
var qs = filteredRepPolicyQuerySeter(name, namespace)
|
||||
return qs.Count()
|
||||
}
|
||||
|
||||
// GetPolicies filter policies and pagination.
|
||||
func GetPolicies(name, namespace string, page, pageSize int64) (policies []*models.RepPolicy, err error) {
|
||||
var qs = filteredRepPolicyQuerySeter(name, namespace)
|
||||
|
||||
// Paginate
|
||||
if page > 0 && pageSize > 0 {
|
||||
qs = qs.Limit(pageSize, (page-1)*pageSize)
|
||||
return total, policies, nil
|
||||
}
|
||||
|
||||
_, err = qs.All(&policies)
|
||||
query := queries[0]
|
||||
if len(query.Name) != 0 {
|
||||
qs = qs.Filter("Name__icontains", query.Name)
|
||||
}
|
||||
if len(query.Namespace) != 0 {
|
||||
// TODO: Namespace filter not implemented yet
|
||||
}
|
||||
if query.SrcRegistry > 0 {
|
||||
qs = qs.Filter("SrcRegistryID__exact", query.SrcRegistry)
|
||||
}
|
||||
if query.DestRegistry > 0 {
|
||||
qs = qs.Filter("DestRegistryID__exact", query.DestRegistry)
|
||||
}
|
||||
|
||||
return
|
||||
total, err := qs.Count()
|
||||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
|
||||
if query.Page > 0 && query.Size > 0 {
|
||||
qs = qs.Limit(query.Size, (query.Page-1)*query.Size)
|
||||
}
|
||||
_, err = qs.All(&policies)
|
||||
if err != nil {
|
||||
return total, nil, err
|
||||
}
|
||||
|
||||
return total, policies, nil
|
||||
}
|
||||
|
||||
// GetRepPolicy return special policy by id.
|
||||
|
|
|
@ -3,9 +3,12 @@ package dao
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/goharbor/harbor/src/replication/ng/dao/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
common_models "github.com/goharbor/harbor/src/common/models"
|
||||
"github.com/goharbor/harbor/src/replication/ng/dao/models"
|
||||
"github.com/goharbor/harbor/src/replication/ng/model"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -84,34 +87,6 @@ func TestAddRepPolicy(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetTotalOfRepPolicies(t *testing.T) {
|
||||
type args struct {
|
||||
name string
|
||||
namespace string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want int64
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "GetTotalOfRepPolicies 1", args: args{name: "Test 1"}, want: 1},
|
||||
{name: "GetTotalOfRepPolicies 2", args: args{name: "Test"}, want: 3},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := GetTotalOfRepPolicies(tt.args.name, tt.args.namespace)
|
||||
if tt.wantErr {
|
||||
require.NotNil(t, err, "wantErr: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPolicies(t *testing.T) {
|
||||
type args struct {
|
||||
name string
|
||||
|
@ -131,7 +106,16 @@ func TestGetPolicies(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotPolicies, err := GetPolicies(tt.args.name, tt.args.namespace, tt.args.page, tt.args.pageSize)
|
||||
_, gotPolicies, err := GetPolicies([]*model.PolicyQuery{
|
||||
{
|
||||
Name: tt.args.name,
|
||||
Namespace: tt.args.namespace,
|
||||
Pagination: common_models.Pagination{
|
||||
Page: tt.args.page,
|
||||
Size: tt.args.pageSize,
|
||||
},
|
||||
},
|
||||
}...)
|
||||
if tt.wantErr {
|
||||
require.NotNil(t, err, "wantErr: %s", err)
|
||||
return
|
||||
|
|
|
@ -152,6 +152,8 @@ type PolicyQuery struct {
|
|||
Name string
|
||||
// TODO: need to consider how to support listing the policies
|
||||
// of one namespace in both pull and push modes
|
||||
Namespace string
|
||||
Namespace string
|
||||
SrcRegistry int64
|
||||
DestRegistry int64
|
||||
models.Pagination
|
||||
}
|
||||
|
|
|
@ -156,25 +156,8 @@ func (m *DefaultManager) Create(policy *model.Policy) (int64, error) {
|
|||
|
||||
// List returns all the policies
|
||||
func (m *DefaultManager) List(queries ...*model.PolicyQuery) (total int64, policies []*model.Policy, err error) {
|
||||
// default query parameters
|
||||
var name = ""
|
||||
var namespace = ""
|
||||
var page int64 = 1
|
||||
var pageSize int64 = 15
|
||||
|
||||
if len(queries) > 0 {
|
||||
name = queries[0].Name
|
||||
namespace = queries[0].Namespace
|
||||
page = queries[0].Pagination.Page
|
||||
pageSize = queries[0].Pagination.Size
|
||||
}
|
||||
|
||||
var persistPolicies []*persist_models.RepPolicy
|
||||
persistPolicies, err = dao.GetPolicies(name, namespace, page, pageSize)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = dao.GetTotalOfRepPolicies(name, namespace)
|
||||
total, persistPolicies, err = dao.GetPolicies(queries...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user