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.
121 lines
3.8 KiB
Go
121 lines
3.8 KiB
Go
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)
|
|
} |