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:
@ -1,7 +1,9 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// InstanceStatus 实例状态
|
||||
@ -33,43 +35,65 @@ const (
|
||||
|
||||
// Instance Helm 应用实例领域实体
|
||||
type Instance struct {
|
||||
ID string
|
||||
ClusterID string
|
||||
Name string // Helm Release Name
|
||||
Namespace string
|
||||
RegistryID string
|
||||
Repository string // OCI Repository (e.g., charts/app)
|
||||
Chart string // Chart Name
|
||||
Version string // Chart Version
|
||||
Description string
|
||||
Values map[string]interface{} // Helm Values (JSON)
|
||||
ValuesYAML string // Helm Values (YAML format)
|
||||
Status InstanceStatus
|
||||
StatusReason string
|
||||
LastOperation InstanceOperation
|
||||
LastError string
|
||||
Revision int // Helm Release Revision
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
ID string
|
||||
WorkspaceID string // 所属 workspace
|
||||
OwnerID string // 创建者用户 ID
|
||||
ClusterID string
|
||||
RegistryID string
|
||||
ChartReferenceID string // 引用的 Chart 引用
|
||||
ValuesTemplateID string // 使用的 Values 模板
|
||||
|
||||
Name string // Helm Release Name
|
||||
Namespace string
|
||||
Repository string // OCI Repository (e.g., charts/app)
|
||||
Chart string // Chart Name
|
||||
Version string // Chart Version
|
||||
Description string
|
||||
Values map[string]interface{} // Helm Values (JSON)
|
||||
ValuesYAML string // Helm Values (YAML format)
|
||||
UserOverrideYAML string // 用户额外覆盖的配置
|
||||
|
||||
Status InstanceStatus
|
||||
StatusReason string
|
||||
LastOperation InstanceOperation
|
||||
LastError string
|
||||
Revision int // Helm Release Revision
|
||||
|
||||
// 资源使用统计(Helm 安装时从集群获取并更新)
|
||||
CPURequested float64 // CPU 请求量 (cores)
|
||||
MemoryRequested string // 内存请求量 (e.g., "2Gi")
|
||||
GPURequested float64 // GPU 请求量 (cards)
|
||||
GPUMemoryRequested string // GPU 内存请求量 (e.g., "16Gi")
|
||||
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// NewInstance 创建新实例
|
||||
func NewInstance(clusterID, name, namespace, registryID, repository, chart, version string) *Instance {
|
||||
func NewInstance(workspaceID, ownerID, clusterID, registryID, chartReferenceID, valuesTemplateID, name, namespace, repository, chart, version string) *Instance {
|
||||
now := time.Now()
|
||||
return &Instance{
|
||||
ClusterID: clusterID,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
RegistryID: registryID,
|
||||
Repository: repository,
|
||||
Chart: chart,
|
||||
Version: version,
|
||||
Status: StatusPending,
|
||||
StatusReason: "Pending install",
|
||||
LastOperation: OperationInstall,
|
||||
Revision: 1,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
WorkspaceID: workspaceID,
|
||||
OwnerID: ownerID,
|
||||
ClusterID: clusterID,
|
||||
RegistryID: registryID,
|
||||
ChartReferenceID: chartReferenceID,
|
||||
ValuesTemplateID: valuesTemplateID,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
Repository: repository,
|
||||
Chart: chart,
|
||||
Version: version,
|
||||
Status: StatusPending,
|
||||
StatusReason: "Pending install",
|
||||
LastOperation: OperationInstall,
|
||||
Revision: 1,
|
||||
CPURequested: 0,
|
||||
MemoryRequested: "0Mi",
|
||||
GPURequested: 0,
|
||||
GPUMemoryRequested: "0Mi",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,13 +178,43 @@ func (i *Instance) Upgrade(version string, values map[string]interface{}) {
|
||||
i.BeginOperation(OperationUpgrade, "Pending upgrade")
|
||||
}
|
||||
|
||||
// ValidateReleaseName 验证 Helm Release 名称是否符合 RFC 1123 DNS 子域名规范
|
||||
// Helm release 名称必须:
|
||||
// - 只能包含小写字母(a-z)、数字(0-9)和连字符(-)
|
||||
// - 不能以连字符开头或结尾
|
||||
// - 长度不超过 53 个字符
|
||||
func ValidateReleaseName(name string) error {
|
||||
if name == "" {
|
||||
return ErrInvalidInstanceName
|
||||
}
|
||||
|
||||
// 检查长度(RFC 1123 DNS 子域名最大长度为 63,但 Helm 限制为 53)
|
||||
if len(name) > 53 {
|
||||
return ErrInvalidInstanceName
|
||||
}
|
||||
|
||||
// 不能以连字符开头或结尾
|
||||
if strings.HasPrefix(name, "-") || strings.HasSuffix(name, "-") {
|
||||
return ErrInvalidInstanceName
|
||||
}
|
||||
|
||||
// 只能包含小写字母、数字和连字符
|
||||
for _, r := range name {
|
||||
if !(unicode.IsLower(r) || unicode.IsDigit(r) || r == '-') {
|
||||
return ErrInvalidInstanceName
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate 验证实例配置
|
||||
func (i *Instance) Validate() error {
|
||||
if i.ClusterID == "" {
|
||||
return ErrInvalidClusterID
|
||||
}
|
||||
if i.Name == "" {
|
||||
return ErrInvalidInstanceName
|
||||
if err := ValidateReleaseName(i.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
if i.Namespace == "" {
|
||||
return ErrInvalidNamespace
|
||||
|
||||
Reference in New Issue
Block a user