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.
149 lines
4.2 KiB
Go
149 lines
4.2 KiB
Go
package entity
|
||
|
||
import (
|
||
"time"
|
||
)
|
||
|
||
// IsolationMode 集群隔离模式
|
||
type IsolationMode string
|
||
|
||
const (
|
||
IsolationModeNamespace IsolationMode = "namespace" // 共享集群模式,多 workspace 使用不同 namespace
|
||
IsolationModeCluster IsolationMode = "cluster" // 私有集群模式,每个 workspace 独立集群
|
||
)
|
||
|
||
// Cluster Kubernetes 集群领域实体
|
||
type Cluster struct {
|
||
ID string
|
||
WorkspaceID string // 所属 workspace,NULL 表示全局共享
|
||
OwnerID string // 创建者用户 ID
|
||
Name string
|
||
Host string // Kubernetes API Server URL
|
||
CAData string // Base64 encoded CA certificate
|
||
CertData string // Base64 encoded client certificate
|
||
KeyData string // Base64 encoded client key
|
||
Token string // Bearer token (alternative to cert auth)
|
||
Description string
|
||
|
||
// 隔离模式
|
||
IsolationMode IsolationMode // 'namespace' | 'cluster'
|
||
DefaultNamespace string // 当 isolation_mode=namespace 时的默认 namespace 前缀
|
||
|
||
IsShared bool // 是否为共享集群(admin 创建供多 workspace 使用)
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
}
|
||
|
||
// NewCluster 创建新集群
|
||
func NewCluster(workspaceID, ownerID, name, host string) *Cluster {
|
||
now := time.Now()
|
||
return &Cluster{
|
||
WorkspaceID: workspaceID,
|
||
OwnerID: ownerID,
|
||
Name: name,
|
||
Host: host,
|
||
IsolationMode: IsolationModeNamespace, // 默认 namespace 隔离模式
|
||
DefaultNamespace: workspaceID, // 默认使用 workspace ID 作为 namespace 前缀
|
||
IsShared: false,
|
||
CreatedAt: now,
|
||
UpdatedAt: now,
|
||
}
|
||
}
|
||
|
||
// Update 更新集群信息
|
||
func (c *Cluster) Update(name, host, description string) {
|
||
if name != "" {
|
||
c.Name = name
|
||
}
|
||
if host != "" {
|
||
c.Host = host
|
||
}
|
||
c.Description = description
|
||
c.UpdatedAt = time.Now()
|
||
}
|
||
|
||
// SetCertAuth 设置证书认证
|
||
func (c *Cluster) SetCertAuth(caData, certData, keyData string) {
|
||
c.CAData = caData
|
||
c.CertData = certData
|
||
c.KeyData = keyData
|
||
c.UpdatedAt = time.Now()
|
||
}
|
||
|
||
// SetTokenAuth 设置 Token 认证
|
||
func (c *Cluster) SetTokenAuth(token string) {
|
||
c.Token = token
|
||
c.UpdatedAt = time.Now()
|
||
}
|
||
|
||
// Validate 验证集群配置
|
||
func (c *Cluster) Validate() error {
|
||
if c.Name == "" {
|
||
return ErrInvalidClusterName
|
||
}
|
||
if c.Host == "" {
|
||
return ErrInvalidClusterHost
|
||
}
|
||
|
||
// 检查是否有 kubeconfig 格式(完整的 kubeconfig 在 CAData 中)
|
||
hasKubeconfig := len(c.CAData) > 100 && (c.CAData[:11] == "apiVersion:" || c.CAData[:5] == "kind:")
|
||
|
||
// 认证方式:证书、Token、kubeconfig 或空(使用本地 kubeconfig)
|
||
hasCertAuth := c.CertData != "" && c.KeyData != ""
|
||
hasToken := c.Token != ""
|
||
hasNoAuth := c.CertData == "" && c.KeyData == "" && c.Token == ""
|
||
|
||
// 如果有 kubeconfig 格式,或有证书,或有 token,或没有凭证(依赖 TestConnection 使用本地 kubeconfig),都是有效的
|
||
if hasKubeconfig || hasCertAuth || hasToken || hasNoAuth {
|
||
return nil
|
||
}
|
||
|
||
return ErrInvalidClusterAuth
|
||
}
|
||
|
||
// GetNamespace 获取部署用的 namespace
|
||
// namespace 隔离模式: {workspace_id}-{instance_name} 或 {default_namespace}-{username}
|
||
// cluster 隔离模式: 使用 workspace 的默认 namespace
|
||
func (c *Cluster) GetNamespace(workspaceName, instanceName string) string {
|
||
if c.IsolationMode == IsolationModeCluster {
|
||
return c.DefaultNamespace
|
||
}
|
||
// namespace 隔离模式
|
||
if c.DefaultNamespace != "" {
|
||
return c.DefaultNamespace + "-" + instanceName
|
||
}
|
||
return workspaceName + "-" + instanceName
|
||
}
|
||
|
||
// GetKubeConfig 生成 kubeconfig 内容
|
||
func (c *Cluster) GetKubeConfig() string {
|
||
// 如果 CAData 已经包含完整的 kubeconfig,直接返回
|
||
if len(c.CAData) > 100 && (c.CAData[:11] == "apiVersion:" || c.CAData[:5] == "kind:") {
|
||
return c.CAData
|
||
}
|
||
|
||
// 否则从证书数据生成 kubeconfig
|
||
kubeconfig := `apiVersion: v1
|
||
kind: Config
|
||
clusters:
|
||
- cluster:
|
||
certificate-authority-data: ` + c.CAData + `
|
||
server: ` + c.Host + `
|
||
name: ` + c.Name + `
|
||
contexts:
|
||
- context:
|
||
cluster: ` + c.Name + `
|
||
user: ` + c.Name + `
|
||
name: ` + c.Name + `
|
||
current-context: ` + c.Name + `
|
||
users:
|
||
- name: ` + c.Name + `
|
||
user:
|
||
client-certificate-data: ` + c.CertData + `
|
||
client-key-data: ` + c.KeyData + `
|
||
`
|
||
|
||
return kubeconfig
|
||
}
|
||
|