From 9bf7bab6e6c5562f9baec25ab7a36bd13e858831 Mon Sep 17 00:00:00 2001 From: mrpye Date: Mon, 20 Feb 2023 12:24:09 +0000 Subject: [PATCH 1/2] Added import all images from folder --- charts/cimpex-0.1.0.tgz | Bin 0 -> 3797 bytes docs/docs.go | 40 +++++++++++++++++++++ docs/swagger.json | 40 +++++++++++++++++++++ docs/swagger.yaml | 26 ++++++++++++++ documents/api.md | 44 +++++++++++++++++++++++ modules/api/api.go | 60 ++++++++++++++++++++++++++++++- modules/body_types/body_types.go | 1 + 7 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 charts/cimpex-0.1.0.tgz diff --git a/charts/cimpex-0.1.0.tgz b/charts/cimpex-0.1.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..0ef3fe7b5ffd5dcdc2a5f4637ea88d53052328d9 GIT binary patch literal 3797 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 L?DiBl08jt`KH7Ib literal 0 HcmV?d00001 diff --git a/docs/docs.go b/docs/docs.go index 40b3e07..308d1f8 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -143,6 +143,43 @@ const docTemplate = `{ } } }, + "/imports": { + "post": { + "produces": [ + "application/json" + ], + "summary": "Import the tar files in the directory", + "operationId": "post-import-list-docker-images", + "parameters": [ + { + "description": "query params", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/body_types.ImportExportRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/body_types.PackageInfo" + } + } + }, + "404": { + "description": "error", + "schema": { + "type": "string" + } + } + } + } + }, "/list": { "post": { "produces": [ @@ -191,6 +228,9 @@ const docTemplate = `{ "image_name_tag": { "type": "string" }, + "status": { + "type": "string" + }, "tar_path": { "type": "string" } diff --git a/docs/swagger.json b/docs/swagger.json index 0fdc576..41d6bb1 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -137,6 +137,43 @@ } } }, + "/imports": { + "post": { + "produces": [ + "application/json" + ], + "summary": "Import the tar files in the directory", + "operationId": "post-import-list-docker-images", + "parameters": [ + { + "description": "query params", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/body_types.ImportExportRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/body_types.PackageInfo" + } + } + }, + "404": { + "description": "error", + "schema": { + "type": "string" + } + } + } + } + }, "/list": { "post": { "produces": [ @@ -185,6 +222,9 @@ "image_name_tag": { "type": "string" }, + "status": { + "type": "string" + }, "tar_path": { "type": "string" } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index f9a4d76..6b42d85 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -13,6 +13,8 @@ definitions: properties: image_name_tag: type: string + status: + type: string tar_path: type: string type: object @@ -107,6 +109,30 @@ paths: schema: type: string summary: Import Docker Image to Registry from tar file + /imports: + post: + operationId: post-import-list-docker-images + parameters: + - description: query params + in: body + name: request + required: true + schema: + $ref: '#/definitions/body_types.ImportExportRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/body_types.PackageInfo' + type: array + "404": + description: error + schema: + type: string + summary: Import the tar files in the directory /list: post: operationId: post-list-docker-images diff --git a/documents/api.md b/documents/api.md index 1e6ae3b..c6b47dd 100644 --- a/documents/api.md +++ b/documents/api.md @@ -40,6 +40,7 @@ cimpex is a CLI application written in Golang that gives the ability import and | POST | /export | [post export docker image](#post-export-docker-image) | Export Docker Image from Registry to tar file | | POST | /exports | [post exports docker images](#post-exports-docker-images) | Exports Docker Images from Registry to tar file | | POST | /import | [post import docker image](#post-import-docker-image) | Import Docker Image to Registry from tar file | +| POST | /imports | [post import list docker images](#post-import-list-docker-images) | Import the tar files in the directory | | POST | /list | [post list docker images](#post-list-docker-images) | List the docker images tar files in the directory | @@ -198,6 +199,48 @@ Status: Not Found +### Import the tar files in the directory (*post-import-list-docker-images*) + +``` +POST /imports +``` + +#### Produces + * application/json + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| request | `body` | [BodyTypesImportExportRequest](#body-types-import-export-request) | `models.BodyTypesImportExportRequest` | | ✓ | | query params | + +#### All responses +| Code | Status | Description | Has headers | Schema | +|------|--------|-------------|:-----------:|--------| +| [200](#post-import-list-docker-images-200) | OK | OK | | [schema](#post-import-list-docker-images-200-schema) | +| [404](#post-import-list-docker-images-404) | Not Found | error | | [schema](#post-import-list-docker-images-404-schema) | + +#### Responses + + +##### 200 - OK +Status: OK + +###### Schema + + + +[][BodyTypesPackageInfo](#body-types-package-info) + +##### 404 - error +Status: Not Found + +###### Schema + + + + + ### List the docker images tar files in the directory (*post-list-docker-images*) ``` @@ -265,6 +308,7 @@ Status: Not Found | Name | Type | Go type | Required | Default | Description | Example | |------|------|---------|:--------:| ------- |-------------|---------| | image_name_tag | string| `string` | | | | | +| status | string| `string` | | | | | | tar_path | string| `string` | | | | | diff --git a/modules/api/api.go b/modules/api/api.go index 1df4707..e656f94 100644 --- a/modules/api/api.go +++ b/modules/api/api.go @@ -186,6 +186,59 @@ func postListImages(c *gin.Context) { } +// @Summary Import the tar files in the directory +// @ID post-import-list-docker-images +// @Produce json +// @Param request body body_types.ImportExportRequest.request true true "query params" +// @Success 200 {object} []body_types.PackageInfo.response +// @Failure 404 {string} string "error" +// @Router /imports [post] +func postImportImagesFromFolder(c *gin.Context) { + + var importRequest body_types.ImportExportRequest + + // Call BindJSON to bind the received JSON to + if err := c.BindJSON(&importRequest); err != nil { + c.IndentedJSON(http.StatusBadRequest, "Bad payload") + return + } + token := strings.Split(c.Request.Header["Authorization"][0], " ")[1] + dec := helper.DecodeB64(token) + parts := strings.Split(dec, ":") + if parts[0] == "" || parts[1] == "" { + c.IndentedJSON(http.StatusUnauthorized, "Missing username or password") + return + } + + reg := registry.CreateDockerRegistry(parts[0], parts[1], importRequest.IgnoreSSL) + + files, err := helper.WalkMatch(web_base_folder, "*.tar") + if err != nil { + c.IndentedJSON(http.StatusCreated, err.Error()) + return + } + + var results []body_types.PackageInfo + + for _, o := range files { + name_tag, _ := reg.GetImageNameTag(path.Join(web_base_folder, o)) + err := reg.Upload(importRequest.Target+name_tag, path.Join(web_base_folder, o)) + if err != nil { + if name_tag != "" { + results = append(results, body_types.PackageInfo{TarPath: o, ImageName: name_tag, Status: err.Error()}) + } + } else { + if name_tag != "" { + results = append(results, body_types.PackageInfo{TarPath: o, ImageName: name_tag, Status: "OK"}) + } + } + + } + + c.IndentedJSON(http.StatusCreated, results) + +} + // Function to start web server func StartWebServer(ip string, port string, base_folder string) { //**************** @@ -201,6 +254,7 @@ func StartWebServer(ip string, port string, base_folder string) { router.GET("/docs/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) router.POST("/import", postImport) + router.POST("/imports", postImportImagesFromFolder) router.POST("/export", postExport) router.POST("/exports", postExports) router.POST("/list", postListImages) @@ -219,6 +273,10 @@ func StartWebServer(ip string, port string, base_folder string) { web_base_folder = os.Getenv("BASE_FOLDER") } - router.Run(web_ip + ":" + web_port) + //**************** + //Start the server + //**************** + fmt.Printf("Web-Server started %s:%s", web_ip, web_port) + router.Run(fmt.Sprintf("%s:%s", web_ip, web_port)) } diff --git a/modules/body_types/body_types.go b/modules/body_types/body_types.go index d439d88..204038b 100644 --- a/modules/body_types/body_types.go +++ b/modules/body_types/body_types.go @@ -9,4 +9,5 @@ type ImportExportRequest struct { type PackageInfo struct { ImageName string `json:"image_name_tag"` TarPath string `json:"tar_path"` + Status string `json:"status"` } From 0f06e37314eb256a3711e468ac2529718db1e169 Mon Sep 17 00:00:00 2001 From: mrpye Date: Sat, 25 Mar 2023 15:44:11 +0000 Subject: [PATCH 2/2] update docs --- README.md | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 640c7e1..64a2c44 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Check out the CLI documentation [here](./documents/cimpex.md) Export and image fromm a registry with no authentication ``` bash -curl --location --request POST 'http://localhost:9020/export' \ +curl --location --request POST 'http://localhost:8080/export' \ --header 'Content-Type: application/json' \ --data-raw '{ "target":"cimpex:v1.0.0", @@ -105,11 +105,11 @@ curl --location --request POST 'http://localhost:9020/export' \ Export from a registry with authentication ```bash -curl --location --request POST 'http://172.16.10.237:9020/export' \ +curl --location --request POST 'http://localhost:8080/export' \ --header 'Authorization: Basic YWRtaW46cGFzc3dvcmQ=' \ --header 'Content-Type: application/json' \ --data-raw '{ - "target":"172.19.2.152/library/cimpex:v1.0.0", + "target":"127.0.0.1/library/cimpex:v1.0.0", "tar":"cimpex-v1-0-0.tar", "ignore_ssl":true } @@ -121,7 +121,7 @@ curl --location --request POST 'http://172.16.10.237:9020/export' \ ## Export images from a registry ``` bash -curl --location --request POST 'http://localhost:9020/exports' \ +curl --location --request POST 'http://localhost:8080/exports' \ --header 'Content-Type: application/json' \ --data-raw '[{ "target":"cimpex:v1.0.0", @@ -174,12 +174,35 @@ curl --location --request POST 'localhost:8080/import' \ - ignore_ssl (Ignore ssl cert) +
+Import images to a registry from the BASE_FOLDER + folder + +Import an images and imports to the target registry + +```bash +curl --location 'localhost:8080/imports' \ +--header 'Authorization: Basic YWRtaW46cGFzc3dvcmQ=' \ +--header 'Content-Type: application/json' \ +--data '{ + "target":"127.0.0.1/library/", + "ignore_ssl":true +}' + +``` + +## Json Payload + +- target (the docker registry) +- ignore_ssl (Ignore ssl cert) +
+
List images in the folder ```bash -curl --location --request POST 'localhost:8080/list' \ +curl --location --request POST ''http://localhost:8080/list' \ --header 'Content-Type: application/json' ```
@@ -189,7 +212,7 @@ curl --location --request POST 'localhost:8080/list' \ Test is alive ```bash -curl --location --request GET 'localhost:8080/' +curl --location --request GET ''http://localhost:8080/' ``` Return OK