From afb89623a4de133ae8b3e8bdd28e7093ff354df9 Mon Sep 17 00:00:00 2001 From: lengrongfu <1275177125@qq.com> Date: Mon, 22 May 2023 15:49:45 +0800 Subject: [PATCH] add portal upload or download image proposals Signed-off-by: lengrongfu <1275177125@qq.com> --- .../portal-upordown-image/data-flow.drawio | 167 ++++++++++++++++++ .../portal-upordown-image/data-flow.png | Bin 0 -> 57379 bytes proposals/new/portal-upordown-image.md | 149 ++++++++++++++++ 3 files changed, 316 insertions(+) create mode 100644 proposals/images/portal-upordown-image/data-flow.drawio create mode 100644 proposals/images/portal-upordown-image/data-flow.png create mode 100644 proposals/new/portal-upordown-image.md diff --git a/proposals/images/portal-upordown-image/data-flow.drawio b/proposals/images/portal-upordown-image/data-flow.drawio new file mode 100644 index 00000000..a290d78b --- /dev/null +++ b/proposals/images/portal-upordown-image/data-flow.drawio @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/proposals/images/portal-upordown-image/data-flow.png b/proposals/images/portal-upordown-image/data-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..b9b24c37bdccf36a1542bd421abf2bba245cda87 GIT binary patch literal 57379 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πYU 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 literal 0 HcmV?d00001 diff --git a/proposals/new/portal-upordown-image.md b/proposals/new/portal-upordown-image.md new file mode 100644 index 00000000..7ef9ed8f --- /dev/null +++ b/proposals/new/portal-upordown-image.md @@ -0,0 +1,149 @@ +# Upload or Download Artifacte from portal + +Author: Leng Rongfu + +## Abstract +Current users, upload artifacts to the current registry from the Harbor portal, or download artifacts. + + +## Background +Currently, push/pull images must be able to access the registry service. However, in some enterprises, users are denied access to the /v2 interface of the core service on their local machines, and can only access the Harbor portal page. Therefore, it is more convenient to upload or download images on the page. + + +## User Stories + +### Story 1 +As a system administrator, you can upload or download images from any project. + +### Story 2 +As a project administrator, you can upload or download images from the current project. + +### Story 3 +As a user, when you have the push image permission for a certain project, you can upload images to that project. + +### Story 4 +As a user, when you have the pull image permission for a certain project, you can download images to that project. + +### Story 6 +As a user, when you not have the pull or push image permission for a certain project, you not can download or upload images to that project. + +## Premise +1, The portal can be accessed normally. + +## Proposal + +We propose the following solutions: + +1. Add "Upload Image" and "Download Image" buttons to the Action section on the Repositories detail page. +2. When a user has the push image permission, the "Upload Image" button is clickable. +3. When a user has the pull image permission, the "Download Image" button is clickable. +4. Because it consumes resources, system administrators can set the number of concurrent uploads or downloads allowed. + +### APIs for upload/download image + + 1. Upload image + + ``` + POST /api/v2.0/projects/{project}/repositories/{repositorie}/artifacts/upload?tag=v1 + Content-type: form-data + Body: file + + ``` + + 2. Download image + + ``` + GET /api/v2.0/projects/{project}/repositories/{repositorie}/artifacts/download?tag=v1 + + ``` + + +### DB scheme + +> ConfigEntry is System Setting use table. +``` +type ConfigEntry struct { + ID int64 `orm:"pk;auto;column(id)" json:"-"` + Key string `orm:"column(k)" json:"k"` + Value string `orm:"column(v)" json:"v"` +} +``` +Key: `upload_concurrent` +Key: `download_concurrent` + +### Configuration Manager + +Add the function to configure the limit of concurrent uploads or downloads on the System Setting page, and store it in the ConfigEntry database table through the Configuration Controller. + + +Use `src/controller/config/controller.go` `Controller` to manager concurrent. + + +### ArtifactAPI + +```go +type ArtifactAPI interface { + UploadArtifact(ctx context.Context, params artifact.UploadArtifactParams) middleware.Responder + DownloadArtifact(ctx context.Context, params artifact.DownloadArtifactParams) middleware.Responder +} + +type UploadArtifactParams { + HTTPRequest *http.Request `json:"-"` + XRequestID *string + tag string + ProjectName string + RepositoryName string +} + +type DownloadArtifactParams{ + HTTPRequest *http.Request `json:"-"` + XRequestID *string + tag string + ProjectName string + RepositoryName string +} +``` + +### Solution + +![data-flow](../images/portal-upordown-image/data-flow.png) + +Image uploading and downloading are performed in the Harbor-core service. During uploading, the input stream is read from the http.Request and then directly pushed to the registry. During downloading, the image is pulled from the registry and then directly written into the http.ResponseWriter. + +#### Use skopeo tools + +use `skopeo` command tools to push or pull image. + +```go +func uploadHandler(w http.ResponseWriter, r *http.Request) { + file, _, err := r.FormFile("file") + cmd := exec.Command("skopeo", "copy","docker-archive:/dev/stdin", "docker://registry.com/library/busybox:v1") + cmd.Stdin = file + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr +} +func downloadHandler(w http.ResponseWriter, r *http.Request) { + cmd := exec.Command("skopeo", "copy", "--format=v2s2", "--quiet", "docker://registry.com/library/busybox:v1", "docker-archive:/dev/stdout") + cmd.Stdin = os.Stdin + cmd.Stdout = w + cmd.Stderr = os.Stderr +} +``` + +#### Use Regclient + +use `github.com/regclient/regclient` project to push or pull image. + +```go +func uploadHandler(w http.ResponseWriter, r *http.Request) { + file, _, err := r.FormFile("file") + imageRef, err := ref.New("registry.com/library/busybox:v1") + err = regClient.ImageImport(context.Background(), imageRef, &file) +} + +func downloadHandler(w http.ResponseWriter, r *http.Request) { + imageRef, err := ref.New("registry.com/library/busybox:v1") + regClient.ImageExport(context.Background(), imageRef, w) +} +``` +