package util
|
|
import (
|
"context"
|
"crypto/tls"
|
"fmt"
|
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/tools/clientcmd"
|
"net/http"
|
"os"
|
"time"
|
|
"golang.org/x/crypto/ssh"
|
)
|
|
// homeDir 获取当前用户的家目录路径
|
func HomeDir() string {
|
if h := os.Getenv("HOME"); h != "" {
|
return h
|
}
|
return os.Getenv("USERPROFILE") // Windows 环境下获取用户目录
|
}
|
|
func SSHExec(nodeIP, sshUsername, sshPassword, remoteSSHCommand string, sshPort int) (string, error) {
|
// SSH 连接配置
|
config := &ssh.ClientConfig{
|
User: sshUsername,
|
Auth: []ssh.AuthMethod{
|
ssh.Password(sshPassword),
|
},
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
}
|
|
// 连接到远程服务器
|
client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", nodeIP, sshPort), config)
|
if err != nil {
|
return "", fmt.Errorf("failed to connect to node %s: %v", nodeIP, err)
|
}
|
defer client.Close()
|
|
// 创建会话
|
session, err := client.NewSession()
|
if err != nil {
|
return "", fmt.Errorf("failed to create SSH session: %v", err)
|
}
|
defer session.Close()
|
|
// 创建一个具有超时的上下文
|
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second)
|
defer cancel()
|
|
// 通过会话执行远程命令
|
outputChan := make(chan string)
|
errorChan := make(chan error)
|
go func() {
|
// 创建一个连接标准输入的管道
|
stdinPipe, err := session.StdinPipe()
|
if err != nil {
|
errorChan <- fmt.Errorf("failed to create stdin pipe: %v", err)
|
return
|
}
|
|
// 启动会话
|
if err := session.Start(fmt.Sprintf("sudo -SE %s", remoteSSHCommand)); err != nil {
|
errorChan <- fmt.Errorf("failed to start command: %v err:%v", remoteSSHCommand, err)
|
return
|
}
|
|
// 将密码写入标准输入管道
|
_, err = fmt.Fprintf(stdinPipe, "%s\n", sshPassword)
|
if err != nil {
|
errorChan <- fmt.Errorf("failed to write password to stdin: %v", err)
|
return
|
}
|
|
// 等待会话结束
|
if err := session.Wait(); err != nil {
|
errorChan <- fmt.Errorf("command execution failed: %v err:%v", remoteSSHCommand, err)
|
return
|
}
|
|
outputChan <- ""
|
}()
|
|
// 等待结果或超时
|
select {
|
case <-ctx.Done():
|
// 关闭会话以终止远程命令
|
session.Close()
|
// 等待会话关闭的 goroutine 结束
|
<-outputChan
|
return "", fmt.Errorf("SSH command execution timed out")
|
case err := <-errorChan:
|
return "", err
|
case <-outputChan:
|
fmt.Printf("Command: %v executed on the remote server: %s\n", remoteSSHCommand, nodeIP)
|
return "", nil
|
}
|
}
|
|
// 安装Docker
|
func InstallDocker(nodeIP, sshUsername, sshPassword string, sshPort int) error {
|
// 检查Docker是否已安装
|
checkCommand := "which docker"
|
_, err := SSHExec(nodeIP, sshUsername, sshPassword, checkCommand, sshPort)
|
if err == nil {
|
fmt.Println("Docker is already installed on the remote server.")
|
return nil
|
}
|
|
// 安装Docker
|
installCommand := "sudo curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh && sudo systemctl start docker && sudo systemctl enable docker"
|
_, err = SSHExec(nodeIP, sshUsername, sshPassword, installCommand, sshPort)
|
if err != nil {
|
return fmt.Errorf("failed to install Docker on the remote server:%v %v", nodeIP, err)
|
}
|
|
fmt.Println("Docker has been installed on the remote server.")
|
return nil
|
}
|
|
// Create an HTTP client with insecure TLS configuration
|
func CreateHTTPClient() *http.Client {
|
transport := &http.Transport{
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
}
|
return &http.Client{Transport: transport}
|
}
|
|
// 安装kubectl
|
func InstallKubectl(nodeIP, sshUsername, sshPassword string, sshPort int) error {
|
// 检查kubectl是否已安装
|
checkCommand := "which kubectl"
|
_, err := SSHExec(nodeIP, sshUsername, sshPassword, checkCommand, sshPort)
|
if err == nil {
|
fmt.Println("kubectl is already installed on the remote server.")
|
return nil
|
}
|
|
// 安装kubectl
|
installCommand := "sudo curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && sudo chmod +x kubectl && sudo mv kubectl /usr/local/bin/"
|
_, err = SSHExec(nodeIP, sshUsername, sshPassword, installCommand, sshPort)
|
if err != nil {
|
return fmt.Errorf("failed to install kubectl on the remote server: %v", err)
|
}
|
|
fmt.Println("kubectl has been installed on the remote server.")
|
return nil
|
}
|
|
var kubeConfig string
|
|
func GetClient(cluster string) (*kubernetes.Clientset, error) {
|
// 配置 Kubernetes 集群的 kubeconfig 路径
|
//if kubeConfig == nil {
|
// kubeConfig = flag.String("kubeconfig", filepath.Join(HomeDir(), ".kube", cluster, "config"), "kubeconfig file")
|
// flag.Parse()
|
//}
|
|
kubeConfig = fmt.Sprintf("%s/.kube/%s/config", HomeDir(), cluster)
|
|
// 创建 Kubernetes 客户端
|
config, err := clientcmd.BuildConfigFromFlags("", kubeConfig)
|
if err != nil {
|
panic(err.Error())
|
}
|
|
clientset, err := kubernetes.NewForConfig(config)
|
if err != nil {
|
panic(err.Error())
|
}
|
|
return clientset, nil
|
}
|