package utils
import (
"context"
"encoding/base64"
"fmt"
"strconv"
"strings"
"gitcode.com/openFuyao/e2e-auto-test/e2e/framework/executor"
config "gitcode.com/openFuyao/e2e-auto-test/e2e/installation/bke-config"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
type ClusterChecker struct {
clientSet *kubernetes.Clientset
executor executor.Executor
clusterName string
parentKubeconfigPath string
}
func NewClusterChecker(exec executor.Executor, clusterName string) *ClusterChecker {
return NewClusterCheckerWithParentKubeconfig(exec, clusterName, "")
}
func NewClusterCheckerWithParentKubeconfig(exec executor.Executor, clusterName, parentKubeconfigPath string) *ClusterChecker {
return &ClusterChecker{
executor: exec,
clusterName: clusterName,
parentKubeconfigPath: parentKubeconfigPath,
}
}
func (c *ClusterChecker) GetKubeconfig() (string, error) {
return c.GetKubeconfigWithKubeconfig(c.parentKubeconfigPath)
}
func (c *ClusterChecker) GetKubeconfigWithKubeconfig(kubeconfigPath string) (string, error) {
bcName := "bke-" + c.clusterName
kubeconfigArg := ""
if kubeconfigPath != "" {
kubeconfigArg = fmt.Sprintf("KUBECONFIG=%s ", kubeconfigPath)
}
secretCmd := fmt.Sprintf("%skubectl get secret %s-kubeconfig -n %s -o jsonpath='{.data.value}'", kubeconfigArg, bcName, bcName)
result, err := c.executor.Exec(secretCmd)
if err == nil && result.ExitCode == 0 && result.Stdout != "" {
decoded, err := base64.StdEncoding.DecodeString(strings.TrimSpace(result.Stdout))
if err == nil && strings.Contains(string(decoded), "apiVersion:") {
return string(decoded), nil
}
}
if kubeconfigPath == "" {
paths := []string{
fmt.Sprintf("/root/.bke/%s/admin.conf", bcName),
fmt.Sprintf("/root/.bke/%s/kubeconfig", bcName),
fmt.Sprintf("~/.bke/%s/admin.conf", bcName),
}
for _, path := range paths {
cmd := fmt.Sprintf("cat %s", path)
result, err := c.executor.Exec(cmd)
if err == nil && result.ExitCode == 0 {
if strings.Contains(result.Stdout, "apiVersion:") {
return result.Stdout, nil
}
}
}
}
return "", fmt.Errorf("无法获取业务集群 %s 的 kubeconfig (尝试了 Secret 和文件路径)", c.clusterName)
}
func (c *ClusterChecker) SaveKubeconfigToFile() (string, error) {
return c.SaveKubeconfigToFileWithKubeconfig(c.parentKubeconfigPath)
}
func (c *ClusterChecker) SaveKubeconfigToFileWithKubeconfig(parentKubeconfigPath string) (string, error) {
kubeconfig, err := c.GetKubeconfigWithKubeconfig(parentKubeconfigPath)
if err != nil {
return "", err
}
kubeconfigPath := fmt.Sprintf("/tmp/kubeconfig-%s", c.clusterName)
encoded := base64.StdEncoding.EncodeToString([]byte(kubeconfig))
cmd := fmt.Sprintf("cat <<EOF | base64 -d > %s\n%s\nEOF", kubeconfigPath, encoded)
result, err := c.executor.Exec(cmd)
if err != nil {
return "", fmt.Errorf("保存kubeconfig失败: %w", err)
}
if result.ExitCode != 0 {
return "", fmt.Errorf("保存kubeconfig失败: %s", result.Stderr)
}
return kubeconfigPath, nil
}
func (c *ClusterChecker) execKubectl(kubeconfigPath, args string) (*executor.ExecResult, error) {
cmd := fmt.Sprintf("KUBECONFIG=%s kubectl %s", kubeconfigPath, args)
result, err := c.executor.Exec(cmd)
if err != nil {
if result != nil {
if result.Stderr != "" {
return result, fmt.Errorf("执行 kubectl 失败: %w, exit_code: %d, stderr: %s, stdout: %s", err, result.ExitCode, result.Stderr, result.Stdout)
}
return result, fmt.Errorf("执行 kubectl 失败: %w, exit_code: %d, stdout: %s", err, result.ExitCode, result.Stdout)
}
return result, fmt.Errorf("执行 kubectl 失败: %w", err)
}
if result != nil && result.ExitCode != 0 {
if result.Stderr != "" {
return result, fmt.Errorf("kubectl 命令执行失败,exit_code: %d, stderr: %s, stdout: %s", result.ExitCode, result.Stderr, result.Stdout)
}
return result, fmt.Errorf("kubectl 命令执行失败,exit_code: %d, stdout: %s", result.ExitCode, result.Stdout)
}
return result, nil
}
func (c *ClusterChecker) GetNodeCount() (int, error) {
return c.GetNodeCountWithKubeconfig(c.parentKubeconfigPath)
}
func (c *ClusterChecker) GetNodeCountWithKubeconfig(parentKubeconfigPath string) (int, error) {
kubeconfigPath, err := c.SaveKubeconfigToFileWithKubeconfig(parentKubeconfigPath)
if err != nil {
return 0, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath, "get nodes --no-headers | wc -l")
if err != nil {
return 0, err
}
count, _ := strconv.Atoi(strings.TrimSpace(result.Stdout))
return count, nil
}
func (c *ClusterChecker) GetReadyNodeCount() (int, error) {
return c.GetReadyNodeCountWithKubeconfig(c.parentKubeconfigPath)
}
func (c *ClusterChecker) GetReadyNodeCountWithKubeconfig(parentKubeconfigPath string) (int, error) {
kubeconfigPath, err := c.SaveKubeconfigToFileWithKubeconfig(parentKubeconfigPath)
if err != nil {
return 0, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath, "get nodes --no-headers | grep ' Ready' | wc -l")
if err != nil {
return 0, err
}
count, _ := strconv.Atoi(strings.TrimSpace(result.Stdout))
return count, nil
}
func (c *ClusterChecker) GetNodes() ([]string, error) {
return c.GetNodesWithKubeconfig(c.parentKubeconfigPath)
}
func (c *ClusterChecker) GetNodesWithKubeconfig(parentKubeconfigPath string) ([]string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFileWithKubeconfig(parentKubeconfigPath)
if err != nil {
return nil, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath, "get nodes -o jsonpath='{.items[*].metadata.name}'")
if err != nil {
return nil, err
}
nodes := strings.Fields(strings.Trim(result.Stdout, "'"))
return nodes, nil
}
func (c *ClusterChecker) GetNodeStatus(nodeName string) (string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return "", err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath,
fmt.Sprintf("get node %s -o jsonpath='{.status.conditions[?(@.type==\"Ready\")].status}'", nodeName))
if err != nil {
return "", err
}
return strings.Trim(result.Stdout, "'"), nil
}
func (c *ClusterChecker) GetPodCount(namespace string) (int, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return 0, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
nsArg := "-A"
if namespace != "" {
nsArg = fmt.Sprintf("-n %s", namespace)
}
result, err := c.execKubectl(kubeconfigPath, fmt.Sprintf("get pods %s --no-headers | wc -l", nsArg))
if err != nil {
return 0, err
}
count, _ := strconv.Atoi(strings.TrimSpace(result.Stdout))
return count, nil
}
func (c *ClusterChecker) GetRunningPodCount(namespace string) (int, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return 0, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
nsArg := "-A"
if namespace != "" {
nsArg = fmt.Sprintf("-n %s", namespace)
}
result, err := c.execKubectl(kubeconfigPath,
fmt.Sprintf("get pods %s --no-headers --field-selector=status.phase=Running | wc -l", nsArg))
if err != nil {
return 0, err
}
count, _ := strconv.Atoi(strings.TrimSpace(result.Stdout))
return count, nil
}
func (c *ClusterChecker) GetNamespaceCount() (int, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return 0, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath, "get namespaces --no-headers | wc -l")
if err != nil {
return 0, err
}
count, _ := strconv.Atoi(strings.TrimSpace(result.Stdout))
return count, nil
}
func (c *ClusterChecker) GetClusterResourceStatus() (*config.ClusterResourceStatus, error) {
status := &config.ClusterResourceStatus{}
nodeCount, err := c.GetNodeCount()
if err != nil {
return nil, fmt.Errorf("获取节点数量失败: %w", err)
}
status.NodeCount = nodeCount
readyNodeCount, err := c.GetReadyNodeCount()
if err != nil {
return nil, fmt.Errorf("获取Ready节点数量失败: %w", err)
}
status.ReadyNodeCount = readyNodeCount
podCount, err := c.GetPodCount("")
if err != nil {
return nil, fmt.Errorf("获取Pod数量失败: %w", err)
}
status.PodCount = podCount
runningPodCount, err := c.GetRunningPodCount("")
if err != nil {
return nil, fmt.Errorf("获取Running Pod数量失败: %w", err)
}
status.RunningPodCount = runningPodCount
namespaceCount, err := c.GetNamespaceCount()
if err != nil {
return nil, fmt.Errorf("获取命名空间数量失败: %w", err)
}
status.NamespaceCount = namespaceCount
return status, nil
}
func (c *ClusterChecker) CheckSystemPods() (bool, string, error) {
return c.CheckNamespacePodsReady("kube-system")
}
func (c *ClusterChecker) CheckNamespacePodsReady(namespace string) (bool, string, error) {
return c.CheckNamespacePodsReadyWithKubeconfig(namespace, "")
}
func (c *ClusterChecker) CheckNamespacePodsReadyWithKubeconfig(namespace, parentKubeconfigPath string) (bool, string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFileWithKubeconfig(parentKubeconfigPath)
if err != nil {
return false, "", err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath,
fmt.Sprintf("get pods -n %s --no-headers", namespace))
if err != nil {
return false, "", err
}
output := result.Stdout
lines := strings.Split(strings.TrimSpace(output), "\n")
allReady := true
notReadyPods := []string{}
for _, line := range lines {
if line == "" {
continue
}
fields := strings.Fields(line)
if len(fields) < 3 {
continue
}
podName := fields[0]
status := fields[2]
if status != "Running" && status != "Completed" {
allReady = false
notReadyPods = append(notReadyPods, fmt.Sprintf("%s(%s)", podName, status))
}
}
if len(lines) == 1 && lines[0] == "" {
return false, "no pods found", nil
}
return allReady, strings.Join(notReadyPods, ", "), nil
}
func (c *ClusterChecker) GetNamespacePodStatuses(namespace string) (map[string]string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return nil, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath,
fmt.Sprintf("get pods -n %s --no-headers", namespace))
if err != nil {
return nil, err
}
output := result.Stdout
lines := strings.Split(strings.TrimSpace(output), "\n")
podStatuses := make(map[string]string)
for _, line := range lines {
if line == "" {
continue
}
fields := strings.Fields(line)
if len(fields) < 3 {
continue
}
podName := fields[0]
status := fields[2]
podStatuses[podName] = status
}
return podStatuses, nil
}
func (c *ClusterChecker) GetPodResourceRequest(namespace, selector, resourceType string) (string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return "", err
}
defer c.cleanupKubeconfig(kubeconfigPath)
args := fmt.Sprintf("get pods -n %s -l %s -o jsonpath='{.items[0].spec.containers[-1].resources.requests.%s}'", namespace, selector, resourceType)
result, err := c.execKubectl(kubeconfigPath, args)
if err != nil {
return "", err
}
return strings.TrimSpace(result.Stdout), nil
}
func (c *ClusterChecker) CheckCoreDNS() (bool, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return false, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath,
"get pods -n kube-system -l k8s-app=kube-dns --no-headers | grep Running | wc -l")
if err != nil {
return false, err
}
count, _ := strconv.Atoi(strings.TrimSpace(result.Stdout))
return count > 0, nil
}
func (c *ClusterChecker) CheckCalico() (bool, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return false, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath,
"get pods -n kube-system -l k8s-app=calico-node --no-headers | grep Running | wc -l")
if err != nil {
return false, err
}
count, _ := strconv.Atoi(strings.TrimSpace(result.Stdout))
return count > 0, nil
}
func (c *ClusterChecker) GetClusterVersion() (string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return "", err
}
defer c.cleanupKubeconfig(kubeconfigPath)
result, err := c.execKubectl(kubeconfigPath, "version --short 2>/dev/null | grep 'Server Version' || kubectl --kubeconfig "+kubeconfigPath+" version -o json | grep gitVersion | head -1")
if err != nil {
return "", err
}
return strings.TrimSpace(result.Stdout), nil
}
func (c *ClusterChecker) VerifyDNSResolution() (bool, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return false, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
testCmd := `run dns-test --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default 2>&1 | grep -q "Address" && echo "success" || echo "failed"`
result, err := c.execKubectl(kubeconfigPath, testCmd)
if err != nil {
return false, nil
}
return strings.Contains(result.Stdout, "success"), nil
}
func (c *ClusterChecker) cleanupKubeconfig(path string) {
c.executor.Exec(fmt.Sprintf("rm -f %s", path))
}
func (c *ClusterChecker) WaitForAllNodesReady(expectedCount int) (bool, error) {
readyCount, err := c.GetReadyNodeCount()
if err != nil {
return false, err
}
return readyCount == expectedCount, nil
}
func (c *ClusterChecker) WaitForSystemPodsReady() (bool, error) {
allRunning, notRunning, err := c.CheckSystemPods()
if err != nil {
return false, err
}
if !allRunning {
return false, fmt.Errorf("以下Pod未就绪: %s", notRunning)
}
return true, nil
}
func (c *ClusterChecker) CheckNodeHasLabel(labelKey, labelValue string) (bool, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return false, err
}
defer c.cleanupKubeconfig(kubeconfigPath)
selector := fmt.Sprintf("%s=%s", labelKey, labelValue)
args := fmt.Sprintf("get nodes -l %s --no-headers", selector)
result, err := c.execKubectl(kubeconfigPath, args)
if err != nil {
return false, err
}
output := strings.TrimSpace(result.Stdout)
return output != "", nil
}
func (c *ClusterChecker) GetPodNodeName(namespace, selector string) (string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return "", err
}
defer c.cleanupKubeconfig(kubeconfigPath)
nsArg := "-A"
if namespace != "" {
nsArg = fmt.Sprintf("-n %s", namespace)
}
args := fmt.Sprintf("get pods %s -l %s -o jsonpath='{.items[*].spec.nodeName}'", nsArg, selector)
result, err := c.execKubectl(kubeconfigPath, args)
if err != nil {
return "", err
}
return strings.TrimSpace(result.Stdout), nil
}
func (c *ClusterChecker) GetNodeLabels(nodeName string) (map[string]string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return nil, err
}
args := fmt.Sprintf("get node %s -o jsonpath='{.metadata.labels}'", nodeName)
result, err := c.execKubectl(kubeconfigPath, args)
if err != nil {
return nil, err
}
labels := make(map[string]string)
labels["_raw"] = strings.TrimSpace(strings.Trim(result.Stdout, "'"))
return labels, nil
}
func (c *ClusterChecker) CheckAllNodesHaveLabel(labelKey string) (bool, error) {
kubeconfigPath, err := c.SaveKubeconfigToFile()
if err != nil {
return false, err
}
totalResult, err := c.execKubectl(kubeconfigPath, "get nodes --no-headers | wc -l")
if err != nil {
return false, err
}
totalCount, _ := strconv.Atoi(strings.TrimSpace(totalResult.Stdout))
labeledArgs := fmt.Sprintf("get nodes -l %s --no-headers | wc -l", labelKey)
labeledResult, err := c.execKubectl(kubeconfigPath, labeledArgs)
if err != nil {
return false, err
}
labeledCount, _ := strconv.Atoi(strings.TrimSpace(labeledResult.Stdout))
return totalCount > 0 && totalCount == labeledCount, nil
}
func (c *ClusterChecker) verifySingleStaticPodKubeconfig(kubeconfigPath, podName, componentName string) (bool, string, error) {
args := fmt.Sprintf("get pod %s -n kube-system -o jsonpath='{.spec.containers[0].command[*]}'", podName)
result, err := c.execKubectl(kubeconfigPath, args)
if err != nil {
return false, "", fmt.Errorf("获取 Pod command 失败: %w", err)
}
commandArgs := strings.Fields(result.Stdout)
var authKubeconfigPath string
for i, arg := range commandArgs {
if arg == "--authorization-kubeconfig" && i+1 < len(commandArgs) {
authKubeconfigPath = commandArgs[i+1]
break
}
}
if authKubeconfigPath == "" {
return false, fmt.Sprintf("Pod %s 的 command 中未找到 --authorization-kubeconfig 参数", podName), nil
}
args = fmt.Sprintf("get pod %s -n kube-system -o jsonpath='{range .spec.containers[0].volumeMounts[*]}{.name}:{.mountPath}{\\n}{end}'", podName)
result, err = c.execKubectl(kubeconfigPath, args)
if err != nil {
return false, "", fmt.Errorf("获取 Pod volume mounts 失败: %w", err)
}
mountLines := strings.Split(strings.TrimSpace(result.Stdout), "\n")
found := false
var matchedMountPath string
for _, line := range mountLines {
if line == "" {
continue
}
parts := strings.SplitN(line, ":", 2)
if len(parts) != 2 {
continue
}
mountPath := parts[1]
if mountPath == authKubeconfigPath {
found = true
matchedMountPath = mountPath
break
}
if strings.HasPrefix(authKubeconfigPath, mountPath+"/") || strings.HasPrefix(authKubeconfigPath, mountPath) {
found = true
matchedMountPath = mountPath
break
}
}
if !found {
return false, fmt.Sprintf("Pod %s 的 --authorization-kubeconfig 指向 %s,但未找到对应的 volume mount (已检查的挂载路径: %v)", podName, authKubeconfigPath, mountLines), nil
}
return true, fmt.Sprintf("Pod %s: --authorization-kubeconfig=%s 已挂载到 %s", podName, authKubeconfigPath, matchedMountPath), nil
}
func (c *ClusterChecker) VerifyStaticPodKubeconfig(componentName string, parentKubeconfigPath string) (bool, string, error) {
kubeconfigPath, err := c.SaveKubeconfigToFileWithKubeconfig(parentKubeconfigPath)
if err != nil {
return false, "", err
}
defer c.cleanupKubeconfig(kubeconfigPath)
masterNodes := []string{}
labels := []string{
"node-role.kubernetes.io/master",
"node-role.kubernetes.io/control-plane",
}
for _, label := range labels {
args := fmt.Sprintf("get nodes -l %s --no-headers -o custom-columns=NAME:.metadata.name", label)
result, err := c.execKubectl(kubeconfigPath, args)
if err == nil && result.Stdout != "" {
nodes := strings.Fields(result.Stdout)
if len(nodes) > 0 {
masterNodes = nodes
break
}
}
}
if len(masterNodes) == 0 {
args := fmt.Sprintf("get pods -n kube-system --no-headers -o custom-columns=NAME:.metadata.name | grep '^%s-'", componentName)
result, err := c.execKubectl(kubeconfigPath, args)
if err == nil && result.Stdout != "" {
podNames := strings.Fields(result.Stdout)
for _, podName := range podNames {
if strings.HasPrefix(podName, componentName+"-") {
nodeName := strings.TrimPrefix(podName, componentName+"-")
masterNodes = append(masterNodes, nodeName)
}
}
}
}
if len(masterNodes) == 0 {
return false, fmt.Sprintf("未找到 master 节点,无法验证 %s 配置", componentName), nil
}
allValid := true
errors := []string{}
successes := []string{}
for _, nodeName := range masterNodes {
expectedPodName := fmt.Sprintf("%s-%s", componentName, nodeName)
args := fmt.Sprintf("get pod %s -n kube-system --no-headers -o custom-columns=NAME:.metadata.name", expectedPodName)
result, err := c.execKubectl(kubeconfigPath, args)
if err != nil || strings.TrimSpace(result.Stdout) == "" {
allValid = false
errors = append(errors, fmt.Sprintf("节点 %s: 未找到 Pod %s", nodeName, expectedPodName))
continue
}
valid, msg, err := c.verifySingleStaticPodKubeconfig(kubeconfigPath, expectedPodName, componentName)
if err != nil {
allValid = false
errors = append(errors, fmt.Sprintf("节点 %s: %v", nodeName, err))
continue
}
if !valid {
allValid = false
errors = append(errors, fmt.Sprintf("节点 %s: %s", nodeName, msg))
} else {
successes = append(successes, fmt.Sprintf("节点 %s: %s", nodeName, msg))
}
}
if allValid {
return true, fmt.Sprintf("所有 %d 个 master 节点的 %s 配置正确: %s", len(masterNodes), componentName, strings.Join(successes, "; ")), nil
}
return false, fmt.Sprintf("部分 master 节点的 %s 配置不正确: %s", componentName, strings.Join(errors, "; ")), nil
}
func (c *ClusterChecker) VerifyKubeControllerManagerKubeconfig(parentKubeconfigPath string) (bool, string, error) {
return c.VerifyStaticPodKubeconfig("kube-controller-manager", parentKubeconfigPath)
}
func (c *ClusterChecker) VerifyKubeSchedulerKubeconfig(parentKubeconfigPath string) (bool, string, error) {
return c.VerifyStaticPodKubeconfig("kube-scheduler", parentKubeconfigPath)
}
func (c *ClusterChecker) VerifyComponentKubeconfigs(parentKubeconfigPath string) (map[string]bool, map[string]string, error) {
results := make(map[string]bool)
messages := make(map[string]string)
ok, msg, err := c.VerifyKubeControllerManagerKubeconfig(parentKubeconfigPath)
if err != nil {
return nil, nil, fmt.Errorf("验证 kube-controller-manager kubeconfig 失败: %w", err)
}
results["kube-controller-manager"] = ok
messages["kube-controller-manager"] = msg
ok, msg, err = c.VerifyKubeSchedulerKubeconfig(parentKubeconfigPath)
if err != nil {
return nil, nil, fmt.Errorf("验证 kube-scheduler kubeconfig 失败: %w", err)
}
results["kube-scheduler"] = ok
messages["kube-scheduler"] = msg
return results, messages, nil
}
func (c *ClusterChecker) SetClientSet(kubeconfigPath string) error {
if c.clientSet != nil {
return nil
}
kubeconfigStr, err := c.GetKubeconfigWithKubeconfig(kubeconfigPath)
if err != nil {
return err
}
kubeConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(kubeconfigStr))
if err != nil {
return err
}
clientSet, err := kubernetes.NewForConfig(kubeConfig)
if err != nil {
panic(err)
}
c.clientSet = clientSet
return nil
}
func (c *ClusterChecker) IsNamespaceHasPods(namespace string) (bool, error) {
return c.IsNamespaceHasPodsWithKubeconfig(namespace, "")
}
func (c *ClusterChecker) IsNamespaceHasPodsWithKubeconfig(namespace string, parentKubeconfigPath string) (bool, error) {
if err := c.SetClientSet(parentKubeconfigPath); err != nil {
return false, err
}
podList, err := c.clientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
return len(podList.Items) > 0, err
}
func (c *ClusterChecker) IsNamespaceHasPodByName(namespace, podNamePrefix string) (bool, error) {
return c.IsNamespaceHasPodByNameWithKubeconfig(namespace, podNamePrefix, "")
}
func (c *ClusterChecker) IsNamespaceHasPodByNameWithKubeconfig(namespace, podNamePrefix, parentKubeconfigPath string) (bool, error) {
if err := c.SetClientSet(parentKubeconfigPath); err != nil {
return false, err
}
pods, err := c.clientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return false, err
}
for _, pod := range pods.Items {
if strings.HasPrefix(pod.Name, podNamePrefix) {
return true, nil
}
}
return false, nil
}
func (c *ClusterChecker) GetDeploymentImages(namespace, deploymentName string) ([]string, error) {
return c.GetDeploymentImagesWithKubeconfig(namespace, deploymentName, "")
}
func (c *ClusterChecker) GetDeploymentImagesWithKubeconfig(namespace, deploymentName, parentKubeconfigPath string) ([]string, error) {
if err := c.SetClientSet(parentKubeconfigPath); err != nil {
return []string{}, err
}
deployment, err := c.clientSet.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metav1.GetOptions{})
if err != nil {
return []string{}, err
}
return getImagesFromDeployment(deployment), nil
}
func getImagesFromDeployment(deployment *appsv1.Deployment) []string {
var images []string
for _, c := range deployment.Spec.Template.Spec.Containers {
images = append(images, c.Image)
}
for _, c := range deployment.Spec.Template.Spec.InitContainers {
images = append(images, c.Image)
}
return images
}
func GetImageTag(image string) string {
parts := strings.Split(image, ":")
if len(parts) == 2 {
return parts[1]
}
return "latest"
}