1088 lines
29 KiB
Go
1088 lines
29 KiB
Go
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("清空路由表...")
|
||
|
||
commandExecutor := [][]string{
|
||
{
|
||
"iptables",
|
||
"-F",
|
||
},
|
||
{
|
||
"iptables",
|
||
"-t",
|
||
"nat",
|
||
"-F",
|
||
},
|
||
{
|
||
"iptables",
|
||
"-t",
|
||
"mangle",
|
||
"-F",
|
||
},
|
||
{
|
||
"iptables",
|
||
"-t",
|
||
"raw",
|
||
"-F",
|
||
},
|
||
{
|
||
"ip6tables",
|
||
"-F",
|
||
},
|
||
{
|
||
"ip6tables",
|
||
"-t",
|
||
"nat",
|
||
"-F",
|
||
},
|
||
{
|
||
"ip6tables",
|
||
"-t",
|
||
"mangle",
|
||
"-F",
|
||
},
|
||
{
|
||
"ip6tables",
|
||
"-t",
|
||
"raw",
|
||
"-F",
|
||
},
|
||
}
|
||
|
||
for _, command := range commandExecutor {
|
||
op.SingleLineCommandExecutor(command)
|
||
}
|
||
|
||
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: "通用工具安装 利用本机的yum,apt等从网络安装常用的软件",
|
||
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.RealTimeCommandExecutor([]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,
|
||
)
|
||
|
||
}
|