This commit is contained in:
mangomqy
2025-11-13 02:54:06 +00:00
commit c5e51ed069
254 changed files with 54901 additions and 0 deletions

View File

@ -0,0 +1,193 @@
package rest
import (
"errors"
"net/http"
"github.com/gorilla/mux"
"github.com/ocdp/cluster-service/internal/adapter/input/http/dto"
"github.com/ocdp/cluster-service/internal/domain/entity"
"github.com/ocdp/cluster-service/internal/domain/service"
)
// ArtifactHandler Artifact Handler
type ArtifactHandler struct {
artifactService *service.ArtifactService
}
// NewArtifactHandler 创建 Artifact Handler
func NewArtifactHandler(artifactService *service.ArtifactService) *ArtifactHandler {
return &ArtifactHandler{
artifactService: artifactService,
}
}
// ListRepositories 列出 Registry 中的所有 repositories
// @Summary 列出 Registry 中的所有 Repositories
// @Description 列出指定 Registry 中的所有 Repository
// @Tags Artifacts
// @Accept json
// @Produce json
// @Param registry_id path string true "Registry ID"
// @Success 200 {object} dto.RepositoryListResponse
// @Failure 500 {object} dto.ErrorResponse
// @Router /registries/{registry_id}/repositories [get]
func (h *ArtifactHandler) ListRepositories(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
registryID := vars["registry_id"]
repositories, err := h.artifactService.ListRepositories(r.Context(), registryID)
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to list repositories", err.Error())
return
}
// Get registry info for URL
registry, err := h.artifactService.GetRegistry(r.Context(), registryID)
registryURL := ""
if err == nil && registry != nil {
registryURL = registry.URL
}
// Determine source and message based on repository count
source := "catalog"
catalogSupported := true
message := ""
if len(repositories) == 0 {
source = "unavailable"
message = "No repositories found in this registry"
}
response := &dto.RepositoryListResponse{
RegistryID: registryID,
RegistryURL: registryURL,
Repositories: repositories,
Total: len(repositories),
CatalogSupported: catalogSupported,
Source: source,
Message: message,
}
respondJSON(w, http.StatusOK, response)
}
// ListArtifacts 列出 repository 中的所有 artifacts返回扁平化的 Tag 数组)
// @Summary 列出 Repository 中的所有 Artifacts
// @Description 列出指定 Repository 中的所有 Artifact支持按类型过滤
// @Tags Artifacts
// @Accept json
// @Produce json
// @Param registry_id path string true "Registry ID"
// @Param repository_name path string true "Repository Name (URL encoded, e.g. charts%2Fnginx)"
// @Param media_type query string false "过滤 Artifact 类型 (all, chart, image, other)" default(all)
// @Success 200 {array} dto.TagResponse
// @Failure 500 {object} dto.ErrorResponse
// @Router /registries/{registry_id}/repositories/{repository_name}/artifacts [get]
func (h *ArtifactHandler) ListArtifacts(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
registryID := vars["registry_id"]
repositoryName := vars["repository_name"]
// 获取 mediaType 过滤参数(默认为 "all"
mediaTypeFilter := r.URL.Query().Get("media_type")
if mediaTypeFilter == "" {
mediaTypeFilter = "all"
}
artifacts, err := h.artifactService.ListArtifacts(r.Context(), registryID, repositoryName, mediaTypeFilter)
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to list artifacts", err.Error())
return
}
// 转换为前端期望的扁平化 Tag 数组
tagResponses := make([]*dto.TagResponse, 0, len(artifacts))
for _, artifact := range artifacts {
tagResponses = append(tagResponses, &dto.TagResponse{
RepositoryName: artifact.Repository,
Tag: artifact.Tag,
Type: string(artifact.Type),
MediaType: artifact.MediaType,
Size: artifact.Size,
})
}
// 直接返回数组,不包装
respondJSON(w, http.StatusOK, tagResponses)
}
// GetArtifact 获取 artifact 详情
// @Summary 获取 Artifact 详情
// @Description 获取指定 Artifact 的详细信息
// @Tags Artifacts
// @Accept json
// @Produce json
// @Param registry_id path string true "Registry ID"
// @Param repository_name path string true "Repository Name (URL encoded)"
// @Param reference path string true "Artifact Reference (tag or digest)"
// @Success 200 {object} dto.ArtifactResponse
// @Failure 404 {object} dto.ErrorResponse
// @Router /registries/{registry_id}/repositories/{repository_name}/artifacts/{reference} [get]
func (h *ArtifactHandler) GetArtifact(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
registryID := vars["registry_id"]
repositoryName := vars["repository_name"]
reference := vars["reference"]
artifact, err := h.artifactService.GetArtifact(r.Context(), registryID, repositoryName, reference)
if err != nil {
respondError(w, http.StatusNotFound, "Artifact not found", err.Error())
return
}
response := &dto.ArtifactResponse{
RepositoryName: artifact.Repository,
Tag: artifact.Tag,
Digest: artifact.Digest,
Type: string(artifact.Type),
Size: artifact.Size,
CreatedAt: artifact.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
}
respondJSON(w, http.StatusOK, response)
}
// GetArtifactValuesSchema 获取 Helm Chart 的 values schema
// @Summary 获取 Helm Chart Values Schema
// @Description 获取 Helm Chart 的 values.schema.json (仅支持 Chart 类型)
// @Tags Artifacts
// @Accept json
// @Produce json
// @Param registry_id path string true "Registry ID"
// @Param repository_name path string true "Repository Name (URL encoded)"
// @Param reference path string true "Artifact Reference (tag or digest)"
// @Success 200 {object} dto.ValuesSchemaResponse
// @Failure 500 {object} dto.ErrorResponse
// @Router /registries/{registry_id}/repositories/{repository_name}/artifacts/{reference}/values-schema [get]
func (h *ArtifactHandler) GetArtifactValuesSchema(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
registryID := vars["registry_id"]
repositoryName := vars["repository_name"]
reference := vars["reference"]
schema, err := h.artifactService.GetValuesSchema(r.Context(), registryID, repositoryName, reference)
if err != nil {
switch {
case errors.Is(err, entity.ErrRegistryNotFound),
errors.Is(err, entity.ErrRepositoryNotFound),
errors.Is(err, entity.ErrArtifactNotFound),
errors.Is(err, entity.ErrValuesSchemaNotFound):
respondError(w, http.StatusNotFound, "Values schema not found", err.Error())
default:
respondError(w, http.StatusInternalServerError, "Failed to get values schema", err.Error())
}
return
}
response := &dto.ValuesSchemaResponse{
Schema: schema,
}
respondJSON(w, http.StatusOK, response)
}