feat: complete E2E deployment flow with storage layered config and values template versioning
- 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
This commit is contained in:
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@ -124,11 +125,11 @@ func (r *ClusterRepository) GetByID(ctx context.Context, id string) (*entity.Clu
|
||||
return nil, fmt.Errorf("failed to get cluster: %w", err)
|
||||
}
|
||||
|
||||
// 解密敏感数据
|
||||
cluster.CAData, _ = r.encryptor.Decrypt(encryptedCAData)
|
||||
cluster.CertData, _ = r.encryptor.Decrypt(encryptedCertData)
|
||||
cluster.KeyData, _ = r.encryptor.Decrypt(encryptedKeyData)
|
||||
cluster.Token, _ = r.encryptor.Decrypt(encryptedToken)
|
||||
// 解密敏感数据(检测 kubeconfig 格式则跳过解密)
|
||||
cluster.CAData = r.decryptIfNeeded(encryptedCAData, "ca_data")
|
||||
cluster.CertData = r.decryptIfNeeded(encryptedCertData, "cert_data")
|
||||
cluster.KeyData = r.decryptIfNeeded(encryptedKeyData, "key_data")
|
||||
cluster.Token = r.decryptIfNeeded(encryptedToken, "token")
|
||||
|
||||
return cluster, nil
|
||||
}
|
||||
@ -169,15 +170,35 @@ func (r *ClusterRepository) GetByName(ctx context.Context, name string) (*entity
|
||||
return nil, fmt.Errorf("failed to get cluster: %w", err)
|
||||
}
|
||||
|
||||
// 解密敏感数据
|
||||
cluster.CAData, _ = r.encryptor.Decrypt(encryptedCAData)
|
||||
cluster.CertData, _ = r.encryptor.Decrypt(encryptedCertData)
|
||||
cluster.KeyData, _ = r.encryptor.Decrypt(encryptedKeyData)
|
||||
cluster.Token, _ = r.encryptor.Decrypt(encryptedToken)
|
||||
// 解密敏感数据(检测 kubeconfig 格式则跳过解密)
|
||||
cluster.CAData = r.decryptIfNeeded(encryptedCAData, "ca_data")
|
||||
cluster.CertData = r.decryptIfNeeded(encryptedCertData, "cert_data")
|
||||
cluster.KeyData = r.decryptIfNeeded(encryptedKeyData, "key_data")
|
||||
cluster.Token = r.decryptIfNeeded(encryptedToken, "token")
|
||||
|
||||
return cluster, nil
|
||||
}
|
||||
|
||||
// decryptIfNeeded 解密数据。如果数据以 "apiVersion:" 或 "kind:" 开头(kubeconfig 格式),
|
||||
// 则跳过解密直接返回原值。
|
||||
func (r *ClusterRepository) decryptIfNeeded(data string, fieldName string) string {
|
||||
if data == "" {
|
||||
return ""
|
||||
}
|
||||
// 检测 kubeconfig 格式(明文 YAML)
|
||||
if (len(data) > 10 && data[:11] == "apiVersion:") ||
|
||||
(len(data) > 5 && data[:5] == "kind:") {
|
||||
return data
|
||||
}
|
||||
// 否则尝试解密
|
||||
decrypted, err := r.encryptor.Decrypt(data)
|
||||
if err != nil {
|
||||
log.Printf("[ClusterRepository] WARNING: failed to decrypt %s for field %s: %v (field will be empty)", data[:min(50, len(data))], fieldName, err)
|
||||
return ""
|
||||
}
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// Update 更新集群
|
||||
func (r *ClusterRepository) Update(ctx context.Context, cluster *entity.Cluster) error {
|
||||
cluster.UpdatedAt = time.Now()
|
||||
@ -352,18 +373,18 @@ func (r *ClusterRepository) scanClusters(rows *sql.Rows) ([]*entity.Cluster, err
|
||||
cluster.OwnerID = ownerID.String
|
||||
cluster.DefaultNamespace = defaultNamespace.String
|
||||
|
||||
// 解密敏感数据
|
||||
// 解密敏感数据(检测 kubeconfig 格式则跳过解密)
|
||||
if encryptedCAData.Valid {
|
||||
cluster.CAData, _ = r.encryptor.Decrypt(encryptedCAData.String)
|
||||
cluster.CAData = r.decryptIfNeeded(encryptedCAData.String, "ca_data")
|
||||
}
|
||||
if encryptedCertData.Valid {
|
||||
cluster.CertData, _ = r.encryptor.Decrypt(encryptedCertData.String)
|
||||
cluster.CertData = r.decryptIfNeeded(encryptedCertData.String, "cert_data")
|
||||
}
|
||||
if encryptedKeyData.Valid {
|
||||
cluster.KeyData, _ = r.encryptor.Decrypt(encryptedKeyData.String)
|
||||
cluster.KeyData = r.decryptIfNeeded(encryptedKeyData.String, "key_data")
|
||||
}
|
||||
if encryptedToken.Valid {
|
||||
cluster.Token, _ = r.encryptor.Decrypt(encryptedToken.String)
|
||||
cluster.Token = r.decryptIfNeeded(encryptedToken.String, "token")
|
||||
}
|
||||
|
||||
clusters = append(clusters, cluster)
|
||||
|
||||
Reference in New Issue
Block a user