Files
ProjectOctopus/agent-wdd/cmd/Base.go
zeaslity 35646ff89f 优化Harbor、Docker和Zsh安装流程,改进命令执行和文件操作
- 重构Harbor安装命令,改进容器检查和启动逻辑
- 修改Docker和DockerCompose安装方法,优化文件移动和权限设置
- 更新Zsh插件安装命令,简化git克隆过程
- 调整UnzipFile工具方法,支持更多压缩文件类型
- 修正Docker Daemon配置文件中的安装节标签
- 更新测试脚本,简化文件上传流程
2025-03-11 15:59:21 +08:00

1039 lines
28 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 cmd
import (
"agent-wdd/cmd/beans"
"agent-wdd/config"
"agent-wdd/log"
"agent-wdd/op"
"agent-wdd/utils"
"fmt"
"os"
"runtime"
"strings"
"time"
"github.com/spf13/cobra"
)
var (
ubuntuCommonTools = []string{
"iputils-ping", "net-tools", "dnsutils", "lsof", "curl", "wget", "mtr-tiny", "vim", "htop", "lrzsz",
}
centosCommonTools = []string{
"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的文件路径
harborLocalInstallPath = "/root/wdd/harbor-offline-installer-v2.9.0.tgz" // 本地安装harbor的文件路径
)
func init() {
switch runtime.GOARCH {
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的文件路径
}
}
// 添加base子命令
func addBaseSubcommands(cmd *cobra.Command) {
// 1.1 docker
dockerCmd := &cobra.Command{
Use: "docker",
Short: "Docker相关操作",
}
addDockerSubcommands(dockerCmd)
// 1.2 dockercompose
dockerComposeCmd := &cobra.Command{
Use: "dockercompose",
Short: "Docker Compose相关操作",
}
addDockerComposeSubcommands(dockerComposeCmd)
// 其他base子命令...
swapCmd := &cobra.Command{
Use: "swap",
Short: "关闭系统的Swap",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Swap 关闭!")
// 实现这个函数能够关闭centos或者ubuntu系统的swap
// 备份文件存在pass
if !utils.FileExistAndNotNull("/etc/fstab_back_wdd_swap") {
utils.AppendOverwriteContentToFile(
"/etc/fstab",
"/etc/fstab_back_wdd_swap",
)
}
// 执行关闭操作
op.SingleLineCommandExecutor([]string{
"swapoff",
"-a",
})
op.SingleLineCommandExecutor([]string{
"sed",
"-i",
"/swap/d",
"/etc/fstab",
})
log.Info("Swap 关闭成功!")
},
}
selinuxCmd := &cobra.Command{
Use: "selinux",
Short: "关闭selinux",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Selinux 关闭!")
// 如果configCache的OS为空则收集OS信息
if config.ConfigCache.Agent.OS.Hostname == "" {
log.Warning("ConfigCache OS is nil")
config.ConfigCache.Agent.OS.Gather()
config.ConfigCache.Agent.OS.SaveConfig()
}
os := config.ConfigCache.Agent.OS
if os.IsUbuntuType {
log.Info("Ubuntu 系统跳过关闭selinux")
return
} else {
op.SingleLineCommandExecutor([]string{
"setenforce",
"0",
})
// 备份一下/etc/selinux/config
if !utils.FileExistAndNotNull("/etc/selinux/config_back_wdd_selinux") {
utils.AppendOverwriteContentToFile(
"/etc/selinux/config",
"/etc/selinux/config_back_wdd_selinux",
)
}
// 持久化关闭selinux
utils.FindAndDeleteContentInFile("SELINUX=enforcing", "/etc/selinux/config")
utils.FindAndDeleteContentInFile("SELINUX=permissive", "/etc/selinux/config")
utils.FindAndDeleteContentInFile("SELINUX=disabled", "/etc/selinux/config")
utils.AppendContentToFile("SELINUX=disabled", "/etc/selinux/config")
}
log.Info("Selinux 关闭成功!")
},
}
firewallCmd := &cobra.Command{
Use: "firewall",
Short: "关闭防火墙",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Firewall 关闭!")
// 调用systemd关闭firewalld
op.SystemdDown("firewalld")
op.SystemdDisable("firewalld")
// 调用systemd关闭ufw
op.SystemdDown("ufw")
op.SystemdDisable("ufw")
// 清空路由表
log.Info("清空路由表...")
op.HardCodeCommandExecutor("iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -t raw -F")
op.HardCodeCommandExecutor("ip6tables -F && ip6tables -t nat -F && ip6tables -t mangle -F && ip6tables -t raw -F")
log.Info("Firewall 关闭成功!")
},
}
sysconfigCmd := &cobra.Command{
Use: "sysconfig",
Short: "修改系统的sysconfig",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Sysconfig 修改!")
// 修改系统的sysconfig
sysctlConfigFile := "/etc/sysctl.d/wdd-k8s.conf"
if !utils.AppendOverwriteContentToFile(beans.SysctlConfig, sysctlConfigFile) {
log.Error("[ModifySysConfigBastion] - error appending sysctl config to sysctl.d !")
return
}
op.SingleLineCommandExecutor([]string{
"sysctl",
"-p",
sysctlConfigFile,
})
log.Info("Sysconfig 修改成功!")
},
}
// 通用工具安装
commonToolsInstall := &cobra.Command{
Use: "tools",
Short: "通用工具安装 利用本机的yumapt等从网络安装常用的软件",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Common tool installation!")
// Whether It can connect to internet
if config.CanConnectInternet() <= 1 {
log.Error("服务器无法连接互联网无法执行tools")
return
}
// package install
// only support ubuntu(debian) centos(debian openEuler)
packOperator := op.AgentPackOperator
packOperator.PackageInit()
os := config.ConfigCache.Agent.OS
if os.IsUbuntuType {
packOperator.Install(ubuntuCommonTools)
} else {
packOperator.Install(centosCommonTools)
}
},
}
sshCmd := &cobra.Command{
Use: "ssh",
Short: "修改ssh配置",
}
addSSHSubcommands(sshCmd)
// harbor 相关的函数
harborCmd := &cobra.Command{
Use: "harbor",
Short: "harbor相关的操作",
}
addHarborSubcommands(harborCmd)
cmd.AddCommand(
dockerCmd,
dockerComposeCmd,
harborCmd,
swapCmd,
commonToolsInstall,
selinuxCmd,
firewallCmd,
sysconfigCmd,
sshCmd,
// 其他命令...
)
}
// 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/")
// 获取本机的内网IPv4地址
configCache := config.ConfigCache
if len(configCache.Agent.Network.Interfaces) == 0 {
log.Error("没有获取到本机的ipv4地址无法安装harbor! 请执行 info all !")
}
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
}
// 运行install.sh
op.SingleLineCommandExecutor([]string{"cd", "/root/wdd/harbor"})
ok, log1 := op.SingleLineCommandExecutor([]string{"/bin/bash", "/root/wdd/harbor/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
op.SingleLineCommandExecutor([]string{"cd", "/root/wdd/harbor"})
ok, log1 := op.SingleLineCommandExecutor([]string{"docker-compose", "up", "-d"})
if !ok {
log.Error("启动harbor失败: %s", log1)
return
}
// 等待10秒
time.Sleep(10 * 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.SingleLineCommandExecutor([]string{"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是否运行 如果存在Exit 或者 Restarting 则表示有错误!
func checkHarborIsRunning() bool {
_, resultLog := op.PipeLineCommandExecutor([][]string{
{
"docker",
"ps",
"-a",
},
{
"grep",
"goharbor/",
},
{
"grep",
"-E",
"'Exit|Restarting'",
},
{
"wc",
"-l",
},
})
if strings.TrimSpace(resultLog[0]) != "0" {
log.Error("harbor启动失败! 请检查日志!")
return false
}
return true
}
func addSSHSubcommands(sshCmd *cobra.Command) {
keyCmd := &cobra.Command{
Use: "key",
Short: "安装默认的ssh-key",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("")
log.Info("安装默认的ssh-key!")
// 创建.ssh目录
utils.CreateFolder("/root/.ssh")
// 检查密钥是否存在
if utils.FileExistAndNotNull("/root/.ssh/id_ed25519") &&
utils.FileExistAndNotNull("/root/.ssh/id_ed25519.pub") &&
utils.FindContentInFile("wdd@cmii.com", "/root/.ssh/authorized_keys") {
log.Info("SSH密钥已存在无需重新安装。")
return
}
// 下载标准的私钥和公钥
if !utils.AppendOverwriteContentToFile(beans.Ed25519PrivateKey, "/root/.ssh/id_ed25519") {
log.Error("[InstallDefaultSSHKey] - error appending private ssh key to authorized_keys !")
return
}
if !utils.AppendOverwriteContentToFile(beans.Ed25519PublicKey, "/root/.ssh/id_ed25519.pub") {
log.Error("[InstallDefaultSSHKey] - error appending public ssh key to authorized_keys !")
return
}
// 写入到authorized_keys
if !utils.AppendFileToFile("/root/.ssh/id_ed25519.pub", "/root/.ssh/authorized_keys") {
log.Error("[InstallDefaultSSHKey] - error appending ssh key to authorized_keys !")
return
}
// 设置权限
op.SingleLineCommandExecutor([]string{
"chmod",
"600",
"/root/.ssh/id_ed25519",
})
// 检查
if utils.FindContentInFile("wdd@cmii.com", "/root/.ssh/authorized_keys") {
log.Info("[InstallDefaultSSHKey] - install success !")
fmt.Println("")
} else {
log.Error("[InstallDefaultSSHKey] - authorized_keys don't contain the ssh-pub key !")
}
fmt.Println("")
fmt.Println("")
},
}
portCmd := &cobra.Command{
Use: "port",
Short: "修改ssh端口",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("")
log.Info("修改ssh端口!")
// 检查参数
if len(args) > 0 {
fmt.Printf("modify ssh port to: %s\n", args[0])
}
// 没有传递参数,使用默认参数
port := "22333"
log.Info("[ModifySSHPort] modify ssh port to: %s", port)
// 文件中已经包含了Port 22333 则pass
sshdPortString := fmt.Sprintf("Port %s", port)
if utils.FindContentInFile(sshdPortString, "/etc/ssh/sshd_config") {
log.Info("[ModifySSHPort] ssh port already modified to: %s", port)
} else {
// 修改ssh端口
utils.AppendContentToFile(sshdPortString, "/etc/ssh/sshd_config")
}
// 重启ssh服务
ok, resultLog := op.SystemdRestart("sshd")
if !ok {
log.Error("[ModifySSHPort] restart sshd error: %s", resultLog)
return
}
log.Info("[ModifySSHPort] modify ssh port to: %s success!", port)
fmt.Println("")
fmt.Println("")
},
}
configCmd := &cobra.Command{
Use: "config",
Short: "修改ssh配置 为wdd默认配置!",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("")
log.Info("修改ssh配置 为wdd默认配置!")
// 备份文件
if !utils.FileExistAndNotNull("/etc/ssh/sshd_config_back_wdd_ssh") {
utils.AppendOverwriteContentToFile("/etc/ssh/sshd_config", "/etc/ssh/sshd_config_back_wdd_ssh")
}
// 修改ssh配置
utils.AppendOverwriteContentToFile(beans.DefaultSshdConfig, "/etc/ssh/sshd_config")
// 重启ssh服务
ok, resultLog := op.SystemdRestart("sshd")
if !ok {
log.Error("sshd 重启失败: %s", resultLog)
return
}
log.Info("[sshd配置修改] 成功!")
fmt.Println("")
fmt.Println("")
},
}
sshCmd.AddCommand(keyCmd, portCmd, configCmd)
}
// 添加docker子命令
func addDockerSubcommands(cmd *cobra.Command) {
onlineCmd := &cobra.Command{
Use: "online [version]",
Short: "网络安装Docker, 如果不指定参数默认安装20.10.24版本",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("")
log.Info("网络安装Docker, 如果不指定参数默认安装20.10.24版本")
// 检查参数
if len(args) > 0 {
fmt.Printf("Installing Docker version: %s\n", args[0])
}
// 安装docker
packOperator := op.AgentPackOperator
packOperator.PackageInit()
configCache := config.ConfigCache
if configCache.Agent.OS.IsUbuntuType {
// 安装apt-transport-https ca-certificates curl gnupg software-properties-common 依赖部分
packOperator.Install([]string{"apt-transport-https", "ca-certificates", "curl", "gnupg", "software-properties-common"})
// 安装docker的 gpg key
dockerGPGFilePath := "/etc/apt/keyrings/docker.gpg"
dockerAPTFilePath := "/etc/apt/sources.list.d/docker.list"
dockerGPGSource := "https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg"
dockerAPTSource := "https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu"
// 创建docker的 gpg key 文件
utils.CreateFolder("/etc/apt/keyrings")
// 删除docker的 gpg key 文件
utils.RemoveFile(dockerGPGFilePath)
utils.RemoveFile(dockerAPTFilePath)
// 如果可以访问外网,则使用外网源
if configCache.Agent.Network.Internet == 9 {
dockerGPGSource = "https://download.docker.com/linux/ubuntu/gpg"
dockerAPTSource = "https://download.docker.com/linux/ubuntu"
}
ok, l2 := op.PipeLineCommandExecutor([][]string{
{
"curl",
"-fsSL",
dockerGPGSource,
},
{
"gpg",
"--dearmor",
"-o",
dockerGPGFilePath,
},
})
if !ok {
log.Error("下载docker gpg文件失败: %s", l2)
return
}
if !utils.FileExistAndNotNull(dockerGPGFilePath) {
log.Error("添加gpg失败")
return
}
op.SingleLineCommandExecutor([]string{
"chmod",
"a+r",
dockerGPGFilePath,
},
)
if configCache.Agent.OS.OSReleaseCode == "" {
log.Error("获取系统发行版代号失败! 无法安装docker!")
return
}
dockerAPTSourceCommand := "deb [arch=" + configCache.Agent.OS.Arch + " signed-by=" + dockerGPGFilePath + "] " + dockerAPTSource + " " + configCache.Agent.OS.OSReleaseCode + " stable"
log.Info("dockerAPTSourceCommand is => %s ", dockerAPTSourceCommand)
utils.AppendOverwriteContentToFile(dockerAPTSourceCommand, dockerAPTFilePath)
// 强制初始化APT update
packOperator.PackageInitForce()
// 20.04 default
specificDockerVersion := "5:20.10.24~3-0~ubuntu-" + configCache.Agent.OS.OSReleaseCode
// apt-cache madison docker-ce | grep 20.10.20 | awk '{print$3}'
// get by method
ok, log4 := op.PipeLineCommandExecutor([][]string{
{
"apt-cache",
"madison",
"docker-ce",
},
{
"grep",
"20.10.20",
},
{
"awk",
"'{print$3}'",
},
})
if ok && log4 != nil && len(log4) > 0 {
specificDockerVersion = strings.TrimSpace(log4[0])
fmt.Println("get docker version from online => " + specificDockerVersion)
}
log.Info("需要安装的docker版本为 => %s", specificDockerVersion)
dockerStaffList := []string{
"docker-ce=" + specificDockerVersion,
"docker-ce-cli=" + specificDockerVersion,
"containerd.io",
"docker-compose-plugin",
}
ok = packOperator.Install(dockerStaffList)
if !ok {
log.Error("安装docker存在问题请检查!")
return
}
} else {
log.Error("当前系统不是ubuntu系统暂时无法安装docker! 请使用local的方式安装")
return
}
log.Info("安装docker成功!")
// 启动docker
op.SystemdUp("docker")
op.SystemdEnable("docker")
// 检查docker是否启动成功
ok, resultLog := op.SystemIsRunning("docker")
if !ok {
log.Error("docker启动失败: %s", resultLog)
return
}
log.Info("docker启动成功! ")
fmt.Println("")
fmt.Println("")
},
}
removeCmd := &cobra.Command{
Use: "remove",
Short: "卸载Docker",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Removing Docker...")
// 检查docker是二进制安装还是通过包安装的
dockerExists := op.CommandExistsByPath("docker")
if !dockerExists {
log.Info("Docker 未安装,无需卸载!")
return
}
// 卸载docker
packOperator := op.AgentPackOperator
packOperator.PackageInit()
packOperator.Remove([]string{"docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin", "docker-compose-plugin"})
// 删除docker目录
utils.RemoveFile("/usr/bin/docker")
utils.RemoveFile("/usr/bin/docker-compose")
utils.RemoveFile("/usr/bin/docker-buildx")
utils.RemoveFile("/usr/bin/docker-compose-plugin")
utils.RemoveFile("/usr/bin/containerd")
// 删除docker的配置文件 systemd
utils.RemoveFile("/etc/systemd/system/docker.service")
utils.RemoveFile("/etc/systemd/system/docker.socket")
utils.RemoveFile("/etc/systemd/system/containerd.service")
utils.RemoveFile(beans.ContainerdServiceFile)
utils.RemoveFile(beans.DockerSocketFile)
utils.RemoveFile(beans.DockerServiceFile)
// 删除docker的日志文件
utils.RemoveFile("/var/log/docker")
log.Info("Docker 卸载成功!")
},
}
localCmd := &cobra.Command{
Use: "local",
Short: "本地安装Docker, 默认安装20.10.15版本, 安装文件应该为 " + dockerLocalInstallPath,
Run: func(cmd *cobra.Command, args []string) {
log.Info("Installing Docker from local file: %s", dockerLocalInstallPath)
exist := utils.FileExistAndNotNull(dockerLocalInstallPath)
if !exist {
log.Error("Docker local install file not found: %s", dockerLocalInstallPath)
return
}
// 解压文件
utils.UnzipFile(dockerLocalInstallPath, "/root/wdd/")
// 设置权限
dockerBinList := []string{
"docker-init",
"containerd",
"ctr",
"runc",
"dockerd",
"docker-proxy",
"containerd-shim",
"docker",
"containerd-shim-runc-v2",
}
// 删除旧的docker 二进制文件
for _, bin := range dockerBinList {
utils.RemoveFile("/usr/bin/" + bin)
}
// 安装docker
err := utils.MoveFolerToAnother("/root/wdd/docker/", "/usr/bin")
if err != nil {
log.Error("Failed to move Docker binaries: %s", err.Error())
return
}
for _, bin := range dockerBinList {
ok, resultLog := op.SingleLineCommandExecutor([]string{"chmod", "777", "/usr/bin/" + bin})
if !ok {
log.Error("Failed to set permissions for Docker binaries: %s", resultLog)
}
}
// 配置并启动Docker服务
// systemd daemonize docker
utils.AppendOverwriteContentToFile(beans.ContainerdDaemonService, beans.ContainerdServiceFile)
if !utils.FileExistAndNotNull(beans.ContainerdServiceFile) {
log.Error("docker deamon file not exists !")
}
utils.AppendOverwriteContentToFile(beans.DockerSocketDaemonService, beans.DockerSocketFile)
if !utils.FileExistAndNotNull(beans.DockerSocketFile) {
log.Error("docker deamon file not exists !")
}
utils.AppendOverwriteContentToFile(beans.DockerDaemonService, beans.DockerServiceFile)
if !utils.FileExistAndNotNull(beans.DockerServiceFile) {
log.Error("docker deamon file not exists !")
}
log.Info("docker dameon file append success !")
ok, resultLog := op.SystemdDaemonReload()
if !ok {
log.Error("daemon reload error ! %s", resultLog)
return
}
op.SingleLineCommandExecutor([]string{"systemctl", "unmask", "containerd"})
op.SingleLineCommandExecutor([]string{"systemctl", "unmask", "docker.socket"})
op.SingleLineCommandExecutor([]string{"systemctl", "unmask", "docker"})
op.SingleLineCommandExecutor([]string{"groupadd", "docker"})
op.SingleLineCommandExecutor([]string{"usermod", "-aG", "docker", "root"})
op.SingleLineCommandExecutor([]string{"newgrp", "docker"})
systemdUp, resultLog := op.SystemdUp("containerd")
if !systemdUp {
log.Error("[InstallDockerBastion] - start containerd service error ! %s", resultLog)
return
}
ok, resultLog = op.SystemdUp("docker.socket")
if !ok {
log.Error("[InstallDockerBastion] - start docker.socket error ! %s", resultLog)
return
}
ok, resultLog = op.SystemdUp("docker")
if !ok {
log.Error("[InstallDockerBastion] - start docker service error ! %s", resultLog)
return
}
log.Info("Docker installed successfully from local file!")
},
}
configCmd := &cobra.Command{
Use: "config",
Short: "配置Docker",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("")
log.Info("配置Docker-此命令仅在主节点执行即可")
// 检查docker是否安装
dockerExists := op.CommandExistsByPath("docker")
if !dockerExists {
log.Error("Docker 未安装,请先安装 Docker")
return
}
// 获取当前内网IP
ip := config.ConfigCache.Agent.Network.Interfaces[0].IPv4
if ip == "" {
log.Error("获取当前内网IP失败, 无法进行docker config配置")
return
}
// 配置docker的daemon.json
if !utils.AppendOverwriteContentToFile(beans.DockerDeamonConfig, "/etc/docker/daemon.json") {
log.Error("配置docker的daemon.json失败")
return
}
// 替换其中的字段
utils.FindAndReplaceContentInFile("DockerRegisterDomain", ip, "/etc/docker/daemon.json")
// 重启docker
op.SystemdRestart("docker")
// 检查docker是否重启成功
ok, resultLog := op.SystemIsRunning("docker")
if !ok {
log.Error("docker daemon config 失败, docker重启失败: %s", resultLog)
return
}
daemonJsonContent := utils.ReadAllContentFromFile("/etc/docker/daemon.json")
log.Info("修改daemon config 成功, docker重启成功!")
utils.BeautifulPrintListWithTitle(daemonJsonContent, "docker daemon.json")
fmt.Println("")
fmt.Println("")
},
}
cmd.AddCommand(onlineCmd, removeCmd, localCmd, configCmd)
}
func addDockerComposeSubcommands(cmd *cobra.Command) {
installCmd := &cobra.Command{
Use: "online [version]",
Short: "安装Docker Compose",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Installing Docker Compose...")
// 检查参数
if len(args) > 0 {
fmt.Printf("Installing Docker Compose version: %s\n", args[0])
}
// 默认安装最新版本
version := "latest"
if len(args) > 0 {
version = args[0]
}
// 如果是最新版本则通过GitHub API查询
if version == "latest" {
latestVersion, err := op.GetLatestGithubReleaseVersion("docker", "compose")
if err != nil {
log.Error("获取Docker Compose最新版本失败: %s", err)
} else {
version = latestVersion
log.Info("获取到Docker Compose最新版本: %s", version)
}
}
log.Info("安装 Docker Compose 版本: %s", version)
// 检查是否可以连接互联网
if config.CanConnectInternet() <= 1 {
log.Error("服务器无法连接互联网,无法在线安装 Docker Compose")
return
}
// 检查 Docker 是否已安装
dockerExists := op.CommandExistsByPath("docker")
if !dockerExists {
log.Error("Docker 未安装,请先安装 Docker")
return
}
// 根据架构选择合适的下载链接
arch := runtime.GOARCH
downloadURL := fmt.Sprintf("https://github.com/docker/compose/releases/download/%s/docker-compose-linux-%s", version, arch)
log.Info("Downloading Docker Compose from: %s", downloadURL)
// 下载 Docker Compose
ok, ccc := utils.DownloadFile(downloadURL, "/usr/local/bin/docker-compose")
if !ok {
log.Error("下载 Docker Compose 失败: %s", ccc)
return
}
// 设置执行权限
chmodCmd := []string{"chmod", "+x", "/usr/local/bin/docker-compose"}
ok, resultLog := op.SingleLineCommandExecutor(chmodCmd)
if !ok {
log.Error("设置 Docker Compose 权限失败: %s", resultLog)
return
}
// 创建软链接
linkCmd := []string{"ln", "-sf", "/usr/local/bin/docker-compose", "/usr/bin/docker-compose"}
op.SingleLineCommandExecutor(linkCmd)
// 验证安装
verifyCmd := []string{"/usr/local/bin/docker-compose", "version"}
ok, resultLog = op.SingleLineCommandExecutor(verifyCmd)
if !ok {
log.Error("Docker Compose 安装验证失败: %s", resultLog)
return
}
log.Info("Docker Compose 安装成功: %s", resultLog)
},
}
removeCmd := &cobra.Command{
Use: "remove",
Short: "卸载Docker Compose",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Removing Docker Compose...")
if utils.RemoveFile("/usr/local/bin/docker-compose") {
log.Info("Docker Compose removed successfully!")
} else {
log.Error("Failed to remove Docker Compose!")
}
},
}
localCmd := &cobra.Command{
Use: "local",
Short: "本地安装DockerCompose 安装文件应该为 " + dockerComposeLocalInstallPath,
Run: func(cmd *cobra.Command, args []string) {
log.Info("Installing Docker Compose from local file...")
exist := utils.FileExistAndNotNull(dockerComposeLocalInstallPath)
if !exist {
log.Error("Docker local install file not found: %s", dockerComposeLocalInstallPath)
return
}
// move file to /usr/local/bin
err := utils.MoveFileToAnother(dockerComposeLocalInstallPath, "/usr/local/bin/docker-compose")
if err != nil {
log.Error("Failed to move Docker Compose binaries: %s", err.Error())
return
}
// set permission
chmodCmd := []string{"chmod", "+x", "/usr/local/bin/docker-compose"}
ok, resultLog := op.SingleLineCommandExecutor(chmodCmd)
if !ok {
log.Error("Failed to set permissions for Docker Compose binaries: %s", resultLog)
return
}
// 创建软链接
linkCmd := []string{"ln", "-sf", "/usr/local/bin/docker-compose", "/usr/bin/docker-compose"}
op.SingleLineCommandExecutor(linkCmd)
// 验证安装
verifyCmd := []string{"/usr/local/bin/docker-compose", "version"}
ok, resultLog = op.SingleLineCommandExecutor(verifyCmd)
if !ok {
log.Error("Docker Compose 安装验证失败: %s", resultLog)
return
}
log.Info("Docker Compose installed successfully from local file!")
},
}
versionCmd := &cobra.Command{
Use: "version",
Short: "查看Docker Compose版本",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Docker Compose version...")
ok, resultLog := op.SingleLineCommandExecutor([]string{"docker-compose", "--version"})
if !ok {
log.Error("Failed to get Docker Compose version: %s", resultLog)
return
}
log.Info("Docker Compose version: %s", resultLog)
},
}
cmd.AddCommand(
installCmd,
removeCmd,
localCmd,
versionCmd,
)
}