fix
wangpengfei
2023-06-20 77365bf2308a64c6800881ad5b3471d79b7112b8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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
}