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:
Wenkai Yin 2020-02-07 09:11:54 +08:00
parent 9a42b20499
commit c267aaa474
7 changed files with 118 additions and 1 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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
}

View File

@ -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{})
}

View File

@ -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)

View 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()
}

View File

@ -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)
}