mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-24 01:27:49 +01:00
Implement repository deletion API
Implement repository deletion API based on the new design Signed-off-by: Wenkai Yin <yinw@vmware.com>
This commit is contained in:
parent
9a42b20499
commit
c267aaa474
@ -229,6 +229,28 @@ paths:
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/projects/{project_name}/repositories/{repository_name}:
|
||||
delete:
|
||||
summary: Delete repository
|
||||
description: Delete the repository specified by name
|
||||
tags:
|
||||
- repository
|
||||
operationId: deleteRepository
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectName'
|
||||
- $ref: '#/parameters/repositoryName'
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/responses/200'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
parameters:
|
||||
requestId:
|
||||
name: X-Request-Id
|
||||
|
@ -295,6 +295,7 @@ func (c *controller) Delete(ctx context.Context, id int64) error {
|
||||
}
|
||||
|
||||
func (c *controller) CreateTag(ctx context.Context, tag *Tag) (int64, error) {
|
||||
// TODO fire event
|
||||
return c.tagMgr.Create(ctx, &(tag.Tag))
|
||||
}
|
||||
func (c *controller) ListTags(ctx context.Context, query *q.Query, option *TagOption) (int64, []*Tag, error) {
|
||||
|
@ -16,6 +16,7 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/goharbor/harbor/src/api/artifact"
|
||||
"github.com/goharbor/harbor/src/common/models"
|
||||
"github.com/goharbor/harbor/src/common/utils"
|
||||
ierror "github.com/goharbor/harbor/src/internal/error"
|
||||
@ -41,6 +42,8 @@ type Controller interface {
|
||||
Get(ctx context.Context, id int64) (repository *models.RepoRecord, err error)
|
||||
// GetByName gets the repository specified by name
|
||||
GetByName(ctx context.Context, name string) (repository *models.RepoRecord, err error)
|
||||
// Delete the repository specified by ID
|
||||
Delete(ctx context.Context, id int64) (err error)
|
||||
}
|
||||
|
||||
// NewController creates an instance of the default repository controller
|
||||
@ -48,12 +51,14 @@ func NewController() Controller {
|
||||
return &controller{
|
||||
proMgr: project.Mgr,
|
||||
repoMgr: repository.Mgr,
|
||||
artCtl: artifact.Ctl,
|
||||
}
|
||||
}
|
||||
|
||||
type controller struct {
|
||||
proMgr project.Manager
|
||||
repoMgr repository.Manager
|
||||
artCtl artifact.Controller
|
||||
}
|
||||
|
||||
func (c *controller) Ensure(ctx context.Context, name string) (bool, int64, error) {
|
||||
@ -108,3 +113,25 @@ func (c *controller) Get(ctx context.Context, id int64) (*models.RepoRecord, err
|
||||
func (c *controller) GetByName(ctx context.Context, name string) (*models.RepoRecord, error) {
|
||||
return c.repoMgr.GetByName(ctx, name)
|
||||
}
|
||||
|
||||
func (c *controller) Delete(ctx context.Context, id int64) error {
|
||||
// TODO auth
|
||||
// TODO how to make sure the logic included by middlewares(immutable, readonly, quota, etc)
|
||||
// TODO is covered when deleting the artifacts of the repository
|
||||
_, artifacts, err := c.artCtl.List(ctx, &q.Query{
|
||||
Keywords: map[string]interface{}{
|
||||
"RepositoryID": id,
|
||||
},
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, artifact := range artifacts {
|
||||
if err = c.artCtl.Delete(ctx, artifact.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return c.repoMgr.Delete(ctx, id)
|
||||
|
||||
// TODO fire event
|
||||
}
|
||||
|
@ -15,7 +15,9 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"github.com/goharbor/harbor/src/api/artifact"
|
||||
"github.com/goharbor/harbor/src/common/models"
|
||||
artifacttesting "github.com/goharbor/harbor/src/testing/api/artifact"
|
||||
"github.com/goharbor/harbor/src/testing/pkg/project"
|
||||
"github.com/goharbor/harbor/src/testing/pkg/repository"
|
||||
"github.com/stretchr/testify/suite"
|
||||
@ -27,14 +29,17 @@ type controllerTestSuite struct {
|
||||
ctl *controller
|
||||
proMgr *project.FakeManager
|
||||
repoMgr *repository.FakeManager
|
||||
artCtl *artifacttesting.FakeController
|
||||
}
|
||||
|
||||
func (c *controllerTestSuite) SetupTest() {
|
||||
c.proMgr = &project.FakeManager{}
|
||||
c.repoMgr = &repository.FakeManager{}
|
||||
c.artCtl = &artifacttesting.FakeController{}
|
||||
c.ctl = &controller{
|
||||
proMgr: c.proMgr,
|
||||
repoMgr: c.repoMgr,
|
||||
artCtl: c.artCtl,
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +109,16 @@ func (c *controllerTestSuite) TestGetByName() {
|
||||
c.Equal(int64(1), repository.RepositoryID)
|
||||
}
|
||||
|
||||
func (c *controllerTestSuite) TestDelete() {
|
||||
art := &artifact.Artifact{}
|
||||
art.ID = 1
|
||||
c.artCtl.On("List").Return(1, []*artifact.Artifact{art}, nil)
|
||||
c.artCtl.On("Delete").Return(nil)
|
||||
c.repoMgr.On("Delete").Return(nil)
|
||||
err := c.ctl.Delete(nil, 1)
|
||||
c.Require().Nil(err)
|
||||
}
|
||||
|
||||
func TestControllerTestSuite(t *testing.T) {
|
||||
suite.Run(t, &controllerTestSuite{})
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ import (
|
||||
// New returns http handler for API V2.0
|
||||
func New() http.Handler {
|
||||
h, api, err := restapi.HandlerAPI(restapi.Config{
|
||||
ArtifactAPI: newArtifactAPI(),
|
||||
ArtifactAPI: newArtifactAPI(),
|
||||
RepositoryAPI: newRepositoryAPI(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
45
src/server/v2.0/handler/repository.go
Normal file
45
src/server/v2.0/handler/repository.go
Normal file
@ -0,0 +1,45 @@
|
||||
// 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 handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/goharbor/harbor/src/api/repository"
|
||||
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/repository"
|
||||
)
|
||||
|
||||
func newRepositoryAPI() *repositoryAPI {
|
||||
return &repositoryAPI{
|
||||
repoCtl: repository.Ctl,
|
||||
}
|
||||
}
|
||||
|
||||
type repositoryAPI struct {
|
||||
BaseAPI
|
||||
repoCtl repository.Controller
|
||||
}
|
||||
|
||||
func (r *repositoryAPI) DeleteRepository(ctx context.Context, params operation.DeleteRepositoryParams) middleware.Responder {
|
||||
repository, err := r.repoCtl.GetByName(ctx, fmt.Sprintf("%s/%s", params.ProjectName, params.RepositoryName))
|
||||
if err != nil {
|
||||
return r.SendError(ctx, err)
|
||||
}
|
||||
if err := r.repoCtl.Delete(ctx, repository.RepositoryID); err != nil {
|
||||
return r.SendError(ctx, err)
|
||||
}
|
||||
return operation.NewDeleteRepositoryOK()
|
||||
}
|
@ -62,3 +62,9 @@ func (f *FakeController) GetByName(ctx context.Context, name string) (*models.Re
|
||||
}
|
||||
return repository, args.Error(1)
|
||||
}
|
||||
|
||||
// Delete ...
|
||||
func (f *FakeController) Delete(ctx context.Context, id int64) error {
|
||||
args := f.Called()
|
||||
return args.Error(0)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user