feat(frontend): add Helm chart browser, monitoring, chart-references and values templates pages
Add new frontend pages for the multi-tenant OCDP platform: - Charts page (/charts): Browse Harbor OCI registries to list Helm chart repositories and versions, with deploy modal to launch charts on selected clusters - Monitoring page (/monitoring): Display cluster metrics (CPU/Memory/GPU usage) and per-node details with resource utilization bars - Chart References page (/chart-references): CRUD for chart metadata references - Values Templates page (/templates): CRUD for Helm values templates with version history and rollback support - Sidebar: Add Charts navigation, update Storage and Templates links - api.ts: Add all API client functions (clusterApi, registryApi, instanceApi, monitoringApi, storageApi, chartReferenceApi, valuesTemplateApi, workspaceApi, userApi) with full TypeScript types Note: deploy flow and values template rollback not yet end-to-end tested.
This commit is contained in:
137
backend/internal/domain/service/chart_reference_service.go
Normal file
137
backend/internal/domain/service/chart_reference_service.go
Normal file
@ -0,0 +1,137 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/ocdp/cluster-service/internal/domain/entity"
|
||||
"github.com/ocdp/cluster-service/internal/domain/repository"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrChartReferenceNotFound = errors.New("chart reference not found")
|
||||
ErrChartReferenceExists = errors.New("chart reference already exists")
|
||||
)
|
||||
|
||||
// ChartReferenceService Chart 引用领域服务
|
||||
type ChartReferenceService struct {
|
||||
chartRefRepo repository.ChartReferenceRepository
|
||||
registryRepo repository.RegistryRepository
|
||||
}
|
||||
|
||||
// NewChartReferenceService 创建 Chart 引用服务
|
||||
func NewChartReferenceService(
|
||||
chartRefRepo repository.ChartReferenceRepository,
|
||||
registryRepo repository.RegistryRepository,
|
||||
) *ChartReferenceService {
|
||||
return &ChartReferenceService{
|
||||
chartRefRepo: chartRefRepo,
|
||||
registryRepo: registryRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建 Chart 引用
|
||||
func (s *ChartReferenceService) Create(
|
||||
ctx context.Context,
|
||||
workspaceID, registryID, repository, chartName, description string,
|
||||
) (*entity.ChartReference, error) {
|
||||
// 检查 Registry 是否存在
|
||||
registry, err := s.registryRepo.GetByID(ctx, registryID)
|
||||
if err != nil {
|
||||
return nil, errors.New("registry not found")
|
||||
}
|
||||
|
||||
// 检查名称是否已存在
|
||||
existing, _ := s.chartRefRepo.GetByName(ctx, workspaceID, chartName)
|
||||
if existing != nil {
|
||||
return nil, ErrChartReferenceExists
|
||||
}
|
||||
|
||||
chartRef := entity.NewChartReference(workspaceID, registry.ID, repository, chartName, description)
|
||||
chartRef.Description = description
|
||||
|
||||
if err := s.chartRefRepo.Create(ctx, chartRef); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return chartRef, nil
|
||||
}
|
||||
|
||||
// GetByID 获取 Chart 引用
|
||||
func (s *ChartReferenceService) GetByID(ctx context.Context, id string) (*entity.ChartReference, error) {
|
||||
chartRef, err := s.chartRefRepo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, ErrChartReferenceNotFound
|
||||
}
|
||||
return chartRef, nil
|
||||
}
|
||||
|
||||
// GetByWorkspace 获取工作空间的所有 Chart 引用
|
||||
func (s *ChartReferenceService) GetByWorkspace(ctx context.Context, workspaceID string) ([]*entity.ChartReference, error) {
|
||||
return s.chartRefRepo.GetByWorkspace(ctx, workspaceID)
|
||||
}
|
||||
|
||||
// GetByRegistry 获取 Registry 的所有 Chart 引用
|
||||
func (s *ChartReferenceService) GetByRegistry(ctx context.Context, registryID string) ([]*entity.ChartReference, error) {
|
||||
return s.chartRefRepo.GetByRegistry(ctx, registryID)
|
||||
}
|
||||
|
||||
// Update 更新 Chart 引用
|
||||
func (s *ChartReferenceService) Update(
|
||||
ctx context.Context,
|
||||
id, registryID, repository, chartName, description string,
|
||||
isEnabled bool,
|
||||
) (*entity.ChartReference, error) {
|
||||
chartRef, err := s.chartRefRepo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, ErrChartReferenceNotFound
|
||||
}
|
||||
|
||||
if registryID != "" {
|
||||
chartRef.RegistryID = registryID
|
||||
}
|
||||
if repository != "" {
|
||||
chartRef.Repository = repository
|
||||
}
|
||||
if chartName != "" {
|
||||
chartRef.ChartName = chartName
|
||||
}
|
||||
chartRef.Description = description
|
||||
chartRef.IsEnabled = isEnabled
|
||||
|
||||
if err := s.chartRefRepo.Update(ctx, chartRef); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return chartRef, nil
|
||||
}
|
||||
|
||||
// Delete 删除 Chart 引用
|
||||
func (s *ChartReferenceService) Delete(ctx context.Context, id string) error {
|
||||
return s.chartRefRepo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
// List 列出所有 Chart 引用(管理员用)
|
||||
func (s *ChartReferenceService) List(ctx context.Context) ([]*entity.ChartReference, error) {
|
||||
return s.chartRefRepo.List(ctx)
|
||||
}
|
||||
|
||||
// Enable 启用 Chart 引用
|
||||
func (s *ChartReferenceService) Enable(ctx context.Context, id string) error {
|
||||
chartRef, err := s.chartRefRepo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return ErrChartReferenceNotFound
|
||||
}
|
||||
chartRef.IsEnabled = true
|
||||
return s.chartRefRepo.Update(ctx, chartRef)
|
||||
}
|
||||
|
||||
// Disable 禁用 Chart 引用
|
||||
func (s *ChartReferenceService) Disable(ctx context.Context, id string) error {
|
||||
chartRef, err := s.chartRefRepo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return ErrChartReferenceNotFound
|
||||
}
|
||||
chartRef.IsEnabled = false
|
||||
return s.chartRefRepo.Update(ctx, chartRef)
|
||||
}
|
||||
Reference in New Issue
Block a user