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
|
}
|