From 06b044dabc2fe2872ab6b1e686db8b75b48d452e Mon Sep 17 00:00:00 2001 From: zeaslity Date: Fri, 7 Mar 2025 10:58:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EHarbor=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=92=8C=E4=BC=98=E5=8C=96=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在Base.go中添加Harbor安装、启动、停止和卸载子命令 - 实现Harbor本地安装流程,包括配置文件修改和容器检查 - 在Excutor.go中改进命令执行错误处理 - 在FileUtils.go中新增MoveFileToAnother方法,优化文件移动逻辑 - 修复DockerCompose本地安装命令的文件路径和移动方法 --- agent-wdd/cmd/Base.go | 181 ++++++++++++++++++++++++++-- agent-wdd/cmd/beans/HarborConfig.go | 54 +++++++++ agent-wdd/op/Excutor.go | 6 +- agent-wdd/utils/FileUtils.go | 33 +++++ 4 files changed, 266 insertions(+), 8 deletions(-) create mode 100644 agent-wdd/cmd/beans/HarborConfig.go diff --git a/agent-wdd/cmd/Base.go b/agent-wdd/cmd/Base.go index 5606eec..5f284b7 100644 --- a/agent-wdd/cmd/Base.go +++ b/agent-wdd/cmd/Base.go @@ -7,8 +7,10 @@ import ( "agent-wdd/op" "agent-wdd/utils" "fmt" + "os" "runtime" "strings" + "time" "github.com/spf13/cobra" ) @@ -21,8 +23,9 @@ var ( "deltarpm", "net-tools", "iputils", "bind-utils", "lsof", "curl", "wget", "vim", "mtr", "htop", } - dockerLocalInstallPath = "/root/wdd/docker-amd64-20.10.15.tgz" // 本地安装docker的文件路径 - dockerComposeLocalInstallPath = "/root/wdd/docker-compose-v2.18.0-linux-amd64" // 本地安装docker compose的文件路径 + dockerLocalInstallPath = "/root/wdd/docker-amd64-20.10.15.tgz" // 本地安装docker的文件路径 + dockerComposeLocalInstallPath = "/root/wdd/docker-compose-v2.18.0-linux-amd64" // 本地安装docker compose的文件路径 + harborLocalInstallPath = "/root/wdd/harbor-offline-installer-v2.9.0.tgz" // 本地安装harbor的文件路径 ) func init() { @@ -30,9 +33,11 @@ func init() { case "amd64": dockerLocalInstallPath = "/root/wdd/docker-amd64-20.10.15.tgz" // 本地安装docker的文件路径 dockerComposeLocalInstallPath = "/root/wdd/docker-compose-v2.18.0-linux-amd64" // 本地安装docker compose的文件路径 + harborLocalInstallPath = "/root/wdd/harbor-offline-installer-v2.9.0.tgz" // 本地安装harbor的文件路径 case "arm64": dockerLocalInstallPath = "/root/wdd/docker-arm64-20.10.15.tgz" // 本地安装docker的文件路径 dockerComposeLocalInstallPath = "/root/wdd/docker-compose-v2.18.0-linux-arm64" // 本地安装docker compose的文件路径 + harborLocalInstallPath = "/root/wdd/harbor-offline-installer-v2.9.0-arm64.tgz" // 本地安装harbor的文件路径 } } @@ -205,6 +210,13 @@ func addBaseSubcommands(cmd *cobra.Command) { } addSSHSubcommands(sshCmd) + // harbor 相关的函数 + harborCmd := &cobra.Command{ + Use: "harbor", + Short: "harbor相关的操作", + } + addHarborSubcommands(harborCmd) + cmd.AddCommand( dockerCmd, dockerComposeCmd, @@ -218,6 +230,162 @@ func addBaseSubcommands(cmd *cobra.Command) { ) } +// addHarborSubcommands 添加harbor子命令 +func addHarborSubcommands(harborCmd *cobra.Command) { + harborInstallCmd := &cobra.Command{ + Use: "install", + Short: "安装harbor 从本地安装 " + harborLocalInstallPath, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("") + log.Info("安装harbor") + + // 检查是否存在harbor目录 + if utils.FileExistAndNotNull("/root/wdd/harbor/harbor.yml") { + log.Info("harbor已存在,无需安装!") + return + } + + // 解压harbor + utils.UnzipFile(harborLocalInstallPath, "/root/wdd/harbor") + + // 获取本机的内网IPv4地址 + configCache := config.ConfigCache + ip := configCache.Agent.Network.Interfaces[0].IPv4 + + if ip == "" { + log.Error("没有获取到本机的ipv4地址,无法安装harbor! 请执行 info all !") + return + } + + // 修改harbor的配置 + utils.AppendOverwriteContentToFile(beans.HarborYamlConfig, "/root/wdd/harbor/harbor.yml") + utils.FindAndReplaceContentInFile("HarborHostName", ip, "/root/wdd/harbor/harbor.yml") + + if !utils.FileExistAndNotNull("/root/wdd/harbor/harbor.yml") { + log.Error("修改harbor的配置失败! 请检查文件是否存在!") + return + } + + // 进入harbor目录 + os.Chdir("/root/wdd/harbor") + + // 运行install.sh + ok, log1 := op.HardCodeCommandExecutor("bash install.sh") + if !ok { + log.Error("安装harbor失败: %s", log1) + return + } + + // wait to see the harbor is running + log.Info("等待10秒 harbor启动...") + time.Sleep(10 * time.Second) + + // 执行docker ps -a 查看 harbor名称的容器是否存在 Exit 或者 Restarting 则表示有错误! + if !checkHarborIsRunning() { + log.Error("harbor启动失败! 请检查日志!") + return + } + + log.Info("安装harbor成功!") + + }, + } + + harborUninstallCmd := &cobra.Command{ + Use: "uninstall", + Short: "卸载harbor", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("") + log.Info("暂未实现harbor卸载!") + + }, + } + + harborStartCmd := &cobra.Command{ + Use: "start", + Short: "启动harbor", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("") + log.Info("启动harbor") + + // 检查harbor是否存在 + if !utils.FileExistAndNotNull("/root/wdd/harbor/docker-compose.yml") { + log.Error("harbor不存在! 请先安装harbor!") + return + } + + // 进入harbor目录 + os.Chdir("/root/wdd/harbor") + + // 启动harbor + ok, log1 := op.HardCodeCommandExecutor("docker-compose up -d") + if !ok { + log.Error("启动harbor失败: %s", log1) + return + } + + // 等待5秒 + time.Sleep(5 * time.Second) + + // 检查harbor是否启动成功 + if !checkHarborIsRunning() { + log.Error("harbor启动失败! 请检查日志!") + return + } + + log.Info("启动harbor成功!") + fmt.Println("") + fmt.Println("") + }, + } + + // 停止harbor + harborStopCmd := &cobra.Command{ + Use: "stop", + Short: "停止harbor", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("") + log.Info("停止harbor") + + // 检查harbor是否存在 + if !utils.FileExistAndNotNull("/root/wdd/harbor/docker-compose.yml") { + log.Error("harbor不存在! 请先安装harbor!") + return + } + + // 进入harbor目录 + os.Chdir("/root/wdd/harbor") + + // 停止harbor + ok, log1 := op.HardCodeCommandExecutor("docker-compose down") + if !ok { + log.Error("停止harbor失败: %s", log1) + return + } + + log.Info("停止harbor成功!") + fmt.Println("") + fmt.Println("") + }, + } + + harborCmd.AddCommand(harborInstallCmd, harborUninstallCmd, harborStartCmd, harborStopCmd) +} + +// checkHarborIsRunning 检查harbor是否运行 +func checkHarborIsRunning() bool { + ok, log2 := op.HardCodeCommandExecutor("docker ps -a | grep goharbor/ | grep -E 'Exit|Restarting' | wc -l") + if !ok { + log.Error("查看harbor容器是否存在失败: %s", log2) + return false + } + if strings.TrimSpace(log2[0]) != "0" { + log.Error("harbor启动失败! 请检查日志!") + return false + } + return true +} + func addSSHSubcommands(sshCmd *cobra.Command) { keyCmd := &cobra.Command{ Use: "key", @@ -770,20 +938,19 @@ func addDockerComposeSubcommands(cmd *cobra.Command) { } localCmd := &cobra.Command{ - Use: "local [path]", + Use: "local", Short: "本地安装DockerCompose 安装文件应该为 " + dockerComposeLocalInstallPath, - Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { log.Info("Installing Docker Compose from local file...") - exist := utils.FileExistAndNotNull(dockerLocalInstallPath) + exist := utils.FileExistAndNotNull(dockerComposeLocalInstallPath) if !exist { - log.Error("Docker local install file not found: %s", dockerLocalInstallPath) + log.Error("Docker local install file not found: %s", dockerComposeLocalInstallPath) return } // move file to /usr/local/bin - err := utils.MoveFolerToAnother(dockerComposeLocalInstallPath, "/usr/local/bin") + err := utils.MoveFileToAnother(dockerComposeLocalInstallPath, "/usr/local/bin") if err != nil { log.Error("Failed to move Docker Compose binaries: %s", err.Error()) return diff --git a/agent-wdd/cmd/beans/HarborConfig.go b/agent-wdd/cmd/beans/HarborConfig.go new file mode 100644 index 0000000..f2c7217 --- /dev/null +++ b/agent-wdd/cmd/beans/HarborConfig.go @@ -0,0 +1,54 @@ +package beans + +// HarborYamlConfig 是harbor的配置文件 +var HarborYamlConfig = ` +hostname: HarborHostName + +http: + port: 8033 + +harbor_admin_password: V2ryStr@ngPss + +database: + password: V2ryStr@ngPss + max_idle_conns: 50 + max_open_conns: 1000 + conn_max_lifetime: 3600 + conn_max_idle_time: 3600 + +data_volume: /var/lib/docker/harbor-data + +jobservice: + max_job_workers: 10 + job_loggers: + - STD_OUTPUT + - FILE + logger_sweeper_duration: 3 + +notification: + webhook_job_max_retry: 10 + webhook_job_http_client_timeout: 10 + + +log: + level: warning + local: + rotate_count: 50 + rotate_size: 200M + location: /var/log/harbor + +cache: + enabled: false + expire_hours: 24 + +_version: 2.9.0 + +proxy: + http_proxy: + https_proxy: + no_proxy: + components: + - core + - jobservice + - trivy +` diff --git a/agent-wdd/op/Excutor.go b/agent-wdd/op/Excutor.go index 4cd20b8..f442cb8 100644 --- a/agent-wdd/op/Excutor.go +++ b/agent-wdd/op/Excutor.go @@ -179,7 +179,11 @@ func HardCodeCommandExecutor(hardCodeCommand string) (ok bool, resultLog []strin cmd := exec.Command(hardCodeCommand) // 执行命令并获取错误信息 - cmd.Run() + err := cmd.Run() + + if err != nil { + return false, []string{"HardCodeCommandExecutor " + hardCodeCommand + " 执行命令失败", err.Error()} + } // 合并输出结果 stdoutBuf := bytes.Buffer{} diff --git a/agent-wdd/utils/FileUtils.go b/agent-wdd/utils/FileUtils.go index ae88399..6d4c3ff 100644 --- a/agent-wdd/utils/FileUtils.go +++ b/agent-wdd/utils/FileUtils.go @@ -391,6 +391,39 @@ func FindAndDeleteContentInFile(content string, targetFile string) bool { return true } +// MoveFileToAnother 将源文件移动到目标文件 +func MoveFileToAnother(srcFile, dstFile string) error { + + // 如果dstFile是目录,则将srcFile移动到dstFile目录下 + if IsDirOrFile(dstFile) { + dstFile = filepath.Join(dstFile, filepath.Base(srcFile)) + } + + // 如果目标文件存在,则删除目标文件 + if FileExists(dstFile) { + err := os.Remove(dstFile) + if err != nil { + return fmt.Errorf("删除目标文件失败: %w", err) + } + } + + // 如果源文件不存在,则返回错误 + if !FileExists(srcFile) { + return fmt.Errorf("源文件不存在: %s", srcFile) + } + + // 如果目标文件夹不存在,则创建目标文件夹 + if !FileExists(filepath.Dir(dstFile)) { + err := os.MkdirAll(filepath.Dir(dstFile), os.ModePerm) + if err != nil { + return fmt.Errorf("创建目标文件夹失败: %w", err) + } + } + + // 移动文件 + return os.Rename(srcFile, dstFile) +} + // MoveFolerToAnother 将源文件夹的所有文件递归移动到目标文件夹 func MoveFolerToAnother(srcDir, dstDir string) error { // 读取源文件夹中的所有条目