Files
ocdp-go/backend/internal/domain/entity/artifact.go
mangomqy c5e51ed069 ocdp v1
2025-11-13 02:54:06 +00:00

172 lines
5.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package entity
import (
"strings"
"time"
)
// ArtifactType Artifact 类型
type ArtifactType string
const (
ArtifactTypeChart ArtifactType = "chart" // Helm Chart
ArtifactTypeImage ArtifactType = "image" // Docker/OCI Image
ArtifactTypeOther ArtifactType = "other" // Other types
)
// Artifact OCI Artifact 领域实体
type Artifact struct {
RegistryID string
Repository string
Tag string
Digest string
Type ArtifactType
Size int64
MediaType string
ConfigType string // Config layer 的 mediaType (用于更准确的类型判断)
Annotations map[string]string
CreatedAt time.Time
}
// Repository 仓库信息
type Repository struct {
RegistryID string
Name string
TagCount int
}
// NewArtifact 创建新 Artifact
func NewArtifact(registryID, repository, tag, digest string) *Artifact {
return &Artifact{
RegistryID: registryID,
Repository: repository,
Tag: tag,
Digest: digest,
Annotations: make(map[string]string),
CreatedAt: time.Now(),
}
}
// SetType 设置 Artifact 类型(根据 mediaType 识别为 chart | image | other
// 已废弃:请使用 DetermineType() 方法,它提供更准确的类型判断
func (a *Artifact) SetType(mediaType string) {
lowerMediaType := strings.ToLower(strings.TrimSpace(mediaType))
containsAny := func(target string, keywords ...string) bool {
for _, keyword := range keywords {
if keyword != "" && strings.Contains(target, keyword) {
return true
}
}
return false
}
switch {
case lowerMediaType == "":
a.Type = ArtifactTypeOther
case containsAny(lowerMediaType,
"helm", "cncf.helm", "helm.chart", "helm+", "chart+json", "chart.v1", "helm-package", "helm.config",
):
a.Type = ArtifactTypeChart
case containsAny(lowerMediaType,
"docker", "vnd.docker", "docker.distribution", "docker.container.image",
"vnd.oci", "oci.image", "opencontainers", "container.image",
):
a.Type = ArtifactTypeImage
case strings.Contains(lowerMediaType, "image") || strings.Contains(lowerMediaType, "manifest") || strings.Contains(lowerMediaType, "container"):
a.Type = ArtifactTypeImage
default:
a.Type = ArtifactTypeOther
}
}
// DetermineType 智能判断 Artifact 类型(综合多种信息)
// 优先级:
// 1. ConfigType (config.mediaType) - 最准确
// 2. Annotations - 可能包含类型标注
// 3. Repository 名称 - charts/ 前缀暗示
// 4. MediaType - 兜底判断
func (a *Artifact) DetermineType() {
containsAny := func(target string, keywords ...string) bool {
for _, keyword := range keywords {
if keyword != "" && strings.Contains(target, keyword) {
return true
}
}
return false
}
// 1. 优先检查 ConfigType最准确的判断方式
if a.ConfigType != "" {
lowerConfigType := strings.ToLower(strings.TrimSpace(a.ConfigType))
// Helm Chart 的 config.mediaType
if containsAny(lowerConfigType,
"helm.config", "cncf.helm", "helm.chart", "chart.content",
) {
a.Type = ArtifactTypeChart
return
}
// Docker/OCI Image 的 config.mediaType
if containsAny(lowerConfigType,
"docker.container.image", "oci.image.config",
) {
a.Type = ArtifactTypeImage
return
}
}
// 2. 检查 Annotations
for key, value := range a.Annotations {
lowerKey := strings.ToLower(key)
lowerValue := strings.ToLower(value)
if containsAny(lowerKey, "helm", "chart") ||
containsAny(lowerValue, "helm", "chart") {
a.Type = ArtifactTypeChart
return
}
}
// 3. 检查 Repository 名称(辅助判断)
if strings.HasPrefix(strings.ToLower(a.Repository), "charts/") {
// charts/ 开头的仓库很可能是 Helm Chart
// 但需要结合 MediaType 进一步确认
lowerMediaType := strings.ToLower(strings.TrimSpace(a.MediaType))
// 如果是 OCI manifest 格式,很可能是以 OCI 格式存储的 Helm Chart
if strings.Contains(lowerMediaType, "oci.image.manifest") ||
strings.Contains(lowerMediaType, "vnd.oci") {
a.Type = ArtifactTypeChart
return
}
}
// 4. 回退到基于 MediaType 的判断(兜底逻辑)
lowerMediaType := strings.ToLower(strings.TrimSpace(a.MediaType))
switch {
case lowerMediaType == "":
a.Type = ArtifactTypeOther
case containsAny(lowerMediaType,
"helm", "cncf.helm", "helm.chart", "helm+", "chart+json", "chart.v1", "helm-package", "helm.config",
):
a.Type = ArtifactTypeChart
case containsAny(lowerMediaType,
"docker", "vnd.docker", "docker.distribution", "docker.container.image",
):
a.Type = ArtifactTypeImage
case strings.Contains(lowerMediaType, "image") || strings.Contains(lowerMediaType, "manifest"):
a.Type = ArtifactTypeImage
default:
a.Type = ArtifactTypeOther
}
}
// IsChart 判断是否为 Helm Chart
func (a *Artifact) IsChart() bool {
return a.Type == ArtifactTypeChart
}