Files
ProjectOctopus/agent-wdd/op/PackageOperator.go
zeaslity 5c2325b7e4 优化Docker和SSH命令,增强系统配置和安装流程
- 更新Docker安装命令,默认版本升级到20.10.24
- 新增Docker配置命令,支持主节点配置daemon.json
- 修改SSH相关命令,增加输出换行以提高可读性
- 优化Zsh插件安装,使用完整git路径
- 改进系统配置中的主机名生成逻辑,增加内网IP最后一段标识
- 完善操作系统类型检测,扩展Ubuntu类型系统识别
- 调整包管理操作中的输出格式
2025-03-05 16:47:14 +08:00

245 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package op
import (
"agent-wdd/config"
"agent-wdd/log"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
type PackageOperator struct {
installPrefix []string // 安装前缀
removePrefix []string // 移除前缀
upgradePrefix []string // 升级前缀
initCommand []string
}
var (
AgentPackOperator = &PackageOperator{}
aptPackageOperator = &PackageOperator{
installPrefix: []string{
"apt-get", "install", "--allow-downgrades", "-y",
},
removePrefix: []string{
"apt", "remove", "-y",
},
upgradePrefix: []string{},
initCommand: []string{
"apt-get", "update",
},
}
yumPackageOperator = &PackageOperator{
installPrefix: []string{
"yum", "install", "-y",
},
removePrefix: []string{
"yum", "remove", "-y",
},
upgradePrefix: []string{},
initCommand: []string{
"yum", "makecache",
},
}
)
func (op *PackageOperator) Install(tools []string) bool {
// 判定本机的包管理Operator
ok := generatePackageOperator()
if !ok {
log.Error("PackageOperator init failed! 无法执行安装操作 %s", tools)
return false
}
// install seperately
for _, tool := range tools {
ok, result := SingleLineCommandExecutor(append(AgentPackOperator.installPrefix, tool))
if !ok {
log.Error("[install] failed! => %s", tool)
}
// 打印安装的过程内容
beautifulPrintListWithTitle(result, fmt.Sprintf("安装 %s 的过程内容", tool))
}
return true
}
// PackageInit 初始化包管理器, 同样会判定主机是否可以联网如果本机是ubuntu或者debian, 则使用apt, 否则使用yum
func (op *PackageOperator) PackageInit() bool {
log.Info("PackageInit !")
// beautifulPrintListWithTitle(config.ConfigCache)
// package init
os := config.ConfigCache.Agent.OS
if os.PackInit {
log.Info("PackageInit already done! skip!")
return true
}
// 判定本机的包管理Operator
ok := generatePackageOperator()
if !ok {
return false
}
os.PackInit = true
os.SaveConfig()
if os.IsUbuntuType {
ok, resultLog := SingleLineCommandExecutor(aptPackageOperator.initCommand)
if !ok {
log.Error("APT init failed! please check ! %s", resultLog)
}
}
return true
}
func (op *PackageOperator) PackageInitForce() bool {
log.Info("PackageInitForce !")
os := config.ConfigCache.Agent.OS
if os.IsUbuntuType {
ok, resultLog := SingleLineCommandExecutor(aptPackageOperator.initCommand)
if !ok {
log.Error("APT init failed! please check ! %s", resultLog)
}
log.Info("APT init success! %s", resultLog)
}
return true
}
func (op *PackageOperator) Remove(tools []string) {
// 判定本机的包管理Operator
generatePackageOperator()
// install seperately
for _, tool := range tools {
ok, result := SingleLineCommandExecutor(append(AgentPackOperator.removePrefix, tool))
if !ok {
log.Error("[remove] failed! => %s", tool)
beautifulPrintListWithTitle(result, fmt.Sprintf("移除 %s 的过程内容", tool))
}
}
}
func generatePackageOperator() bool {
// cache return
if AgentPackOperator.initCommand != nil {
log.Info("PackageOperator init success! %v", AgentPackOperator.initCommand)
return true
}
// 检查是否可以连接互联网
if config.CanConnectInternet() <= 1 {
log.Error("服务器无法连接互联网,无法初始化包管理器")
return false
}
// 检查本机是否存在OS的信息
os := config.ConfigCache.Agent.OS
if os.Hostname == "" {
os.Gather()
os.SaveConfig()
}
if os.IsUbuntuType {
log.Info("Ubuntu type detected! use apt package operator!")
AgentPackOperator = aptPackageOperator
} else {
log.Info("Other type detected! use yum package operator!")
AgentPackOperator = yumPackageOperator
}
return true
}
// GetLatestGithubReleaseVersion 获取GitHub仓库的最新版本
func GetLatestGithubReleaseVersion(repoOwner, repoName string) (string, error) {
// 检查是否可以连接互联网
if config.CanConnectInternet() <= 1 {
return "", fmt.Errorf("服务器无法连接互联网无法获取GitHub最新版本")
}
// 设置超时时间为10秒的HTTP客户端
client := &http.Client{
Timeout: 10 * time.Second,
}
// 构建GitHub API URL
apiURL := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", repoOwner, repoName)
// 发送GET请求
resp, err := client.Get(apiURL)
if err != nil {
return "", fmt.Errorf("请求GitHub API失败: %v", err)
}
defer resp.Body.Close()
// 检查响应状态码
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("GitHub API返回非200状态码: %d", resp.StatusCode)
}
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("读取响应内容失败: %v", err)
}
// 解析JSON响应
var release struct {
TagName string `json:"tag_name"`
}
if err := json.Unmarshal(body, &release); err != nil {
return "", fmt.Errorf("解析JSON响应失败: %v", err)
}
return release.TagName, nil
}
// CommandExists 判定命令是否存在
func CommandExists(command string) bool {
ok, _ := SingleLineCommandExecutor([]string{"command", "-v", command})
return ok
}
func CommandExistsByPath(command string) bool {
// 查询 /usr/bin /usr/local/bin中是否有可执行文件
_, result := SingleLineCommandExecutor([]string{"find", "/usr/bin", "/usr/local/bin", "-name", command})
if result == nil || len(result) == 0 {
return false
}
return true
}
func beautifulPrintListWithTitle(contend []string, title string) {
fmt.Println()
fmt.Println(">>>>>>>> " + title + " <<<<<<<<")
for _, line := range contend {
if line == "EOF" {
// do nothing
continue
}
fmt.Println(line)
}
fmt.Println(">>>>>>>> end <<<<<<<<")
fmt.Println()
}