mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-19 15:17:43 +01:00
Merge pull request #10588 from ywk253100/200126_delete_get_artifact
Implement artifact/tag related API
This commit is contained in:
commit
26ade207d3
@ -18,80 +18,6 @@ securityDefinitions:
|
|||||||
security:
|
security:
|
||||||
- basicAuth: []
|
- basicAuth: []
|
||||||
paths:
|
paths:
|
||||||
/projects/{project_name}/repositories/{repository_name}/artifacts/{digest}:
|
|
||||||
get:
|
|
||||||
summary: Get the specific artifact
|
|
||||||
description: Get the artifact specified by the digest under the project and repository
|
|
||||||
tags:
|
|
||||||
- artifact
|
|
||||||
operationId: getArtifact
|
|
||||||
parameters:
|
|
||||||
- $ref: '#/parameters/requestId'
|
|
||||||
- $ref: '#/parameters/projectName'
|
|
||||||
- $ref: '#/parameters/repositoryName'
|
|
||||||
- $ref: '#/parameters/digest'
|
|
||||||
- name: with_tag
|
|
||||||
in: query
|
|
||||||
description: Specify whether the tags are inclued inside the returning artifacts
|
|
||||||
type: boolean
|
|
||||||
required: false
|
|
||||||
default: true
|
|
||||||
- name: with_label
|
|
||||||
in: query
|
|
||||||
description: Specify whether the labels are inclued inside the returning artifacts
|
|
||||||
type: boolean
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
- name: with_scan_overview
|
|
||||||
in: query
|
|
||||||
description: Specify whether the scan overview is inclued inside the returning artifacts
|
|
||||||
type: boolean
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
# should be in tag level
|
|
||||||
- name: with_signatrue
|
|
||||||
in: query
|
|
||||||
description: Specify whether the signature is inclued inside the returning artifacts
|
|
||||||
type: boolean
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
- name: with_immutable_status
|
|
||||||
in: query
|
|
||||||
description: Specify whether the immutable status is inclued inside the tags of the returning artifacts. Only works when setting "with_tag=true"
|
|
||||||
type: boolean
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Success
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/Artifact'
|
|
||||||
'401':
|
|
||||||
$ref: '#/responses/401'
|
|
||||||
'403':
|
|
||||||
$ref: '#/responses/403'
|
|
||||||
'500':
|
|
||||||
$ref: '#/responses/500'
|
|
||||||
delete:
|
|
||||||
summary: Delete the specific artifact
|
|
||||||
description: Delete the artifact specified by the digest under the project and repository
|
|
||||||
tags:
|
|
||||||
- artifact
|
|
||||||
operationId: deleteArtifact
|
|
||||||
parameters:
|
|
||||||
- $ref: '#/parameters/requestId'
|
|
||||||
- $ref: '#/parameters/projectName'
|
|
||||||
- $ref: '#/parameters/repositoryName'
|
|
||||||
- $ref: '#/parameters/digest'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Success
|
|
||||||
'401':
|
|
||||||
$ref: '#/responses/401'
|
|
||||||
'403':
|
|
||||||
$ref: '#/responses/403'
|
|
||||||
'500':
|
|
||||||
$ref: '#/responses/500'
|
|
||||||
/projects/{project_name}/repositories/{repository_name}/artifacts:
|
/projects/{project_name}/repositories/{repository_name}/artifacts:
|
||||||
get:
|
get:
|
||||||
summary: List artifacts
|
summary: List artifacts
|
||||||
@ -129,7 +55,7 @@ paths:
|
|||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
# should be in tag level
|
# should be in tag level
|
||||||
- name: with_signatrue
|
- name: with_signature
|
||||||
in: query
|
in: query
|
||||||
description: Specify whether the signature is inclued inside the returning artifacts
|
description: Specify whether the signature is inclued inside the returning artifacts
|
||||||
type: boolean
|
type: boolean
|
||||||
@ -156,10 +82,151 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/Artifact'
|
$ref: '#/definitions/Artifact'
|
||||||
|
'400':
|
||||||
|
$ref: '#/responses/400'
|
||||||
'401':
|
'401':
|
||||||
$ref: '#/responses/401'
|
$ref: '#/responses/401'
|
||||||
'403':
|
'403':
|
||||||
$ref: '#/responses/403'
|
$ref: '#/responses/403'
|
||||||
|
'404':
|
||||||
|
$ref: '#/responses/404'
|
||||||
|
'500':
|
||||||
|
$ref: '#/responses/500'
|
||||||
|
/projects/{project_name}/repositories/{repository_name}/artifacts/{reference}:
|
||||||
|
get:
|
||||||
|
summary: Get the specific artifact
|
||||||
|
description: Get the artifact specified by the reference under the project and repository. The reference can be digest or tag.
|
||||||
|
tags:
|
||||||
|
- artifact
|
||||||
|
operationId: getArtifact
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/parameters/requestId'
|
||||||
|
- $ref: '#/parameters/projectName'
|
||||||
|
- $ref: '#/parameters/repositoryName'
|
||||||
|
- $ref: '#/parameters/reference'
|
||||||
|
- name: with_tag
|
||||||
|
in: query
|
||||||
|
description: Specify whether the tags are inclued inside the returning artifacts
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
- name: with_label
|
||||||
|
in: query
|
||||||
|
description: Specify whether the labels are inclued inside the returning artifacts
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
- name: with_scan_overview
|
||||||
|
in: query
|
||||||
|
description: Specify whether the scan overview is inclued inside the returning artifacts
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
# should be in tag level
|
||||||
|
- name: with_signature
|
||||||
|
in: query
|
||||||
|
description: Specify whether the signature is inclued inside the returning artifacts
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
- name: with_immutable_status
|
||||||
|
in: query
|
||||||
|
description: Specify whether the immutable status is inclued inside the tags of the returning artifacts. Only works when setting "with_tag=true"
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Success
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Artifact'
|
||||||
|
'400':
|
||||||
|
$ref: '#/responses/400'
|
||||||
|
'401':
|
||||||
|
$ref: '#/responses/401'
|
||||||
|
'403':
|
||||||
|
$ref: '#/responses/403'
|
||||||
|
'404':
|
||||||
|
$ref: '#/responses/404'
|
||||||
|
'500':
|
||||||
|
$ref: '#/responses/500'
|
||||||
|
delete:
|
||||||
|
summary: Delete the specific artifact
|
||||||
|
description: Delete the artifact specified by the reference under the project and repository. The reference can be digest or tag
|
||||||
|
tags:
|
||||||
|
- artifact
|
||||||
|
operationId: deleteArtifact
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/parameters/requestId'
|
||||||
|
- $ref: '#/parameters/projectName'
|
||||||
|
- $ref: '#/parameters/repositoryName'
|
||||||
|
- $ref: '#/parameters/reference'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/responses/200'
|
||||||
|
'401':
|
||||||
|
$ref: '#/responses/401'
|
||||||
|
'403':
|
||||||
|
$ref: '#/responses/403'
|
||||||
|
'404':
|
||||||
|
$ref: '#/responses/404'
|
||||||
|
'500':
|
||||||
|
$ref: '#/responses/500'
|
||||||
|
/projects/{project_name}/repositories/{repository_name}/artifacts/{reference}/tags:
|
||||||
|
post:
|
||||||
|
summary: Create tag
|
||||||
|
description: Create a tag for the specified artifact
|
||||||
|
tags:
|
||||||
|
- artifact
|
||||||
|
operationId: createTag
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/parameters/requestId'
|
||||||
|
- $ref: '#/parameters/projectName'
|
||||||
|
- $ref: '#/parameters/repositoryName'
|
||||||
|
- $ref: '#/parameters/reference'
|
||||||
|
- name: tag
|
||||||
|
in: body
|
||||||
|
description: The JSON object of tag.
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Tag'
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
$ref: '#/responses/201'
|
||||||
|
'400':
|
||||||
|
$ref: '#/responses/400'
|
||||||
|
'401':
|
||||||
|
$ref: '#/responses/401'
|
||||||
|
'403':
|
||||||
|
$ref: '#/responses/403'
|
||||||
|
'404':
|
||||||
|
$ref: '#/responses/404'
|
||||||
|
'409':
|
||||||
|
$ref: '#/responses/409'
|
||||||
|
'500':
|
||||||
|
$ref: '#/responses/500'
|
||||||
|
/projects/{project_name}/repositories/{repository_name}/artifacts/{reference}/tags/{tag_name}:
|
||||||
|
delete:
|
||||||
|
summary: Delete tag
|
||||||
|
description: Delete the tag of the specified artifact
|
||||||
|
tags:
|
||||||
|
- artifact
|
||||||
|
operationId: deleteTag
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/parameters/requestId'
|
||||||
|
- $ref: '#/parameters/projectName'
|
||||||
|
- $ref: '#/parameters/repositoryName'
|
||||||
|
- $ref: '#/parameters/reference'
|
||||||
|
- $ref: '#/parameters/tagName'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/responses/200'
|
||||||
|
'401':
|
||||||
|
$ref: '#/responses/401'
|
||||||
|
'403':
|
||||||
|
$ref: '#/responses/403'
|
||||||
|
'404':
|
||||||
|
$ref: '#/responses/404'
|
||||||
'500':
|
'500':
|
||||||
$ref: '#/responses/500'
|
$ref: '#/responses/500'
|
||||||
parameters:
|
parameters:
|
||||||
@ -182,10 +249,16 @@ parameters:
|
|||||||
description: The name of the repository
|
description: The name of the repository
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
digest:
|
reference:
|
||||||
name: digest
|
name: reference
|
||||||
in: path
|
in: path
|
||||||
description: The digest of the artifact
|
description: The reference of the artifact, can be digest or tag
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
tagName:
|
||||||
|
name: tag_name
|
||||||
|
in: path
|
||||||
|
description: The name of the tag
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
page:
|
page:
|
||||||
@ -205,6 +278,26 @@ parameters:
|
|||||||
description: The size of per page
|
description: The size of per page
|
||||||
default: 10
|
default: 10
|
||||||
responses:
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Success
|
||||||
|
headers:
|
||||||
|
X-Request-Id:
|
||||||
|
description: The ID of the corresponding request for the response
|
||||||
|
type: string
|
||||||
|
'201':
|
||||||
|
description: Created
|
||||||
|
headers:
|
||||||
|
X-Request-Id:
|
||||||
|
description: The ID of the corresponding request for the response
|
||||||
|
type: string
|
||||||
|
'400':
|
||||||
|
description: Bad request
|
||||||
|
headers:
|
||||||
|
X-Request-Id:
|
||||||
|
description: The ID of the corresponding request for the response
|
||||||
|
type: string
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Error'
|
||||||
'401':
|
'401':
|
||||||
description: Unauthorized
|
description: Unauthorized
|
||||||
headers:
|
headers:
|
||||||
@ -221,6 +314,22 @@ responses:
|
|||||||
type: string
|
type: string
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Error'
|
$ref: '#/definitions/Error'
|
||||||
|
'404':
|
||||||
|
description: Not found
|
||||||
|
headers:
|
||||||
|
X-Request-Id:
|
||||||
|
description: The ID of the corresponding request for the response
|
||||||
|
type: string
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Error'
|
||||||
|
'409':
|
||||||
|
description: Conflict
|
||||||
|
headers:
|
||||||
|
X-Request-Id:
|
||||||
|
description: The ID of the corresponding request for the response
|
||||||
|
type: string
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Error'
|
||||||
'500':
|
'500':
|
||||||
description: Internal server error
|
description: Internal server error
|
||||||
headers:
|
headers:
|
||||||
|
@ -54,8 +54,10 @@ type Controller interface {
|
|||||||
GetByReference(ctx context.Context, repository, reference string, option *Option) (artifact *Artifact, err error)
|
GetByReference(ctx context.Context, repository, reference string, option *Option) (artifact *Artifact, err error)
|
||||||
// Delete the artifact specified by ID. All tags attached to the artifact are deleted as well
|
// Delete the artifact specified by ID. All tags attached to the artifact are deleted as well
|
||||||
Delete(ctx context.Context, id int64) (err error)
|
Delete(ctx context.Context, id int64) (err error)
|
||||||
// Tags returns the tags according to the query, specify the properties returned with option
|
// ListTags lists the tags according to the query, specify the properties returned with option
|
||||||
Tags(ctx context.Context, query *q.Query, option *TagOption) (total int64, tags []*Tag, err error)
|
ListTags(ctx context.Context, query *q.Query, option *TagOption) (total int64, tags []*Tag, err error)
|
||||||
|
// CreateTag creates a tag
|
||||||
|
CreateTag(ctx context.Context, tag *Tag) (id int64, err error)
|
||||||
// DeleteTag deletes the tag specified by tagID
|
// DeleteTag deletes the tag specified by tagID
|
||||||
DeleteTag(ctx context.Context, tagID int64) (err error)
|
DeleteTag(ctx context.Context, tagID int64) (err error)
|
||||||
// UpdatePullTime updates the pull time for the artifact. If the tagID is provides, update the pull
|
// UpdatePullTime updates the pull time for the artifact. If the tagID is provides, update the pull
|
||||||
@ -285,7 +287,11 @@ func (c *controller) Delete(ctx context.Context, id int64) error {
|
|||||||
// TODO fire delete artifact event
|
// TODO fire delete artifact event
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (c *controller) Tags(ctx context.Context, query *q.Query, option *TagOption) (int64, []*Tag, error) {
|
|
||||||
|
func (c *controller) CreateTag(ctx context.Context, tag *Tag) (int64, error) {
|
||||||
|
return c.tagMgr.Create(ctx, &(tag.Tag))
|
||||||
|
}
|
||||||
|
func (c *controller) ListTags(ctx context.Context, query *q.Query, option *TagOption) (int64, []*Tag, error) {
|
||||||
total, tgs, err := c.tagMgr.List(ctx, query)
|
total, tgs, err := c.tagMgr.List(ctx, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
|
@ -385,7 +385,7 @@ func (c *controllerTestSuite) TestDelete() {
|
|||||||
c.tagMgr.AssertExpectations(c.T())
|
c.tagMgr.AssertExpectations(c.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controllerTestSuite) TestTags() {
|
func (c *controllerTestSuite) TestListTags() {
|
||||||
c.tagMgr.On("List").Return(1, []*tag.Tag{
|
c.tagMgr.On("List").Return(1, []*tag.Tag{
|
||||||
{
|
{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
@ -394,7 +394,7 @@ func (c *controllerTestSuite) TestTags() {
|
|||||||
Name: "latest",
|
Name: "latest",
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
total, tags, err := c.ctl.Tags(nil, nil, nil)
|
total, tags, err := c.ctl.ListTags(nil, nil, nil)
|
||||||
c.Require().Nil(err)
|
c.Require().Nil(err)
|
||||||
c.Equal(int64(1), total)
|
c.Equal(int64(1), total)
|
||||||
c.Len(tags, 1)
|
c.Len(tags, 1)
|
||||||
@ -402,6 +402,13 @@ func (c *controllerTestSuite) TestTags() {
|
|||||||
// TODO check other properties: label, etc
|
// TODO check other properties: label, etc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *controllerTestSuite) TestCreateTag() {
|
||||||
|
c.tagMgr.On("Create").Return(1, nil)
|
||||||
|
id, err := c.ctl.CreateTag(nil, &Tag{})
|
||||||
|
c.Require().Nil(err)
|
||||||
|
c.Equal(int64(1), id)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *controllerTestSuite) TestDeleteTag() {
|
func (c *controllerTestSuite) TestDeleteTag() {
|
||||||
c.tagMgr.On("Delete").Return(nil)
|
c.tagMgr.On("Delete").Return(nil)
|
||||||
err := c.ctl.DeleteTag(nil, 1)
|
err := c.ctl.DeleteTag(nil, 1)
|
||||||
|
@ -76,6 +76,7 @@ require (
|
|||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/theupdateframework/notary v0.6.1
|
github.com/theupdateframework/notary v0.6.1
|
||||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56
|
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56
|
||||||
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect
|
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect
|
||||||
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
|
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
|
||||||
|
@ -19,11 +19,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-openapi/runtime/middleware"
|
"github.com/go-openapi/runtime/middleware"
|
||||||
"github.com/goharbor/harbor/src/api/artifact"
|
"github.com/goharbor/harbor/src/api/artifact"
|
||||||
|
ierror "github.com/goharbor/harbor/src/internal/error"
|
||||||
"github.com/goharbor/harbor/src/pkg/project"
|
"github.com/goharbor/harbor/src/pkg/project"
|
||||||
"github.com/goharbor/harbor/src/pkg/q"
|
"github.com/goharbor/harbor/src/pkg/q"
|
||||||
"github.com/goharbor/harbor/src/pkg/repository"
|
"github.com/goharbor/harbor/src/pkg/repository"
|
||||||
"github.com/goharbor/harbor/src/server/v2.0/models"
|
"github.com/goharbor/harbor/src/server/v2.0/models"
|
||||||
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/artifact"
|
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/artifact"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newArtifactAPI() *artifactAPI {
|
func newArtifactAPI() *artifactAPI {
|
||||||
@ -64,28 +66,8 @@ func (a *artifactAPI) ListArtifacts(ctx context.Context, params operation.ListAr
|
|||||||
query.Keywords["RepositoryID"] = repository.RepositoryID
|
query.Keywords["RepositoryID"] = repository.RepositoryID
|
||||||
|
|
||||||
// set option
|
// set option
|
||||||
option := &artifact.Option{
|
option := option(params.WithTag, params.WithImmutableStatus,
|
||||||
WithTag: true, // return the tag by default
|
params.WithLabel, params.WithScanOverview, params.WithSignature)
|
||||||
}
|
|
||||||
if params.WithTag != nil {
|
|
||||||
option.WithTag = *(params.WithTag)
|
|
||||||
}
|
|
||||||
if option.WithTag {
|
|
||||||
if params.WithImmutableStatus != nil {
|
|
||||||
option.TagOption = &artifact.TagOption{
|
|
||||||
WithImmutableStatus: *(params.WithImmutableStatus),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if params.WithLabel != nil {
|
|
||||||
option.WithLabel = *(params.WithLabel)
|
|
||||||
}
|
|
||||||
if params.WithScanOverview != nil {
|
|
||||||
option.WithScanOverview = *(params.WithScanOverview)
|
|
||||||
}
|
|
||||||
if params.WithSignatrue != nil {
|
|
||||||
option.WithSignature = *(params.WithSignatrue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// list artifacts according to the query and option
|
// list artifacts according to the query and option
|
||||||
total, arts, err := a.artCtl.List(ctx, query, option)
|
total, arts, err := a.artCtl.List(ctx, query, option)
|
||||||
@ -103,11 +85,98 @@ func (a *artifactAPI) ListArtifacts(ctx context.Context, params operation.ListAr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *artifactAPI) GetArtifact(ctx context.Context, params operation.GetArtifactParams) middleware.Responder {
|
func (a *artifactAPI) GetArtifact(ctx context.Context, params operation.GetArtifactParams) middleware.Responder {
|
||||||
// TODO implement
|
// set option
|
||||||
return operation.NewGetArtifactOK()
|
option := option(params.WithTag, params.WithImmutableStatus,
|
||||||
|
params.WithLabel, params.WithScanOverview, params.WithSignature)
|
||||||
|
|
||||||
|
// get the artifact
|
||||||
|
artifact, err := a.artCtl.GetByReference(ctx, fmt.Sprintf("%s/%s", params.ProjectName, params.RepositoryName), params.Reference, option)
|
||||||
|
if err != nil {
|
||||||
|
return a.SendError(ctx, err)
|
||||||
|
}
|
||||||
|
return operation.NewGetArtifactOK().WithPayload(artifact.ToSwagger())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *artifactAPI) DeleteArtifact(ctx context.Context, params operation.DeleteArtifactParams) middleware.Responder {
|
func (a *artifactAPI) DeleteArtifact(ctx context.Context, params operation.DeleteArtifactParams) middleware.Responder {
|
||||||
// TODO implement
|
artifact, err := a.artCtl.GetByReference(ctx, fmt.Sprintf("%s/%s", params.ProjectName, params.RepositoryName), params.Reference, nil)
|
||||||
|
if err != nil {
|
||||||
|
return a.SendError(ctx, err)
|
||||||
|
}
|
||||||
|
if err = a.artCtl.Delete(ctx, artifact.ID); err != nil {
|
||||||
|
return a.SendError(ctx, err)
|
||||||
|
}
|
||||||
return operation.NewDeleteArtifactOK()
|
return operation.NewDeleteArtifactOK()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *artifactAPI) CreateTag(ctx context.Context, params operation.CreateTagParams) middleware.Responder {
|
||||||
|
art, err := a.artCtl.GetByReference(ctx, fmt.Sprintf("%s/%s", params.ProjectName, params.RepositoryName),
|
||||||
|
params.Reference, &artifact.Option{
|
||||||
|
WithTag: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return a.SendError(ctx, err)
|
||||||
|
}
|
||||||
|
tag := &artifact.Tag{}
|
||||||
|
tag.RepositoryID = art.RepositoryID
|
||||||
|
tag.ArtifactID = art.ID
|
||||||
|
tag.Name = params.Tag.Name
|
||||||
|
tag.PushTime = time.Now()
|
||||||
|
if _, err = a.artCtl.CreateTag(ctx, tag); err != nil {
|
||||||
|
return a.SendError(ctx, err)
|
||||||
|
}
|
||||||
|
// TODO set location header?
|
||||||
|
return operation.NewCreateTagCreated()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *artifactAPI) DeleteTag(ctx context.Context, params operation.DeleteTagParams) middleware.Responder {
|
||||||
|
artifact, err := a.artCtl.GetByReference(ctx, fmt.Sprintf("%s/%s", params.ProjectName, params.RepositoryName),
|
||||||
|
params.Reference, &artifact.Option{
|
||||||
|
WithTag: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return a.SendError(ctx, err)
|
||||||
|
}
|
||||||
|
var id int64
|
||||||
|
for _, tag := range artifact.Tags {
|
||||||
|
if tag.Name == params.TagName {
|
||||||
|
id = tag.ID
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// the tag not found
|
||||||
|
if id == 0 {
|
||||||
|
err = ierror.New(nil).WithCode(ierror.NotFoundCode).WithMessage(
|
||||||
|
"tag %s attached to artifact %d not found", params.TagName, artifact.ID)
|
||||||
|
return a.SendError(ctx, err)
|
||||||
|
}
|
||||||
|
if err = a.artCtl.DeleteTag(ctx, id); err != nil {
|
||||||
|
return a.SendError(ctx, err)
|
||||||
|
}
|
||||||
|
return operation.NewDeleteTagOK()
|
||||||
|
}
|
||||||
|
|
||||||
|
func option(withTag, withImmutableStatus, withLabel, withScanOverview, withSignature *bool) *artifact.Option {
|
||||||
|
option := &artifact.Option{
|
||||||
|
WithTag: true, // return the tag by default
|
||||||
|
}
|
||||||
|
if withTag != nil {
|
||||||
|
option.WithTag = *(withTag)
|
||||||
|
}
|
||||||
|
if option.WithTag {
|
||||||
|
if withImmutableStatus != nil {
|
||||||
|
option.TagOption = &artifact.TagOption{
|
||||||
|
WithImmutableStatus: *(withImmutableStatus),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if withLabel != nil {
|
||||||
|
option.WithLabel = *(withLabel)
|
||||||
|
}
|
||||||
|
if withScanOverview != nil {
|
||||||
|
option.WithScanOverview = *(withScanOverview)
|
||||||
|
}
|
||||||
|
if withSignature != nil {
|
||||||
|
option.WithSignature = *(withSignature)
|
||||||
|
}
|
||||||
|
return option
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user