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:
Ivan087
2026-04-15 16:59:31 +08:00
parent c5e51ed069
commit 29d0310f03
283 changed files with 24658 additions and 36038 deletions

View File

@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/google/uuid"
@ -336,9 +337,17 @@ func (s *InstanceService) executeAndSyncRollback(ctx context.Context, instanceID
// executeAndSyncUninstall 异步执行卸载并监控状态
func (s *InstanceService) executeAndSyncUninstall(ctx context.Context, instanceID string, cluster *entity.Cluster, releaseName, namespace string) {
// 先验证 release 名称是否有效
// 如果名称无效,说明这个 release 根本不可能存在于 Helm 中,直接删除数据库记录
if err := entity.ValidateReleaseName(releaseName); err != nil {
// Release 名称无效,直接删除数据库记录
_ = s.instanceRepo.Delete(ctx, instanceID)
return
}
// 执行 Helm 卸载
err := s.helmClient.Uninstall(ctx, cluster, releaseName, namespace)
// 获取实例
instance, getErr := s.instanceRepo.GetByID(ctx, instanceID)
if getErr != nil {
@ -346,13 +355,22 @@ func (s *InstanceService) executeAndSyncUninstall(ctx context.Context, instanceI
}
if err != nil {
// 如果错误不是"未找到",则标记为失败
if !errors.Is(err, entity.ErrInstanceNotFound) {
instance.MarkFailure("Helm uninstall failed", err)
_ = s.instanceRepo.Update(ctx, instance)
} else {
// 如果未找到,说明已经卸载,直接删除数据库记录
// 检查错误类型
if errors.Is(err, entity.ErrInstanceNotFound) {
// 未找到,说明已经卸载,直接删除数据库记录
_ = s.instanceRepo.Delete(ctx, instanceID)
} else {
// 检查是否是 release 名称无效的错误(可能在某些情况下 Helm 会返回这个错误)
errMsg := strings.ToLower(err.Error())
if strings.Contains(errMsg, "release name is invalid") ||
(strings.Contains(errMsg, "invalid") && strings.Contains(errMsg, "release")) {
// Release 名称无效,直接删除数据库记录
_ = s.instanceRepo.Delete(ctx, instanceID)
} else {
// 其他错误,标记为失败
instance.MarkFailure("Helm uninstall failed", err)
_ = s.instanceRepo.Update(ctx, instance)
}
}
return
}
@ -360,7 +378,7 @@ func (s *InstanceService) executeAndSyncUninstall(ctx context.Context, instanceI
// 卸载成功,标记为已卸载
instance.MarkSuccess(entity.StatusUninstalled, instance.Revision, "Instance uninstalled successfully")
_ = s.instanceRepo.Update(ctx, instance)
// 验证卸载是否完成:尝试获取状态,如果获取不到说明已卸载
time.Sleep(3 * time.Second)
_, statusErr := s.helmClient.GetStatus(ctx, cluster, releaseName, namespace)