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,171 @@
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
}