Files
WddSuperAgent/agent-wdd/op/PackageOperator.go

245 lines
5.6 KiB
Go
Raw Permalink 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/host_info"
"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(host_info.ConfigCache)
// package init
os := host_info.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 := host_info.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 host_info.CanConnectInternet() <= 1 {
log.Error("服务器无法连接互联网,无法初始化包管理器")
return false
}
// 检查本机是否存在OS的信息
os := host_info.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 host_info.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()
}