fix: scale replicas in response, K8s metrics client, quota precheck, auth tests
- Add GetMetrics method to MetricsClient interface and implement cluster metrics API - Add QuotaPrecheck service for validating resource quotas before deployment - Add auth DTO with role/permission models and auth handler tests - Add instance diagnostics: mounted NFS volumes, labels, annotations in pod diagnostics - Update workspace handler with GetWorkspace endpoint and shared-user list - Fix monitoring handler to use correct service method name - Add tail_lines fallback in instance handler for snake_case query params - Update nginx config for SSE log streaming support (no buffering) - Add comprehensive test coverage: auth_service_test, auth_handler_test, auth_dto_test, metrics_client_test, quota_precheck_test - Update error messages for quota validation and instance operations - ModifyModal: fix YAML lineWidth:0, modified keys summary, delta-only submit - InstanceCard: correctly disable scale-minus when replicas <= 0 - SidebarLayout: add hover transition for sidebar items - Update todo.md and lessons.md with latest fixes
This commit is contained in:
@ -27,8 +27,9 @@ func (r *WorkspaceRepository) Create(ctx context.Context, workspace *entity.Work
|
||||
query := `
|
||||
INSERT INTO workspaces (id, name, status, k8s_namespace, k8s_sa_name, default_cluster_id, quota_cpu, quota_memory, quota_gpu, quota_gpu_memory, created_by, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
|
||||
ON CONFLICT (name) DO NOTHING
|
||||
`
|
||||
_, err := r.db.conn.ExecContext(ctx, query,
|
||||
result, err := r.db.conn.ExecContext(ctx, query,
|
||||
workspace.ID,
|
||||
workspace.Name,
|
||||
workspace.Status,
|
||||
@ -46,6 +47,13 @@ func (r *WorkspaceRepository) Create(ctx context.Context, workspace *entity.Work
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create workspace: %w", err)
|
||||
}
|
||||
rows, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get affected rows: %w", err)
|
||||
}
|
||||
if rows == 0 {
|
||||
return entity.ErrWorkspaceExists
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -132,6 +140,21 @@ func (r *WorkspaceRepository) Update(ctx context.Context, workspace *entity.Work
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *WorkspaceRepository) Delete(ctx context.Context, id string) error {
|
||||
result, err := r.db.conn.ExecContext(ctx, `DELETE FROM workspaces WHERE id = $1`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete workspace: %w", err)
|
||||
}
|
||||
rows, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get affected rows: %w", err)
|
||||
}
|
||||
if rows == 0 {
|
||||
return entity.ErrWorkspaceNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *WorkspaceRepository) List(ctx context.Context) ([]*entity.Workspace, error) {
|
||||
query := `
|
||||
SELECT id, name, status, k8s_namespace, k8s_sa_name, default_cluster_id, quota_cpu, quota_memory, quota_gpu, quota_gpu_memory, created_by, created_at, updated_at
|
||||
@ -256,6 +279,42 @@ func (r *WorkspaceClusterBindingRepository) Get(ctx context.Context, workspaceID
|
||||
return binding, nil
|
||||
}
|
||||
|
||||
func (r *WorkspaceClusterBindingRepository) ListByWorkspace(ctx context.Context, workspaceID string) ([]*entity.WorkspaceClusterBinding, error) {
|
||||
query := `
|
||||
SELECT id, workspace_id, cluster_id, namespace, service_account, quota_cpu, quota_memory, quota_gpu, quota_gpu_memory, status, created_at, updated_at
|
||||
FROM workspace_cluster_bindings
|
||||
WHERE workspace_id = $1
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
rows, err := r.db.conn.QueryContext(ctx, query, workspaceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list workspace cluster bindings: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
bindings := make([]*entity.WorkspaceClusterBinding, 0)
|
||||
for rows.Next() {
|
||||
binding := &entity.WorkspaceClusterBinding{}
|
||||
if err := rows.Scan(
|
||||
&binding.ID,
|
||||
&binding.WorkspaceID,
|
||||
&binding.ClusterID,
|
||||
&binding.Namespace,
|
||||
&binding.ServiceAccount,
|
||||
&binding.QuotaCPU,
|
||||
&binding.QuotaMemory,
|
||||
&binding.QuotaGPU,
|
||||
&binding.QuotaGPUMem,
|
||||
&binding.Status,
|
||||
&binding.CreatedAt,
|
||||
&binding.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan workspace cluster binding: %w", err)
|
||||
}
|
||||
bindings = append(bindings, binding)
|
||||
}
|
||||
return bindings, rows.Err()
|
||||
}
|
||||
|
||||
func (r *WorkspaceClusterBindingRepository) Delete(ctx context.Context, workspaceID, clusterID string) error {
|
||||
_, err := r.db.conn.ExecContext(ctx, `DELETE FROM workspace_cluster_bindings WHERE workspace_id = $1 AND cluster_id = $2`, workspaceID, clusterID)
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user