[agent-go] [Bastion] - install docker; docker-compose; install harbor
This commit is contained in:
14
.run/agent-go bastion.run.xml
Normal file
14
.run/agent-go bastion.run.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="agent-go bastion" type="GoApplicationRunConfiguration"
|
||||||
|
factoryName="Go Application">
|
||||||
|
<module name="ProjectOctopus"/>
|
||||||
|
<target name="wdd-test-192"/>
|
||||||
|
<working_directory value="$PROJECT_DIR$/agent-go"/>
|
||||||
|
<parameters value="-mode=bastion"/>
|
||||||
|
<kind value="PACKAGE"/>
|
||||||
|
<package value="wdd.io/agent-go"/>
|
||||||
|
<directory value="$PROJECT_DIR$"/>
|
||||||
|
<filePath value="$PROJECT_DIR$/agent-go/main.go"/>
|
||||||
|
<method v="2"/>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
14
.run/agent-go main.run.xml
Normal file
14
.run/agent-go main.run.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="agent-go main" type="GoApplicationRunConfiguration"
|
||||||
|
factoryName="Go Application">
|
||||||
|
<module name="ProjectOctopus"/>
|
||||||
|
<target name="LapPro-10.250.0.100"/>
|
||||||
|
<working_directory value="$PROJECT_DIR$/agent-go"/>
|
||||||
|
<parameters value="-age"/>
|
||||||
|
<kind value="PACKAGE"/>
|
||||||
|
<package value="wdd.io/agent-go"/>
|
||||||
|
<directory value="$PROJECT_DIR$"/>
|
||||||
|
<filePath value="$PROJECT_DIR$/agent-go/main.go"/>
|
||||||
|
<method v="2"/>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -3,10 +3,14 @@ package a_executor
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"wdd.io/agent-go/a_agent"
|
"wdd.io/agent-go/a_agent"
|
||||||
|
"wdd.io/agent-go/a_executor/beans"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var OctopusAgentInstallPrefix = "/root/wdd/"
|
||||||
|
|
||||||
type BaseFunc interface {
|
type BaseFunc interface {
|
||||||
|
|
||||||
// Command 返回基础函数的命令行
|
// Command 返回基础函数的命令行
|
||||||
@@ -384,11 +388,11 @@ func (op *AgentOsOperator) installDefaultSSHKeyExec(funcArgs []string) (bool, []
|
|||||||
}
|
}
|
||||||
|
|
||||||
// download standard private and public key
|
// download standard private and public key
|
||||||
ok, resultLog := BasicDownloadFileByCurl(op.OssOfflinePrefix+"id_ed25519_private_key", "/root/.ssh/id_ed25519")
|
ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+"id_ed25519_private_key", "", "", "", "/root/.ssh/id_ed25519")
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, resultLog
|
return false, resultLog
|
||||||
}
|
}
|
||||||
ok, resultLog = BasicDownloadFileByCurl(op.OssOfflinePrefix+"id_ed25519_public_key.pub", "/root/.ssh/id_ed25519.pub")
|
ok, resultLog = BasicDownloadFile(op.OssOfflinePrefix+"id_ed25519_public_key.pub", "", "", "", "/root/.ssh/id_ed25519.pub")
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, resultLog
|
return false, resultLog
|
||||||
}
|
}
|
||||||
@@ -445,7 +449,6 @@ func (op *AgentOsOperator) removeDocker() [][]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (op *AgentOsOperator) removeDockerExec() (bool, []string) {
|
func (op *AgentOsOperator) removeDockerExec() (bool, []string) {
|
||||||
var resultLog []string
|
|
||||||
|
|
||||||
dockerServiceStopCommand := [][]string{
|
dockerServiceStopCommand := [][]string{
|
||||||
{
|
{
|
||||||
@@ -467,7 +470,8 @@ func (op *AgentOsOperator) removeDockerExec() (bool, []string) {
|
|||||||
|
|
||||||
ok, l := AllCompleteExecutor(dockerServiceStopCommand)
|
ok, l := AllCompleteExecutor(dockerServiceStopCommand)
|
||||||
if !ok {
|
if !ok {
|
||||||
resultLog = append(resultLog, l...)
|
log.Error("[removeDockerExec] - 停止docker服务失败!")
|
||||||
|
return false, l
|
||||||
}
|
}
|
||||||
|
|
||||||
dockerStaff := []string{
|
dockerStaff := []string{
|
||||||
@@ -491,14 +495,25 @@ func (op *AgentOsOperator) removeDockerExec() (bool, []string) {
|
|||||||
|
|
||||||
for _, staff := range dockerStaff {
|
for _, staff := range dockerStaff {
|
||||||
removeCommand := append(op.RemoveCommandPrefix, staff)
|
removeCommand := append(op.RemoveCommandPrefix, staff)
|
||||||
|
AllCommandExecutor(removeCommand)
|
||||||
|
}
|
||||||
|
|
||||||
ok, result := AllCommandExecutor(removeCommand)
|
_ = os.Remove(beans.DockerServiceFile)
|
||||||
if !ok {
|
_ = os.Remove(beans.DockerDaemonService)
|
||||||
resultLog = append(resultLog, result...)
|
_ = os.Remove(beans.DockerSocketFile)
|
||||||
|
|
||||||
|
AllCommandExecutor([]string{
|
||||||
|
"systemctl",
|
||||||
|
"daemon-reload",
|
||||||
|
})
|
||||||
|
|
||||||
|
return true, []string{
|
||||||
|
"[removeDockerExec] - docker remove success !",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, resultLog
|
func (op *AgentOsOperator) RemoveDockerBastion() (bool, []string) {
|
||||||
|
return op.removeDockerExec()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (op *AgentOsOperator) installDocker(args []string) [][]string {
|
func (op *AgentOsOperator) installDocker(args []string) [][]string {
|
||||||
@@ -616,7 +631,7 @@ func (op *AgentOsOperator) installDocker(args []string) [][]string {
|
|||||||
|
|
||||||
func (op *AgentOsOperator) installDockerExec(args []string) (bool, []string) {
|
func (op *AgentOsOperator) installDockerExec(args []string) (bool, []string) {
|
||||||
|
|
||||||
BasicCreateFolder("/root/wdd/")
|
BasicCreateFolder(OctopusAgentInstallPrefix)
|
||||||
|
|
||||||
op.removeDockerExec()
|
op.removeDockerExec()
|
||||||
|
|
||||||
@@ -855,7 +870,7 @@ func (op *AgentOsOperator) installDockerOfflineExec(args []string) (bool, []stri
|
|||||||
dockerOfflineFileName = "docker-arm64-20.10.15.tgz"
|
dockerOfflineFileName = "docker-arm64-20.10.15.tgz"
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+dockerOfflineFileName, "", "", "", "/root/wdd/"+dockerOfflineFileName)
|
ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+dockerOfflineFileName, "", "", "", OctopusAgentInstallPrefix+dockerOfflineFileName)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, resultLog
|
return false, resultLog
|
||||||
}
|
}
|
||||||
@@ -865,7 +880,7 @@ func (op *AgentOsOperator) installDockerOfflineExec(args []string) (bool, []stri
|
|||||||
PureResultSingleExecute([]string{
|
PureResultSingleExecute([]string{
|
||||||
"tar",
|
"tar",
|
||||||
"-vxf",
|
"-vxf",
|
||||||
"/root/wdd/" + dockerOfflineFileName,
|
OctopusAgentInstallPrefix + dockerOfflineFileName,
|
||||||
"-C",
|
"-C",
|
||||||
"/root/wdd",
|
"/root/wdd",
|
||||||
})
|
})
|
||||||
@@ -878,17 +893,17 @@ func (op *AgentOsOperator) installDockerOfflineExec(args []string) (bool, []stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// systemd daemonize docker
|
// systemd daemonize docker
|
||||||
downloadOk, log2 := BasicDownloadFileByCurl(op.OssOfflinePrefix+"docker-containerd-daemon.service", "/lib/systemd/system/containerd.service")
|
downloadOk, log2 := BasicDownloadFile(op.OssOfflinePrefix+"docker-containerd-daemon.service", "", "", "", beans.ContainerdServiceFile)
|
||||||
if !downloadOk {
|
if !downloadOk {
|
||||||
return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
|
return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadOk, log2 = BasicDownloadFileByCurl(op.OssOfflinePrefix+"docker-socket-daemon.service", "/lib/systemd/system/docker.socket")
|
downloadOk, log2 = BasicDownloadFile(op.OssOfflinePrefix+"docker-socket-daemon.service", "", "", "", beans.DockerSocketDaemonService)
|
||||||
if !downloadOk {
|
if !downloadOk {
|
||||||
return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
|
return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadOk, log2 = BasicDownloadFileByCurl(op.OssOfflinePrefix+"docker-daemon.service", "/lib/systemd/system/docker.service")
|
downloadOk, log2 = BasicDownloadFile(op.OssOfflinePrefix+"docker-daemon.service", "", "", "", beans.DockerServiceFile)
|
||||||
if !downloadOk {
|
if !downloadOk {
|
||||||
return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
|
return false, append(log2, "[installDockerOfflineExec] - daemon file download error !")
|
||||||
}
|
}
|
||||||
@@ -965,7 +980,7 @@ func (op *AgentOsOperator) InstallDockerBastion() (bool, []string) {
|
|||||||
|
|
||||||
BasicRemoveFolderComplete("/root/wdd/docker")
|
BasicRemoveFolderComplete("/root/wdd/docker")
|
||||||
|
|
||||||
dockerLocalFile := "/root/wdd/" + dockerOfflineFileName
|
dockerLocalFile := OctopusAgentInstallPrefix + dockerOfflineFileName
|
||||||
if !BasicFileExistAndNotNull(dockerLocalFile) {
|
if !BasicFileExistAndNotNull(dockerLocalFile) {
|
||||||
sprintf := fmt.Sprintf("docker offline file not exists ! => %s", dockerLocalFile)
|
sprintf := fmt.Sprintf("docker offline file not exists ! => %s", dockerLocalFile)
|
||||||
log.Error(sprintf)
|
log.Error(sprintf)
|
||||||
@@ -989,6 +1004,91 @@ func (op *AgentOsOperator) InstallDockerBastion() (bool, []string) {
|
|||||||
|
|
||||||
// daemon docker
|
// daemon docker
|
||||||
|
|
||||||
|
// systemd daemonize docker
|
||||||
|
BasicAppendOverwriteContentToFile(beans.ContainerdDaemonService, beans.ContainerdServiceFile)
|
||||||
|
if !BasicFileExistAndNotNull(beans.ContainerdServiceFile) {
|
||||||
|
return false, []string{"docker deamon file not exists !"}
|
||||||
|
}
|
||||||
|
BasicAppendOverwriteContentToFile(beans.DockerSocketDaemonService, beans.DockerSocketFile)
|
||||||
|
if !BasicFileExistAndNotNull(beans.DockerSocketFile) {
|
||||||
|
return false, []string{"docker deamon file not exists !"}
|
||||||
|
}
|
||||||
|
BasicAppendOverwriteContentToFile(beans.DockerDaemonService, beans.DockerServiceFile)
|
||||||
|
if !BasicFileExistAndNotNull(beans.DockerServiceFile) {
|
||||||
|
return false, []string{"docker deamon file not exists !"}
|
||||||
|
}
|
||||||
|
log.InfoF("[InstallDockerBastion] - docker dameon file append success !")
|
||||||
|
|
||||||
|
// run the docker
|
||||||
|
executor, log3 := AllCommandExecutor([]string{
|
||||||
|
"systemctl",
|
||||||
|
"daemon-reload",
|
||||||
|
})
|
||||||
|
if !executor {
|
||||||
|
return false, append(log3, "[InstallDockerBastion] - daemon reload error !")
|
||||||
|
}
|
||||||
|
|
||||||
|
AllCompleteExecutor([][]string{
|
||||||
|
{
|
||||||
|
"systemctl",
|
||||||
|
"unmask",
|
||||||
|
"containerd",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"systemctl",
|
||||||
|
"unmask",
|
||||||
|
"docker.socket",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"systemctl",
|
||||||
|
"unmask",
|
||||||
|
"docker",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
AllCompleteExecutor([][]string{
|
||||||
|
{
|
||||||
|
"groupadd",
|
||||||
|
"docker",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"usermod",
|
||||||
|
"-aG",
|
||||||
|
"docker",
|
||||||
|
"root",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"newgrp",
|
||||||
|
"docker",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
systemdUp, _ := BasicSystemdUp("containerd")
|
||||||
|
if !systemdUp {
|
||||||
|
log.Warn("[InstallDockerBastion] - start containerd service error !")
|
||||||
|
}
|
||||||
|
|
||||||
|
commandExecutor, _ := AllCompleteExecutor([][]string{
|
||||||
|
{
|
||||||
|
"systemctl",
|
||||||
|
"start",
|
||||||
|
"docker.socket",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"systemctl",
|
||||||
|
"enable",
|
||||||
|
"docker.socket",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if !commandExecutor {
|
||||||
|
log.Warn("[InstallDockerBastion] - start docker.socket error !")
|
||||||
|
}
|
||||||
|
|
||||||
|
up, log4 := BasicSystemdUp("docker")
|
||||||
|
if !up {
|
||||||
|
return false, append(log4, "[InstallDockerBastion] - start docker service error !")
|
||||||
|
}
|
||||||
|
|
||||||
return true, []string{
|
return true, []string{
|
||||||
"[InstallDockerBastion] - docker offline installation from local success!",
|
"[InstallDockerBastion] - docker offline installation from local success!",
|
||||||
}
|
}
|
||||||
@@ -1058,7 +1158,7 @@ func (op *AgentOsOperator) installDockerComposeExec() (bool, []string) {
|
|||||||
|
|
||||||
log.InfoF("需要安装的docker版本为 => %s", DockerComposeFile)
|
log.InfoF("需要安装的docker版本为 => %s", DockerComposeFile)
|
||||||
|
|
||||||
ok, resultLog := BasicDownloadFileByCurl(DockerComposeFile, "/usr/local/bin/docker-compose")
|
ok, resultLog := BasicDownloadFile(DockerComposeFile, "", "", "", "/usr/local/bin/docker-compose")
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, resultLog
|
return false, resultLog
|
||||||
}
|
}
|
||||||
@@ -1091,7 +1191,7 @@ func (op *AgentOsOperator) installHelm() [][]string {
|
|||||||
{
|
{
|
||||||
"mkdir",
|
"mkdir",
|
||||||
"-p",
|
"-p",
|
||||||
"/root/wdd/",
|
OctopusAgentInstallPrefix,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rm",
|
"rm",
|
||||||
@@ -1212,7 +1312,7 @@ func (op *AgentOsOperator) modifyDockerConfigExec(args []string) (bool, []string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// download new
|
// download new
|
||||||
ok, resultLog := BasicDownloadFileByCurl(op.OssOfflinePrefix+"docker-daemon-template.json", dockerDaemonFile)
|
ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+"docker-daemon-template.json", "", "", "", dockerDaemonFile)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, append(resultLog, "[modifyDockerConfigExec] - error download docker-daemon-template.json !")
|
return false, append(resultLog, "[modifyDockerConfigExec] - error download docker-daemon-template.json !")
|
||||||
}
|
}
|
||||||
@@ -1299,7 +1399,7 @@ func (op *AgentOsOperator) installNFSOfflineExec() (bool, []string) {
|
|||||||
nfsClientOfflinePackageOSSUrl := op.OssOfflinePrefix + nfsClientOfflinePackageName
|
nfsClientOfflinePackageOSSUrl := op.OssOfflinePrefix + nfsClientOfflinePackageName
|
||||||
log.InfoF("[installNFSOfflineExec]- start to download nfs-client offline package from => %s", nfsClientOfflinePackageOSSUrl)
|
log.InfoF("[installNFSOfflineExec]- start to download nfs-client offline package from => %s", nfsClientOfflinePackageOSSUrl)
|
||||||
|
|
||||||
ok, resultLog := BasicDownloadFileByCurl(nfsClientOfflinePackageOSSUrl, "/root/wdd/"+nfsClientOfflinePackageName)
|
ok, resultLog := BasicDownloadFile(nfsClientOfflinePackageOSSUrl, "", "", "", OctopusAgentInstallPrefix+nfsClientOfflinePackageName)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, append(resultLog, "[installNFSOfflineExec]- download nfs-client offline package error !", nfsClientOfflinePackageOSSUrl)
|
return false, append(resultLog, "[installNFSOfflineExec]- download nfs-client offline package error !", nfsClientOfflinePackageOSSUrl)
|
||||||
}
|
}
|
||||||
@@ -1310,7 +1410,7 @@ func (op *AgentOsOperator) installNFSOfflineExec() (bool, []string) {
|
|||||||
AllCommandExecutor([]string{
|
AllCommandExecutor([]string{
|
||||||
"tar",
|
"tar",
|
||||||
"-zvxf",
|
"-zvxf",
|
||||||
"/root/wdd/" + nfsClientOfflinePackageName,
|
OctopusAgentInstallPrefix + nfsClientOfflinePackageName,
|
||||||
"-C",
|
"-C",
|
||||||
"/root/wdd",
|
"/root/wdd",
|
||||||
})
|
})
|
||||||
@@ -1429,7 +1529,7 @@ func (op *AgentOsOperator) installNFSServerOfflineExec() (bool, []string) {
|
|||||||
// download from oss
|
// download from oss
|
||||||
nfsServerOfflinePackageOSSUrl := op.OssOfflinePrefix + nfsServerOfflinePackageName
|
nfsServerOfflinePackageOSSUrl := op.OssOfflinePrefix + nfsServerOfflinePackageName
|
||||||
log.InfoF("[installNFSServerOfflineExec]- start to download nfs-server offline package from => %s", nfsServerOfflinePackageOSSUrl)
|
log.InfoF("[installNFSServerOfflineExec]- start to download nfs-server offline package from => %s", nfsServerOfflinePackageOSSUrl)
|
||||||
ok, resultLog := BasicDownloadFileByCurl(nfsServerOfflinePackageOSSUrl, "/root/wdd/"+nfsServerOfflinePackageName)
|
ok, resultLog := BasicDownloadFileByCurl(nfsServerOfflinePackageOSSUrl, OctopusAgentInstallPrefix+nfsServerOfflinePackageName)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, append(resultLog, "[installNFSServerOfflineExec]- download nfs-server offline package error !", nfsServerOfflinePackageOSSUrl)
|
return false, append(resultLog, "[installNFSServerOfflineExec]- download nfs-server offline package error !", nfsServerOfflinePackageOSSUrl)
|
||||||
}
|
}
|
||||||
@@ -1440,7 +1540,7 @@ func (op *AgentOsOperator) installNFSServerOfflineExec() (bool, []string) {
|
|||||||
AllCommandExecutor([]string{
|
AllCommandExecutor([]string{
|
||||||
"tar",
|
"tar",
|
||||||
"-zvxf",
|
"-zvxf",
|
||||||
"/root/wdd/" + nfsServerOfflinePackageName,
|
OctopusAgentInstallPrefix + nfsServerOfflinePackageName,
|
||||||
"-C",
|
"-C",
|
||||||
"/root/wdd",
|
"/root/wdd",
|
||||||
})
|
})
|
||||||
@@ -1516,7 +1616,7 @@ func (op *AgentOsOperator) installHarbor() [][]string {
|
|||||||
//{
|
//{
|
||||||
// "mkdir",
|
// "mkdir",
|
||||||
// "-p",
|
// "-p",
|
||||||
// "/root/wdd/",
|
// OctopusAgentInstallPrefix,
|
||||||
//},
|
//},
|
||||||
//{
|
//{
|
||||||
// "rm",
|
// "rm",
|
||||||
@@ -1535,7 +1635,7 @@ func (op *AgentOsOperator) installHarbor() [][]string {
|
|||||||
"-zvxf",
|
"-zvxf",
|
||||||
"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
|
"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
|
||||||
"-C",
|
"-C",
|
||||||
"/root/wdd/",
|
OctopusAgentInstallPrefix,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rm",
|
"rm",
|
||||||
@@ -1575,12 +1675,9 @@ func (op *AgentOsOperator) installHarbor() [][]string {
|
|||||||
|
|
||||||
return installHarborFunc
|
return installHarborFunc
|
||||||
}
|
}
|
||||||
|
func (op *AgentOsOperator) checkHarborInstallExec() (bool, []string) {
|
||||||
// installHarborExec install harbor offline
|
|
||||||
func (op *AgentOsOperator) installHarborExec() (bool, []string) {
|
|
||||||
|
|
||||||
// check docker-compose
|
// check docker-compose
|
||||||
if !BasicFileExistAndNotNull("/usr/local/bin/docker-compose") {
|
if !BasicCommandExistByPath("/usr/local/bin/docker-compose") {
|
||||||
return false, []string{
|
return false, []string{
|
||||||
"[install harbor] - docker-compose uninstalled ! can't install harbor!",
|
"[install harbor] - docker-compose uninstalled ! can't install harbor!",
|
||||||
}
|
}
|
||||||
@@ -1626,25 +1723,32 @@ func (op *AgentOsOperator) installHarborExec() (bool, []string) {
|
|||||||
"[install harbor] - script do not support for aarch64 version of harbor installation !",
|
"[install harbor] - script do not support for aarch64 version of harbor installation !",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// installHarborExec install harbor offline
|
||||||
|
func (op *AgentOsOperator) installHarborExec() (bool, []string) {
|
||||||
|
|
||||||
|
// 抽离
|
||||||
|
checkHarborInstallExec, i := op.checkHarborInstallExec()
|
||||||
|
if !checkHarborInstallExec {
|
||||||
|
return false, i
|
||||||
|
}
|
||||||
|
|
||||||
// download offline file
|
// download offline file
|
||||||
harborOfflineFileURL := op.OssOfflinePrefix + "harbor-offline-installer-v2.9.0.tgz"
|
harborOfflineFileURL := op.OssOfflinePrefix + "harbor-offline-installer-v2.9.0.tgz"
|
||||||
log.InfoF("[install harbor] - start to download harbor offline installer from => %s !", harborOfflineFileURL)
|
log.InfoF("[install harbor] - start to download harbor offline installer from => %s !", harborOfflineFileURL)
|
||||||
|
|
||||||
BasicCreateFolder("/root/wdd/")
|
BasicCreateFolder(OctopusAgentInstallPrefix)
|
||||||
|
|
||||||
BasicRemoveFolderComplete("/root/wdd/harbor-offline-installer-v2.9.0.tgz")
|
BasicRemoveFolderComplete("/root/wdd/harbor-offline-installer-v2.9.0.tgz")
|
||||||
BasicRemoveFolderComplete("/root/wdd/harbor")
|
BasicRemoveFolderComplete("/root/wdd/harbor")
|
||||||
|
|
||||||
downloadOk, l := BasicDownloadFileByCurl(harborOfflineFileURL, "/root/wdd/harbor-offline-installer-v2.9.0.tgz")
|
log.Info("[install harbor] - start to download harbor offline installation file!")
|
||||||
|
downloadOk, l := BasicDownloadFile(harborOfflineFileURL, "", "", "", "/root/wdd/harbor-offline-installer-v2.9.0.tgz")
|
||||||
if !downloadOk {
|
if !downloadOk {
|
||||||
return false, append(l, "download harbor offline installer failed!")
|
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
|
// unzip
|
||||||
AllCompleteExecutor([][]string{
|
AllCompleteExecutor([][]string{
|
||||||
{
|
{
|
||||||
@@ -1652,7 +1756,7 @@ func (op *AgentOsOperator) installHarborExec() (bool, []string) {
|
|||||||
"-zvxf",
|
"-zvxf",
|
||||||
"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
|
"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
|
||||||
"-C",
|
"-C",
|
||||||
"/root/wdd/",
|
OctopusAgentInstallPrefix,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rm",
|
"rm",
|
||||||
@@ -1663,17 +1767,25 @@ func (op *AgentOsOperator) installHarborExec() (bool, []string) {
|
|||||||
|
|
||||||
// configuration
|
// configuration
|
||||||
log.Info("[install harbor] - start to download harbor config file!")
|
log.Info("[install harbor] - start to download harbor config file!")
|
||||||
AllCommandExecutor([]string{
|
ok, resultLog := BasicDownloadFile(op.OssOfflinePrefix+"harbor-config-template.yml", "", "", "", "/root/wdd/harbor/harbor.yml")
|
||||||
"wget",
|
if !ok {
|
||||||
"--no-check-certificate",
|
return false, resultLog
|
||||||
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 !"}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// install and config
|
||||||
|
installHarborAndConfig, i2 := op.installHarborAndConfig()
|
||||||
|
if !installHarborAndConfig {
|
||||||
|
return false, i2
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := "[install harbor] - harbor start complete !"
|
||||||
|
log.Info(msg)
|
||||||
|
|
||||||
|
return true, []string{msg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op *AgentOsOperator) installHarborAndConfig() (bool, []string) {
|
||||||
|
|
||||||
log.Info("[install harbor] - start to modify harbor config file!")
|
log.Info("[install harbor] - start to modify harbor config file!")
|
||||||
|
|
||||||
AllCommandExecutor([]string{
|
AllCommandExecutor([]string{
|
||||||
@@ -1686,7 +1798,8 @@ func (op *AgentOsOperator) installHarborExec() (bool, []string) {
|
|||||||
BasicReplace("/root/wdd/harbor/harbor.yml", "HarborHostPort", "8033")
|
BasicReplace("/root/wdd/harbor/harbor.yml", "HarborHostPort", "8033")
|
||||||
BasicReplace("/root/wdd/harbor/harbor.yml", "HarborAdminPas", "V2ryStr@ngPss")
|
BasicReplace("/root/wdd/harbor/harbor.yml", "HarborAdminPas", "V2ryStr@ngPss")
|
||||||
|
|
||||||
log.InfoF("[install harbor] - harbor config changed success to => %s!", op.AgentServerInfo.ServerIPInV4)
|
log.InfoF("[install harbor] - harbor config file changed to => %s %s %s !\n", op.AgentServerInfo.ServerIPInV4, "8033", "V2ryStr@ngPss")
|
||||||
|
|
||||||
// install
|
// install
|
||||||
log.Info("[install harbor] - going to start harbor !")
|
log.Info("[install harbor] - going to start harbor !")
|
||||||
executor := ReadTimeCommandExecutor([]string{
|
executor := ReadTimeCommandExecutor([]string{
|
||||||
@@ -1700,7 +1813,51 @@ func (op *AgentOsOperator) installHarborExec() (bool, []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := "[install harbor] - harbor start complete !"
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op *AgentOsOperator) InstallHarborBastion() (bool, []string) {
|
||||||
|
// 抽离
|
||||||
|
checkHarborInstallExec, i := op.checkHarborInstallExec()
|
||||||
|
if !checkHarborInstallExec {
|
||||||
|
return false, i
|
||||||
|
}
|
||||||
|
|
||||||
|
// local file check exists
|
||||||
|
if !BasicFileExistAndNotNull("/root/wdd/harbor-offline-installer-v2.9.0.tgz") {
|
||||||
|
return false, []string{"[InstallHarborBastion] - harbor offline installer not exists !"}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unzip
|
||||||
|
AllCompleteExecutor([][]string{
|
||||||
|
{
|
||||||
|
"tar",
|
||||||
|
"-zvxf",
|
||||||
|
"/root/wdd/harbor-offline-installer-v2.9.0.tgz",
|
||||||
|
"-C",
|
||||||
|
OctopusAgentInstallPrefix,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rm",
|
||||||
|
"-rf",
|
||||||
|
"/root/wdd/harbor/harbor.yml",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// configuration
|
||||||
|
if !BasicAppendOverwriteContentToFile(beans.HarborTemplateFile, "/root/wdd/harbor/harbor.yml") {
|
||||||
|
return false, []string{
|
||||||
|
"[InstallHarborBastion] - harbor config file append failed !",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// install and config
|
||||||
|
installHarborAndConfig, i2 := op.installHarborAndConfig()
|
||||||
|
if !installHarborAndConfig {
|
||||||
|
return false, i2
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := "[InstallHarborBastion] - harbor install SUCCESSES !"
|
||||||
log.Info(msg)
|
log.Info(msg)
|
||||||
|
|
||||||
return true, []string{msg}
|
return true, []string{msg}
|
||||||
@@ -2197,7 +2354,7 @@ func (op *AgentOsOperator) installZSH() [][]string {
|
|||||||
{
|
{
|
||||||
"mkdir",
|
"mkdir",
|
||||||
"-p",
|
"-p",
|
||||||
"/root/wdd/",
|
OctopusAgentInstallPrefix,
|
||||||
},
|
},
|
||||||
append(
|
append(
|
||||||
op.InstallCommandPrefix,
|
op.InstallCommandPrefix,
|
||||||
@@ -2331,7 +2488,7 @@ func (op *AgentOsOperator) installZSHExec() (bool, []string) {
|
|||||||
BasicRemoveFolderComplete("/root/.oh-my-zsh")
|
BasicRemoveFolderComplete("/root/.oh-my-zsh")
|
||||||
BasicRemoveFolderComplete("/root/wdd/zsh-install.sh")
|
BasicRemoveFolderComplete("/root/wdd/zsh-install.sh")
|
||||||
BasicRemoveFolderComplete("/root/wdd/oh-my-zsh-plugins-list.txt")
|
BasicRemoveFolderComplete("/root/wdd/oh-my-zsh-plugins-list.txt")
|
||||||
BasicCreateFolder("/root/wdd/")
|
BasicCreateFolder(OctopusAgentInstallPrefix)
|
||||||
|
|
||||||
ok, resultLog := AllCommandExecutor(
|
ok, resultLog := AllCommandExecutor(
|
||||||
append(op.InstallCommandPrefix, "zsh", "git"))
|
append(op.InstallCommandPrefix, "zsh", "git"))
|
||||||
@@ -2348,7 +2505,7 @@ func (op *AgentOsOperator) installZSHExec() (bool, []string) {
|
|||||||
}
|
}
|
||||||
log.InfoF("开始下载zsh的安装脚本 => %s", zshRemoteGitUrl)
|
log.InfoF("开始下载zsh的安装脚本 => %s", zshRemoteGitUrl)
|
||||||
|
|
||||||
resultOk, l := BasicDownloadFileByCurl(zshRemoteGitUrl, "/root/wdd/zsh-install.sh")
|
resultOk, l := BasicDownloadFile(zshRemoteGitUrl, "", "", "", "/root/wdd/zsh-install.sh")
|
||||||
if !resultOk {
|
if !resultOk {
|
||||||
l = append(l, "zsh-install.sh 下载失败! 安装终止")
|
l = append(l, "zsh-install.sh 下载失败! 安装终止")
|
||||||
return false, l
|
return false, l
|
||||||
|
|||||||
@@ -578,6 +578,14 @@ func BasicDownloadFile(downloadUrl string, socksProxyUrl string, proxyUser strin
|
|||||||
return false, resultLog
|
return false, resultLog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check file exists
|
||||||
|
existAndNotNull := BasicFileExistAndNotNull(desFile)
|
||||||
|
if !existAndNotNull {
|
||||||
|
return false, []string{
|
||||||
|
"[BasicDownloadFile] - file not exist download error!",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true, resultLog
|
return true, resultLog
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,6 +732,17 @@ func BasicAppendContentToFile(content string, targetFile string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BasicAppendOverwriteContentToFile 向目标文件中写入一些内容,覆盖源文件
|
||||||
|
func BasicAppendOverwriteContentToFile(content string, targetFile string) bool {
|
||||||
|
|
||||||
|
err := os.Remove(targetFile)
|
||||||
|
if err != nil {
|
||||||
|
log.WarnF("[BasicAppendOverwriteContentToFile] - Error removing file: %s , error is %s", targetFile, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return BasicAppendContentToFile(content, targetFile)
|
||||||
|
}
|
||||||
|
|
||||||
// BasicAppendNullToFile 清空一个文件
|
// BasicAppendNullToFile 清空一个文件
|
||||||
func BasicAppendNullToFile(targetFile string) bool {
|
func BasicAppendNullToFile(targetFile string) bool {
|
||||||
|
|
||||||
|
|||||||
112
agent-go/a_executor/beans/DockerDaemonConfig.go
Normal file
112
agent-go/a_executor/beans/DockerDaemonConfig.go
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
package beans
|
||||||
|
|
||||||
|
var ContainerdServiceFile = "/lib/systemd/system/containerd.service"
|
||||||
|
var DockerSocketFile = "/lib/systemd/system/docker.socket"
|
||||||
|
var DockerServiceFile = "/lib/systemd/system/docker.service"
|
||||||
|
|
||||||
|
var ContainerdDaemonService = `
|
||||||
|
# Copyright The containerd Authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=containerd container runtime
|
||||||
|
Documentation=https://containerd.io
|
||||||
|
After=network.target local-fs.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStartPre=-/sbin/modprobe overlay
|
||||||
|
ExecStart=/usr/bin/containerd
|
||||||
|
|
||||||
|
Type=notify
|
||||||
|
Delegate=yes
|
||||||
|
KillMode=process
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||||
|
# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||||
|
LimitNPROC=infinity
|
||||||
|
LimitCORE=infinity
|
||||||
|
LimitNOFILE=infinity
|
||||||
|
# Comment TasksMax if your systemd version does not supports it.
|
||||||
|
# Only systemd 226 and above support this version.
|
||||||
|
TasksMax=infinity
|
||||||
|
OOMScoreAdjust=-999
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
`
|
||||||
|
|
||||||
|
var DockerSocketDaemonService = `
|
||||||
|
[Unit]
|
||||||
|
Description=Docker Socket for the API
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=/var/run/docker.sock
|
||||||
|
SocketMode=0660
|
||||||
|
SocketUser=root
|
||||||
|
SocketGroup=docker
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
||||||
|
`
|
||||||
|
|
||||||
|
var DockerDaemonService = `
|
||||||
|
[Unit]
|
||||||
|
Description=Docker Application Container Engine
|
||||||
|
Documentation=https://docs.docker.com
|
||||||
|
After=network-online.target docker.socket firewalld.service containerd.service
|
||||||
|
Wants=network-online.target
|
||||||
|
Requires=docker.socket containerd.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
# the default is not to use systemd for cgroups because the delegate issues still
|
||||||
|
# exists and systemd currently does not support the cgroup feature set required
|
||||||
|
# for containers run by docker
|
||||||
|
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
|
||||||
|
ExecReload=/bin/kill -s HUP $MAINPID
|
||||||
|
TimeoutSec=0
|
||||||
|
RestartSec=2
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
|
||||||
|
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
|
||||||
|
# to make them work for either version of systemd.
|
||||||
|
StartLimitBurst=3
|
||||||
|
|
||||||
|
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
|
||||||
|
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
|
||||||
|
# this option work for either version of systemd.
|
||||||
|
StartLimitInterval=60s
|
||||||
|
|
||||||
|
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||||
|
# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||||
|
LimitNOFILE=infinity
|
||||||
|
LimitNPROC=infinity
|
||||||
|
LimitCORE=infinity
|
||||||
|
|
||||||
|
# Comment TasksMax if your systemd version does not support it.
|
||||||
|
# Only systemd 226 and above support this option.
|
||||||
|
TasksMax=infinity
|
||||||
|
|
||||||
|
# set delegate yes so that systemd does not reset the cgroups of docker containers
|
||||||
|
Delegate=yes
|
||||||
|
|
||||||
|
# kill only the docker process, not all processes in the cgroup
|
||||||
|
KillMode=process
|
||||||
|
OOMScoreAdjust=-500
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
`
|
||||||
53
agent-go/a_executor/beans/HarborTemplateConfig.go
Normal file
53
agent-go/a_executor/beans/HarborTemplateConfig.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package beans
|
||||||
|
|
||||||
|
var HarborTemplateFile = `
|
||||||
|
hostname: HarborHostName
|
||||||
|
|
||||||
|
http:
|
||||||
|
port: HarborHostPort
|
||||||
|
|
||||||
|
harbor_admin_password: HarborAdminPas
|
||||||
|
|
||||||
|
database:
|
||||||
|
password: HarborAdminPas
|
||||||
|
max_idle_conns: 50
|
||||||
|
max_open_conns: 1000
|
||||||
|
conn_max_lifetime: 3600
|
||||||
|
conn_max_idle_time: 3600
|
||||||
|
|
||||||
|
data_volume: /var/lib/docker/harbor-data
|
||||||
|
|
||||||
|
jobservice:
|
||||||
|
max_job_workers: 10
|
||||||
|
job_loggers:
|
||||||
|
- STD_OUTPUT
|
||||||
|
- FILE
|
||||||
|
logger_sweeper_duration: 3
|
||||||
|
|
||||||
|
notification:
|
||||||
|
webhook_job_max_retry: 10
|
||||||
|
webhook_job_http_client_timeout: 10
|
||||||
|
|
||||||
|
|
||||||
|
log:
|
||||||
|
level: warning
|
||||||
|
local:
|
||||||
|
rotate_count: 50
|
||||||
|
rotate_size: 200M
|
||||||
|
location: /var/log/harbor
|
||||||
|
|
||||||
|
cache:
|
||||||
|
enabled: false
|
||||||
|
expire_hours: 24
|
||||||
|
|
||||||
|
_version: 2.9.0
|
||||||
|
|
||||||
|
proxy:
|
||||||
|
http_proxy:
|
||||||
|
https_proxy:
|
||||||
|
no_proxy:
|
||||||
|
components:
|
||||||
|
- core
|
||||||
|
- jobservice
|
||||||
|
- trivy
|
||||||
|
`
|
||||||
@@ -32,8 +32,9 @@ var AllFunctionCache = &bastion_init.Trie{}
|
|||||||
const (
|
const (
|
||||||
InstallDocker = "docker"
|
InstallDocker = "docker"
|
||||||
InstallDockerCompose = "dockercompose"
|
InstallDockerCompose = "dockercompose"
|
||||||
|
InstallHarbor = "harbor"
|
||||||
InstallMinio = "minio"
|
InstallMinio = "minio"
|
||||||
InstallRabbitmq = "rabbitmq"
|
RemoveDocker = "removedocker"
|
||||||
Exit = "exit"
|
Exit = "exit"
|
||||||
Help = "help"
|
Help = "help"
|
||||||
)
|
)
|
||||||
@@ -102,15 +103,20 @@ func BastionModeInit() {
|
|||||||
text = strings.TrimSpace(text)
|
text = strings.TrimSpace(text)
|
||||||
inputCommand := uniformInputCommand(text)
|
inputCommand := uniformInputCommand(text)
|
||||||
fmt.Println("inputCommand: ", inputCommand)
|
fmt.Println("inputCommand: ", inputCommand)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
// execute the function
|
// execute the function
|
||||||
switch inputCommand {
|
switch inputCommand {
|
||||||
case InstallDocker:
|
case InstallDocker:
|
||||||
agentOperator.InstallDockerBastion()
|
beautifulPrintExeResult(agentOperator.InstallDockerBastion())
|
||||||
case InstallDockerCompose:
|
case InstallDockerCompose:
|
||||||
agentOperator.InstallDockerComposeBastion()
|
agentOperator.InstallDockerComposeBastion()
|
||||||
case InstallMinio:
|
case InstallMinio:
|
||||||
agentOperator.InstallMinioBastion()
|
agentOperator.InstallMinioBastion()
|
||||||
|
case InstallHarbor:
|
||||||
|
a_executor.InstallHarborBastion()
|
||||||
|
case RemoveDocker:
|
||||||
|
beautifulPrintExeResult(agentOperator.RemoveDockerBastion())
|
||||||
case Exit:
|
case Exit:
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
case Help:
|
case Help:
|
||||||
@@ -122,6 +128,19 @@ func BastionModeInit() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func beautifulPrintExeResult(resultOk bool, result []string) {
|
||||||
|
fmt.Println()
|
||||||
|
if resultOk {
|
||||||
|
fmt.Println("execute SUCCESS")
|
||||||
|
} else {
|
||||||
|
fmt.Println("execute FAIL")
|
||||||
|
}
|
||||||
|
for _, s := range result {
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
func buildBastionModeFunction() {
|
func buildBastionModeFunction() {
|
||||||
// build the tree search node
|
// build the tree search node
|
||||||
log.Info("build the tree search node")
|
log.Info("build the tree search node")
|
||||||
@@ -130,7 +149,8 @@ func buildBastionModeFunction() {
|
|||||||
tcc.Insert(InstallDocker)
|
tcc.Insert(InstallDocker)
|
||||||
tcc.Insert(InstallDockerCompose)
|
tcc.Insert(InstallDockerCompose)
|
||||||
tcc.Insert(InstallMinio)
|
tcc.Insert(InstallMinio)
|
||||||
tcc.Insert(InstallRabbitmq)
|
tcc.Insert(InstallHarbor)
|
||||||
|
tcc.Insert(RemoveDocker)
|
||||||
tcc.Insert(Help)
|
tcc.Insert(Help)
|
||||||
tcc.Insert(Exit)
|
tcc.Insert(Exit)
|
||||||
|
|
||||||
|
|||||||
98
agent-go/a_init/bastion_init/DPSearch.go
Normal file
98
agent-go/a_init/bastion_init/DPSearch.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package bastion_init
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WordC struct {
|
||||||
|
Word string
|
||||||
|
Rank int
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalize(s string) string {
|
||||||
|
// Convert to lowercase and replace hyphens with underscores for consistent comparison.
|
||||||
|
return strings.Map(func(r rune) rune {
|
||||||
|
if 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return '_'
|
||||||
|
}, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func levDpDist(s1, s2 string) int {
|
||||||
|
m, n := len(s1), len(s2)
|
||||||
|
if m == 0 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
dp := make([][]int, m+1)
|
||||||
|
for i := range dp {
|
||||||
|
dp[i] = make([]int, n+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i <= m; i++ {
|
||||||
|
for j := 1; j <= n; j++ {
|
||||||
|
cost := 0
|
||||||
|
if s1[i-1] != s2[j-1] {
|
||||||
|
cost = 1
|
||||||
|
}
|
||||||
|
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + cost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[m][n]
|
||||||
|
}
|
||||||
|
|
||||||
|
func min(a, b, c int) int {
|
||||||
|
minVal := a
|
||||||
|
if b < minVal {
|
||||||
|
minVal = b
|
||||||
|
}
|
||||||
|
if c < minVal {
|
||||||
|
minVal = c
|
||||||
|
}
|
||||||
|
return minVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindClosestWordDp(words []string, prefix string) (string, error) {
|
||||||
|
normalizedPrefix := normalize(prefix)
|
||||||
|
normalizedWords := make([]string, len(words))
|
||||||
|
for i, word := range words {
|
||||||
|
normalizedWords[i] = normalize(word)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(normalizedWords, func(i, j int) bool {
|
||||||
|
return normalizedWords[i] < normalizedWords[j]
|
||||||
|
})
|
||||||
|
|
||||||
|
minDistance := levDpDist(normalizedPrefix, normalizedWords[0])
|
||||||
|
closestWord := normalizedWords[0]
|
||||||
|
|
||||||
|
for _, word := range normalizedWords {
|
||||||
|
distance := levDpDist(normalizedPrefix, word)
|
||||||
|
if distance < minDistance {
|
||||||
|
minDistance = distance
|
||||||
|
closestWord = word
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace underscores with hyphens and convert back to original case.
|
||||||
|
closestWord = strings.ReplaceAll(strings.ReplaceAll(strings.ToUpper(closestWord), "_", "-"), "\"", "")
|
||||||
|
return closestWord, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
words := []string{"Apple", "Apricot", "Apprentice", "Application"}
|
||||||
|
prefix := "AP"
|
||||||
|
|
||||||
|
closest, err := FindClosestWordDp(words, prefix)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("The closest word to '%s' is '%s'\n", prefix, closest)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,3 +19,15 @@ func TestNewTrie(t *testing.T) {
|
|||||||
fmt.Printf("The closest word to '%s' is '%s'\n", prefix, closest)
|
fmt.Printf("The closest word to '%s' is '%s'\n", prefix, closest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDp(t *testing.T) {
|
||||||
|
words := []string{"Apple", "Apricot", "Apprentice", "Application", "Docker-Compose", "Docker-Compose-File", "Docker-Compose-File-V2", "Docker-Compose-File-V3", "Docker-Compose-File-V4", "Docker-Compose-File-V5", "Docker-Compose-File-V6", "Docker-Co", "Install-Docker"}
|
||||||
|
prefix := "Install"
|
||||||
|
|
||||||
|
closest, err := FindClosestWordDp(words, prefix)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("The closest word to '%s' is '%s'\n", prefix, closest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
2024-03-20-11-53-54 uavcloud-test cmii-uav-platform 5.4.0-staging 5.4.0-032001
|
|
||||||
2024-03-20-11-55-04 uavcloud-test cmii-uav-device 5.5.0-integration 5.4.0-032001
|
|
||||||
2024-03-20-11-56-42 uavcloud-test cmii-uav-surveillance 5.4.0-staging 5.4.0-032001
|
|
||||||
2024-03-20-11-57-50 uavcloud-test cmii-uav-mission 5.4.0-staging 5.4.0-032001
|
|
||||||
2024-03-20-13-47-06 uavcloud-demo cmii-uav-platform 5.4.0-031901 5.4.0-25263-ai-032001
|
|
||||||
2024-03-20-14-18-39 uavcloud-test cmii-uav-platform 5.4.0-032001 5.4.0-032002
|
|
||||||
2024-03-20-17-20-29 uavcloud-demo cmii-uav-industrial-portfolio 5.4.0-27348-032001 5.4.0-26714-032001
|
|
||||||
2024-03-20-17-35-34 uavcloud-demo cmii-uav-platform 5.4.0-25263-ai-032001 5.4.0-26807-25263-emerg-ai-0320
|
|
||||||
2024-03-20-17-46-10 uavcloud-demo cmii-uav-platform 5.4.0-26807-25263-emerg-ai-03205.4.0-26807-25263-emerg-ai-032002
|
|
||||||
2024-03-21-10-00-49 uavcloud-demo cmii-uav-industrial-portfolio 5.4.0-27348-032001 5.4.0-27348-032101
|
|
||||||
2024-03-21-14-32-38 uavcloud-demo cmii-uav-device 5.4.0-25916 5.4.0-0321
|
|
||||||
2024-03-21-14-36-48 uavcloud-demo cmii-uav-alarm 5.4.0 5.4.0-0321
|
|
||||||
2024-03-21-17-47-31 uavcloud-demo cmii-uav-industrial-portfolio 5.4.0-27348-032101 5.4.0-27348-0321
|
|
||||||
2024-03-22-09-17-06 uavcloud-demo cmii-uav-industrial-portfolio 5.4.0-27348-0321 5.4.0-032201
|
|
||||||
2024-03-22-14-02-05 uavcloud-demo cmii-uav-platform 5.4.0-25263-032011 5.4.0-25263-emerg-ai-032201
|
|
||||||
2024-03-22-17-14-43 uavcloud-demo cmii-uav-platform-armypeople 5.4.0 5.4.0-26860-032201
|
|
||||||
2024-03-22-17-17-15 uavcloud-demo cmii-uav-process 5.4.0 5.4.0-032201
|
|
||||||
2024-03-26-16-27-58 uavcloud-demo cmii-uav-multilink 5.4.0 5.4.0-032602
|
|
||||||
2024-03-26-17-11-29 uavcloud-test cmii-uav-platform 5.4.0-032002 5.4.0-032601
|
|
||||||
2024-03-29-20-00-00 uavcloud-demo cmii-uav-waypoint 5.4.0-26768 5.4.0-032901
|
|
||||||
2024-03-29-20-01-31 uavcloud-demo cmii-uav-mqtthandler 5.4.0-25916-032001 5.4.0-032901
|
|
||||||
2024-03-29-20-02-58 uavcloud-demo cmii-uav-airspace 5.4.0-0319 5.4.0-032501
|
|
||||||
2024-03-29-20-04-44 uavcloud-demo cmii-uav-platform-armypeople 5.4.0-032704 5.4.0-032901
|
|
||||||
2024-03-29-20-04-48 uavcloud-demo cmii-uav-platform-open 5.4.0 5.4.0-032901
|
|
||||||
2024-03-29-20-04-52 uavcloud-demo cmii-admin-data 5.4.0 5.4.0-032901
|
|
||||||
2024-03-29-20-06-26 uavcloud-demo cmii-uav-industrial-portfolio 5.4.0-27348-032401 5.4.0-032901
|
|
||||||
2024-03-29-20-09-25 uavcloud-demo cmii-uav-alarm 5.4.0-0321 5.4.0-032501
|
|
||||||
2024-03-29-20-10-45 uavcloud-demo cmii-uav-device 5.4.0-0321 5.4.0-032501
|
|
||||||
2024-03-29-20-12-18 uavcloud-demo cmii-suav-supervision 5.2.0 5.4.0-032501
|
|
||||||
2024-04-08-14-28-00 uavcloud-devflightcmii-uav-industrial-portfolio 5.5.0-snapshot 5.4.0-040801
|
|
||||||
2024-04-08-15-02-00 uavcloud-devflightcmii-uav-industrial-portfolio 5.4.0-040801 5.4.0-040802
|
|
||||||
2024-04-08-17-30-00 uavcloud-devflightcmii-uav-industrial-portfolio 5.4.0-040802 5.4.0-040803
|
|
||||||
2024-04-10-16-12-00 uavcloud-devflightcmii-uav-industrial-portfolio 5.5.0-snapshot 5.4.0-041001
|
|
||||||
2024-04-12-17-30-30 uavcloud-devflightcmii-uav-threedsimulation 5.2.0-snapshot 5.4.0-041201
|
|
||||||
2024-04-14-11-34-00 uavcloud-demo cmii-uav-surveillance 5.4.0-28028-0409 5.4.0-28028-041401
|
|
||||||
2024-04-15-10-37-51 uavcloud-demo cmii-uav-platform-media 5.4.0 5.4.0-041401
|
|
||||||
2024-04-15-17-35-00 uavcloud-demo cmii-uav-airspace 5.4.0-0402 5.4.0-041501
|
|
||||||
2024-04-15-17-41-00 uavcloud-demo cmii-uav-platform 5.4.0-25263-041102 5.4.0-041501
|
|
||||||
2024-04-16-10-24-00 uavcloud-demo cmii-uav-multilink 5.4.0-032701 5.4.0-041601
|
|
||||||
2024-04-16-16-24-00 uavcloud-demo cmii-uav-airspace 5.4.0-041501 5.4.0-041601
|
|
||||||
2024-04-16-16-25-20 uavcloud-demo cmii-admin-data 5.4.0-0403 5.4.0-041601
|
|
||||||
2024-04-16-16-25-35 uavcloud-demo cmii-uav-platform-oms 5.4.0 5.4.0-041601
|
|
||||||
2024-04-16-17-38-00 uavcloud-demo cmii-uav-platform-armypeople 5.4.0-041201 5.4.0-28028-041601
|
|
||||||
2024-04-16-17-57-00 uavcloud-demo cmii-uav-platform-media 5.4.0-041401 5.4.0
|
|
||||||
Reference in New Issue
Block a user