Update swagger file to add retag API

Signed-off-by: 陈德 <chende@caicloud.io>
This commit is contained in:
陈德 2018-09-01 15:10:28 +08:00
parent 48d2435146
commit 75f1cdb449
6 changed files with 59 additions and 15 deletions

View File

@ -41,6 +41,32 @@ paths:
$ref: '#/definitions/Search'
'500':
description: Unexpected internal errors.
/retag:
post:
summary: Retag an image
description: >
This endpoint tags an image with another tag in the same repo, or
to another repo or project.
parameters:
- name: request
in: body
description: reqeust to given source image and target image
required: true
schema:
$ref: '#/definitions/RetagReq'
tags:
- Products
responses:
'200':
description: Image retag successfully.
'400':
description: Invalid image values provided
'401':
description: User has no permission to the source project or destination project.
'404':
description: Project or repository not found.
'500':
description: Unexpected internal errors.
/projects:
get:
summary: List projects
@ -2966,6 +2992,15 @@ definitions:
type: array
items:
$ref: '#/definitions/SearchResult'
RetagReq:
type: object
properties:
src_image:
description: Source image to be retagged, e.g. 'stage/app:v1.0'
type: string
dest_image:
description: Destination image tag to, e.g. 'product/app:v1.0'
type: string
SearchRepository:
type: object
properties:

View File

@ -19,17 +19,21 @@ import (
"strings"
)
// RetagRequest gives the source image and target image of retag
type RetagRequest struct {
SrcImage string `json:"src_image"`
DestImage string `json:"dest_image"`
SrcImage string `json:"src_image"`
DestImage string `json:"dest_image"`
}
// Image holds each part (project, repo, tag) of an image name
type Image struct {
Project string
Repo string
Tag string
}
// ParseImage parses an image name such as 'library/app:v1.0' to a structure with
// project, repo, and tag fields
func ParseImage(image string) (*Image, error) {
repo := strings.SplitN(image, "/", 2)
if len(repo) < 2 {
@ -38,10 +42,10 @@ func ParseImage(image string) (*Image, error) {
i := strings.SplitN(repo[1], ":", 2)
res := &Image{
Project: repo[0],
Repo: i[0],
Repo: i[0],
}
if len(i) == 2 {
res.Tag = i[1]
}
return res, nil
}
}

View File

@ -15,23 +15,24 @@
package models
import (
"testing"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseImage(t *testing.T) {
cases := []struct {
Input string
Input string
Expected *Image
Valid bool
} {
Valid bool
}{
{
Input: "library/busybox",
Expected: &Image{
Project: "library",
Repo: "busybox",
Tag: "",
Repo: "busybox",
Tag: "",
},
Valid: true,
},
@ -39,8 +40,8 @@ func TestParseImage(t *testing.T) {
Input: "library/busybox:v1.0",
Expected: &Image{
Project: "library",
Repo: "busybox",
Tag: "v1.0",
Repo: "busybox",
Tag: "v1.0",
},
Valid: true,
},
@ -62,4 +63,4 @@ func TestParseImage(t *testing.T) {
}
}
}
}
}

View File

@ -258,6 +258,7 @@ func (r *Repository) DeleteManifest(digest string) error {
}
}
// MountBlob ...
func (r *Repository) MountBlob(digest, from string) error {
req, err := http.NewRequest("POST", buildMountBlobURL(r.Endpoint.String(), r.Name, digest, from), nil)
req.Header.Set(http.CanonicalHeaderKey("Content-Length"), "0")

View File

@ -28,6 +28,7 @@ type RetagAPI struct {
BaseController
}
// Retag tags an image to another
func (r *RetagAPI) Retag() {
if !r.SecurityCtx.IsAuthenticated() {
r.HandleUnauthorized()

View File

@ -25,13 +25,15 @@ import (
"github.com/docker/distribution/manifest/schema2"
)
// Retag tags an image to another
func Retag(srcImage, destImage *models.Image) error {
isSameRepo := getRepoName(srcImage) == getRepoName(destImage)
srcClient, err := NewRepositoryClientForUI("harbor-ui", getRepoName(srcImage))
if err != nil {
return err
}
destClient := srcClient
if getRepoName(srcImage) != getRepoName(destImage) {
if !isSameRepo {
destClient, err = NewRepositoryClientForUI("harbor-ui", getRepoName(destImage))
if err != nil {
return err
@ -70,7 +72,7 @@ func Retag(srcImage, destImage *models.Image) error {
return nil
}
if getRepoName(srcImage) != getRepoName(destImage) {
if !isSameRepo {
for _, descriptor := range manifest.References() {
err := destClient.MountBlob(descriptor.Digest.String(), srcClient.Name)
if err != nil {