package executor

import (
	"fmt"
	"net"
	"strings"
	"wdd.io/agent-go/register"
)

type BaseFunc interface {

	// Command 返回基础函数的命令行
	Command(baseFuncName string, funcArgs ...string) []string

	// Exec 执行命令行，只返回正确结果 || 错误，日志
	Exec(baseFuncName string, funcArgs ...string) (bool, []string)
}

type AgentOsOperator struct {
	InstallCommandPrefix []string `json:"install_command_prefix",comment:"apt-get install or yum install"`

	RemoveCommandPrefix []string `json:"remove_command_prefix",comment:"apt-get remove or yum remove"`

	CanAccessInternet bool `json:"can_access_internet",comment:"是否可以访问公网"`

	IsOsTypeUbuntu bool `json:"is_os_type_ubuntu",comment:"主机操作系统是否为debian系列"`

	IsOsTypeCentOS bool `json:"is_os_type_centos",comment:"主机操作系统是否为centos系列"`

	IsOsTypeEuler bool `json:"is_os_type_euler",comment:"主机操作系统是否为国产欧拉系列"`

	IsAgentInnerWall bool `json:"is_agent_inner_wall",comment:"主机是否身处国内"`

	AgentArch string `json:"agent_arch",comment:"主机的CPU架构，可选为amd64 arm64"`

	AgentOSReleaseCode string `json:"agent_os_release_code",comment:"主机操作系统的发行版代号， focal之类的"`

	AgentServerInfo *register.AgentServerInfo `json:"agent_server_info"`

	// 离线下载URL地址
	OssOfflinePrefix string `comment:"必须要用 / 结尾"`
}

func (op *AgentOsOperator) Exec(baseFuncName string, funcArgs ...string) (bool, []string) {

	resultOk := false
	var errorLog []string

	switch baseFuncName {

	case "shutdownFirewall":
		resultOk, errorLog = op.shutdownFirewallExec()
		break
	case "modifyHostname":
		resultOk, errorLog = op.modifyHostnameExec(funcArgs)
		break
	case "enableSwap":
		resultOk, errorLog = op.enableSwapExec()
		break
	case "disableSwap":
		resultOk, errorLog = op.disableSwapExec()
		break
	case "DISABLE_SELINUX":
		resultOk, errorLog = op.disableSELinuxExec()
		break
	case "installDocker":
		resultOk, errorLog = op.installDockerExec(funcArgs)
		break
	case "removeDocker":
		resultOk, errorLog = op.removeDockerExec()
		break
	case "removeDockerCompose":
		resultOk, errorLog = op.removeDockerComposeExec()
		break
	case "installDockerCompose":
		resultOk, errorLog = op.installDockerComposeExec()
		break
	case "installDefaultSSHKey":
		resultOk, errorLog = op.installDefaultSSHKeyExec(funcArgs)
		break
	case "modifyDockerConfig":
		resultOk, errorLog = op.modifyDockerConfigExec(funcArgs)
		break
	case "installHelm":
		resultOk, errorLog = op.installHelmExec()
		break
	case "installNfsOnline":
		resultOk, errorLog = op.installNfsOnlineExec()
		break
	case "installNfsServerOnline":
		resultOk, errorLog = op.installNfsServerOnlineExec()
		break
	case "installHarbor":
		resultOk, errorLog = op.installHarborExec()
		break
	case "chronyToMaster":
		resultOk, errorLog = op.chronyToMasterExec(funcArgs)
		break
	case "installZSH":
		resultOk, errorLog = op.installZSHExec()
		break
	case "modifySshPort":
		resultOk, errorLog = op.modifySshPortExec(funcArgs)
		break
	case "openBBR":
		resultOk, errorLog = op.openBBRExec()
		break
	default:
		resultOk, errorLog = op.okExec(funcArgs)
	}

	return resultOk, errorLog
}

func (op *AgentOsOperator) Command(baseFuncName string, funcArgs ...string) []string {

	var multiLineCommand [][]string

	switch baseFuncName {

	case "shutdownFirewall":
		multiLineCommand = op.shutdownFirewall()
		break
	case "modifyHostname":
		multiLineCommand = op.modifyHostname(funcArgs)
		break
	case "enableSwap":
		multiLineCommand = op.enableSwap()
		break
	case "disableSwap":
		multiLineCommand = op.disableSwap()
		break
	case "installDocker":
		multiLineCommand = op.installDocker(funcArgs)
		break
	case "removeDocker":
		multiLineCommand = op.removeDocker()
		break
	case "removeDockerCompose":
		multiLineCommand = op.removeDockerCompose()
		break
	case "installDockerCompose":
		multiLineCommand = op.installDockerCompose()
		break
	case "modifyDockerConfig":
		multiLineCommand = op.modifyDockerConfig(funcArgs)
		break
	case "installHelm":
		multiLineCommand = op.installHelm()
		break
	case "installHarbor":
		multiLineCommand = op.installHarbor()
		break
	case "chronyToPublicNTP":
		multiLineCommand = op.chronyToPublicNTP()
		break
	case "chronyToMaster":
		multiLineCommand = op.chronyToMaster(funcArgs)
		break
	case "installZSH":
		multiLineCommand = op.installZSH()
		break
	case "modifySshPort":
		multiLineCommand = op.modifySshPort(funcArgs)
		break
	case "openBBR":
		multiLineCommand = op.openBBR()
		break
	default:
		multiLineCommand = op.ok(funcArgs)
	}

	log.DebugF("multiLineCommand are => %v", multiLineCommand)

	var result []string

	// exec the command here
	for _, singleLineCommand := range multiLineCommand {
		singleCommandResult, _ := FormatAllCommandExecutor(singleLineCommand)

		result = append(result, "")
		result = append(result, singleCommandResult...)

		// debug usage
		log.DebugF("exec result are => %v", result)
		for _, logLine := range result {
			fmt.Println(logLine)
		}

	}

	// 归一化处理
	return result
}

func (op *AgentOsOperator) shutdownFirewall() [][]string {

	shutdownFunc := [][]string{
		{"systemctl", "stop", "firewalld"},
		{"systemctl", "disable", "firewalld"},
	}

	if !op.IsOsTypeUbuntu {
		shutdownFunc = append(shutdownFunc,
			[]string{
				"sed",
				"-i",
				"s/SELINUX=enforcing/SELINUX=disabled/g",
				"/etc/selinux/config",
			},
		)
	}

	return shutdownFunc
}

func (op *AgentOsOperator) shutdownFirewallExec() (bool, []string) {

	shutdownFunc := [][]string{
		{"systemctl", "stop", "firewalld"},
		{"systemctl", "disable", "firewalld"},
		{"systemctl", "stop", "ufw"},
		{"systemctl", "disable", "ufw"},
		{"iptables", "-F"},
	}
	// 忽略错误
	_, resultLog := AllCompleteExecutor(shutdownFunc)

	// centos

	return true, resultLog
}

func (op *AgentOsOperator) modifyHostname(args []string) [][]string {

	return [][]string{}
}

func (op *AgentOsOperator) modifyHostnameExec(args []string) (bool, []string) {

	ok, resultLog := AllCommandExecutor(
		[]string{
			"hostnamectl",
			"set-hostname",
			args[0],
		})

	return ok, resultLog
}

func (op *AgentOsOperator) enableSwap() [][]string {

	enableSwapFunc := [][]string{
		{
			"cp",
			"-f",
			"/etc/fstab_back",
			"/etc/fstab",
		},
		{
			"cat",
			"/etc/fstab",
		},
	}

	return enableSwapFunc
}

func (op *AgentOsOperator) enableSwapExec() (bool, []string) {
	return true, nil
}

func (op *AgentOsOperator) disableSwap() [][]string {

	disableSwapFunc := [][]string{
		{
			"swapoff",
			"-a",
		},
		{
			"cp",
			"-f",
			"/etc/fstab",
			"/etc/fstab_back",
		},
		{
			"sed",
			"-i",
			"/swap/d",
			"/etc/fstab",
		},
	}

	return disableSwapFunc
}

func (op *AgentOsOperator) disableSwapExec() (bool, []string) {

	var resultLog []string

	// 备份文件存在，pass
	if !BasicFileExists("/etc/fstab_back_wdd") {
		AllCommandExecutor([]string{
			"cp",
			"-f",
			"/etc/fstab",
			"/etc/fstab_back_wdd",
		})
	}
	// 执行关闭操作
	_, lre := AllCompleteExecutor(
		[][]string{
			{
				"swapoff",
				"-a",
			},
			{
				"sed",
				"-i",
				"/swap/d",
				"/etc/fstab",
			},
		})

	resultLog = append(resultLog, lre...)

	return true, resultLog
}

func (op *AgentOsOperator) disableSELinuxExec() (bool, []string) {

	if op.IsOsTypeUbuntu {
		return true, []string{
			"[disableSELinuxExec] - os is ubuntu, success",
		}
	}

	// delete contend
	BasicFindDeleteContendLineInFile("SELINUX=enforcing", "/etc/selinux/config")
	BasicFindDeleteContendLineInFile("SELINUX=permissive", "/etc/selinux/config")
	BasicFindDeleteContendLineInFile("SELINUX=disabled", "/etc/selinux/config")

	BasicAppendContentToFile("SELINUX=disabled", "/etc/selinux/config")

	// shutdown
	AllCommandExecutor([]string{
		"setenforce",
		"0",
	})

	return true, []string{}
}

func (op *AgentOsOperator) installDefaultSSHKeyExec(funcArgs []string) (bool, []string) {

	// ssh-keygen -t ed25519  -C "wdd@cmii.com"
	// ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa -b 4096
	BasicCreateFolder("/root/.ssh/")

	// check key exists
	if BasicFileExistAndNotNull("/root/.ssh/id_ed25519") {
		if BasicFileExistAndNotNull("/root/.ssh/id_ed25519.pub") {
			if BasicGrepItemInFile("wdd@cmii.com", "/root/.ssh/authorized_keys") {
				return true, nil
			}
		}
	}

	// download standard private and public key
	ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+"id_ed25519_private_key", "/root/.ssh/id_ed25519")
	if !ok {
		return false, resultLog
	}
	ok, resultLog = BasicDownloadFile(op.OssOfflinePrefix+"id_ed25519_public_key.pub", "/root/.ssh/id_ed25519.pub")
	if !ok {
		return false, resultLog
	}

	// write into authorized_keys
	if !BasicAppendSourceToFile("/root/.ssh/id_ed25519.pub", "/root/.ssh/authorized_keys") {
		return false, []string{
			"[installDefaultSSHKeyExec] - error appending ssh key to authorized_keys !",
		}
	}

	AllCommandExecutor([]string{
		"chmod",
		"600",
		"/root/.ssh/id_ed25519",
	})

	// check
	if BasicGrepItemInFile("wdd@cmii.com", "/root/.ssh/authorized_keys") {
		return true, nil
	}

	return false, []string{
		"[installDefaultSSHKeyExec] - authorized_keys don't contain the ssh-pub key !",
	}
}

func (op *AgentOsOperator) removeDocker() [][]string {

	removeDockerLine := append(op.RemoveCommandPrefix, []string{
		"docker-ce",
		"docker.io",
		"docker-ce-cli",
		//"docker",
		//"docker-common",
		//"docker-latest",
		//"docker-latest-logrotate",
		//"docker-logrotate",
		//"docker-selinux",
		//"docker-engine-selinux",
		//"docker-engine",
		//"kubelet",
		//"kubeadm",
		//"kubectl",
		//"docker-client",
		//"docker-client-latest",
	}...)

	removeDockerFunc := [][]string{
		removeDockerLine,
	}

	return removeDockerFunc
}

func (op *AgentOsOperator) removeDockerExec() (bool, []string) {
	var resultLog []string

	dockerServiceStopCommand := [][]string{
		{
			"systemctl",
			"stop",
			"docker.service",
		},
		{
			"systemctl",
			"stop",
			"docker.socket",
		},
		{
			"systemctl",
			"disable",
			"docker.service",
		},
	}

	ok, l := AllCompleteExecutor(dockerServiceStopCommand)
	if !ok {
		resultLog = append(resultLog, l...)
	}

	dockerStaff := []string{
		"docker-ce",
		"docker.io",
		"docker-ce-cli",
		"docker",
		"docker-common",
		"docker-latest",
		"docker-latest-logrotate",
		"docker-logrotate",
		"docker-selinux",
		"docker-engine-selinux",
		"docker-engine",
		"kubelet",
		"kubeadm",
		"kubectl",
		"docker-client",
		"docker-client-latest",
	}

	for _, staff := range dockerStaff {
		removeCommand := append(op.RemoveCommandPrefix, staff)

		ok, result := AllCommandExecutor(removeCommand)
		if !ok {
			resultLog = append(resultLog, result...)
		}
	}

	return true, resultLog
}

func (op *AgentOsOperator) installDocker(args []string) [][]string {

	// remove docker all staff
	installDockerFunc := op.removeDocker()

	if op.IsOsTypeUbuntu {
		//
		installFirstLine := append(op.InstallCommandPrefix, []string{
			"apt-transport-https",
			"ca-certificates",
			"curl",
			"gnupg-agent",
			"software-properties-common",
		}...)

		if op.IsAgentInnerWall {
			// inner gfw
			installDockerFunc = append(installDockerFunc, [][]string{
				installFirstLine,
				{
					"curl",
					"-o",
					"/etc/apt/keyrings/docker-utsc.gpg",
					"https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg",
				},
				{
					"apt-key",
					"add",
					"/etc/apt/keyrings/docker-utsc.gpg",
				},
				{
					"add-apt-repository",
					"deb [arch=" + op.AgentArch + "] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu " + op.AgentOSReleaseCode + " stable",
				},
			}...)
		} else {
			// outside world
			installDockerFunc = append(installDockerFunc, [][]string{
				installFirstLine,
				{
					"curl",
					"-o",
					"/etc/apt/keyrings/docker.gpg",
					"https://download.docker.com/linux/ubuntu/gpg ",
				},
				{
					"apt-key",
					"add",
					"/etc/apt/keyrings/docker.gpg",
				},
				{
					"add-apt-repository",
					"deb [arch=" + op.AgentArch + "] https://download.docker.com/linux/ubuntu " + op.AgentOSReleaseCode + " stable",
				},
			}...)
		}

		// look for specific docker-version to install
		installDockerFunc = append(installDockerFunc, []string{"apt-get", "update"})

		var specificDockerVersion string
		// hard code here 5:20.10.10~3-0~ubuntu-focal
		if strings.HasPrefix(args[0], "19") {
			specificDockerVersion = "5:19.03.15~3-0~ubuntu-" + op.AgentOSReleaseCode
		} else {
			specificDockerVersion = "5:20.10.10~3-0~ubuntu-" + op.AgentOSReleaseCode
		}

		installDockerFunc = append(installDockerFunc,
			append(
				op.InstallCommandPrefix,
				"docker-ce="+specificDockerVersion,
				"docker-ce-cli="+specificDockerVersion,
				"containerd.io",
				"docker-compose-plugin",
			),
		)

	} else {
		installFirstLine := append(op.InstallCommandPrefix,
			[]string{
				"yum-utils",
				"device-mapper-persistent-data",
				"lvm2",
			}...,
		)

		if op.IsAgentInnerWall {
			// inner gfw
			installDockerFunc = append(installDockerFunc, [][]string{
				installFirstLine,
				{
					"yum-config-manager",
					"--add-repo",
					"https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo",
				},
				{
					"sed ",
					"-i ",
					"'s/download.docker.com/mirrors.ustc.edu.cn\\/docker-ce/g' ",
					"/etc/yum.repos.d/docker-ce.repo",
				},
				{},
			}...)
		} else {
			// outside world
		}

	}

	return installDockerFunc
}

func (op *AgentOsOperator) installDockerExec(args []string) (bool, []string) {

	BasicCreateFolder("/root/wdd/")

	op.removeDockerExec()

	if op.IsOsTypeUbuntu {

		if !op.CanAccessInternet {
			// offline version
			log.InfoF("[installDockerExec] - can not access to internet, installing by offline !")
			return op.installDockerOfflineExec(args)
		}

		installDependencyCommand := append(op.InstallCommandPrefix, []string{
			"apt-transport-https",
			"ca-certificates",
			"curl",
			"gnupg",
			"software-properties-common",
		}...)

		ok, l := AllCommandExecutor(installDependencyCommand)
		if !ok {
			//
			return false, l
		}

		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"

		executor, resultLog := AllCompleteExecutor([][]string{
			{
				"rm",
				"-rf",
				dockerGPGFilePath,
			},
			{
				"rm",
				"-rf",
				dockerAPTFilePath,
			},
			{
				"mkdir",
				"-p",
				"/etc/apt/keyrings",
			},
			{
				"install",
				"-m",
				"0755",
				"-d",
				"/etc/apt/keyrings",
			},
		})
		if !executor {
			return false, append(resultLog, "创建docker-key gpg文件失败！")
		}

		// 安装镜像的证书
		if !op.IsAgentInnerWall {
			// outside world
			dockerGPGSource = "https://download.docker.com/linux/ubuntu/gpg"
			dockerAPTSource = "https://download.docker.com/linux/ubuntu"
		}

		ok, l2 := PipelineCommandExecutor([][]string{
			{
				"curl",
				"-fsSL",
				dockerGPGSource,
			},
			{
				"gpg",
				"--dearmor",
				"-o",
				dockerGPGFilePath,
			},
		})
		if !ok {
			return false, append(l2, "下载docker gpg文件失败", dockerGPGSource, dockerAPTSource)
		}
		if !BasicFileExistAndNotNull(dockerGPGFilePath) {
			return false, []string{"添加gpg失败！"}
		}

		resultOk, log2 := AllCompleteExecutor([][]string{
			{
				"chmod",
				"a+r",
				dockerGPGFilePath,
			},
			//{
			//	"add-apt-repository",
			//	"deb [arch=" + op.AgentArch + " signed-by=" + dockerGPGFilePath + " ] " + dockerAPTSource + " " + op.AgentOSReleaseCode + " stable",
			//},
		})
		if !resultOk {
			return false, append(log2, "添加APT源失败！")
		}
		dockerAPTSourceCommand := "deb [arch=" + op.AgentArch + " signed-by=" + dockerGPGFilePath + "] " + dockerAPTSource + " " + op.AgentOSReleaseCode + " stable"

		log.InfoF("dockerAPTSourceCommand is => %s ", dockerAPTSourceCommand)

		ok, log3 := PipelineCommandExecutor([][]string{
			{
				"echo",
				dockerAPTSourceCommand,
			},
			{
				"tee",
				dockerAPTFilePath,
			},
		})
		if !ok {
			return false, append(log3, "添加APT源失败！")
		}

		// look for specific docker-version to install
		ok, log4 := AllCommandExecutor([]string{"apt-get", "update"})
		if !ok {
			return false, append(log4, "apt-get update 失败！")
		}

		// 补充参数
		if args == nil {
			args = []string{
				"20",
			}
		}

		// ubuntu 内部
		var specificDockerVersion string
		// hard code here 5:20.10.10~3-0~ubuntu-focal
		if strings.HasPrefix(args[0], "19") {
			specificDockerVersion = "5:19.03.15~3-0~ubuntu-" + op.AgentOSReleaseCode
		} else {
			specificDockerVersion = "5:20.10.10~3-0~ubuntu-" + op.AgentOSReleaseCode
		}

		log.InfoF("需要安装的docker版本为 => %s", specificDockerVersion)

		dockerStaffList := []string{
			"docker-ce=" + specificDockerVersion,
			"docker-ce-cli=" + specificDockerVersion,
			"containerd.io",
			"docker-compose-plugin",
		}

		for _, s := range dockerStaffList {
			resultOk, log2 = AllCommandExecutor(
				append(op.InstallCommandPrefix, s))
			if !resultOk {
				return false, append(log2, s, "安装失败！")
			}
		}

		// 启动docker服务
		completeExecutor, log5 := AllCompleteExecutor([][]string{
			{
				"systemctl",
				"stop",
				"docker.service",
			},
			{
				"sleep",
				"2",
			},
			{
				"systemctl",
				"start",
				"docker.service",
			},
			{
				"systemctl",
				"enable",
				"docker.service",
			},
		})
		if !completeExecutor {
			return false, append(log5, "启动docker.service失败，请查明原因！", "journalctl -u docker -n 100 -f")
		}
	} else if op.IsOsTypeCentOS {
		if !op.CanAccessInternet || op.IsOsTypeEuler {
			// offline version
			log.InfoF("[installDockerExec] - centos can not access to internet, installing by offline !")
			return op.installDockerOfflineExec(args)
		}

		// download
		var dockerRepo string
		if op.IsAgentInnerWall {
			dockerRepo = "https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo"
		} else {
			dockerRepo = "https://download.docker.com/linux/centos/docker-ce.repo"
		}

		AllCommandExecutor(append(op.InstallCommandPrefix, "yum-utils"))

		ok, resultLog := AllCommandExecutor(
			[]string{
				"yum-config-manager",
				"--add-repo",
				dockerRepo,
			},
		)
		if !ok {
			return false, resultLog
		}

		// todo 20 version
		resultOk, l := AllCommandExecutor(append(op.InstallCommandPrefix, "docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"))

		if !resultOk {
			return false, l
		}

		systemdUp, log2 := BasicSystemdUp("docker")
		if !systemdUp {
			return false, log2
		}
	}

	return true, []string{
		"docker安装成功！",
	}
}

func (op *AgentOsOperator) installDockerOfflineExec(args []string) (bool, []string) {

	log.InfoF("[installDockerOfflineExec] - install docker 20.10.15 by offline method !")
	BasicCreateFolder("/root/wdd")

	// download static binary installer of docker
	var dockerOfflineFileName string
	if strings.HasPrefix(op.AgentArch, "amd") {
		dockerOfflineFileName = "docker-amd64-20.10.15.tgz"
	} else if strings.HasPrefix(op.AgentArch, "arm64") {
		dockerOfflineFileName = "docker-arm64-20.10.15.tgz"
	}

	ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+dockerOfflineFileName, "/root/wdd/"+dockerOfflineFileName)
	if !ok {
		return false, resultLog
	}

	BasicRemoveFolderComplete("/root/wdd/docker")

	PureResultSingleExecute([]string{
		"tar",
		"-vxf",
		"/root/wdd/" + dockerOfflineFileName,
		"-C",
		"/root/wdd",
	})

	HardCodeCommandExecutor("chmod 777 -R /root/wdd/docker/*")

	resultOk, l := HardCodeCommandExecutor("mv /root/wdd/docker/* /usr/bin")
	if !resultOk {
		return false, append(l, "[installDockerOfflineExec] - cp docker executable file error!")
	}

	// systemd daemonize docker
	downloadOk, log2 := BasicDownloadFile(op.OssOfflinePrefix+"docker-containerd-daemon.service", "/lib/systemd/system/containerd.service")
	if !downloadOk {
		return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
	}

	downloadOk, log2 = BasicDownloadFile(op.OssOfflinePrefix+"docker-socket-daemon.service", "/lib/systemd/system/docker.socket")
	if !downloadOk {
		return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
	}

	downloadOk, log2 = BasicDownloadFile(op.OssOfflinePrefix+"docker-daemon.service", "/lib/systemd/system/docker.service")
	if !downloadOk {
		return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
	}

	// run the docker
	executor, log3 := AllCommandExecutor([]string{
		"systemctl",
		"daemon-reload",
	})
	if !executor {
		return false, append(log3, "[installDockerOfflineExec] -  daemon reload error !")
	}

	AllCompleteExecutor([][]string{
		{
			"groupadd",
			"docker",
		},
		{
			"usermod",
			"-aG",
			"docker",
			"root",
		},
		{
			"newgrp",
			"docker",
		},
	})

	systemdUp, log5 := BasicSystemdUp("containerd")
	if !systemdUp {
		return false, append(log5, "[installDockerOfflineExec] - start containerd service error !")
	}

	commandExecutor, log6 := AllCompleteExecutor([][]string{
		{
			"systemctl",
			"start",
			"docker.socket",
		},
		{
			"systemctl",
			"enable",
			"docker.socket",
		},
	})
	if !commandExecutor {
		return false, append(log6, "[installDockerOfflineExec] - start docker.socket error !")
	}

	up, log4 := BasicSystemdUp("docker")
	if !up {
		return false, append(log4, "[installDockerOfflineExec] - start docker service error !")
	}

	return true, []string{
		"[installDockerOfflineExec] - docker offline installation success!",
	}
}

func (op *AgentOsOperator) removeDockerCompose() [][]string {

	installDockerComposeFunc := [][]string{
		append(
			op.RemoveCommandPrefix,
			"docker-compose",
		),
	}

	return installDockerComposeFunc
}

func (op *AgentOsOperator) removeDockerComposeExec() (bool, []string) {

	commandName := "docker-compose"
	if !BasicCommandExists(commandName) {
		return true, []string{
			commandName + " 卸载成功！",
		}
	}
	possibleDockerComposeFilePath := []string{
		"/usr/local/bin/" + commandName,
		"/usr/bin/" + commandName,
	}

	for _, s := range possibleDockerComposeFilePath {
		removeDockerCommand := append(RemoveForcePrefix, s)
		AllCommandExecutor(removeDockerCommand)
	}

	return true, []string{
		commandName + " 卸载成功！",
	}
}

func (op *AgentOsOperator) installDockerCompose() [][]string {

	installDockerComposeFunc := [][]string{
		append(
			op.InstallCommandPrefix,
			"docker-compose",
		),
	}

	return installDockerComposeFunc
}

func (op *AgentOsOperator) installDockerComposeExec() (bool, []string) {
	log.Info("准备安装docker-compose!")

	// 安装特定版本的 docker-compose 2.18.0
	if op.OssOfflinePrefix == "" {
		return false, []string{"离线下载OSS地址不存在！ 无法安装 docker-compose"}
	}

	var DockerComposeFile string
	if strings.HasPrefix(op.AgentArch, "amd") {
		DockerComposeFile = op.OssOfflinePrefix + "docker-compose-linux-x86_64-v2.18.0"
	} else if strings.HasPrefix(op.AgentArch, "arm64") {
		DockerComposeFile = op.OssOfflinePrefix + "docker-compose-linux-aarch64-v2.18.0"
	}

	log.InfoF("需要安装的docker版本为 => %s", DockerComposeFile)

	ok, resultLog := BasicDownloadFile(DockerComposeFile, "/usr/local/bin/docker-compose")
	if !ok {
		return false, resultLog
	}

	log.Debug("docker-compose下载成功!")
	if !BasicFileExistAndNotNull("/usr/local/bin/docker-compose") {
		return false, []string{"docker-compose 下载失败！"}
	}

	AllCompleteExecutor([][]string{
		{
			"chmod", "+x", "/usr/local/bin/docker-compose",
		},
		{
			"ln", "-s", "/usr/local/bin/docker-compose", "/usr/bin/docker-compose",
		},
	})
	log.Info("docker-compose安装成功！")
	return true, []string{"docker-compose安装成功！"}
}
func (op *AgentOsOperator) installHelm() [][]string {
	installHelmFunc := [][]string{
		{
			"mkdir",
			"-p",
			"/root/wdd/",
		},
		{
			"rm",
			"-rf",
			"/root/wdd/helm-v*",
		},
		{
			"rm",
			"-rf",
			"/root/wdd/linux-amd64",
		},
		{
			"wget",
			"--no-check-certificate",
			op.OssOfflinePrefix + "helm-v3.12.1-linux-amd64.tar.gz",
			"-O",
			"/root/wdd/helm-v3.12.1-linux-amd64.tar.gz",
		},
		{
			"tar",
			"-zvxf",
			"/root/wdd/helm-v3.12.1-linux-amd64.tar.gz",
		},
		{
			"chmod",
			"+x",
			"/root/wdd/linux-amd64/helm",
		},
		{
			"mv",
			"/root/wdd/linux-amd64/helm",
			"/usr/local/bin/helm",
		},
		{
			"helm",
			"version",
		},
	}

	/*if op.IsOsTypeUbuntu {
		installHelmFunc = [][]string{
			{
				"curl",
				"-o",
				"/etc/apt/keyrings/helm.gpg",
				"https://baltocdn.com/helm/signing.asc",
			},
			{
				"apt-key",
				"add",
				"/etc/apt/keyrings/helm.gpg",
			},
			{
				"add-apt-repository",
				"https://baltocdn.com/helm/stable/debian/ all main",
			},
			{
				"apt-get",
				"update",
			},
			append(op.InstallCommandPrefix, "helm"),
		}
	} else {
		log.ErrorF("Operation OS is CentOS, Helm not installed!")
	}*/

	return installHelmFunc
}

func (op *AgentOsOperator) installHelmExec() (bool, []string) {
	return true, []string{
		"[installHelmExec] - pretend to install helm success !",
	}
}

func (op *AgentOsOperator) modifyDockerConfig(args []string) [][]string {

	harborIPAddr := args[0] + ":8033"

	modifyDockerConfigFunc := [][]string{
		{
			"mv",
			"/etc/docker/daemon.json",
			"/etc/docker/daemon.backup.json",
		},
		{
			"wget",
			op.OssOfflinePrefix + "daemon-config.json",
			"-O",
			"/etc/docker/daemon.json",
		},
		{
			"sed",
			"-i",
			"s/$DockerRegisterDomain/" + harborIPAddr + "/g",
			"/etc/docker/daemon.json",
		},
		{
			"systemctl",
			"restart",
			"docker.service",
		},
	}

	return modifyDockerConfigFunc
}

func (op *AgentOsOperator) modifyDockerConfigExec(args []string) (bool, []string) {

	dockerDaemonFile := "/etc/docker/daemon.json"
	// check docker daemon json exist
	if BasicFileExistAndNotNull(dockerDaemonFile) {
		AllCommandExecutor([]string{
			"mv",
			dockerDaemonFile,
			"/etc/docker/daemon-json.backup",
		})
	}

	// download new
	ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+"docker-daemon-template.json", dockerDaemonFile)
	if !ok {
		return false, append(resultLog, "[modifyDockerConfigExec] - error download docker-daemon-template.json !")
	}

	// modify config
	parseIP := net.ParseIP(args[0])
	if parseIP == nil {
		return false, []string{
			"[modifyDockerConfigExec] - ip args error !",
			args[0],
		}
	}
	if !BasicReplace(dockerDaemonFile, "DockerRegisterDomain", args[0]) {
		return false, []string{
			"[modifyDockerConfigExec] - modify docker daemon config error !",
		}
	}

	// restart docker
	if !PureResultSingleExecute([]string{
		"systemctl",
		"restart",
		"docker.service",
	}) {
		return false, []string{
			"[modifyDockerConfigExec] - restart docker.service error !",
		}
	}

	return true, nil
}

func (op *AgentOsOperator) installNfsOnlineExec() (bool, []string) {
	if !op.CanAccessInternet {
		return op.installNFSOfflineExec()
	}

	if op.IsOsTypeUbuntu {

		// ubuntu
		installOk, installLog := BasicInstallSoftwares(op.InstallCommandPrefix, false,
			"nfs-common", "nfs-client", "nfs")
		if !installOk {
			return false, installLog
		}

		ok, resultLog := BasicSystemdUp("nfs")
		if !ok {
			return false, append(resultLog, "[installNfsOnlineExec] - start nfs-common.service failed !")
		}
	} else if op.IsOsTypeCentOS {

		// centos
		installOk, installLog := BasicInstallSoftwares(op.InstallCommandPrefix, false,
			"nfs-utils")
		if !installOk {
			return false, installLog
		}

		ok, resultLog := BasicSystemdUp("rpcbind")
		if !ok {
			return false, append(resultLog, "[installNfsOnlineExec] - start rpcbind.service failed !")
		}

	}

	return true, nil
}

func (op *AgentOsOperator) installNFSOfflineExec() (bool, []string) {

	log.InfoF("[installNFSOfflineExec] - start to install nfs-client offline !")
	BasicCreateFolder("/root/wdd")

	// check for version
	//executor, i := HardCodeCommandExecutor("grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '\"' | sed 's/ /-/g'")
	//if !executor {
	//	return false, append(i, "[installNFSOfflineExec]- get offline package name suffix error !")
	//}
	// 2024年1月19日 new version
	nfsClientOfflinePackageName := "nfs-client-" + op.AgentArch + "-" + op.AgentServerInfo.Platform + "-" + op.AgentServerInfo.PlatformVersion + ".tar.gz"

	// download from oss
	nfsClientOfflinePackageOSSUrl := op.OssOfflinePrefix + nfsClientOfflinePackageName
	log.InfoF("[installNFSOfflineExec]- start to download nfs-client offline package from => %s", nfsClientOfflinePackageOSSUrl)

	ok, resultLog := BasicDownloadFile(nfsClientOfflinePackageOSSUrl, "/root/wdd/"+nfsClientOfflinePackageName)
	if !ok {
		return false, append(resultLog, "[installNFSOfflineExec]- download nfs-client offline package error !", nfsClientOfflinePackageOSSUrl)
	}

	BasicRemoveFolderComplete("/root/wdd/tmp")

	// unzip
	AllCommandExecutor([]string{
		"tar",
		"-zvxf",
		"/root/wdd/" + nfsClientOfflinePackageName,
		"-C",
		"/root/wdd",
	})

	// install
	if op.IsOsTypeUbuntu {
		BasicPrettyPrint(HardCodeCommandExecutor("dpkg -i /root/wdd/tmp/nfs-client/*.deb"))
	} else if op.IsOsTypeCentOS {
		BasicPrettyPrint(HardCodeCommandExecutor("rpm -ivh /root/wdd/tmp/nfs-client/*.rpm"))
	}

	ok, resultLog = BasicSystemdUp("nfs")
	if !ok {
		return false, append(resultLog, "[installNFSOfflineExec] - start nfs-common.service failed !")
	}

	return true, []string{
		"[installNFSOfflineExec] - install success !",
	}

}

func (op *AgentOsOperator) installNfsServerOnlineExec() (bool, []string) {

	if !op.CanAccessInternet {
		return op.installNFSServerOfflineExec()
	}

	if !PureResultSingleExecuteBatch([][]string{
		{"mkdir", "-p", nfsDataPath},
		{"chmod", "777", nfsDataPath},
	}) {
		return false, []string{
			"[installNfsServerOnlineExec]- create nfs data folder failed !",
		}
	}

	if !BasicFindContentInFile(nfsDataPath, "/etc/exports") {
		log.DebugF("[installNfsServerOnlineExec]- add nfs path to /etc/exports !")

		nfsExport := nfsDataPath + "  *(rw,no_root_squash,no_all_squash,sync)"
		if !BasicAppendContentToFile(nfsExport, "/etc/exports") {
			return false, []string{
				"[installNfsServerOnlineExec]- add nfs path to /etc/exports failed !",
			}
		}
	}

	// os
	if op.IsOsTypeUbuntu {
		// ubuntu
		installOk, installLog := BasicInstallSoftwares(op.InstallCommandPrefix, true, "nfs-kernel-server",
			"nfs-common")
		if !installOk {
			return false, installLog
		}

		// restart nfs-server
		up, resultLog := BasicSystemdUp("nfs-kernel-server")
		if !up {
			msg := "[installNfsServerOnlineExec]- nfs-kernel-server start error"
			log.Error(msg)
			return false, append(resultLog, msg)
		}

	} else if op.IsOsTypeCentOS {
		// ubuntu
		installOk, installLog := BasicInstallSoftwares(op.InstallCommandPrefix, true, "nfs-utils")
		if !installOk {
			return false, installLog
		}

		// restart nfs-server
		up, resultLog := BasicSystemdUp("rpcbind")
		if !up {
			msg := "[installNfsServerOnlineExec]- rpcbind start error"
			log.Error(msg)
			return false, append(resultLog, msg)
		}
		up, resultLog = BasicSystemdUp("nfs-server")
		if !up {
			msg := "[installNfsServerOnlineExec]- nfs-server start error"
			log.Error(msg)
			return false, append(resultLog, msg)
		}

	}

	ok, i := HardCodeCommandExecutor("rpcinfo -p localhost")
	if !ok {
		return false, append(i,
			"installNfsServerOnlineExec] - rpc info error !",
			"please check nfs server installation")
	}

	return true, nil
}

func (op *AgentOsOperator) installNFSServerOfflineExec() (bool, []string) {

	log.InfoF("[installNFSServerOfflineExec] - start to install nfs server offline !")
	if !BasicCreateFolder("/root/wdd") {
		return false, []string{
			"[installNFSServerOfflineExec] - create install folder error !",
		}
	}

	// check for the version
	//executor, i := HardCodeCommandExecutor("grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '\"' | sed 's/ /-/g'")
	//if !executor {
	//	return false, append(i, "[installNFSServerOfflineExec]- get offline package name suffix error !")
	//}

	nfsServerOfflinePackageName := "nfs-server-" + op.AgentArch + "-" + op.AgentServerInfo.Platform + "-" + op.AgentServerInfo.PlatformVersion + ".tar.gz"

	// download from oss
	nfsServerOfflinePackageOSSUrl := op.OssOfflinePrefix + nfsServerOfflinePackageName
	log.InfoF("[installNFSServerOfflineExec]- start to download nfs-server offline package from => %s", nfsServerOfflinePackageOSSUrl)
	ok, resultLog := BasicDownloadFile(nfsServerOfflinePackageOSSUrl, "/root/wdd/"+nfsServerOfflinePackageName)
	if !ok {
		return false, append(resultLog, "[installNFSServerOfflineExec]- download nfs-server offline package error !", nfsServerOfflinePackageOSSUrl)
	}

	BasicRemoveFolderComplete("/root/wdd/tmp")

	// unzip
	AllCommandExecutor([]string{
		"tar",
		"-zvxf",
		"/root/wdd/" + nfsServerOfflinePackageName,
		"-C",
		"/root/wdd",
	})

	if !PureResultSingleExecuteBatch([][]string{
		{"mkdir", "-p", nfsDataPath},
		{"chmod", "777", nfsDataPath},
	}) {
		return false, []string{
			"[installNFSServerOfflineExec]- create nfs data folder failed !",
		}
	}

	if !BasicFindContentInFile(nfsDataPath, "/etc/exports") {
		log.DebugF("[installNFSServerOfflineExec]- add nfs path to /etc/exports !")

		nfsExport := nfsDataPath + "  *(rw,no_root_squash,no_all_squash,sync)"
		if !BasicAppendContentToFile(nfsExport, "/etc/exports") {
			return false, []string{
				"[installNFSServerOfflineExec]- add nfs path to /etc/exports failed !",
			}
		}
	}

	// install
	if op.IsOsTypeUbuntu {
		BasicPrettyPrint(HardCodeCommandExecutor(
			"dpkg -i /root/wdd/tmp/nfs-server/*.deb",
		))

		up, resultLog := BasicSystemdUp("nfs-kernel-server")
		if !up {
			msg := "[installNfsServerOnlineExec]- nfs-kernel-server start error"
			log.Error(msg)
			return false, append(resultLog, msg)
		}

	} else if op.IsOsTypeCentOS {
		BasicPrettyPrint(HardCodeCommandExecutor(
			"rpm -ivh /root/wdd/tmp/nfs-server/*.rpm",
		))

		// restart nfs-server
		up, resultLog := BasicSystemdUp("rpcbind")
		if !up {
			msg := "[installNfsServerOnlineExec]- rpcbind start error"
			log.Error(msg)
			return false, append(resultLog, msg)
		}
		up, resultLog = BasicSystemdUp("nfs-server")
		if !up {
			msg := "[installNfsServerOnlineExec]- nfs-server start error"
			log.Error(msg)
			return false, append(resultLog, msg)
		}
	}

	rpcinfoOK, i := HardCodeCommandExecutor("rpcinfo -p localhost")
	if !rpcinfoOK {
		return false, append(i,
			"[installNFSServerOfflineExec] - rpc info error !",
			"please check nfs server installation")
	}

	return true, []string{
		"[installNFSServerOfflineExec] - install success !",
	}
}

func (op *AgentOsOperator) installHarbor() [][]string {

	installHarborFunc := [][]string{
		//{
		//	"mkdir",
		//	"-p",
		//	"/root/wdd/",
		//},
		//{
		//	"rm",
		//	"-rf",
		//	"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
		//},
		//{
		//	"wget",
		//	"--no-check-certificate",
		//	op.OssOfflinePrefix + "harbor-offline-installer-v2.9.0.tgz",
		//	"-O",
		//	"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
		//},
		{
			"tar",
			"-zvxf",
			"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
			"-C",
			"/root/wdd/",
		},
		{
			"rm",
			"-rf",
			"/root/wdd/harbor/harbor.yml",
		},
		{
			"wget",
			"--no-check-certificate",
			op.OssOfflinePrefix + "harbor-config-template.yml",
			"-O",
			"/root/wdd/harbor/harbor.yml",
		},
		{
			"sed",
			"-i",
			"s/HarborHostName/" + op.AgentServerInfo.ServerIPInV4 + "/g",
			"/root/wdd/harbor/harbor.yml",
		},
		{
			"sed",
			"-i",
			"s/HarborHostPort/8033/g",
			"/root/wdd/harbor/harbor.yml",
		},
		{
			"sed",
			"-i",
			"s/HarborAdminPas/V2ryStr@ngPss/g",
			"/root/wdd/harbor/harbor.yml",
		},
		{
			"/root/wdd/harbor/install.sh",
			"--with-chartmuseum",
		},
	}

	return installHarborFunc
}

// installHarborExec install harbor offline
func (op *AgentOsOperator) installHarborExec() (bool, []string) {

	// check docker-compose
	if !BasicFileExistAndNotNull("/usr/local/bin/docker-compose") {
		return false, []string{
			"[install harbor] - docker-compose uninstalled ! can't install harbor!",
		}
	}

	// check already installed
	ok, _ := PipelineCommandExecutor([][]string{
		{
			"docker",
			"ps",
		},
		{
			"grep",
			"-q",
			"harbor-core",
		},
	})
	if ok {
		alreadyInstalledLog := []string{
			"[install harbor] - container harbor-core already running! harbor installed !",
		}

		log.Info(alreadyInstalledLog[0])

		resultOk, resultLog := AllCommandExecutor([]string{
			"docker-compose",
			"-f",
			"/root/wdd/harbor/docker-compose.yml",
			"up",
			"-d",
		})

		if !resultOk {
			alreadyInstalledLog = append(alreadyInstalledLog, "restart docker-compose file failed !")
			return false, append(alreadyInstalledLog, resultLog...)
		} else {
			return true, append(alreadyInstalledLog, "restart  docker-compose file success !")
		}
	}

	if strings.HasPrefix(op.AgentArch, "arm64") {
		return false, []string{
			"[install harbor] - script do not support for aarch64 version of harbor installation !",
		}
	}

	// download offline file
	harborOfflineFileURL := op.OssOfflinePrefix + "harbor-offline-installer-v2.9.0.tgz"
	log.InfoF("[install harbor] - start to download harbor offline installer from => %s !", harborOfflineFileURL)

	BasicCreateFolder("/root/wdd/")

	BasicRemoveFolderComplete("/root/wdd/harbor-offline-installer-v2.9.0.tgz")
	BasicRemoveFolderComplete("/root/wdd/harbor")

	downloadOk, l := BasicDownloadFile(harborOfflineFileURL, "/root/wdd/harbor-offline-installer-v2.9.0.tgz")
	if !downloadOk {
		return false, append(l, "download harbor offline installer failed!")
	}

	if !BasicFileExistAndNotNull("/root/wdd/harbor-offline-installer-v2.9.0.tgz") {
		return false, []string{"download harbor offline installer failed!"}
	}

	// unzip
	AllCompleteExecutor([][]string{
		{
			"tar",
			"-zvxf",
			"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
			"-C",
			"/root/wdd/",
		},
		{
			"rm",
			"-rf",
			"/root/wdd/harbor/harbor.yml",
		},
	})

	// configuration
	log.Info("[install harbor] - start to download harbor config file!")
	AllCommandExecutor([]string{
		"wget",
		"--no-check-certificate",
		op.OssOfflinePrefix + "harbor-config-template.yml",
		"-qO",
		"/root/wdd/harbor/harbor.yml",
	})
	if !BasicFileExistAndNotNull("/root/wdd/harbor/harbor.yml") {
		return false, []string{"harbor config template file download error !"}
	}

	log.Info("[install harbor] - start to modify harbor config file!")

	AllCommandExecutor([]string{
		"chmod",
		"+x",
		"/root/wdd/harbor/install.sh",
	})

	BasicReplace("/root/wdd/harbor/harbor.yml", "HarborHostName", op.AgentServerInfo.ServerIPInV4)
	BasicReplace("/root/wdd/harbor/harbor.yml", "HarborHostPort", "8033")
	BasicReplace("/root/wdd/harbor/harbor.yml", "HarborAdminPas", "V2ryStr@ngPss")

	log.InfoF("[install harbor] - harbor config changed success to => %s!", op.AgentServerInfo.ServerIPInV4)
	// install
	log.Info("[install harbor] - going to start harbor !")
	executor := ReadTimeCommandExecutor([]string{
		"bash",
		"/root/wdd/harbor/install.sh",
	},
	)
	if !executor {
		return false, []string{
			"[install harbor] - harbor start FAILED !",
		}
	}

	msg := "[install harbor] - harbor start complete !"
	log.Info(msg)

	return true, []string{msg}
}

func (op *AgentOsOperator) restartHarborExec() (bool, []string) {

	// check pods all run
	allHarborContainerName := []string{
		"harbor-log",
		"harbor-db",
		"harbor-portal",
		"redis",
		"registryctl",
		"registry",
		"registry",
		"harbor-core",
		"nginx",
		"harbor-jobservice",
	}
	harborServiceRunningHealthy := true

	for _, container := range allHarborContainerName {
		ok, _ := PipelineCommandExecutor([][]string{
			{
				"docker",
				"ps",
			},
			{
				"grep",
				"-c",
				container,
			},
		})
		if !ok {
			harborServiceRunningHealthy = false
			msg := fmt.Sprintf("[restartHarborExec] - harbor service unhealthy, container [ %s ] not running, prepare to restart !", container)
			log.Warn(msg)
			break
		}
	}

	if harborServiceRunningHealthy {
		return true, []string{
			"[restartHarborExec] - harbor container run healthy !",
		}
	}

	// docker-compose.yml exists
	harborDockerComposeFile := "/root/wdd/harbor/docker-compose.yml"
	if !BasicFileExistAndNotNull(harborDockerComposeFile) {
		errorLog := fmt.Sprintf("[restartHarborExec] - harborDockerComposeFile %s not exist !", harborDockerComposeFile)
		log.Error(errorLog)
		return false, []string{
			errorLog,
		}
	}

	// execute docker-compose up
	if !BasicCommandExists("docker-compose") {
		return false, []string{
			"[restartHarborExec] - docker-compose not exist !",
		}
	}

	log.InfoF("[restartHarborExec] - prepare to restart harbor docker compose !")
	ok, resultLog := AllCommandExecutor([]string{
		"docker-compose",
		"-f",
		harborDockerComposeFile,
		"up",
		"-d",
	})
	if !ok {
		return false, resultLog
	}

	// wait

	// check pods all run
	for _, container := range allHarborContainerName {
		ok, _ := PipelineCommandExecutor([][]string{
			{
				"docker",
				"ps",
			},
			{
				"grep",
				"-c",
				container,
			},
		})
		if !ok {
			errLog := fmt.Sprintf("[restartHarborExec] - harbor service [ %s ] restart failed !", container)
			log.Error(errLog)
			return false, []string{
				errLog,
			}
		}
	}

	return true, []string{
		"[restartHarborExec] - harbor container restarted and run healthy !",
	}
}

func (op *AgentOsOperator) chronyToPublicNTP() [][]string {

	serverIPInV4 := op.AgentServerInfo.ServerIPInV4
	internalIPCIDR := strings.Join(strings.Split(serverIPInV4, ".")[:2], ".") + ".0.0/16"

	chronyToPublicNTPFunc := [][]string{
		append(
			op.InstallCommandPrefix,
			"chrony",
		),
		{
			"systemctl",
			"enable",
			"chronyd",
		},
		{
			"systemctl",
			"start",
			"chronyd",
		},
	}

	var chronyFile string
	if op.IsOsTypeUbuntu {
		chronyFile = "/etc/chrony/chrony.conf"
	} else {
		chronyFile = "/etc/chrony.conf"
	}

	chronyToPublicNTPFunc = append(chronyToPublicNTPFunc,
		[][]string{
			{
				"sed",
				"-i",
				"$ a allow " + internalIPCIDR,
				chronyFile,
			},
			{
				"sed",
				"-i",
				"s/pool ntp.ubuntu.com iburst/server ntp2.aliyun.com iburst/g",
				chronyFile,
			},
			{
				"systemctl",
				"restart",
				"chronyd",
			},
			{
				"sleep",
				"2",
			},
			{
				"chronyc",
				"-n",
				"sources",
				"-v",
			},
			{
				"chronyc",
				"tracking",
			},
			{
				"timedatectl",
				"set-timezone",
				"Asia/Shanghai",
			},
			{
				"timedatectl",
				"set-ntp",
				"true",
			},
			{
				"systemctl",
				"restart",
				"rsyslog",
			},
		}...,
	)

	return chronyToPublicNTPFunc
}

func (op *AgentOsOperator) chronyToPublicNTPExec() (bool, []string) {

	var chronyFile string
	if op.IsOsTypeUbuntu {
		chronyFile = "/etc/chrony/chrony.conf"
	} else {
		chronyFile = "/etc/chrony.conf"
	}

	ok, resultLog := AllCompleteExecutor([][]string{
		{
			"sed",
			"-i",
			"$ a allow all",
			chronyFile,
		},
		{
			"sed",
			"-i",
			"s/pool ntp.ubuntu.com/server ntp2.aliyun.com/g",
			chronyFile,
		},
		{
			"systemctl",
			"restart",
			"chronyd",
		},
		{
			"timedatectl",
			"set-timezone",
			"Asia/Shanghai",
		},
		{
			"sleep",
			"2",
		}})

	if !ok {
		return false, resultLog
	}

	_, l := AllCompleteExecutor([][]string{
		{
			"chronyc",
			"-n",
			"sources",
			"-v",
		},
		{
			"chronyc",
			"tracking",
		},
		{
			"chronyc",
			"clients",
		},
	})

	// check chrony
	return true, l
}

// installChronyExec make sure chrony is installed
func (op *AgentOsOperator) installChronyExec() (bool, []string) {

	// uninstall systemd-timesyncd.service
	ok, resultLog := BasicSystemdShutdown("systemd-timesyncd.service")
	if !ok {
		return false, resultLog
	}

	// install chrony
	resultOk, l := AllCommandExecutor(
		append(
			op.InstallCommandPrefix,
			"chrony",
		),
	)
	if !resultOk {
		return false, l
	}

	// check installation
	fileExistAndNotNull := BasicFileExistAndNotNull("/etc/chrony/chrony.conf")
	if !fileExistAndNotNull {
		return false, []string{
			"chrony config file is null !",
			"chrony installation is failed !",
			"please check!"}
	}

	up, log2 := BasicSystemdUp("chrony.service")
	if !up {
		return false, log2
	}

	return true, nil
}

func (op *AgentOsOperator) installChronyByDockerExec(funcArgs []string) (bool, []string) {

	// check docker
	if !BasicCommandExistByPath("docker") {
		return false, []string{
			"[installChronyByDockerExec] - docker not installed exited !",
		}
	}

	parseIP := net.ParseIP(funcArgs[0])
	if parseIP == nil {
		return false, []string{
			"[installChronyByDockerExec] - ip args error !",
		}
	}

	// run docker command
	ok, resultLog := AllCommandExecutor([]string{
		"docker",
		"run",
		"--name=chrony",
		"--restart=always",
		"--detach",
		"--cap-add=SYS_TIME",
		"--publish=123:123/udp",
		"--env=NTP_SERVERS=\"ntp1.aliyun.com,ntp2.aliyun.com,ntp3.aliyun.com,ntp4.aliyun.com\"",
		"--env=LOG_LEVEL=0",
		"--env=TZ=Asia/Shanghai",
		"--env=ENABLE_SYSCLK=true",
		funcArgs[0] + ":8033/cmii/chronyd:0.4.3",
	})
	if !ok {
		return false, append(resultLog, "[installChronyByDockerExec] - docker chrony run error !")
	}

	BasicPrettyPrint(AllCommandExecutor([]string{
		"docker",
		"exec",
		"chrony",
		"chronyc",
		"tracking",
	}))

	BasicPrettyPrint(AllCommandExecutor([]string{
		"docker",
		"exec",
		"chrony",
		"chronyc",
		"sources",
	}))

	BasicPrettyPrint(AllCommandExecutor([]string{
		"docker",
		"exec",
		"chrony",
		"chronyc",
		"sourcestats",
	}))

	return true, []string{
		"[installChronyByDockerExec] - install success !",
	}
}

func (op *AgentOsOperator) chronyToMaster(args []string) [][]string {

	masterInnerIP := args[0]

	chronyToMasterFunc := [][]string{
		{
			"sed",
			"-i",
			"$ a NTP=" + masterInnerIP,
			"/etc/systemd/timesyncd.conf",
		},
		{
			"systemctl",
			"daemon-reload",
		},
		{
			"systemctl",
			"restart",
			"systemd-timesyncd.service",
		},
		{
			"sleep",
			"3",
		},
		{
			"timedatectl",
			"show-timesync",
			"--all",
		},
		{
			"timedatectl",
			"status",
		},
	}

	return chronyToMasterFunc
}

func (op *AgentOsOperator) chronyToMasterExec(args []string) (bool, []string) {

	parseIP := net.ParseIP(args[0])
	if parseIP == nil {
		return false, []string{
			"[chronyToMasterExec] - ip args error !",
		}
	}

	if op.IsOsTypeCentOS {
		if !op.CanAccessInternet {
			return op.chronyToMasterByDocker(args)
		}

		// install ntp
		installSoftwares, i := BasicInstallSoftwares(op.InstallCommandPrefix, true, "ntp")
		if !installSoftwares {
			msg := "[chronyToMasterExec] - centos install ntp error!"
			log.ErrorF(msg)
			return false, append(i, msg)
		}

		BasicSystemdUp("ntpd")

		HardCodeCommandExecutor("ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime")

		ok, resultLog := AllCommandExecutor([]string{
			"ntpdate",
			args[0],
		})
		if !ok {
			sprintf := fmt.Sprintf("[chronyToMasterExec] - centos ntpdate to %s error", args[0])
			log.Error(sprintf)
			return false, append(resultLog, sprintf)
		}

		return true, []string{
			"[chronyToMasterExec] - chrony to master success !",
		}
	}

	// modify the systemd-timesync.service
	ntpFile := "/etc/systemd/timesyncd.conf"
	AllCommandExecutor([]string{
		"sed",
		"-i",
		"s/#NTP=/NTP=" + args[0] + "/g",
		ntpFile,
	})

	// set time zone and ntp
	AllCompleteExecutor([][]string{
		{
			"timedatectl",
			"set-timezone",
			"Asia/Shanghai",
		},
		{
			"timedatectl",
			"set-ntp",
			"true",
		},
	})

	BasicPrettyPrint(AllCompleteExecutor([][]string{
		{
			"systemctl",
			"restart",
			"systemd-timesyncd.service",
		},
		{
			"sleep",
			"2",
		},
		{
			"timedatectl",
			"show-timesync",
			"--all",
		},
		{
			"timedatectl",
			"status",
		},
	}))

	return true, []string{
		"[chronyToMasterExec] - install success !",
	}
}

func (op *AgentOsOperator) chronyToMasterByDocker(args []string) (bool, []string) {

	return true, nil
}

func (op *AgentOsOperator) installZSH() [][]string {

	installZSHFunc := [][]string{
		{
			"mkdir",
			"-p",
			"/root/wdd/",
		},
		append(
			op.InstallCommandPrefix,
			"zsh",
			"git",
		),
	}

	if op.IsAgentInnerWall {
		installZSHFunc = append(
			installZSHFunc,
			[][]string{
				{
					"wget",
					"https://cdn.jsdelivr.net/gh/robbyrussell/oh-my-zsh@master/tools/install.sh",
					"-O",
					"/root/wdd/zsh-install.sh",
				},
			}...,
		)

	} else {
		installZSHFunc = append(
			installZSHFunc,
			[][]string{
				{
					"wget",
					"https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh",
					"-O",
					"/root/wdd/zsh-install.sh",
				},
			}...,
		)
	}

	// install
	installZSHFunc = append(
		installZSHFunc,
		[][]string{
			{
				"chmod",
				"+x",
				"/root/wdd/zsh-install.sh",
			},
			{
				"sh",
				"-c",
				"/root/wdd/zsh-install.sh",
			},
		}...,
	)

	// modify ZSH
	if !op.IsAgentInnerWall {
		installZSHFunc = append(
			installZSHFunc,
			[][]string{
				{
					"git",
					"clone",
					"https://github.com/zsh-users/zsh-autosuggestions",
					"/root/.oh-my-zsh/plugins/zsh-autosuggestions",
				},
				{
					"git",
					"clone",
					"https://github.com/zsh-users/zsh-syntax-highlighting.git",
					"/root/.oh-my-zsh/plugins/zsh-syntax-highlighting",
				},
				{
					"wget",
					"https://b2.107421.xyz/oh-my-zsh-plugins-list.txt",
					"-O",
					"oh-my-zsh-plugins-list.txt",
				},
				{
					"wget",
					"-c",
					"-i",
					"./oh-my-zsh-plugins-list.txt",
					"-P",
					"/root/.oh-my-zsh/plugins/",
				},
				{
					"sed",
					"-i",
					"s/robbyrussell/agnoster/g",
					"/root/.zshrc",
				},
				{
					"sed",
					"-i",
					"s/^# DISABLE_AUTO_UPDATE=\"true\"/DISABLE_AUTO_UPDATE=\"true\"/g",
					"/root/.zshrc",
				},
				{
					"sed",
					"-i",
					"s/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting command-not-found z themes)/g",
					"/root/.zshrc",
				},
				{
					"source",
					"/root/.zshrc",
				},
				{
					"chsh",
					"-s",
					"/bin/zsh",
				},
				{
					"zsh",
				},
			}...,
		)
	}

	return installZSHFunc
}

func (op *AgentOsOperator) installZSHExec() (bool, []string) {

	log.Info("[installZSHExec] - 开始安装ZSH!")

	if !op.CanAccessInternet {
		return false, []string{
			"[installZSHExec] - can not access to internet, zsh install failed !",
		}
	}

	BasicRemoveFolderComplete("/root/.oh-my-zsh")
	BasicRemoveFolderComplete("/root/wdd/zsh-install.sh")
	BasicRemoveFolderComplete("/root/wdd/oh-my-zsh-plugins-list.txt")
	BasicCreateFolder("/root/wdd/")

	ok, resultLog := AllCommandExecutor(
		append(op.InstallCommandPrefix, "zsh", "git"))
	if !ok {
		return false, resultLog
	}
	log.InfoF("ZSH环境已经清理, 完成基础安装! 开始安装oh-my-zsh!")

	var zshRemoteGitUrl string
	if op.IsAgentInnerWall {
		zshRemoteGitUrl = "https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh"
	} else {
		zshRemoteGitUrl = "https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh"
	}
	log.InfoF("开始下载zsh的安装脚本 => %s", zshRemoteGitUrl)

	resultOk, l := BasicDownloadFile(zshRemoteGitUrl, "/root/wdd/zsh-install.sh")
	if !resultOk {
		l = append(l, "zsh-install.sh 下载失败！ 安装终止")
		return false, l
	}

	executor, log2 := AllCompleteExecutor([][]string{
		{
			"chmod",
			"+x",
			"/root/wdd/zsh-install.sh",
		},
		{
			"/bin/bash",
			"/root/wdd/zsh-install.sh",
			"REMOTE=https://gitee.com/mirrors/oh-my-zsh.git",
		},
	},
	)
	if !executor {
		return false, log2
	}

	log.Info("zsh安装完成! 开始进行zsh的配置!")
	zshAutoSourcePath := "https://github.com/zsh-users/zsh-autosuggestions"
	zshHighLightingSourcePath := "https://github.com/zsh-users/zsh-syntax-highlighting.git"
	if op.IsAgentInnerWall {
		zshAutoSourcePath = "https://gitee.com/wangl-cc/zsh-autosuggestions.git"
		zshHighLightingSourcePath = "https://gitee.com/xiaoqqya/zsh-syntax-highlighting.git"
	}

	modifyZSHOK, log3 := AllCompleteExecutor(
		[][]string{
			{
				"git",
				"clone",
				zshAutoSourcePath,
				"/root/.oh-my-zsh/plugins/zsh-autosuggestions",
			},
			{
				"git",
				"clone",
				zshHighLightingSourcePath,
				"/root/.oh-my-zsh/plugins/zsh-syntax-highlighting",
			},
			{
				"wget",
				op.OssOfflinePrefix + "oh-my-zsh-plugins-list.txt",
				"-O",
				"/root/wdd/oh-my-zsh-plugins-list.txt",
			},
			{
				"wget",
				"-c",
				"-i",
				"/root/wdd/oh-my-zsh-plugins-list.txt",
				"-P",
				"/root/.oh-my-zsh/plugins/",
			},
			{
				"sed",
				"-i",
				"s/robbyrussell/agnoster/g",
				"/root/.zshrc",
			},
			{
				"sed",
				"-i",
				"s/^# DISABLE_AUTO_UPDATE=\"true\"/DISABLE_AUTO_UPDATE=\"true\"/g",
				"/root/.zshrc",
			},
			{
				"sed",
				"-i",
				"s/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting command-not-found z themes)/g",
				"/root/.zshrc",
			},
			{
				"chsh",
				"-s",
				"/bin/zsh",
			},
			{
				"zsh",
			},
		})
	if !modifyZSHOK {
		log.Warn("ZSH 安装成功，但是配置修改失败！")
		return true, log3
	}

	return true, nil
}

func (op *AgentOsOperator) modifySshPort(args []string) [][]string {

	return [][]string{}
}

func (op *AgentOsOperator) modifySshPortExec(args []string) (bool, []string) {
	return true, nil
}

func (op *AgentOsOperator) openBBR() [][]string {

	return [][]string{}
}

func (op *AgentOsOperator) openBBRExec() (bool, []string) {
	return true, nil
}

func (op *AgentOsOperator) ok(funcArgs []string) [][]string {
	log.InfoF("base function is ok , args are => " + strings.Join(funcArgs, " "))
	return [][]string{
		{"ifconfig"},
	}
}

func (op *AgentOsOperator) okExec(funcArgs []string) (bool, []string) {
	log.WarnF("[okExec] - call empty base func ! func args are => %#v ", funcArgs)
	return true, nil
}
