285 lines
8.3 KiB
Go
285 lines
8.3 KiB
Go
package mock
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/ocdp/cluster-service/internal/domain/entity"
|
|
"github.com/ocdp/cluster-service/internal/domain/repository"
|
|
)
|
|
|
|
// OCIClientMock OCI Registry 客户端 Mock 实现
|
|
type OCIClientMock struct {
|
|
// Mock 数据存储
|
|
repositories map[string][]string // registryID -> []repositoryName
|
|
artifacts map[string]map[string][]*entity.Artifact // registryID -> repository -> []artifact
|
|
}
|
|
|
|
// NewOCIClientMock 创建 Mock 实现
|
|
func NewOCIClientMock() repository.OCIClient {
|
|
mock := &OCIClientMock{
|
|
repositories: make(map[string][]string),
|
|
artifacts: make(map[string]map[string][]*entity.Artifact),
|
|
}
|
|
|
|
// 初始化一些测试数据
|
|
mock.initMockData()
|
|
|
|
return mock
|
|
}
|
|
|
|
func (c *OCIClientMock) initMockData() {
|
|
// Note: This method intentionally left empty
|
|
// Mock data will be generated dynamically per registry to support any registry ID
|
|
}
|
|
|
|
// initArtifactsForRegistry initializes mock artifacts for a given registry ID
|
|
func (c *OCIClientMock) initArtifactsForRegistry(registryID string) {
|
|
c.artifacts[registryID] = make(map[string][]*entity.Artifact)
|
|
|
|
// vllm-serve artifacts (OCI 格式的 Helm Chart)
|
|
c.artifacts[registryID]["charts/vllm-serve"] = []*entity.Artifact{
|
|
{
|
|
RegistryID: registryID,
|
|
Repository: "charts/vllm-serve",
|
|
Tag: "0.1.0",
|
|
Digest: "sha256:abc123def456",
|
|
Type: entity.ArtifactTypeChart,
|
|
Size: 12345678,
|
|
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
|
ConfigType: "application/vnd.cncf.helm.config.v1+json", // Helm Chart 的 config type
|
|
Annotations: map[string]string{
|
|
"org.opencontainers.image.title": "vllm-serve",
|
|
"org.opencontainers.image.version": "0.1.0",
|
|
},
|
|
CreatedAt: time.Now().Add(-24 * time.Hour),
|
|
},
|
|
{
|
|
RegistryID: registryID,
|
|
Repository: "charts/vllm-serve",
|
|
Tag: "0.2.0",
|
|
Digest: "sha256:xyz789uvw012",
|
|
Type: entity.ArtifactTypeChart,
|
|
Size: 13456789,
|
|
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
|
ConfigType: "application/vnd.cncf.helm.config.v1+json", // Helm Chart 的 config type
|
|
Annotations: map[string]string{
|
|
"org.opencontainers.image.title": "vllm-serve",
|
|
"org.opencontainers.image.version": "0.2.0",
|
|
},
|
|
CreatedAt: time.Now(),
|
|
},
|
|
}
|
|
|
|
// nginx artifacts (OCI 格式的 Helm Chart)
|
|
c.artifacts[registryID]["charts/nginx"] = []*entity.Artifact{
|
|
{
|
|
RegistryID: registryID,
|
|
Repository: "charts/nginx",
|
|
Tag: "1.0.0",
|
|
Digest: "sha256:nginx123456",
|
|
Type: entity.ArtifactTypeChart,
|
|
Size: 5678901,
|
|
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
|
ConfigType: "application/vnd.cncf.helm.config.v1+json", // Helm Chart 的 config type
|
|
Annotations: map[string]string{
|
|
"org.opencontainers.image.title": "nginx",
|
|
},
|
|
CreatedAt: time.Now().Add(-48 * time.Hour),
|
|
},
|
|
}
|
|
|
|
// redis artifacts (OCI 格式的 Helm Chart)
|
|
c.artifacts[registryID]["charts/redis"] = []*entity.Artifact{
|
|
{
|
|
RegistryID: registryID,
|
|
Repository: "charts/redis",
|
|
Tag: "6.2.0",
|
|
Digest: "sha256:redis789abc",
|
|
Type: entity.ArtifactTypeChart,
|
|
Size: 8901234,
|
|
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
|
ConfigType: "application/vnd.cncf.helm.config.v1+json", // Helm Chart 的 config type
|
|
Annotations: map[string]string{
|
|
"org.opencontainers.image.title": "redis",
|
|
"org.opencontainers.image.version": "6.2.0",
|
|
},
|
|
CreatedAt: time.Now().Add(-72 * time.Hour),
|
|
},
|
|
}
|
|
|
|
// alpine artifacts (Docker Image)
|
|
c.artifacts[registryID]["library/alpine"] = []*entity.Artifact{
|
|
{
|
|
RegistryID: registryID,
|
|
Repository: "library/alpine",
|
|
Tag: "3.18",
|
|
Digest: "sha256:alpine123",
|
|
Type: entity.ArtifactTypeImage,
|
|
Size: 2345678,
|
|
MediaType: "application/vnd.docker.distribution.manifest.v2+json",
|
|
ConfigType: "application/vnd.docker.container.image.v1+json", // Docker Image 的 config type
|
|
Annotations: map[string]string{
|
|
"org.opencontainers.image.title": "alpine",
|
|
"org.opencontainers.image.version": "3.18",
|
|
},
|
|
CreatedAt: time.Now().Add(-96 * time.Hour),
|
|
},
|
|
{
|
|
RegistryID: registryID,
|
|
Repository: "library/alpine",
|
|
Tag: "latest",
|
|
Digest: "sha256:alpine456",
|
|
Type: entity.ArtifactTypeImage,
|
|
Size: 2456789,
|
|
MediaType: "application/vnd.docker.distribution.manifest.v2+json",
|
|
ConfigType: "application/vnd.docker.container.image.v1+json", // Docker Image 的 config type
|
|
Annotations: map[string]string{
|
|
"org.opencontainers.image.title": "alpine",
|
|
},
|
|
CreatedAt: time.Now().Add(-24 * time.Hour),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (c *OCIClientMock) ListRepositories(ctx context.Context, registry *entity.Registry) ([]string, error) {
|
|
// Check if we have cached data for this registry
|
|
repos, exists := c.repositories[registry.ID]
|
|
if !exists {
|
|
// Generate mock data dynamically for any registry
|
|
repos = []string{
|
|
"charts/vllm-serve",
|
|
"charts/nginx",
|
|
"charts/redis",
|
|
"library/alpine",
|
|
}
|
|
c.repositories[registry.ID] = repos
|
|
|
|
// Also initialize artifacts for this registry
|
|
c.initArtifactsForRegistry(registry.ID)
|
|
}
|
|
return repos, nil
|
|
}
|
|
|
|
func (c *OCIClientMock) ListArtifacts(ctx context.Context, registry *entity.Registry, repository, mediaTypeFilter string) ([]*entity.Artifact, error) {
|
|
regArtifacts, exists := c.artifacts[registry.ID]
|
|
if !exists {
|
|
// Initialize artifacts for this registry if not exists
|
|
c.initArtifactsForRegistry(registry.ID)
|
|
regArtifacts = c.artifacts[registry.ID]
|
|
}
|
|
|
|
artifacts, exists := regArtifacts[repository]
|
|
if !exists {
|
|
return []*entity.Artifact{}, nil
|
|
}
|
|
|
|
// 应用 mediaType 过滤
|
|
if mediaTypeFilter == "" || mediaTypeFilter == "all" {
|
|
return artifacts, nil
|
|
}
|
|
|
|
filtered := make([]*entity.Artifact, 0)
|
|
filter := strings.ToLower(strings.TrimSpace(mediaTypeFilter))
|
|
|
|
for _, artifact := range artifacts {
|
|
switch filter {
|
|
case "chart":
|
|
if artifact.Type == entity.ArtifactTypeChart {
|
|
filtered = append(filtered, artifact)
|
|
}
|
|
case "image":
|
|
if artifact.Type == entity.ArtifactTypeImage {
|
|
filtered = append(filtered, artifact)
|
|
}
|
|
case "other":
|
|
if artifact.Type == entity.ArtifactTypeOther {
|
|
filtered = append(filtered, artifact)
|
|
}
|
|
}
|
|
}
|
|
|
|
return filtered, nil
|
|
}
|
|
|
|
func (c *OCIClientMock) GetArtifact(ctx context.Context, registry *entity.Registry, repository, reference string) (*entity.Artifact, error) {
|
|
regArtifacts, exists := c.artifacts[registry.ID]
|
|
if !exists {
|
|
// Initialize artifacts for this registry if not exists
|
|
c.initArtifactsForRegistry(registry.ID)
|
|
regArtifacts = c.artifacts[registry.ID]
|
|
}
|
|
|
|
artifacts, exists := regArtifacts[repository]
|
|
if !exists {
|
|
return nil, entity.ErrArtifactNotFound
|
|
}
|
|
|
|
// 根据 tag 或 digest 查找
|
|
for _, artifact := range artifacts {
|
|
if artifact.Tag == reference || artifact.Digest == reference {
|
|
return artifact, nil
|
|
}
|
|
}
|
|
|
|
return nil, entity.ErrArtifactNotFound
|
|
}
|
|
|
|
func (c *OCIClientMock) GetValuesSchema(ctx context.Context, registry *entity.Registry, repository, reference string) (string, error) {
|
|
artifact, err := c.GetArtifact(ctx, registry, repository, reference)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if !artifact.IsChart() {
|
|
return "", fmt.Errorf("not a helm chart")
|
|
}
|
|
|
|
// 返回 Mock values schema
|
|
mockSchema := `{
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"type": "object",
|
|
"properties": {
|
|
"replicaCount": {
|
|
"type": "integer",
|
|
"default": 1
|
|
},
|
|
"image": {
|
|
"type": "object",
|
|
"properties": {
|
|
"repository": {
|
|
"type": "string"
|
|
},
|
|
"tag": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`
|
|
return mockSchema, nil
|
|
}
|
|
|
|
func (c *OCIClientMock) PullArtifact(ctx context.Context, registry *entity.Registry, repository, reference, destPath string) error {
|
|
_, err := c.GetArtifact(ctx, registry, repository, reference)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Mock 实现,不实际下载
|
|
return nil
|
|
}
|
|
|
|
func (c *OCIClientMock) PushArtifact(ctx context.Context, registry *entity.Registry, repository, tag, sourcePath string) error {
|
|
// Mock 实现,不实际上传
|
|
return nil
|
|
}
|
|
|
|
func (c *OCIClientMock) CheckHealth(ctx context.Context, registry *entity.Registry) error {
|
|
// Mock 实现,总是返回健康
|
|
return nil
|
|
}
|
|
|