diff --git a/agent-go/executor/AppFunction.go b/agent-go/executor/AppFunction.go index ba6b138..e9f552b 100644 --- a/agent-go/executor/AppFunction.go +++ b/agent-go/executor/AppFunction.go @@ -1,6 +1,7 @@ package executor import ( + "fmt" "net" "time" ) @@ -17,6 +18,7 @@ type AppFunc interface { } var AppExecuteErrorLogPrefix = []string{"App指令执行错误! => "} +var nfsDataPath = "/var/lib/docker/nfs_data" func (op *AgentOsOperator) Deploy(appFuncName string, funcArgs ...string) (bool, []string) { @@ -30,14 +32,17 @@ func (op *AgentOsOperator) Deploy(appFuncName string, funcArgs ...string) (bool, case "DEPLOY_K8S_DASHBOARD": resultOK, result = op.deployK8sDashboard(funcArgs) break + case "DEPLOY_K8S_NAMESPACE": + resultOK, result = op.deployK8sNamespace(funcArgs) + break case "DEPLOY_MINIO": resultOK, result = op.deployMinio(funcArgs) break case "DEPLOY_NFS": resultOK, result = op.deployNFS(funcArgs) break - case "testNFS": - resultOK, result = op.testNFS(funcArgs) + case "DEPLOY_TEST_NFS": + resultOK, result = op.deployTestNFS(funcArgs) break case "deployPVC": resultOK, result = op.deployPVC(funcArgs) @@ -202,6 +207,19 @@ func (op *AgentOsOperator) deployK8sDashboard(funcArgs []string) (bool, []string return true, nil } +func (op *AgentOsOperator) deployK8sNamespace(funcArgs []string) (bool, []string) { + + if !CreateK8sNamespace(funcArgs[1]) { + return false, []string{ + fmt.Sprintf("Namespace of %s create error!", funcArgs[1]), + } + } + + return true, []string{ + fmt.Sprintf("Namespace of %s create success !", funcArgs[1]), + } +} + func (op *AgentOsOperator) deployMinio(funcArgs []string) (bool, []string) { minioTemplateFileName := "minio-docker-compose.yaml" result := append(AppExecuteErrorLogPrefix, "部署MINIO") @@ -255,16 +273,12 @@ func (op *AgentOsOperator) deployMinio(funcArgs []string) (bool, []string) { func (op *AgentOsOperator) deployNFS(funcArgs []string) (bool, []string) { - nfsTemplateFile := "nfs-template.yaml" + nfsTemplateFile := "k8s-nfs-template.yaml" result := append(AppExecuteErrorLogPrefix, "部署NFS") - nfsDataPath := "/nfsdata" // 环境判定 - commandExist, commandName := BasicCommandExistsBatch([]string{ - "kubectl", - }) - if !commandExist { - result = append(result, "命令不存在", commandName) + if !BasicCommandExistByPath("kubectl") { + result = append(result, "命令不存在", "kubectl") return false, result } // 创建目录修改权限 @@ -277,29 +291,27 @@ func (op *AgentOsOperator) deployNFS(funcArgs []string) (bool, []string) { } // 下载模板文件 - if !PureResultSingleExecute([]string{ - "wget", - "-q", - op.OssOfflinePrefix + "/" + nfsTemplateFile, - }) { - result = append(result, "下载模板文件") - return false, result + k8sNFSYamlFile := "/root/wdd/install/k8s-nfs.yaml" + ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+nfsTemplateFile, k8sNFSYamlFile) + if !ok { + return false, resultLog } + // 根据参数 A1C2IP 替换 - if !BasicReplace(nfsTemplateFile, "N1C2IP", funcArgs[0]) { + ip := net.ParseIP(funcArgs[0]) + if ip == nil { + return false, append(result, + "ip args error !") + } + if !BasicReplace(k8sNFSYamlFile, "N1C2IP", funcArgs[0]) { result = append(result, "替换IP信息") return false, result } // 启动服务 - if !PureResultSingleExecute([]string{ - "kubectl", - "apply", - "-f", - nfsTemplateFile, - }) { - result = append(result, "启动NFS失败!") - return false, result + exec, strings := KubectlApplyExec(k8sNFSYamlFile) + if !exec { + return false, strings } // 成功启动 @@ -308,48 +320,43 @@ func (op *AgentOsOperator) deployNFS(funcArgs []string) (bool, []string) { } } -func (op *AgentOsOperator) testNFS(funcArgs []string) (bool, []string) { +func (op *AgentOsOperator) deployTestNFS(funcArgs []string) (bool, []string) { - nfsTemplateFile := "nfs-test-template.yaml" + nfsTemplateFile := "k8s-nfs-test-template.yaml" result := append(AppExecuteErrorLogPrefix, "测试NFS部署") // 环境判定 - commandExist, commandName := BasicCommandExistsBatch([]string{ - "kubectl", - }) - if !commandExist { - result = append(result, "命令不存在", commandName) + if !BasicCommandExistByPath("kubectl") { + result = append(result, "命令不存在", "kubectl") return false, result } // 下载模板文件 - if !PureResultSingleExecute([]string{ - "wget", - "-q", - op.OssOfflinePrefix + "/" + nfsTemplateFile, - }) { - result = append(result, "下载模板文件") - return false, result + k8sNFSYamlFile := "/root/wdd/install/k8s-nfs-test.yaml" + ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+nfsTemplateFile, k8sNFSYamlFile) + if !ok { + return false, resultLog } // 根据参数 A1C2IP 替换 - if !BasicReplace(nfsTemplateFile, "N1C2IP", funcArgs[0]) { + ip := net.ParseIP(funcArgs[0]) + if ip == nil { + return false, append(result, + "ip args error !") + } + if !BasicReplace(k8sNFSYamlFile, "N1C2IP", funcArgs[0]) { result = append(result, "替换IP信息") return false, result } // 启动服务 - if !PureResultSingleExecute([]string{ - "kubectl", - "apply", - "-f", - nfsTemplateFile, - }) { - result = append(result, "启动NFS-TEST失败!") - return false, result + // 启动服务 + exec, strings := KubectlApplyExec(k8sNFSYamlFile) + if !exec { + return false, strings } // 测试文件是否存在 - if !BasicFileExists("/nfsdata/test-pod*/NFS-CREATE-SUCCESS") { + if !BasicFileExists(nfsDataPath + "/test-pod*/NFS-CREATE-SUCCESS") { result = append(result, "NFS 测试功能 异常!!") return false, result } @@ -362,42 +369,31 @@ func (op *AgentOsOperator) testNFS(funcArgs []string) (bool, []string) { func (op *AgentOsOperator) deployPVC(funcArgs []string) (bool, []string) { - pvcTemplateFile := "pvc-template.yaml" + pvcTemplateFile := "k8s-pvc-template.yaml" result := append(AppExecuteErrorLogPrefix, "部署PVC") // 环境判定 - commandExist, commandName := BasicCommandExistsBatch([]string{ - "kubectl", - }) - if !commandExist { - result = append(result, "命令不存在", commandName) + if !BasicCommandExistByPath("kubectl") { + result = append(result, "命令不存在", "kubectl") return false, result } // 下载模板文件 - if !PureResultSingleExecute([]string{ - "wget", - "-q", - op.OssOfflinePrefix + "/" + pvcTemplateFile, - }) { - result = append(result, "下载模板文件") - return false, result + k8sNFSYamlFile := "/root/wdd/install/k8s-pvc.yaml" + ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+pvcTemplateFile, k8sNFSYamlFile) + if !ok { + return false, resultLog } // 根据参数 A1C2IP 替换 - if !BasicReplace(pvcTemplateFile, "SUPREME", funcArgs[0]) { + if !BasicReplace(k8sNFSYamlFile, "SUPREME", funcArgs[1]) { result = append(result, "替换SUPREME信息") return false, result } // 启动服务 - if !PureResultSingleExecute([]string{ - "kubectl", - "apply", - "-f", - pvcTemplateFile, - }) { - result = append(result, "创建PVC失败!") - return false, result + exec, strings := KubectlApplyExec(k8sNFSYamlFile) + if !exec { + return false, strings } // 成功启动 @@ -408,48 +404,44 @@ func (op *AgentOsOperator) deployPVC(funcArgs []string) (bool, []string) { func (op *AgentOsOperator) deployMySQL(funcArgs []string) (bool, []string) { - mysqlTemplate := "mysql-template.yaml" + mysqlTemplate := "k8s-mysql-template.yaml" result := append(AppExecuteErrorLogPrefix, "部署 MySQL !") // 环境判定 - commandExist, commandName := BasicCommandExistsBatch([]string{ - "kubectl", - }) - if !commandExist { - result = append(result, "命令不存在", commandName) + if !BasicCommandExistByPath("kubectl") { + result = append(result, "命令不存在", "kubectl") return false, result } // 下载模板文件 - if !PureResultSingleExecute([]string{ - "wget", - "-q", - op.OssOfflinePrefix + "/" + mysqlTemplate, - }) { - result = append(result, "下载模板文件") - return false, result + k8sMysqlYamlFile := "/root/wdd/install/k8s-mysql.yaml" + ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+mysqlTemplate, k8sMysqlYamlFile) + if !ok { + return false, resultLog } // 根据参数 A1C2IP 替换 - if !BasicReplace(mysqlTemplate, "SUPREME", funcArgs[0]) { - result = append(result, "替换SUPREME信息") - return false, result + ip := net.ParseIP(funcArgs[0]) + if ip == nil { + return false, append(result, + "ip args error !") } - if !BasicReplace(mysqlTemplate, "A1C2IP", funcArgs[1]) { + if !BasicReplace(k8sMysqlYamlFile, "A1C2IP", funcArgs[0]) { result = append(result, "替换A1C2IP信息") return false, result } - // 启动服务 - if !PureResultSingleExecute([]string{ - "kubectl", - "apply", - "-f", - mysqlTemplate, - }) { - result = append(result, "创建MySQL失败!") + // 替换SUPREME信 + if !BasicReplace(k8sMysqlYamlFile, "SUPREME", funcArgs[1]) { + result = append(result, "替换SUPREME信息") return false, result } + // 启动服务 + exec, strings := KubectlApplyExec(k8sMysqlYamlFile) + if !exec { + return false, append(result, strings...) + } + // 成功启动 return true, []string{ "MySQL部署成功!", @@ -473,48 +465,44 @@ func (op *AgentOsOperator) checkMySQL(funcArgs []string) (bool, []string) { func (op *AgentOsOperator) deployMiddlewares(funcArgs []string) (bool, []string) { - middlewaresTemplate := "middleware-template.yaml" + middlewaresTemplate := "k8s-middleware-template.yaml" result := append(AppExecuteErrorLogPrefix, "部署 所有的中间件 !") // 环境判定 - commandExist, commandName := BasicCommandExistsBatch([]string{ - "kubectl", - }) - if !commandExist { - result = append(result, "命令不存在", commandName) + if !BasicCommandExistByPath("kubectl") { + result = append(result, "命令不存在", "kubectl") return false, result } // 下载模板文件 - if !PureResultSingleExecute([]string{ - "wget", - "-q", - op.OssOfflinePrefix + "/" + middlewaresTemplate, - }) { - result = append(result, "下载模板文件") - return false, result + k8sMiddlewaresYamlFile := "/root/wdd/install/k8s-middlewares.yaml" + ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+middlewaresTemplate, k8sMiddlewaresYamlFile) + if !ok { + return false, resultLog } + // 根据参数 A1C2IP 替换 - if !BasicReplace(middlewaresTemplate, "SUPREME", funcArgs[0]) { - result = append(result, "替换SUPREME信息") - return false, result + ip := net.ParseIP(funcArgs[0]) + if ip == nil { + return false, append(result, + "ip args error !") } - if !BasicReplace(middlewaresTemplate, "A1C2IP", funcArgs[1]) { + if !BasicReplace(k8sMiddlewaresYamlFile, "A1C2IP", funcArgs[0]) { result = append(result, "替换A1C2IP信息") return false, result } - // 启动服务 - if !PureResultSingleExecute([]string{ - "kubectl", - "apply", - "-f", - middlewaresTemplate, - }) { - result = append(result, "创建 中间件 失败!") + if !BasicReplace(k8sMiddlewaresYamlFile, "SUPREME", funcArgs[1]) { + result = append(result, "替换SUPREME信息") return false, result } + // 启动服务 + exec, strings := KubectlApplyExec(k8sMiddlewaresYamlFile) + if !exec { + return false, append(result, strings...) + } + // 成功启动 return true, []string{ "中间件部署成功!", @@ -524,48 +512,44 @@ func (op *AgentOsOperator) deployMiddlewares(funcArgs []string) (bool, []string) func (op *AgentOsOperator) deployRedis(funcArgs []string) (bool, []string) { - redisTemplate := "redis-template.yaml" + redisTemplate := "k8s-redis-template.yaml" result := append(AppExecuteErrorLogPrefix, "部署 redis !") // 环境判定 - commandExist, commandName := BasicCommandExistsBatch([]string{ - "kubectl", - }) - if !commandExist { - result = append(result, "命令不存在", commandName) + if !BasicCommandExistByPath("kubectl") { + result = append(result, "命令不存在", "kubectl") return false, result } // 下载模板文件 - if !PureResultSingleExecute([]string{ - "wget", - "-q", - op.OssOfflinePrefix + "/" + redisTemplate, - }) { - result = append(result, "下载模板文件") - return false, result + k8sRedisYamlFile := "/root/wdd/install/k8s-redis.yaml" + ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+redisTemplate, k8sRedisYamlFile) + if !ok { + return false, resultLog } + // 根据参数 A1C2IP 替换 - if !BasicReplace(redisTemplate, "SUPREME", funcArgs[0]) { - result = append(result, "替换SUPREME信息") - return false, result + ip := net.ParseIP(funcArgs[0]) + if ip == nil { + return false, append(result, + "ip args error !") } - if !BasicReplace(redisTemplate, "A1C2IP", funcArgs[1]) { + if !BasicReplace(k8sRedisYamlFile, "A1C2IP", funcArgs[0]) { result = append(result, "替换A1C2IP信息") return false, result } - // 启动服务 - if !PureResultSingleExecute([]string{ - "kubectl", - "apply", - "-f", - redisTemplate, - }) { - result = append(result, "创建 Redis 失败!") + if !BasicReplace(k8sRedisYamlFile, "SUPREME", funcArgs[1]) { + result = append(result, "替换SUPREME信息") return false, result } + // 启动服务 + exec, strings := KubectlApplyExec(k8sRedisYamlFile) + if !exec { + return false, append(result, strings...) + } + // 成功启动 return true, []string{ "Redis 部署成功!", diff --git a/agent-go/executor/HarborExecutor.go b/agent-go/executor/HarborExecutor.go index b8d0684..908b0f8 100644 --- a/agent-go/executor/HarborExecutor.go +++ b/agent-go/executor/HarborExecutor.go @@ -393,7 +393,7 @@ func (hOp *HarborOperator) SyncStatusExec(funcArgs []string) (bool, []string) { // report status return false, []string{ fmt.Sprintf("[sync status] - not complete ! progress is => %s %", - strconv.FormatFloat(float64(execution.Succeed)/float64(execution.Total), 'f', 1, 64)), + strconv.FormatFloat(float64(execution.Succeed)/float64(execution.Total)*100, 'f', 2, 64)), } } } diff --git a/agent-go/executor/K8sFunction.go b/agent-go/executor/K8sFunction.go index 711b452..c59cb17 100644 --- a/agent-go/executor/K8sFunction.go +++ b/agent-go/executor/K8sFunction.go @@ -2,18 +2,21 @@ package executor import ( "fmt" + "k8s.io/apimachinery/pkg/api/errors" + "os" "strings" "sync" "time" "context" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" ) -var k8sConfigFilePath = "/root/.kube/config" +var k8sConfigFilePath = "/root/wdd/kube_config_cluster.yml" var k8sClient = newK8sClientInstance() func newK8sClientInstance() *kubernetes.Clientset { @@ -107,7 +110,7 @@ func CheckDeploymentStatusTimeout(specificDeployment string, supreme string, wai if err != nil { log.ErrorF("[CheckDeploymentStatusTimeout] - 获取deployment信息失败: %v\n", err) } else { - log.DebugF("[CheckDeploymentStatusTimeout] - 命名空间: %s, Deployment %s 还有Pods未处于Running状态 (Ready: %d, Total: %d)\n", supreme, deployment.Name, deployment.Status.ReadyReplicas, deployment.Status.Replicas) + log.DebugF("[CheckDeploymentStatusTimeout] - 命名空间: [ %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 @@ -179,3 +182,80 @@ func KubectlDeleteExec(resourcesYamlFile string) (bool, []string) { return true, append(resultLog, fmt.Sprintf("[KubectlDeleteExec] - %s delete success!", resourcesYamlFile)) } + +func CreateK8sNamespace(namespaceName string) bool { + if k8sClient == nil { + log.ErrorF("k8s client is nil, run k8s function error !") + return false + } + + // create namespace + // 创建命名空间对象 + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespaceName, + }, + } + // 使用客户端创建命名空间 + _, err := k8sClient.CoreV1().Namespaces().Create(context.TODO(), namespace, metav1.CreateOptions{}) + if err != nil { + log.ErrorF("Error creating namespace: %s \n", 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 GetK8sDashBoardAuthKey() { + + // 获取 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) + } + +} diff --git a/server/src/main/java/io/wdd/func/auto/beans/AppFunctionEnum.java b/server/src/main/java/io/wdd/func/auto/beans/AppFunctionEnum.java index 05642a9..b2b3bf5 100644 --- a/server/src/main/java/io/wdd/func/auto/beans/AppFunctionEnum.java +++ b/server/src/main/java/io/wdd/func/auto/beans/AppFunctionEnum.java @@ -31,6 +31,10 @@ public enum AppFunctionEnum { "部署nfs+storage_class, 参数为A1C2IP, SUPREME, N1C2IP" ), + DEPLOY_TEST_NFS( + "DEPLOY_TEST_NFS", + "部署NFS的测试Pod, 参数为A1C2IP, SUPREME, N1C2IP" + ), DEPLOY_STORAGE_CLASS( "DEPLOY_STORAGE_CLASS", diff --git a/server/src/main/java/io/wdd/func/auto/service/HarborFuncScheduler.java b/server/src/main/java/io/wdd/func/auto/service/HarborFuncScheduler.java index 56414f5..5a5f53d 100644 --- a/server/src/main/java/io/wdd/func/auto/service/HarborFuncScheduler.java +++ b/server/src/main/java/io/wdd/func/auto/service/HarborFuncScheduler.java @@ -55,15 +55,15 @@ public class HarborFuncScheduler { .getTopicName(); // create harbor project - if (!CreateHarborProject(projectDeployContext)) { - log.error("create harbor project failed !"); - } +// if (!CreateHarborProject(projectDeployContext)) { +// log.error("create harbor project failed !"); +// } // check harbor project // list - if (!ListHarborProject(projectDeployContext)) { - log.error("list harbor project failed !"); - } +// if (!ListHarborProject(projectDeployContext)) { +// log.error("list harbor project failed !"); +// } int maxSyncStatusCheckCount = 1000; int timePinch = 2; @@ -134,7 +134,6 @@ public class HarborFuncScheduler { } - return true; } @@ -177,7 +176,9 @@ public class HarborFuncScheduler { ServerInfoPO masterNode = projectDeployContext.getMasterNode(); ArrayList syncHarborArgList = new ArrayList<>(); + // zero arg syncHarborArgList.add(HarborFunctionEnum.SYNC_PROJECT_BETWEEN_HARBOR.getOpName()); + // first func args syncHarborArgList.add(masterNode.getServerIpInV4()); // second arg sourceHarborHost