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:
121
backend/internal/domain/service/workspace_service.go
Normal file
121
backend/internal/domain/service/workspace_service.go
Normal file
@ -0,0 +1,121 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/ocdp/cluster-service/internal/domain/entity"
|
||||
"github.com/ocdp/cluster-service/internal/domain/repository"
|
||||
)
|
||||
|
||||
// WorkspaceService 工作空间领域服务
|
||||
type WorkspaceService struct {
|
||||
workspaceRepo repository.WorkspaceRepository
|
||||
quotaRepo repository.QuotaRepository
|
||||
userRepo repository.UserRepository
|
||||
}
|
||||
|
||||
// NewWorkspaceService 创建工作空间服务
|
||||
func NewWorkspaceService(
|
||||
workspaceRepo repository.WorkspaceRepository,
|
||||
quotaRepo repository.QuotaRepository,
|
||||
userRepo repository.UserRepository,
|
||||
) *WorkspaceService {
|
||||
return &WorkspaceService{
|
||||
workspaceRepo: workspaceRepo,
|
||||
quotaRepo: quotaRepo,
|
||||
userRepo: userRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建工作空间
|
||||
func (s *WorkspaceService) Create(ctx context.Context, name, description, createdBy string) (*entity.Workspace, error) {
|
||||
// 检查名称是否已存在
|
||||
existing, _ := s.workspaceRepo.GetByName(ctx, name)
|
||||
if existing != nil {
|
||||
return nil, entity.ErrWorkspaceExists
|
||||
}
|
||||
|
||||
workspace := entity.NewWorkspace(name, description, createdBy)
|
||||
if err := s.workspaceRepo.Create(ctx, workspace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return workspace, nil
|
||||
}
|
||||
|
||||
// GetByID 获取工作空间
|
||||
func (s *WorkspaceService) GetByID(ctx context.Context, id string) (*entity.Workspace, error) {
|
||||
return s.workspaceRepo.GetByID(ctx, id)
|
||||
}
|
||||
|
||||
// GetByName 获取工作空间
|
||||
func (s *WorkspaceService) GetByName(ctx context.Context, name string) (*entity.Workspace, error) {
|
||||
return s.workspaceRepo.GetByName(ctx, name)
|
||||
}
|
||||
|
||||
// Update 更新工作空间
|
||||
func (s *WorkspaceService) Update(ctx context.Context, workspace *entity.Workspace) error {
|
||||
return s.workspaceRepo.Update(ctx, workspace)
|
||||
}
|
||||
|
||||
// Delete 删除工作空间
|
||||
func (s *WorkspaceService) Delete(ctx context.Context, id string) error {
|
||||
// 删除关联的配额
|
||||
if err := s.quotaRepo.DeleteByWorkspace(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.workspaceRepo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
// List 列出所有工作空间
|
||||
func (s *WorkspaceService) List(ctx context.Context) ([]*entity.Workspace, error) {
|
||||
return s.workspaceRepo.List(ctx)
|
||||
}
|
||||
|
||||
// GetQuotas 获取工作空间配额
|
||||
func (s *WorkspaceService) GetQuotas(ctx context.Context, workspaceID string) ([]*entity.WorkspaceQuota, error) {
|
||||
return s.quotaRepo.GetByWorkspace(ctx, workspaceID)
|
||||
}
|
||||
|
||||
// SetQuota 设置配额
|
||||
func (s *WorkspaceService) SetQuota(ctx context.Context, workspaceID string, resourceType entity.ResourceType, hardLimit, softLimit float64) (*entity.WorkspaceQuota, error) {
|
||||
quota := entity.NewWorkspaceQuota(workspaceID, resourceType, hardLimit, softLimit)
|
||||
if err := s.quotaRepo.Create(ctx, quota); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return quota, nil
|
||||
}
|
||||
|
||||
// SetQuotas 批量设置配额
|
||||
func (s *WorkspaceService) SetQuotas(ctx context.Context, workspaceID string, quotas map[entity.ResourceType]struct {
|
||||
HardLimit float64
|
||||
SoftLimit float64
|
||||
}) error {
|
||||
for resourceType, config := range quotas {
|
||||
quota := entity.NewWorkspaceQuota(workspaceID, resourceType, config.HardLimit, config.SoftLimit)
|
||||
if err := s.quotaRepo.Create(ctx, quota); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOrCreateDefaultQuota 获取或创建默认配额
|
||||
func (s *WorkspaceService) GetOrCreateDefaultQuota(ctx context.Context, workspaceID string, resourceType entity.ResourceType) (*entity.WorkspaceQuota, error) {
|
||||
quota, _ := s.quotaRepo.GetByWorkspaceAndType(ctx, workspaceID, resourceType)
|
||||
if quota != nil {
|
||||
return quota, nil
|
||||
}
|
||||
|
||||
// 创建默认配额(无限制)
|
||||
quota = entity.NewWorkspaceQuota(workspaceID, resourceType, 0, 0)
|
||||
if err := s.quotaRepo.Create(ctx, quota); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return quota, nil
|
||||
}
|
||||
|
||||
// GetUsers 获取工作空间的用户
|
||||
func (s *WorkspaceService) GetUsers(ctx context.Context, workspaceID string) ([]*entity.User, error) {
|
||||
return s.userRepo.ListByWorkspace(ctx, workspaceID)
|
||||
}
|
||||
Reference in New Issue
Block a user