package installation
import (
"fmt"
"strings"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"gitcode.com/openFuyao/e2e-auto-test/e2e/framework/executor"
config "gitcode.com/openFuyao/e2e-auto-test/e2e/installation/bke-config"
"gitcode.com/openFuyao/e2e-auto-test/e2e/installation/utils"
)
const (
installTimeout = 10 * time.Minute
mgmtInstallTimeout = 15 * time.Minute
uninstallTimeout = 15 * time.Minute
pollInterval = 30 * time.Second
failedStatesMsgTmpl = "集群进入失败态: state=%s, clusterStatus=%s,不再等待 Healthy"
)
type Cluster3M1WConfig struct {
ClusterName string
ClusterConfig *config.BKEClusterConfig
ConfigPath string
NodeConfigPath string
KubeconfigPath string
}
func Create3M1WManagementCluster(
clusterManager *utils.ClusterManager,
localExecutor *executor.LocalExecutor,
clusterNamePrefix string,
includeClusterAPI bool,
) (*Cluster3M1WConfig, error) {
clusterName := fmt.Sprintf("%s-%d", clusterNamePrefix, time.Now().Unix())
GinkgoWriter.Printf("=== Management Cluster Configuration ===\n")
GinkgoWriter.Printf("Cluster Name: %s\n", clusterName)
nodes := config.LoadTestNodesFromEnv()
Expect(len(nodes)).To(BeNumerically(">=", 4), "3Master1Worker management cluster requires at least 4 nodes (nodes 1-4)")
mgmtNodes := make([]config.NodeInfo, 4)
copy(mgmtNodes, nodes[:4])
for i := 0; i < 3; i++ {
mgmtNodes[i].Role = []string{"master/node", "etcd"}
}
mgmtNodes[3].Role = []string{"node"}
GinkgoWriter.Printf("Nodes Configuration:\n")
for i, node := range mgmtNodes {
GinkgoWriter.Printf(" Node %d: IP=%s, Hostname=%s, Roles=%v\n", i+1, node.IP, node.Hostname, node.Role)
}
clusterConfig := config.NewDefaultBKEClusterConfig(clusterName, mgmtNodes)
if includeClusterAPI {
clusterConfig.ExcludeAddons = []string{"openfuyao-system-controller"}
}
partialCluster := &Cluster3M1WConfig{
ClusterName: clusterName,
ClusterConfig: clusterConfig,
}
vipHost, vipPort := config.LoadManagementClusterVIPFromEnv()
if vipHost != "" {
clusterConfig.ControlPlaneEndpoint = &config.ControlPlaneEndpoint{
Host: vipHost,
Port: vipPort,
}
GinkgoWriter.Printf("VIP Configuration: host=%s, port=%s\n", vipHost, vipPort)
} else {
GinkgoWriter.Printf("VIP Configuration: Not configured (will be set to empty object {} in YAML)\n")
}
GinkgoWriter.Printf("Addons Configuration:\n")
for _, addon := range clusterConfig.Addons {
GinkgoWriter.Printf(" - %s (version: %s)\n", addon.Name, addon.Version)
}
GinkgoWriter.Printf("========================================\n")
By("Generating cluster config file")
configPath, nodeConfigPath, err := clusterManager.GetConfigGenerator().GenerateAndUpload(clusterConfig)
if err != nil {
return partialCluster, fmt.Errorf("failed to generate config file: %w", err)
}
partialCluster.ConfigPath = configPath
partialCluster.NodeConfigPath = nodeConfigPath
GinkgoWriter.Printf("Config file path: %s\n", configPath)
GinkgoWriter.Printf("Node config file path: %s\n", nodeConfigPath)
By("Executing bke cluster create command")
err = clusterManager.CreateClusterInBackgroundWithKubeconfig(configPath, nodeConfigPath, "")
if err != nil {
return partialCluster, fmt.Errorf("failed to create cluster: %w", err)
}
err = WaitAndVerify3M1WCluster(clusterManager, localExecutor, clusterName, "")
if err != nil {
return partialCluster, fmt.Errorf("failed to wait and verify cluster: %w", err)
}
By("Getting cluster kubeconfig")
checker := utils.NewClusterCheckerWithParentKubeconfig(localExecutor, clusterName, "")
kubeconfigPath, err := checker.SaveKubeconfigToFile()
if err != nil {
return partialCluster, fmt.Errorf("failed to get kubeconfig: %w", err)
}
partialCluster.KubeconfigPath = kubeconfigPath
GinkgoWriter.Printf("Cluster kubeconfig saved to: %s\n", kubeconfigPath)
return partialCluster, nil
}
func Create3M1WWorkloadCluster(
clusterManager *utils.ClusterManager,
localExecutor *executor.LocalExecutor,
mgmtKubeconfigPath string,
clusterNamePrefix string,
) (*Cluster3M1WConfig, error) {
clusterName := fmt.Sprintf("%s-%d", clusterNamePrefix, time.Now().Unix())
GinkgoWriter.Printf("=== Workload Cluster Configuration ===\n")
GinkgoWriter.Printf("Cluster Name: %s\n", clusterName)
nodes := config.LoadTestNodesFromEnv()
Expect(len(nodes)).To(BeNumerically(">=", 8), "3Master1Worker workload cluster requires at least 8 nodes (uses nodes 5-8)")
workloadNodes := make([]config.NodeInfo, 4)
copy(workloadNodes, nodes[4:8])
for i := 0; i < 3; i++ {
workloadNodes[i].Role = []string{"master/node", "etcd"}
}
workloadNodes[3].Role = []string{"node"}
GinkgoWriter.Printf("Nodes Configuration:\n")
for i, node := range workloadNodes {
GinkgoWriter.Printf(" Node %d: IP=%s, Hostname=%s, Roles=%v\n", i+5, node.IP, node.Hostname, node.Role)
}
clusterConfig := config.NewDefaultBKEClusterConfig(clusterName, workloadNodes)
vipHost, vipPort := config.LoadWorkloadClusterVIPFromEnv()
if vipHost != "" {
clusterConfig.ControlPlaneEndpoint = &config.ControlPlaneEndpoint{
Host: vipHost,
Port: vipPort,
}
GinkgoWriter.Printf("VIP Configuration: host=%s, port=%s\n", vipHost, vipPort)
} else {
GinkgoWriter.Printf("VIP Configuration: Not configured (will be set to empty object {} in YAML)\n")
}
GinkgoWriter.Printf("Addons Configuration:\n")
for _, addon := range clusterConfig.Addons {
GinkgoWriter.Printf(" - %s (version: %s)\n", addon.Name, addon.Version)
}
GinkgoWriter.Printf("========================================\n")
By("Generating workload cluster config file")
configPath, nodeConfigPath, err := clusterManager.GetConfigGenerator().GenerateAndUpload(clusterConfig)
if err != nil {
return nil, fmt.Errorf("failed to generate workload cluster config file: %w", err)
}
GinkgoWriter.Printf("Workload cluster config file path: %s\n", configPath)
GinkgoWriter.Printf("Workload cluster node config file path: %s\n", nodeConfigPath)
By("Creating namespace and applying workload cluster config on management cluster")
err = clusterManager.CreateClusterWithKubeconfig(configPath, nodeConfigPath, mgmtKubeconfigPath)
if err != nil {
return nil, fmt.Errorf("failed to create workload cluster: %w", err)
}
err = WaitAndVerify3M1WCluster(clusterManager, localExecutor, clusterName, mgmtKubeconfigPath)
if err != nil {
return nil, fmt.Errorf("failed to wait and verify workload cluster: %w", err)
}
return &Cluster3M1WConfig{
ClusterName: clusterName,
ClusterConfig: clusterConfig,
ConfigPath: configPath,
NodeConfigPath: nodeConfigPath,
KubeconfigPath: "",
}, nil
}
func Delete3M1WManagementCluster(
clusterManager *utils.ClusterManager,
localExecutor *executor.LocalExecutor,
clusterName string,
kubeconfigPath string,
) {
By("Cleaning up management cluster")
mgmtChecker := utils.NewClusterCheckerWithParentKubeconfig(localExecutor, clusterName, "")
mgmtKubeconfigPath, err := mgmtChecker.SaveKubeconfigToFile()
if err != nil {
GinkgoWriter.Printf("[DEBUG] Failed to get management cluster kubeconfig: %v\n", err)
if kubeconfigPath != "" {
mgmtKubeconfigPath = kubeconfigPath
}
} else if kubeconfigPath != "" {
defer localExecutor.Exec(fmt.Sprintf("rm -f %s", mgmtKubeconfigPath))
mgmtKubeconfigPath = kubeconfigPath
}
if clusterManager.ClusterExistsWithKubeconfig(clusterName, "") {
By("Triggering management cluster deletion on bootstrap cluster")
err := clusterManager.DeleteClusterWithKubeconfig(clusterName, "")
if err != nil {
GinkgoWriter.Printf("Failed to trigger management cluster deletion on bootstrap cluster: %v\n", err)
}
} else {
GinkgoWriter.Printf("[DEBUG] Management cluster BC does not exist on bootstrap cluster\n")
}
if mgmtKubeconfigPath != "" {
By("Triggering management cluster self BC deletion on management cluster")
err := clusterManager.DeleteManagementClusterSelfBC(mgmtKubeconfigPath)
if err != nil {
GinkgoWriter.Printf("Failed to trigger management cluster self BC deletion: %v\n", err)
}
}
By("Waiting for management cluster to be completely deleted")
Eventually(func() bool {
existsOnBootstrap := clusterManager.ClusterExistsWithKubeconfig(clusterName, "")
existsOnSelf := false
if mgmtKubeconfigPath != "" {
bcName := "bke-cluster"
namespace := "bke-cluster"
checkSelfCmd := fmt.Sprintf("KUBECONFIG=%s kubectl get bc %s -n %s --no-headers 2>/dev/null", mgmtKubeconfigPath, bcName, namespace)
result, _ := localExecutor.Exec(checkSelfCmd)
existsOnSelf = result.ExitCode == 0 && strings.TrimSpace(result.Stdout) != ""
if !existsOnSelf {
GinkgoWriter.Printf("[DEBUG] Management cluster self BC (bke-cluster) not found: exit_code=%d\n", result.ExitCode)
}
}
if existsOnBootstrap || existsOnSelf {
if existsOnBootstrap {
phase, state, clusterStatus, _ := clusterManager.GetClusterFullStatusWithKubeconfig(clusterName, "")
GinkgoWriter.Printf("[DEBUG] Management cluster BC on bootstrap still exists: phase=%s, state=%s, clusterStatus=%s\n", phase, state, clusterStatus)
}
if existsOnSelf {
GinkgoWriter.Printf("[DEBUG] Management cluster self BC (bke-cluster) still exists on management cluster\n")
}
return false
} else {
GinkgoWriter.Printf("[DEBUG] Management cluster BC resources deleted (both on bootstrap and self)\n")
nodes := config.LoadTestNodesFromEnv()
if len(nodes) >= 4 {
result, _ := utils.ExecuteCommandOnNode(nodes[0], "systemctl is-active kubelet 2>&1 || echo inactive")
GinkgoWriter.Printf("[DEBUG] Node %s kubelet status: %s\n", nodes[0].IP, strings.TrimSpace(result.Stdout))
}
return true
}
}, uninstallTimeout, 60*time.Second).Should(BeTrue(), "Management cluster should be completely deleted")
existsOnBootstrap := clusterManager.ClusterExistsWithKubeconfig(clusterName, "")
existsOnSelf := false
if mgmtKubeconfigPath != "" {
bcName := "bke-cluster"
namespace := "bke-cluster"
checkSelfCmd := fmt.Sprintf("KUBECONFIG=%s kubectl get bc %s -n %s --no-headers 2>/dev/null", mgmtKubeconfigPath, bcName, namespace)
result, _ := localExecutor.Exec(checkSelfCmd)
existsOnSelf = result.ExitCode == 0 && strings.TrimSpace(result.Stdout) != ""
}
if existsOnBootstrap || existsOnSelf {
By("Management cluster still exists after timeout, executing force reset on all management nodes")
nodes := config.LoadTestNodesFromEnv()
if len(nodes) >= 4 {
mgmtNodes := make([]config.NodeInfo, 4)
copy(mgmtNodes, nodes[:4])
err := clusterManager.ForceResetManagementCluster(mgmtNodes, localExecutor)
if err != nil {
GinkgoWriter.Printf("Failed to force reset management cluster: %v\n", err)
} else {
GinkgoWriter.Printf("Force reset management cluster completed on all nodes\n")
}
} else {
GinkgoWriter.Printf("Not enough management nodes found (need 4, got %d), skipping force reset\n", len(nodes))
}
}
}
func WaitAndVerifyManagementCluster(
clusterManager *utils.ClusterManager,
localExecutor *executor.LocalExecutor,
clusterName string,
) (mgmtKubeconfigPath string, err error) {
By("等待引导节点上管理集群 BC 变为 Healthy")
Eventually(func() bool {
phase, state, clusterStatus, e := clusterManager.GetClusterFullStatusWithKubeconfig(clusterName, "")
if e != nil {
GinkgoWriter.Printf("[bootstrap] 获取集群状态失败: %v\n", e)
return false
}
GinkgoWriter.Printf("[bootstrap] phase=%s, state=%s, clusterStatus=%s\n", phase, state, clusterStatus)
failOnClusterFailure(state, clusterStatus)
return state == "Healthy"
}, mgmtInstallTimeout, pollInterval).Should(BeTrue(), "引导节点上管理集群 BC 应该变为 Healthy")
By("获取管理集群 kubeconfig")
checker := utils.NewClusterCheckerWithParentKubeconfig(localExecutor, clusterName, "")
Eventually(func() bool {
path, e := checker.SaveKubeconfigToFile()
if e != nil {
GinkgoWriter.Printf("获取管理集群 kubeconfig 失败: %v\n", e)
return false
}
mgmtKubeconfigPath = path
return true
}, 5*time.Minute, 10*time.Second).Should(BeTrue(), "应该成功获取管理集群 kubeconfig")
By("等待管理集群自管 BC 变为 Healthy")
Eventually(func() bool {
phase, state, clusterStatus, e := clusterManager.GetManagementClusterSelfFullStatus(mgmtKubeconfigPath)
if e != nil {
GinkgoWriter.Printf("[mgmt-self] 获取自管 BC 状态失败: %v\n", e)
return false
}
GinkgoWriter.Printf("[mgmt-self] phase=%s, state=%s, clusterStatus=%s\n", phase, state, clusterStatus)
failOnClusterFailure(state, clusterStatus)
return state == "Healthy"
}, mgmtInstallTimeout, pollInterval).Should(BeTrue(), "管理集群自管 BC 应该变为 Healthy")
err = verifyManagementClusterHealth(clusterManager, clusterName, mgmtKubeconfigPath)
return mgmtKubeconfigPath, err
}
func verifyManagementClusterHealth(
clusterManager *utils.ClusterManager,
clusterName string,
mgmtKubeconfigPath string,
) error {
By("验证引导节点上管理集群 BC 状态")
phase, state, clusterStatus, err := clusterManager.GetClusterFullStatusWithKubeconfig(clusterName, "")
if err != nil {
return fmt.Errorf("failed to get bootstrap cluster full status: %w", err)
}
if state != "Healthy" {
return fmt.Errorf("bootstrap cluster state is not Healthy: %s", state)
}
GinkgoWriter.Printf("[bootstrap] 最终状态: phase=%s, state=%s, clusterStatus=%s\n", phase, state, clusterStatus)
By("验证管理集群自管 BC 状态")
phase, state, clusterStatus, err = clusterManager.GetManagementClusterSelfFullStatus(mgmtKubeconfigPath)
if err != nil {
return fmt.Errorf("failed to get management cluster self BC status: %w", err)
}
if state != "Healthy" {
return fmt.Errorf("management cluster self BC state is not Healthy: %s", state)
}
GinkgoWriter.Printf("[mgmt-self] 最终状态: phase=%s, state=%s, clusterStatus=%s\n", phase, state, clusterStatus)
return nil
}
func Verify3M1WCluster(
clusterManager *utils.ClusterManager,
localExecutor *executor.LocalExecutor,
clusterName string,
kubeconfigPath string,
) error {
if kubeconfigPath == "" {
checker := utils.NewClusterCheckerWithParentKubeconfig(localExecutor, clusterName, "")
mgmtKubeconfigPath, err := checker.SaveKubeconfigToFile()
if err != nil {
return fmt.Errorf("failed to get management cluster kubeconfig: %w", err)
}
return verifyManagementClusterHealth(clusterManager, clusterName, mgmtKubeconfigPath)
}
By("Verifying cluster is Healthy")
var state string
var err error
state, err = clusterManager.GetClusterStatusWithKubeconfig(clusterName, kubeconfigPath)
if err != nil {
return fmt.Errorf("failed to get cluster status: %w", err)
}
if state != "Healthy" {
return fmt.Errorf("cluster state is not Healthy: %s", state)
}
By("Verifying cluster full status")
var phase, clusterStatus string
phase, state, clusterStatus, err = clusterManager.GetClusterFullStatusWithKubeconfig(clusterName, kubeconfigPath)
if err != nil {
return fmt.Errorf("failed to get cluster full status: %w", err)
}
if state != "Healthy" {
return fmt.Errorf("cluster state is not Healthy: %s", state)
}
if clusterStatus != "Ready" {
return fmt.Errorf("cluster status is not Ready: %s", clusterStatus)
}
GinkgoWriter.Printf("Cluster status: phase=%s, state=%s, clusterStatus=%s\n", phase, state, clusterStatus)
By("Verifying node count")
checker := utils.NewClusterCheckerWithParentKubeconfig(localExecutor, clusterName, kubeconfigPath)
var count int
count, err = checker.GetNodeCountWithKubeconfig(kubeconfigPath)
if err != nil {
return fmt.Errorf("failed to get node count: %w", err)
}
if count == 0 {
nodes, _ := checker.GetNodesWithKubeconfig(kubeconfigPath)
return fmt.Errorf("expected 4 nodes (3 Master + 1 Worker), got 0 (nodes list: %v). This may indicate kubeconfig issue or nodes not yet joined", nodes)
}
if count != 4 {
return fmt.Errorf("expected 4 nodes (3 Master + 1 Worker), got %d", count)
}
By("Verifying all nodes are Ready")
var readyCount int
readyCount, err = checker.GetReadyNodeCountWithKubeconfig(kubeconfigPath)
if err != nil {
return fmt.Errorf("failed to get ready node count: %w", err)
}
if readyCount != 4 {
return fmt.Errorf("expected 4 ready nodes, got %d", readyCount)
}
return nil
}
func WaitAndVerify3M1WCluster(
clusterManager *utils.ClusterManager,
localExecutor *executor.LocalExecutor,
clusterName string,
kubeconfigPath string,
) error {
By("Waiting for cluster status to become Healthy and Ready")
if kubeconfigPath != "" {
Eventually(func() bool {
phase, state, clusterStatus, err := clusterManager.GetClusterFullStatusWithKubeconfig(clusterName, kubeconfigPath)
if err != nil {
GinkgoWriter.Printf("Failed to get cluster full status: %v\n", err)
GinkgoWriter.Printf("Current cluster status: state=%s (phase and clusterStatus unavailable)\n", state)
return false
} else {
GinkgoWriter.Printf("Current cluster status: phase=%s, state=%s, clusterStatus=%s\n", phase, state, clusterStatus)
}
failOnClusterFailure(state, clusterStatus)
return state == "Healthy" && clusterStatus == "Ready"
}, installTimeout, pollInterval).Should(BeTrue(), "Cluster should become Healthy and Ready")
} else {
_, err := WaitAndVerifyManagementCluster(clusterManager, localExecutor, clusterName)
return err
}
return Verify3M1WCluster(clusterManager, localExecutor, clusterName, kubeconfigPath)
}
func Delete3M1WWorkloadCluster(
clusterManager *utils.ClusterManager,
localExecutor *executor.LocalExecutor,
clusterName string,
mgmtKubeconfigPath string,
) {
By("Cleaning up workload cluster")
if mgmtKubeconfigPath != "" && clusterManager.ClusterExistsWithKubeconfig(clusterName, mgmtKubeconfigPath) {
By("Triggering workload cluster deletion on management cluster")
err := clusterManager.DeleteClusterWithKubeconfig(clusterName, mgmtKubeconfigPath)
if err != nil {
GinkgoWriter.Printf("Failed to trigger workload cluster deletion: %v\n", err)
}
By("Waiting for workload cluster to be completely deleted")
Eventually(func() bool {
exists := clusterManager.ClusterExistsWithKubeconfig(clusterName, mgmtKubeconfigPath)
if exists {
phase, state, clusterStatus, _ := clusterManager.GetClusterFullStatusWithKubeconfig(clusterName, mgmtKubeconfigPath)
GinkgoWriter.Printf("[DEBUG] Workload cluster still exists: phase=%s, state=%s, clusterStatus=%s\n", phase, state, clusterStatus)
bcCheckCmd := fmt.Sprintf("kubectl --kubeconfig %s get bc bke-%s -n bke-%s --no-headers 2>&1", mgmtKubeconfigPath, clusterName, clusterName)
result, _ := localExecutor.Exec(bcCheckCmd)
GinkgoWriter.Printf("[DEBUG] Workload BC resource check: exit_code=%d, stdout=%s, stderr=%s\n", result.ExitCode, result.Stdout, result.Stderr)
} else {
GinkgoWriter.Printf("[DEBUG] Workload cluster BC resource deleted\n")
nodes := config.LoadTestNodesFromEnv()
if len(nodes) >= 8 {
result, _ := utils.ExecuteCommandOnNode(nodes[4], "systemctl is-active kubelet 2>&1 || echo inactive")
GinkgoWriter.Printf("[DEBUG] Workload cluster node %s kubelet status: %s\n", nodes[4].IP, strings.TrimSpace(result.Stdout))
}
}
return !exists
}, uninstallTimeout, 60*time.Second).Should(BeTrue(), "Workload cluster should be completely deleted")
} else {
GinkgoWriter.Printf("[DEBUG] Workload cluster does not exist or mgmtKubeconfigPath is empty, skipping deletion\n")
}
}
func DisconnectNetwork(node config.NodeInfo, localExecutor *executor.LocalExecutor) (string, error) {
By(fmt.Sprintf("Disconnecting network on node %s (%s)", node.Hostname, node.IP))
timestamp := time.Now().Unix()
backupFile := fmt.Sprintf("/etc/resolv.conf.backup.%d", timestamp)
_ = localExecutor
backupCmd := fmt.Sprintf("cp /etc/resolv.conf %s", backupFile)
result, err := utils.ExecuteCommandOnNode(node, backupCmd)
if err != nil {
return "", fmt.Errorf("failed to backup resolv.conf: %w", err)
}
if result.ExitCode != 0 {
return "", fmt.Errorf("backup command failed (exit code %d): %s", result.ExitCode, result.Stderr)
}
commentCmd := "sed -i \"s/^/#/\" /etc/resolv.conf"
result, err = utils.ExecuteCommandOnNode(node, commentCmd)
if err != nil {
return backupFile, fmt.Errorf("failed to comment resolv.conf: %w", err)
}
if result.ExitCode != 0 {
return backupFile, fmt.Errorf("comment command failed (exit code %d): %s", result.ExitCode, result.Stderr)
}
verifyCmd := "cat /etc/resolv.conf"
result, err = utils.ExecuteCommandOnNode(node, verifyCmd)
if err == nil && result.ExitCode == 0 {
GinkgoWriter.Printf("Resolv.conf after commenting on node %s:\n%s\n", node.IP, result.Stdout)
}
return backupFile, nil
}
func RestoreNetwork(node config.NodeInfo, localExecutor *executor.LocalExecutor, backupFile string) error {
By(fmt.Sprintf("Restoring network on node %s (%s)", node.Hostname, node.IP))
_ = localExecutor
if backupFile == "" {
findBackupCmd := "ls -t /etc/resolv.conf.backup.* 2>/dev/null | head -1"
result, err := utils.ExecuteCommandOnNode(node, findBackupCmd)
if err == nil && result.ExitCode == 0 && strings.TrimSpace(result.Stdout) != "" {
backupFile = strings.TrimSpace(result.Stdout)
}
}
if backupFile != "" {
restoreCmd := fmt.Sprintf("cp %s /etc/resolv.conf", backupFile)
result, err := utils.ExecuteCommandOnNode(node, restoreCmd)
if err == nil && result.ExitCode == 0 {
GinkgoWriter.Printf("Restored resolv.conf from backup: %s\n", backupFile)
return nil
}
GinkgoWriter.Printf("Failed to restore from backup %s, trying to uncomment instead\n", backupFile)
}
uncommentCmd := "sed -i \"s/^#//\" /etc/resolv.conf"
result, err := utils.ExecuteCommandOnNode(node, uncommentCmd)
if err != nil {
return fmt.Errorf("failed to uncomment resolv.conf: %w", err)
}
if result.ExitCode != 0 {
return fmt.Errorf("uncomment command failed (exit code %d): %s", result.ExitCode, result.Stderr)
}
if backupFile == "" {
GinkgoWriter.Printf("Uncommented resolv.conf (no backup found)\n")
} else {
GinkgoWriter.Printf("Uncommented resolv.conf (backup restore failed)\n")
}
return nil
}
func getTestPatchYAMLContent() []byte {
return []byte(`registry:
imageAddress: cr.openfuyao.cn/openfuyao/registry:2.8.1
architecture:
- amd64
- arm64
openFuyaoVersion: v25.09.999
kubernetesVersion: v1.33.1-of.2
etcdVersion: v3.5.21-of.1
containerdVersion: v2.1.2
repos:
- architecture:
- amd64
- arm64
isKubernetes: false
needDownload: true
subImages:
- sourceRepo: cr.openfuyao.cn/openfuyao/coredns
targetRepo: kubernetes/kubernetes
images:
- name: coredns
usedPodInfo:
- podPrefix: coredns
namespace: kube-system
tag:
- v1.10.2
- sourceRepo: cr.openfuyao.cn/openfuyao/ingress-nginx
targetRepo: kubernetes/ingress-nginx
images:
- name: controller
usedPodInfo:
- podPrefix: ingress-nginx-controller
namespace: ingress-nginx
tag:
- v1.9.5
- sourceRepo: cr.openfuyao.cn/openfuyao
targetRepo: kubernetes
images:
- name: user-management-operator
usedPodInfo:
- podPrefix: user-management-operator
namespace: openfuyao-system
tag:
- 1.2.3
files:
- address: https://openfuyao.obs.cn-north-4.myhuaweicloud.com/containerd/containerd/releases/download/patch_test/
files:
- fileName: containerd-v2.1.2-linux-amd64.tar.gz
- fileName: containerd-v2.1.2-linux-arm64.tar.gz
`)
}
func getTestPatchYAMLContentLargeScale() []byte {
return []byte(`registry:
imageAddress: hub.oepkgs.net/openfuyao/registry:2.8.1
architecture:
- amd64
- arm64
repos:
- architecture:
- amd64
- arm64
needDownload: true
subImages:
- sourceRepo: hub.oepkgs.net/openfuyao
targetRepo: kubernetes
images:
- name: registry
tag: ["2.8.1"]
- name: nginx
tag: ["1.23.0-alpine"]
- name: helm/chartmuseum
tag: ["v0.16.2"]
- name: openebs/nfs-server-alpine
tag: ["0.9.0"]
- name: rancher/k3s
tag: ["v1.25.16-k3s4"]
- name: rancher/mirrored-pause
tag: ["3.6"]
- architecture:
- amd64
- arm64
needDownload: true
subImages:
- sourceRepo: cr.openfuyao.cn/openfuyao
targetRepo: kubernetes
images:
- name: coredns
tag: ["1.12.2-of.1"]
- sourceRepo: cr.openfuyao.cn/openfuyao
targetRepo: kubernetes
images:
- name: kube-apiserver
tag: ["1.34.3-of.1"]
- name: kube-controller-manager
tag: ["1.34.3-of.1"]
- name: kube-scheduler
tag: ["1.34.3-of.1"]
- name: kube-proxy
tag: ["1.34.3-of.1"]
- name: etcd
tag: ["3.6.7-of.1"]
- sourceRepo: cr.openfuyao.cn/openfuyao/keepalived
targetRepo: kubernetes/keepalived
images:
- name: keepalived
tag: ["1.3.5"]
- sourceRepo: hub.oepkgs.net/openfuyao
targetRepo: kubernetes
images:
- name: haproxy
tag: ["2.1.4"]
- sourceRepo: hub.oepkgs.net/openfuyao/calico
targetRepo: kubernetes/calico
images:
- name: cni
tag: ["v3.31.3"]
- name: node
tag: ["v3.31.3"]
- name: kube-controllers
tag: ["v3.31.3"]
- architecture:
- amd64
- arm64
needDownload: true
subImages:
- sourceRepo: cr.openfuyao.cn/openfuyao
targetRepo: kubernetes
images:
- name: bke-console-website
tag: ["latest"]
- name: bke-console-service
tag: ["latest"]
- name: installer-website
tag: ["latest"]
- name: installer-service
tag: ["latest"]
- name: application-management-service
tag: ["latest"]
- name: cluster-api-provider-bke
tag: ["latest"]
- name: bke-manifests
tag: ["latest"]
- name: bkeagent-deployer
tag: ["latest"]
- name: bkeagent-launcher
tag: ["latest"]
- name: console-service
tag: ["latest"]
- name: console-website
tag: ["latest"]
- name: marketplace-service
tag: ["latest"]
- name: monitoring-service
tag: ["latest"]
- name: oauth-proxy
tag: ["latest"]
- name: oauth-server
tag: ["latest"]
- name: oauth-webhook
tag: ["latest"]
- name: openfuyao-system-controller
tag: ["latest"]
- name: plugin-management-service
tag: ["latest"]
- name: user-management-operator
tag: ["latest"]
- name: web-terminal-service
tag: ["latest"]
- name: kubectl-openfuyao
tag: ["latest"]
- sourceRepo: hub.oepkgs.net/openfuyao/brancz
targetRepo: kubernetes/brancz
images:
- name: kube-rbac-proxy
tag: ["v0.18.0"]
- sourceRepo: hub.oepkgs.net/openfuyao
targetRepo: kubernetes
images:
- name: busybox
tag: ["1.36.1"]
- sourceRepo: hub.oepkgs.net/openfuyao/cluster-api
targetRepo: kubernetes/cluster-api
images:
- name: cluster-api-controller
tag: ["v1.4.3"]
- name: kubeadm-bootstrap-controller
tag: ["v1.4.3"]
- name: kubeadm-control-plane-controller
tag: ["v1.4.3"]
- sourceRepo: hub.oepkgs.net/openfuyao/ingress-nginx
targetRepo: kubernetes/ingress-nginx
images:
- name: controller
tag: ["v1.9.4"]
- name: kube-webhook-certgen
tag: ["v20231011-8b53cabe0"]
- sourceRepo: hub.oepkgs.net/openfuyao/jimmidyson
targetRepo: kubernetes/jimmidyson
images:
- name: configmap-reload
tag: ["v0.13.0"]
`)
}
func isClusterFailedState(state, clusterStatus string) bool {
return state == "DeployFailed" || clusterStatus == "InitializationFailed"
}
func failOnClusterFailure(state, clusterStatus string) {
if isClusterFailedState(state, clusterStatus) {
Fail(fmt.Sprintf(failedStatesMsgTmpl, state, clusterStatus))
}
}