wip: oci image management

This commit is contained in:
loveuer
2025-11-09 15:19:11 +08:00
commit 8de8234372
58 changed files with 6142 additions and 0 deletions

153
handler/manifest.go Normal file
View File

@@ -0,0 +1,153 @@
package handler
import (
"strconv"
"strings"
"gitea.loveuer.com/loveuer/cluster/controller"
"gitea.loveuer.com/loveuer/cluster/internal/registry/storage"
"github.com/gofiber/fiber/v3"
)
// GetManifest 获取 manifest
func GetManifest(store storage.Storage) fiber.Handler {
return func(c fiber.Ctx) error {
repo := c.Locals("repo_name")
repoStr := ""
if repo != nil {
repoStr = repo.(string)
}
if repoStr == "" {
repoStr = strings.TrimPrefix(c.Params("name"), "/")
}
reference := c.Locals("reference")
referenceStr := ""
if reference != nil {
referenceStr = reference.(string)
}
data, mediaType, digest, err := controller.GetManifest(store, repoStr, referenceStr)
if err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"errors": []fiber.Map{
{
"code": "MANIFEST_UNKNOWN",
"message": err.Error(),
},
},
})
}
c.Set("Content-Type", mediaType)
c.Set("Content-Length", strconv.FormatInt(int64(len(data)), 10))
c.Set("Docker-Content-Digest", digest)
return c.Send(data)
}
}
// PutManifest 推送 manifest
func PutManifest(store storage.Storage) fiber.Handler {
return func(c fiber.Ctx) error {
repo := c.Locals("repo_name")
repoStr := ""
if repo != nil {
repoStr = repo.(string)
}
if repoStr == "" {
repoStr = c.Params("name")
}
reference := c.Locals("reference")
referenceStr := ""
if reference != nil {
referenceStr = reference.(string)
}
// 读取请求体
data := c.Body()
// 获取 Content-Type
mediaType := c.Get("Content-Type")
if mediaType == "" {
mediaType = "application/vnd.docker.distribution.manifest.v2+json"
}
digest, err := controller.PutManifest(store, repoStr, referenceStr, data, mediaType)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"errors": []fiber.Map{
{
"code": "INTERNAL_ERROR",
"message": err.Error(),
},
},
})
}
// 返回 Location 和 Digest
c.Set("Location", c.Path())
c.Set("Docker-Content-Digest", digest)
return c.SendStatus(fiber.StatusCreated)
}
}
// DeleteManifest 删除 manifest
func DeleteManifest(store storage.Storage) fiber.Handler {
return func(c fiber.Ctx) error {
repo := c.Locals("repo_name")
repoStr := ""
if repo != nil {
repoStr = repo.(string)
}
if repoStr == "" {
repoStr = c.Params("name")
}
reference := c.Locals("reference")
referenceStr := ""
if reference != nil {
referenceStr = reference.(string)
}
if err := controller.DeleteManifest(store, repoStr, referenceStr); err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"errors": []fiber.Map{
{
"code": "MANIFEST_UNKNOWN",
"message": err.Error(),
},
},
})
}
return c.SendStatus(fiber.StatusAccepted)
}
}
// HeadManifest 检查 manifest 是否存在
func HeadManifest(store storage.Storage) fiber.Handler {
return func(c fiber.Ctx) error {
repo := c.Locals("repo_name")
repoStr := ""
if repo != nil {
repoStr = repo.(string)
}
if repoStr == "" {
repoStr = strings.TrimPrefix(c.Params("name"), "/")
}
reference := c.Locals("reference")
referenceStr := ""
if reference != nil {
referenceStr = reference.(string)
}
exists, data, mediaType, digest, err := controller.HeadManifest(store, repoStr, referenceStr)
if err != nil || !exists {
return c.SendStatus(fiber.StatusNotFound)
}
c.Set("Content-Type", mediaType)
c.Set("Content-Length", strconv.FormatInt(int64(len(data)), 10))
c.Set("Docker-Content-Digest", digest)
return c.SendStatus(fiber.StatusOK)
}
}