package cluster import ( "_/E_/git/aps_deploy/src/util" "bytes" "encoding/json" "fmt" "log" "net/http" "os" "strings" "../util" ) type Cluster struct { ID string `json:"id"` Name string `json:"name"` } type ClustersResponse struct { Data []Cluster `json:"data"` } type RegistrationTokenResponse struct { Command string `json:"command"` } type NodeCommandResponse struct { NodeCommand string `json:"nodeCommand"` } func CreateRegistrationToken(serverURL, bearerToken, clusterID string) (string, error) { url := fmt.Sprintf("%s/v3/clusterregistrationtokens", serverURL) payload := strings.NewReader(fmt.Sprintf(`{ "clusterId": "%s" }`, clusterID)) req, err := http.NewRequest("POST", url, payload) if err != nil { return "", fmt.Errorf("failed to create registration token request: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", bearerToken)) req.Header.Set("Content-Type", "application/json") client := util.CreateHTTPClient() resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("failed to create registration token: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated { return "", fmt.Errorf("failed to create registration token: unexpected status code %d", resp.StatusCode) } var tokenResp RegistrationTokenResponse err = json.NewDecoder(resp.Body).Decode(&tokenResp) if err != nil { return "", fmt.Errorf("failed to decode registration token response: %v", err) } return tokenResp.Command, nil } func GetNodeCommand(serverURL, bearerToken, clusterID string) (string, error) { url := fmt.Sprintf("%s/v3/clusterregistrationtokens", serverURL) payload := map[string]interface{}{ "clusterId": clusterID, } payloadBytes, err := json.Marshal(payload) if err != nil { return "", fmt.Errorf("failed to marshal payload: %v", err) } req, err := http.NewRequest("POST", url, bytes.NewReader(payloadBytes)) if err != nil { return "", fmt.Errorf("failed to create node command request: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", bearerToken)) req.Header.Set("Content-Type", "application/json") client := util.CreateHTTPClient() resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("failed to get node command: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated { return "", fmt.Errorf("failed to get node command: unexpected status code %d", resp.StatusCode) } var nodeCommandResponse NodeCommandResponse err = json.NewDecoder(resp.Body).Decode(&nodeCommandResponse) if err != nil { return "", fmt.Errorf("failed to decode node command response: %v", err) } return nodeCommandResponse.NodeCommand, nil } func GetClusterID(serverURL, bearerToken, clusterName string) (string, error) { url := fmt.Sprintf("%s/v3/clusters", serverURL) req, err := http.NewRequest("GET", url, nil) if err != nil { return "", fmt.Errorf("failed to create cluster list request: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", bearerToken)) client := util.CreateHTTPClient() resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("failed to get cluster list: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("failed to get cluster list: unexpected status code %d", resp.StatusCode) } // Parse the API response var clustersResponse ClustersResponse err = json.NewDecoder(resp.Body).Decode(&clustersResponse) if err != nil { return "", fmt.Errorf("failed to decode cluster list response: %v", err) } // Print cluster names for _, cluster := range clustersResponse.Data { if cluster.Name == clusterName { fmt.Printf("Cluster ID: %s, Name: %s\n", cluster.ID, cluster.Name) return cluster.ID, nil } } return "", fmt.Errorf("cluster '%s' not found", clusterName) } type Node struct { ClusterName string `json:"clusterName"` Roles []string `json:"roles"` IP string `json:"ip"` SSHUsername string `json:"sshUsername"` SSHPassword string `json:"sshPassword"` SSHPort int `json:"sshPort"` } type RancherConfig struct { RancherURL string `json:"rancherURL"` BearerToken string `json:"bearerToken"` } type ClusterCreateRequest struct { Name string `json:"name"` Driver string `json:"driver"` ControlPlaneProvider string `json:"controlPlaneProvider"` WorkerNodeProvider string `json:"workerNodeProvider"` RancherKubernetesEngineConfig interface{} `json:"rancherKubernetesEngineConfig"` // Add other cluster properties as needed } type ClusterCreateResponse struct { ID string `json:"id"` Name string `json:"name"` // Add other response fields as needed } func createClusterData(clusterName string) []byte { requestBody := ClusterCreateRequest{ Name: clusterName, Driver: "custom", ControlPlaneProvider: "external", WorkerNodeProvider: "external", RancherKubernetesEngineConfig: map[string]interface{}{ "ignoreDockerVersion": true, "kubernetesVersion": "v1.20.15-rancher2-1", // Add other RKE config properties as needed }, // Add other cluster properties as needed } requestBodyBytes, err := json.Marshal(requestBody) if err != nil { log.Fatalf("Failed to marshal request body: %v", err) } return requestBodyBytes } // Deploy Kubernetes roles on a node using SSH func Deployk8sRolesOnNode(nodeIP, sshUsername, sshPassword, remoteSSHCommand string, sshPort int, roles []string) error { rancherAgentInstalled, err := isRancherAgentInstalled(nodeIP, sshUsername, sshPassword, sshPort) if err == nil { return nil } if !rancherAgentInstalled { // Add role parameters to nodeCommand for _, role := range roles { switch role { case "etcd": remoteSSHCommand += " --etcd" case "controlplane": remoteSSHCommand += " --controlplane" case "worker": remoteSSHCommand += " --worker" default: log.Fatalf("invalid role specified : %s", role) } } _, err := sshExec(nodeIP, sshUsername, sshPassword, remoteSSHCommand, sshPort) if err != nil { return fmt.Errorf("failed to deploy Kubernetes roles on the remote server: %v", err) } return nil } } func IsRancherInstalled(ip, username, password string, sshPort int) (bool, error) { // 检查Rancher容器是否已运行 checkRancherCommand := "sudo docker ps --format '{{.Image}}' | grep -q rancher/rancher:v2.5.17" _, err := sshExec(ip, username, password, checkRancherCommand, sshPort) if err != nil { // 如果执行命令出错,则说明Rancher未安装或发生其他错误 return false, fmt.Errorf("failed to check Rancher installation: %v", err) } return true, nil } func IsRancherAgentInstalled(ip, username, password string, sshPort int) (bool, error) { // 检查Rancher容器是否已运行 checkRancherCommand := "sudo docker ps --format '{{.Image}}' | grep -q rancher/rancher-agent:v2.5." _, err := sshExec(ip, username, password, checkRancherCommand, sshPort) if err != nil { // 如果执行命令出错,则说明Rancher未安装或发生其他错误 return false, fmt.Errorf("failed to check Rancher installation: %v", err) } return true, nil } func CreateCluster(rancherConfig RancherConfig, clusterName string) error { requestBody := createClusterData(clusterName) url := fmt.Sprintf("%s/v3/clusters", rancherConfig.RancherURL) req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody)) if err != nil { return fmt.Errorf("Failed to create HTTP request: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", rancherConfig.BearerToken)) req.Header.Set("Content-Type", "application/json") client := util.CreateHTTPClient() resp, err := client.Do(req) if err != nil { return fmt.Errorf("Failed to send HTTP request: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated { return fmt.Errorf("Failed to create cluster, status code: %d", resp.StatusCode) } var responseBody ClusterCreateResponse err = json.NewDecoder(resp.Body).Decode(&responseBody) if err != nil { return fmt.Errorf("Failed to decode response body: %v", err) } fmt.Printf("Cluster created: ID=%s, Name=%s\n", responseBody.ID, responseBody.Name) return nil } func main() { clusterName := "kubernetus" nodes := []Node{ { ClusterName: clusterName, Roles: []string{"etcd", "controlplane", "worker"}, IP: "192.168.20.189", SSHUsername: "basic", SSHPassword: "123", SSHPort: 22, }, { ClusterName: clusterName, Roles: []string{"worker"}, IP: "192.168.20.10", SSHUsername: "basic", SSHPassword: "123", SSHPort: 22, }, { ClusterName: clusterName, Roles: []string{"worker"}, IP: "192.168.20.115", SSHUsername: "basic", SSHPassword: "alien123", SSHPort: 22, }, // Add more nodes here if needed } // Create the cluster // Rancher configuration /*rancherConfig := RancherConfig{ RancherURL: "https://192.168.20.119:8443", BearerToken: "token-nnrsc:w68zdt8s47fnpjd5xqdl5hhzpz4j2d56kt5nx49nsswcbpdzc28kh5", }*/ rancherConfig := RancherConfig{ RancherURL: "https://192.168.20.189:8443", BearerToken: "token-t4cdf:h7zhmbvbzdvd9mmjw8zmt8rh4m7rl5gtqpqljlhl9tlr2z26j9lf4l", } // Deploy clusterId clusterID, err := GetClusterID(rancherConfig.RancherURL, rancherConfig.BearerToken, clusterName) if err != nil { log.Fatal(err) err = CreateCluster(rancherConfig, clusterName) if err != nil { log.Fatalf("Failed to create cluster: %v", err) } fmt.Printf("Cluster created: %s\n", clusterName) clusterID, err = GetClusterID(rancherConfig.RancherURL, rancherConfig.BearerToken, clusterName) if err != nil { log.Fatal(err) } } fmt.Println(clusterID) // Deploy nodeCommand nodeCommand, err := GetNodeCommand(rancherConfig.RancherURL, rancherConfig.BearerToken, clusterID) if err != nil { log.Fatal(err) } fmt.Println(nodeCommand) for _, node := range nodes { //Deploy Docker on each node err = util.InstallDocker(node.IP, node.SSHUsername, node.SSHPassword, node.SSHPort) if err != nil { log.Fatal(err) } // Deploy Kubectl on each node err = util.InstallKubectl(node.IP, node.SSHUsername, node.SSHPassword, node.SSHPort) if err != nil { log.Fatal(err) } // Deploy Kubernetes roles on each node err = Deployk8sRolesOnNode(node.IP, node.SSHUsername, node.SSHPassword, nodeCommand, node.SSHPort, node.Roles) if err != nil { log.Fatal(err) } } os.Exit(0) }