- Instance deployment: charts browser, deploy modal, instances list - Values Template version management (create/history/rollback) - Storage layered config (cluster > workspace > shared priority) - Cluster credential decryptIfNeeded for mixed encrypted/plaintext kubeconfig - YAML syntax validation (client-side + server-side warning) - Frontend: charts, instances, storage, templates, admin pages - Backend: storage service, instance service, cluster service, helm client - Multi-Tenant Kubeconfig.md: added by user
133 lines
4.2 KiB
Go
133 lines
4.2 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 创建工作空间(支持 cluster_ids 和初始配额)
|
|
func (s *WorkspaceService) Create(ctx context.Context, name, description, createdBy string, clusterIDs []string, quotas map[entity.ResourceType]struct {
|
|
HardLimit float64
|
|
SoftLimit float64
|
|
}) (*entity.Workspace, error) {
|
|
// 检查名称是否已存在
|
|
existing, _ := s.workspaceRepo.GetByName(ctx, name)
|
|
if existing != nil {
|
|
return nil, entity.ErrWorkspaceExists
|
|
}
|
|
|
|
workspace := entity.NewWorkspace(name, description, createdBy, clusterIDs)
|
|
if err := s.workspaceRepo.Create(ctx, workspace); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 如果提供了配额,创建它们
|
|
for resourceType, config := range quotas {
|
|
quota := entity.NewWorkspaceQuota(workspace.ID, resourceType, config.HardLimit, config.SoftLimit)
|
|
if err := s.quotaRepo.Create(ctx, quota); err != nil {
|
|
// 记录错误但不阻止工作空间创建
|
|
continue
|
|
}
|
|
}
|
|
|
|
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)
|
|
} |