package cluster import ( "bytes" "encoding/json" "fmt" "io/ioutil" "log" "net/http" "os" "path/filepath" "strings" "basic.com/aps/aps_deploy.git/src/rancher" "basic.com/aps/aps_deploy.git/src/util" ) type Cluster struct { ID string `json:"id"` Name string `json:"name"` } type ClustersResponse struct { Data []Cluster `json:"data"` } type KubectlConfigResponse struct { BaseType string `json:"baseType"` Config string `json:"config"` Type string `json:"type"` } 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 get 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) } func GetClusters(serverURL, bearerToken string) ([]string, error) { url := fmt.Sprintf("%s/v3/clusters", serverURL) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, fmt.Errorf("failed to get 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 nil, fmt.Errorf("failed to get cluster list: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return nil, 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) log.Println("3333333333333333333333333") log.Printf("%v", resp.Body) if err != nil { return nil, fmt.Errorf("failed to decode cluster list response: %v", err) } var clusters = make([]string, 0) // Print cluster names for _, cluster := range clustersResponse.Data { clusters = append(clusters, cluster.ID) fmt.Printf("Cluster ID: %s, Name: %s\n", cluster.ID, cluster.Name) } return clusters, nil } func GetKubectlConfig(serverURL, bearerToken, clusterName string) (string, error) { url := fmt.Sprintf("%s/v3/clusters/%s?action=generateKubeconfig", serverURL, clusterName) req, err := http.NewRequest("POST", url, nil) if err != nil { return "", fmt.Errorf("failed to get cluster list request: %v", err) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", bearerToken)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "application/json") 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 kubectlConfig KubectlConfigResponse err = json.NewDecoder(resp.Body).Decode(&kubectlConfig) if err != nil { return "", fmt.Errorf("failed to decode cluster list response: %v", err) } // 保存 kubeconfig 到文件 homeDir, err := os.UserHomeDir() if err != nil { log.Fatalf("Failed to get home directory: %v", err) } kubeconfigDir := filepath.Join(homeDir, ".kube", clusterName) err = os.MkdirAll(kubeconfigDir, 0700) if err != nil { log.Fatalf("Failed to create .kube directory: %v", err) } kubeconfigPath := filepath.Join(kubeconfigDir, "config") err = ioutil.WriteFile(kubeconfigPath, []byte(kubectlConfig.Config), 0600) if err != nil { log.Fatalf("Failed to save kubeconfig: %v", err) } return kubectlConfig.Config, nil } 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 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 := util.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 := util.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 := util.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(rancherClusterConfig rancher.RancherClusterConfig, clusterName string) (string, error) { requestBody := createClusterData(clusterName) fmt.Println(rancherClusterConfig.RancherURL) url := fmt.Sprintf("%s/v3/clusters", rancherClusterConfig.RancherURL) fmt.Println("url: ", url) fmt.Println("body: ", requestBody) 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", rancherClusterConfig.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 { fmt.Println("1111111111111111111111111111 ", resp) 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 responseBody.ID, nil }