From af98a0dcfc3bb851f8ec393e7634239a6bf79c03 Mon Sep 17 00:00:00 2001 From: zeaslity Date: Mon, 8 Apr 2024 15:53:30 +0800 Subject: [PATCH] [ Cmii ] [ Octopus ] - update image tag --- agent-go/a_executor/ImageFunction.go | 27 + agent-go/a_executor/K8sFunction.go | 788 +++++++++++++++------------ agent-go/go.mod | 25 +- agent-go/go.sum | 74 ++- 4 files changed, 559 insertions(+), 355 deletions(-) diff --git a/agent-go/a_executor/ImageFunction.go b/agent-go/a_executor/ImageFunction.go index e074efa..5921d2c 100644 --- a/agent-go/a_executor/ImageFunction.go +++ b/agent-go/a_executor/ImageFunction.go @@ -1,6 +1,7 @@ package a_executor import ( + "fmt" "strings" "wdd.io/agent-common/image" ) @@ -270,7 +271,33 @@ func (op *AgentOsOperator) pushImageToTargetHarbor(funcArgs []string) (bool, []s targetImageFullName, } } + func (op *AgentOsOperator) updateImageTag(funcArgs []string) (bool, []string) { + namespace := funcArgs[6] + imageFullName := funcArgs[0] + if !strings.HasPrefix(imageFullName, image.CmiiHarborPrefix) { + return false, []string{ + "cant update this image !", + } + } + appName := image.ImageFullNameToAppName(imageFullName) + newTag := image.ImageFullNameToImageTag(imageFullName) + + sprintf := fmt.Sprintf("start to update [%s] image tag [%s] to [%s]", namespace, appName, newTag) + log.Info(sprintf) + + update, resultLog := K8sDeploymentUpdateTag(namespace, appName, newTag) + if !update { + return false, []string{ + sprintf, + } + } + return true, []string{ + resultLog, + } +} + +func (op *AgentOsOperator) updateImageTagByFile(funcArgs []string) (bool, []string) { namespace := funcArgs[6] //targetImageFullName := funcArgs[7] proxyUrl := funcArgs[4] diff --git a/agent-go/a_executor/K8sFunction.go b/agent-go/a_executor/K8sFunction.go index 4b4e12d..a4784ac 100644 --- a/agent-go/a_executor/K8sFunction.go +++ b/agent-go/a_executor/K8sFunction.go @@ -1,349 +1,445 @@ package a_executor -//var k8sConfigFilePath = "/root/wdd/kube_config_cluster.yml" -//var k8sClient = newK8sClientInstance() +import ( + "context" + "fmt" + v1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "os" + "strings" + "sync" + "time" + image2 "wdd.io/agent-common/image" + "wdd.io/agent-common/utils" +) -//func newK8sClientInstance() *kubernetes.Clientset { -// once := sync.Once{} -// -// if !BasicFileExistAndNotNull(k8sConfigFilePath) { -// log.WarnF("[newK8sClientInstance] - k8s config %s does not exist ! ", k8sConfigFilePath) -// return nil -// } -// -// var client *kubernetes.Clientset -// once.Do(func() { -// // 使用kubeconfig文件初始化客户端 -// config, err := clientcmd.BuildConfigFromFlags("", k8sConfigFilePath) -// if err != nil { -// log.ErrorF("[newK8sClientInstance] - load from %s error !", k8sConfigFilePath) -// -// } -// -// client, err = kubernetes.NewForConfig(config) -// if err != nil { -// log.Error("[newK8sClientInstance] - create k8s client error !") -// } -// }) -// -// return client -//} -// -//func K8sCheckPodStatusTimeout(specificPod string, supreme string, waitTimeOut int) bool { -// -// if k8sClient == nil { -// // this should be the first call of k8s function -// k8sClient = newK8sClientInstance() -// if k8sClient == nil { -// log.ErrorF("k8s client is nil, run k8s function error !") -// return false -// } -// } -// -// // 设置超时时间和时间间隔 -// timeout := time.After(time.Duration(waitTimeOut) * time.Second) -// tick := time.Tick(5 * time.Second) -// -// // 监控Pod状态 -// for { -// select { -// case <-timeout: -// log.ErrorF("[K8sCheckPodStatusTimeout] - 命名空间: [%s], Pod名称: [%s], 状态: 失败!", supreme, specificPod) -// return false -// case <-tick: -// pod, err := k8sClient.CoreV1().Pods(supreme).Get(context.TODO(), specificPod, metav1.GetOptions{}) -// if err != nil { -// log.ErrorF("[K8sCheckPodStatusTimeout] - 命名空间: [%s], Pod名称: [%s], 获取Pod信息失败 !", supreme, err.Error()) -// } else { -// log.DebugF("[K8sCheckPodStatusTimeout] - 命名空间: [%s], Pod名称: [%s], 状态: [%s]", supreme, pod.Name, pod.Status.Phase) -// if pod.Status.Phase == corev1.PodRunning || pod.Status.Phase == corev1.PodSucceeded { -// return true -// } -// } -// } -// } -//} -// -//func K8sCheckDeploymentStatusTimeout(specificDeployment string, supreme string, waitTimeOut int) bool { -// -// if k8sClient == nil { -// // this should be the first call of k8s function -// k8sClient = newK8sClientInstance() -// if k8sClient == nil { -// log.ErrorF("k8s client is nil, run k8s function error !") -// return false -// } -// } -// -// // 设置超时时间和时间间隔 -// timeout := time.After(time.Duration(waitTimeOut) * time.Second) -// tick := time.Tick(5 * time.Second) -// -// // 监控Pod状态 -// for { -// select { -// case <-timeout: -// log.ErrorF("[K8sCheckDeploymentStatusTimeout] - 命名空间: %s, Deployment名称: %s, 状态: 失败!\n", supreme, specificDeployment) -// return false -// case <-tick: -// deployment, err := k8sClient.AppsV1().Deployments(supreme).Get(context.TODO(), specificDeployment, metav1.GetOptions{}) -// if err != nil { -// log.ErrorF("[K8sCheckDeploymentStatusTimeout] - 命名空间: [%s], Deployment 名称: [%s], 获取Deployment信息失败 !", supreme, err.Error()) -// } else { -// log.DebugF("[K8sCheckDeploymentStatusTimeout] - 命名空间: [ %s ], Deployment: [ %s ] 还有Pods未处于Running状态 (Ready: %d, Total: %d)\n", supreme, deployment.Name, deployment.Status.ReadyReplicas, deployment.Status.Replicas) -// -// if deployment.Status.ReadyReplicas == deployment.Status.Replicas { -// return true -// } -// -// } -// } -// } -//} -// -//func K8sListPVCInNamespace(supreme string) (bool, []string) { -// -// if k8sClient == nil { -// // this should be the first call of k8s function -// k8sClient = newK8sClientInstance() -// if k8sClient == nil { -// log.ErrorF("k8s client is nil, run k8s function error !") -// return false, []string{ -// "[K8sListPVCInNamespace] - k8s client not exits !", -// } -// } -// } -// -// pvcs, err := k8sClient.CoreV1().PersistentVolumeClaims(supreme).List(context.TODO(), metav1.ListOptions{}) -// if err != nil { -// log.ErrorF("[K8sListPVCInNamespace] - error list pvc list in namespace %s", supreme) -// return false, nil -// } -// -// var pvcList []string -// for _, pvc := range pvcs.Items { -// pvcList = append(pvcList, pvc.Name) -// } -// -// log.DebugF("K8sListPVCInNamespace - all pvc in namespace of [ %s ] are %v", supreme, pvcList) -// return true, pvcList -//} -// -//func K8sCheckPVCStatusTimeOut(specificPvcName string, supreme string, waitTimeOut int) bool { -// -// if k8sClient == nil { -// // this should be the first call of k8s function -// k8sClient = newK8sClientInstance() -// if k8sClient == nil { -// log.ErrorF("k8s client is nil, run k8s function error !") -// return false -// } -// } -// -// // 设置超时时间和时间间隔 -// timeout := time.After(time.Duration(waitTimeOut) * time.Second) -// tick := time.Tick(5 * time.Second) -// -// // 监控Pod状态 -// for { -// select { -// case <-timeout: -// log.ErrorF("[K8sCheckPVCStatusTimeOut] - 命名空间: %s, PVC 名称: %s, 状态: 失败! ", supreme, specificPvcName) -// return false -// case <-tick: -// pvc, err := k8sClient.CoreV1().PersistentVolumeClaims(supreme).Get(context.TODO(), specificPvcName, metav1.GetOptions{}) -// if err != nil { -// log.ErrorF("[K8sCheckPVCStatusTimeOut] - 命名空间: [ %s ], 获取 PVC [%s] 信息失败: %s ", supreme, specificPvcName, err.Error()) -// } -// -// if pvc.Status.Phase == corev1.ClaimBound { -// log.DebugF("[K8sCheckPVCStatusTimeOut] - PVC %s in namespace %s is running", specificPvcName, supreme) -// return true -// } else { -// log.WarnF("[K8sCheckPVCStatusTimeOut] - PVC %s in namespace %s run failed !", specificPvcName, supreme) -// return false -// } -// } -// } -//} -// -//func KubectlCheckPodStatus(specific string, supreme string) bool { -// -// if !BasicCommandExists("kubectl") { -// log.Error("kubectl命令不存在,无法查看Pod状态,请查看!") -// } -// -// ok, resultLog := AllCommandExecutor([]string{ -// "kubectl", "-n", supreme, "get", "pod", specific, "-o", "jsonpath='{.status.phase}'", -// }) -// if !ok { -// return false -// } -// -// for _, resultLine := range resultLog { -// if strings.HasPrefix(resultLine, "Running") { -// return true -// } -// } -// -// return false -//} -// -//func KubectlApplyExec(resourcesYamlFile string) (bool, []string) { -// -// // check kubectl -// if !BasicCommandExistByPath("kubectl") { -// return false, []string{ -// "[KubectlApplyExec] - kubectl command not exist !", -// } -// } -// -// // check resourcesYamlFile -// if !BasicFileExistAndNotNull(resourcesYamlFile) { -// return false, []string{ -// fmt.Sprintf("[KubectlApplyExec] - wrong resourcesYamlFile %s not exist !", resourcesYamlFile), -// } -// } -// -// // apply -f -// ok, resultLog := AllCommandExecutor([]string{ -// "/usr/local/bin/kubectl", -// "apply", -// "-f", -// resourcesYamlFile, -// }) -// if !ok { -// return false, resultLog -// } -// -// return true, append(resultLog, -// fmt.Sprintf("[KubectlApplyExec] - %s apply success!", resourcesYamlFile)) -//} -// -//func KubectlDeleteExec(resourcesYamlFile string) (bool, []string) { -// -// // check kubectl -// if !BasicCommandExistByPath("kubectl") { -// return false, []string{ -// "[KubectlDeleteExec] - kubectl command not exist !", -// } -// } -// -// // check resourcesYamlFile -// if !BasicFileExistAndNotNull(resourcesYamlFile) { -// return false, []string{ -// fmt.Sprintf("[KubectlDeleteExec] - wrong resourcesYamlFile %s not exist !", resourcesYamlFile), -// } -// } -// -// // apply -f -// ok, resultLog := AllCommandExecutor([]string{ -// "/usr/local/bin/kubectl", -// "delete", -// "-f", -// resourcesYamlFile, -// }) -// if !ok { -// return false, resultLog -// } -// -// return true, append(resultLog, -// fmt.Sprintf("[KubectlDeleteExec] - %s delete success!", resourcesYamlFile)) -//} -// -//func K8sCreateNamespace(namespaceName string) bool { -// if k8sClient == nil { -// // this should be the first call of k8s function -// k8sClient = newK8sClientInstance() -// if k8sClient == nil { -// log.ErrorF("k8s client is nil, run k8s function error !") -// return false -// } -// } -// -// namespace, err := k8sClient.CoreV1().Namespaces().Get(context.TODO(), namespaceName, metav1.GetOptions{}) -// if err == nil { -// log.InfoF("[K8sCreateNamespace] - namespace of [%s] already exists!", namespaceName) -// return true -// } -// -// // create namespace -// // 创建命名空间对象 -// namespace = &corev1.Namespace{ -// ObjectMeta: metav1.ObjectMeta{ -// Name: namespaceName, -// }, -// } -// // 使用客户端创建命名空间 -// namespace, err = k8sClient.CoreV1().Namespaces().Create(context.TODO(), namespace, metav1.CreateOptions{}) -// if err != nil { -// log.ErrorF("Error getting namespace: %s ", err.Error()) -// return false -// } -// -// // check namespace exists -// // 尝试获取名为 "xxg" 的命名空间 -// namespace, err = k8sClient.CoreV1().Namespaces().Get(context.TODO(), namespaceName, metav1.GetOptions{}) -// // 如果返回错误,需要判断是因为命名空间不存在还是其他错误 -// if err != nil { -// if errors.IsNotFound(err) { -// log.ErrorF("Namespace %s cant be got !", namespaceName) -// return false -// } else { -// log.ErrorF("Error retrieving namespace: %s\n", err.Error()) -// } -// return false -// } -// -// log.DebugF("Namespace %s create successful !", namespaceName) -// return true -//} -// -//func K8sGetDashBoardAuthKey() bool { -// -// if k8sClient == nil { -// // this should be the first call of k8s function -// k8sClient = newK8sClientInstance() -// if k8sClient == nil { -// log.ErrorF("k8s client is nil, run k8s function error !") -// return false -// } -// } -// -// // 获取 kube-system 命名空间的 secrets 列表 -// secrets, err := k8sClient.CoreV1().Secrets("kube-system").List(context.TODO(), metav1.ListOptions{}) -// if err != nil { -// fmt.Printf("Error retrieving secrets from kube-system namespace: %s\n", err.Error()) -// os.Exit(1) -// } -// -// // 过滤出名为 admin-user 的 secret -// var adminUserSecretName string -// for _, secret := range secrets.Items { -// if strings.Contains(secret.Name, "admin-user") { -// adminUserSecretName = secret.Name -// break -// } -// } -// -// if adminUserSecretName == "" { -// fmt.Println("No admin-user secret found") -// os.Exit(1) -// } -// -// // 获取并打印特定的 secret 描述信息 -// secret, err := k8sClient.CoreV1().Secrets("kube-system").Get(context.TODO(), adminUserSecretName, metav1.GetOptions{}) -// if err != nil { -// fmt.Printf("Error retrieving secret %s: %s\n", adminUserSecretName, err.Error()) -// os.Exit(1) -// } -// -// // 打印 secret 的详细信息,根据需要格式化输出 -// fmt.Printf("Name: %s\nNamespace: %s\nData:\n", secret.Name, secret.Namespace) -// for key, value := range secret.Data { -// fmt.Printf("%s: %s\n", key, value) -// } -// -// return false -// -//} +var k8sConfigFilePath = "/root/wdd/kube_config_cluster.yml" +var k8sClient = newK8sClientInstance() + +func newK8sClientInstance() *kubernetes.Clientset { + once := sync.Once{} + + if !BasicFileExistAndNotNull(k8sConfigFilePath) { + log.WarnF("[newK8sClientInstance] - k8s config %s does not exist ! ", k8sConfigFilePath) + return nil + } + + var client *kubernetes.Clientset + once.Do(func() { + // 使用kubeconfig文件初始化客户端 + config, err := clientcmd.BuildConfigFromFlags("", k8sConfigFilePath) + if err != nil { + log.ErrorF("[newK8sClientInstance] - load from %s error !", k8sConfigFilePath) + + } + + client, err = kubernetes.NewForConfig(config) + if err != nil { + log.Error("[newK8sClientInstance] - create k8s client error !") + } + }) + + return client +} + +func K8sCheckPodStatusTimeout(specificPod string, supreme string, waitTimeOut int) bool { + + if k8sClient == nil { + // this should be the first call of k8s function + k8sClient = newK8sClientInstance() + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return false + } + } + + // 设置超时时间和时间间隔 + timeout := time.After(time.Duration(waitTimeOut) * time.Second) + tick := time.Tick(5 * time.Second) + + // 监控Pod状态 + for { + select { + case <-timeout: + log.ErrorF("[K8sCheckPodStatusTimeout] - 命名空间: [%s], Pod名称: [%s], 状态: 失败!", supreme, specificPod) + return false + case <-tick: + pod, err := k8sClient.CoreV1().Pods(supreme).Get(context.TODO(), specificPod, metav1.GetOptions{}) + if err != nil { + log.ErrorF("[K8sCheckPodStatusTimeout] - 命名空间: [%s], Pod名称: [%s], 获取Pod信息失败 !", supreme, err.Error()) + } else { + log.DebugF("[K8sCheckPodStatusTimeout] - 命名空间: [%s], Pod名称: [%s], 状态: [%s]", supreme, pod.Name, pod.Status.Phase) + if pod.Status.Phase == corev1.PodRunning || pod.Status.Phase == corev1.PodSucceeded { + return true + } + } + } + } +} + +func K8sCheckDeploymentStatusTimeout(specificDeployment string, supreme string, waitTimeOut int) bool { + + if k8sClient == nil { + // this should be the first call of k8s function + k8sClient = newK8sClientInstance() + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return false + } + } + + // 设置超时时间和时间间隔 + timeout := time.After(time.Duration(waitTimeOut) * time.Second) + tick := time.Tick(5 * time.Second) + + // 监控Pod状态 + for { + select { + case <-timeout: + log.ErrorF("[K8sCheckDeploymentStatusTimeout] - 命名空间: %s, Deployment名称: %s, 状态: 失败!\n", supreme, specificDeployment) + return false + case <-tick: + deployment, err := k8sClient.AppsV1().Deployments(supreme).Get(context.TODO(), specificDeployment, metav1.GetOptions{}) + if err != nil { + log.ErrorF("[K8sCheckDeploymentStatusTimeout] - 命名空间: [%s], Deployment 名称: [%s], 获取Deployment信息失败 !", supreme, err.Error()) + } else { + log.DebugF("[K8sCheckDeploymentStatusTimeout] - 命名空间: [ %s ], Deployment: [ %s ] 还有Pods未处于Running状态 (Ready: %d, Total: %d)\n", supreme, deployment.Name, deployment.Status.ReadyReplicas, deployment.Status.Replicas) + + if deployment.Status.ReadyReplicas == deployment.Status.Replicas { + return true + } + + } + } + } +} + +func K8sDeploymentUpdateTag(supreme, appName, newTag string) (bool, string) { + + if k8sClient == nil { + // this should be the first call of k8s function + k8sClient = newK8sClientInstance() + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return false, "" + } + } + + if newTag == "" { + log.WarnF("[K8sDeploymentUpdateTag] - can not update image tag to null!") + return false, "" + } + + deployment := K8sDeploymentExists(supreme, appName) + if deployment == nil { + return false, "" + } + + updateResultLog := "" + + containers := deployment.Spec.Template.Spec.Containers + if len(containers) == 1 { + // only update this kind + container := containers[0] + + oldName := container.Image + + split := strings.Split(container.Image, ":") + if strings.HasPrefix(container.Image, image2.CmiiHarborPrefix) { + // harbor + container.Image = split[0] + ":" + newTag + } else if strings.Contains(container.Image, "8033") { + // 192.168.6.6:8033/rancher/k8s-dns-sidecar:v1.0.2 + container.Image = split[0] + ":" + split[1] + ":" + newTag + } + + updateResultLog = fmt.Sprintf(" [%s] [%s] [%s] from [%s] to [%s]", utils.TimeSplitFormatString(), supreme, appName, oldName, container.Image) + log.Info(updateResultLog) + + // re assign + deployment.Spec.Template.Spec.Containers[0] = container + + // update + _, err := k8sClient.AppsV1().Deployments(deployment.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{}) + if err != nil { + log.ErrorF("[K8sDeploymentUpdateTag] - update [%s] [%s] from [%s] to [%s] error ! %s", supreme, appName, split[1], container.Image, err.Error()) + return false, "" + } + } else if len(containers) == 2 { + log.ErrorF("[K8sDeploymentUpdateTag] - cant update app with 2 containers !") + return false, "" + } + + return true, updateResultLog +} + +func K8sDeploymentExists(supreme, appName string) *v1.Deployment { + + if k8sClient == nil { + // this should be the first call of k8s function + k8sClient = newK8sClientInstance() + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return nil + } + } + + deployment, err := k8sClient.AppsV1().Deployments(supreme).Get(context.TODO(), appName, metav1.GetOptions{}) + if err != nil { + log.ErrorF("[DeploymentExist] - deployments [%s] [%s] not exists ! %s", supreme, appName, err.Error()) + return nil + } + + return deployment +} + +func K8sListPVCInNamespace(supreme string) (bool, []string) { + + if k8sClient == nil { + // this should be the first call of k8s function + k8sClient = newK8sClientInstance() + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return false, []string{ + "[K8sListPVCInNamespace] - k8s client not exits !", + } + } + } + + pvcs, err := k8sClient.CoreV1().PersistentVolumeClaims(supreme).List(context.TODO(), metav1.ListOptions{}) + if err != nil { + log.ErrorF("[K8sListPVCInNamespace] - error list pvc list in namespace %s", supreme) + return false, nil + } + + var pvcList []string + for _, pvc := range pvcs.Items { + pvcList = append(pvcList, pvc.Name) + } + + log.DebugF("K8sListPVCInNamespace - all pvc in namespace of [ %s ] are %v", supreme, pvcList) + return true, pvcList +} + +func K8sCheckPVCStatusTimeOut(specificPvcName string, supreme string, waitTimeOut int) bool { + + if k8sClient == nil { + // this should be the first call of k8s function + k8sClient = newK8sClientInstance() + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return false + } + } + + // 设置超时时间和时间间隔 + timeout := time.After(time.Duration(waitTimeOut) * time.Second) + tick := time.Tick(5 * time.Second) + + // 监控Pod状态 + for { + select { + case <-timeout: + log.ErrorF("[K8sCheckPVCStatusTimeOut] - 命名空间: %s, PVC 名称: %s, 状态: 失败! ", supreme, specificPvcName) + return false + case <-tick: + pvc, err := k8sClient.CoreV1().PersistentVolumeClaims(supreme).Get(context.TODO(), specificPvcName, metav1.GetOptions{}) + if err != nil { + log.ErrorF("[K8sCheckPVCStatusTimeOut] - 命名空间: [ %s ], 获取 PVC [%s] 信息失败: %s ", supreme, specificPvcName, err.Error()) + } + + if pvc.Status.Phase == corev1.ClaimBound { + log.DebugF("[K8sCheckPVCStatusTimeOut] - PVC %s in namespace %s is running", specificPvcName, supreme) + return true + } else { + log.WarnF("[K8sCheckPVCStatusTimeOut] - PVC %s in namespace %s run failed !", specificPvcName, supreme) + return false + } + } + } +} + +func KubectlCheckPodStatus(specific string, supreme string) bool { + + if !BasicCommandExists("kubectl") { + log.Error("kubectl命令不存在,无法查看Pod状态,请查看!") + } + + ok, resultLog := AllCommandExecutor([]string{ + "kubectl", "-n", supreme, "get", "pod", specific, "-o", "jsonpath='{.status.phase}'", + }) + if !ok { + return false + } + + for _, resultLine := range resultLog { + if strings.HasPrefix(resultLine, "Running") { + return true + } + } + + return false +} + +func KubectlApplyExec(resourcesYamlFile string) (bool, []string) { + + // check kubectl + if !BasicCommandExistByPath("kubectl") { + return false, []string{ + "[KubectlApplyExec] - kubectl command not exist !", + } + } + + // check resourcesYamlFile + if !BasicFileExistAndNotNull(resourcesYamlFile) { + return false, []string{ + fmt.Sprintf("[KubectlApplyExec] - wrong resourcesYamlFile %s not exist !", resourcesYamlFile), + } + } + + // apply -f + ok, resultLog := AllCommandExecutor([]string{ + "/usr/local/bin/kubectl", + "apply", + "-f", + resourcesYamlFile, + }) + if !ok { + return false, resultLog + } + + return true, append(resultLog, + fmt.Sprintf("[KubectlApplyExec] - %s apply success!", resourcesYamlFile)) +} + +func KubectlDeleteExec(resourcesYamlFile string) (bool, []string) { + + // check kubectl + if !BasicCommandExistByPath("kubectl") { + return false, []string{ + "[KubectlDeleteExec] - kubectl command not exist !", + } + } + + // check resourcesYamlFile + if !BasicFileExistAndNotNull(resourcesYamlFile) { + return false, []string{ + fmt.Sprintf("[KubectlDeleteExec] - wrong resourcesYamlFile %s not exist !", resourcesYamlFile), + } + } + + // apply -f + ok, resultLog := AllCommandExecutor([]string{ + "/usr/local/bin/kubectl", + "delete", + "-f", + resourcesYamlFile, + }) + if !ok { + return false, resultLog + } + + return true, append(resultLog, + fmt.Sprintf("[KubectlDeleteExec] - %s delete success!", resourcesYamlFile)) +} + +func K8sCreateNamespace(namespaceName string) bool { + if k8sClient == nil { + // this should be the first call of k8s function + k8sClient = newK8sClientInstance() + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return false + } + } + + namespace, err := k8sClient.CoreV1().Namespaces().Get(context.TODO(), namespaceName, metav1.GetOptions{}) + if err == nil { + log.InfoF("[K8sCreateNamespace] - namespace of [%s] already exists!", namespaceName) + return true + } + + // create namespace + // 创建命名空间对象 + namespace = &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespaceName, + }, + } + // 使用客户端创建命名空间 + namespace, err = k8sClient.CoreV1().Namespaces().Create(context.TODO(), namespace, metav1.CreateOptions{}) + if err != nil { + log.ErrorF("Error getting namespace: %s ", err.Error()) + return false + } + + // check namespace exists + // 尝试获取名为 "xxg" 的命名空间 + namespace, err = k8sClient.CoreV1().Namespaces().Get(context.TODO(), namespaceName, metav1.GetOptions{}) + // 如果返回错误,需要判断是因为命名空间不存在还是其他错误 + if err != nil { + if errors.IsNotFound(err) { + log.ErrorF("Namespace %s cant be got !", namespaceName) + return false + } else { + log.ErrorF("Error retrieving namespace: %s\n", err.Error()) + } + return false + } + + log.DebugF("Namespace %s create successful !", namespaceName) + return true +} + +func K8sGetDashBoardAuthKey() bool { + + if k8sClient == nil { + // this should be the first call of k8s function + k8sClient = newK8sClientInstance() + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return false + } + } + + // 获取 kube-system 命名空间的 secrets 列表 + secrets, err := k8sClient.CoreV1().Secrets("kube-system").List(context.TODO(), metav1.ListOptions{}) + if err != nil { + fmt.Printf("Error retrieving secrets from kube-system namespace: %s\n", err.Error()) + os.Exit(1) + } + + // 过滤出名为 admin-user 的 secret + var adminUserSecretName string + for _, secret := range secrets.Items { + if strings.Contains(secret.Name, "admin-user") { + adminUserSecretName = secret.Name + break + } + } + + if adminUserSecretName == "" { + fmt.Println("No admin-user secret found") + os.Exit(1) + } + + // 获取并打印特定的 secret 描述信息 + secret, err := k8sClient.CoreV1().Secrets("kube-system").Get(context.TODO(), adminUserSecretName, metav1.GetOptions{}) + if err != nil { + fmt.Printf("Error retrieving secret %s: %s\n", adminUserSecretName, err.Error()) + os.Exit(1) + } + + // 打印 secret 的详细信息,根据需要格式化输出 + fmt.Printf("Name: %s\nNamespace: %s\nData:\n", secret.Name, secret.Namespace) + for key, value := range secret.Data { + fmt.Printf("%s: %s\n", key, value) + } + + return false + +} diff --git a/agent-go/go.mod b/agent-go/go.mod index 82c9f05..dee9a5f 100644 --- a/agent-go/go.mod +++ b/agent-go/go.mod @@ -10,6 +10,9 @@ require ( github.com/streadway/amqp v1.1.0 golang.org/x/net v0.24.0 gopkg.in/yaml.v3 v3.0.1 + k8s.io/api v0.29.1 + k8s.io/apimachinery v0.29.1 + k8s.io/client-go v0.29.1 wdd.io/agent-common v0.0.0 ) @@ -17,6 +20,8 @@ replace wdd.io/agent-common => ../agent-common require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -33,13 +38,21 @@ require ( github.com/go-openapi/validate v0.22.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/goharbor/harbor/src v0.0.0-20230220075213-6015b3efa7d0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect @@ -59,10 +72,20 @@ require ( go.opentelemetry.io/otel/trace v1.14.0 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.27.0 // indirect + golang.org/x/oauth2 v0.10.0 // indirect golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apimachinery v0.26.2 // indirect k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/agent-go/go.sum b/agent-go/go.sum index e565ced..c161464 100644 --- a/agent-go/go.sum +++ b/agent-go/go.sum @@ -55,6 +55,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -112,6 +114,8 @@ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= @@ -165,9 +169,14 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -177,9 +186,12 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -195,6 +207,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -209,10 +223,14 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= @@ -225,8 +243,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -248,10 +266,21 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mittwald/goharbor-client/v5 v5.5.3 h1:AClQeSVjO7ThTjBWGso1j9szueTxdb8LthRBuOpibyQ= github.com/mittwald/goharbor-client/v5 v5.5.3/go.mod h1:P83UsJz83Ku8eB/Kg+d4+sA1E8rKQ0ScWDkbnQDSElA= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/panjf2000/ants/v2 v2.7.2 h1:2NUt9BaZFO5kQzrieOmK/wdb/tQ/K+QHaxN8sOgD63U= @@ -272,8 +301,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE= github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU= github.com/shoenig/go-m1cpu v0.1.4 h1:SZPIgRM2sEF9NJy50mRHu9PKGwxyyTTJIWvCtgVbozs= @@ -311,8 +340,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= @@ -449,6 +479,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -516,6 +548,8 @@ golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -532,6 +566,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -586,6 +622,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -615,6 +653,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -678,16 +717,23 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -703,12 +749,24 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= -k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/api v0.29.1 h1:DAjwWX/9YT7NQD4INu49ROJuZAAAP/Ijki48GUPzxqw= +k8s.io/api v0.29.1/go.mod h1:7Kl10vBRUXhnQQI8YR/R327zXC8eJ7887/+Ybta+RoQ= +k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc= +k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= +k8s.io/client-go v0.29.1 h1:19B/+2NGEwnFLzt0uB5kNJnfTsbV8w6TgQRz9l7ti7A= +k8s.io/client-go v0.29.1/go.mod h1:TDG/psL9hdet0TI9mGyHJSgRkW3H9JZk2dNEUS7bRks= k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=