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:
116
backend/internal/domain/service/storage_service.go
Normal file
116
backend/internal/domain/service/storage_service.go
Normal file
@ -0,0 +1,116 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/ocdp/cluster-service/internal/domain/entity"
|
||||
"github.com/ocdp/cluster-service/internal/domain/repository"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrStorageNotFound = errors.New("storage backend not found")
|
||||
ErrStorageExists = errors.New("storage backend already exists")
|
||||
)
|
||||
|
||||
// StorageService 存储后端领域服务
|
||||
type StorageService struct {
|
||||
storageRepo repository.StorageRepository
|
||||
}
|
||||
|
||||
// NewStorageService 创建存储后端服务
|
||||
func NewStorageService(storageRepo repository.StorageRepository) *StorageService {
|
||||
return &StorageService{
|
||||
storageRepo: storageRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建存储后端
|
||||
func (s *StorageService) Create(
|
||||
ctx context.Context,
|
||||
workspaceID, ownerID, name string,
|
||||
storageType entity.StorageType,
|
||||
config entity.StorageConfig,
|
||||
description string,
|
||||
isDefault, isShared bool,
|
||||
) (*entity.StorageBackend, error) {
|
||||
// 检查名称是否已存在
|
||||
existing, _ := s.storageRepo.GetByName(ctx, workspaceID, name)
|
||||
if existing != nil {
|
||||
return nil, ErrStorageExists
|
||||
}
|
||||
|
||||
storage := entity.NewStorageBackend(workspaceID, ownerID, name, storageType, config)
|
||||
storage.Description = description
|
||||
storage.IsDefault = isDefault
|
||||
storage.IsShared = isShared
|
||||
|
||||
if err := s.storageRepo.Create(ctx, storage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
// GetByID 获取存储后端
|
||||
func (s *StorageService) GetByID(ctx context.Context, id string) (*entity.StorageBackend, error) {
|
||||
storage, err := s.storageRepo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, ErrStorageNotFound
|
||||
}
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
// GetByWorkspace 获取工作空间的所有存储后端
|
||||
func (s *StorageService) GetByWorkspace(ctx context.Context, workspaceID string) ([]*entity.StorageBackend, error) {
|
||||
return s.storageRepo.GetByWorkspace(ctx, workspaceID)
|
||||
}
|
||||
|
||||
// GetShared 获取所有共享存储后端
|
||||
func (s *StorageService) GetShared(ctx context.Context) ([]*entity.StorageBackend, error) {
|
||||
return s.storageRepo.GetShared(ctx)
|
||||
}
|
||||
|
||||
// GetDefault 获取工作空间的默认存储后端
|
||||
func (s *StorageService) GetDefault(ctx context.Context, workspaceID string) (*entity.StorageBackend, error) {
|
||||
return s.storageRepo.GetDefault(ctx, workspaceID)
|
||||
}
|
||||
|
||||
// Update 更新存储后端
|
||||
func (s *StorageService) Update(
|
||||
ctx context.Context,
|
||||
id, name, description string,
|
||||
storageType entity.StorageType,
|
||||
config entity.StorageConfig,
|
||||
isDefault, isShared bool,
|
||||
) (*entity.StorageBackend, error) {
|
||||
storage, err := s.storageRepo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, ErrStorageNotFound
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
storage.Name = name
|
||||
}
|
||||
storage.Description = description
|
||||
storage.Type = storageType
|
||||
storage.Config = config
|
||||
storage.IsDefault = isDefault
|
||||
storage.IsShared = isShared
|
||||
|
||||
if err := s.storageRepo.Update(ctx, storage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
// Delete 删除存储后端
|
||||
func (s *StorageService) Delete(ctx context.Context, id string) error {
|
||||
return s.storageRepo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
// List 列出所有存储后端(管理员用)
|
||||
func (s *StorageService) List(ctx context.Context) ([]*entity.StorageBackend, error) {
|
||||
return s.storageRepo.List(ctx)
|
||||
}
|
||||
Reference in New Issue
Block a user