JCC-CSScheduler/common/pkgs/mq/executor/sugoncloud.go

403 lines
9.7 KiB
Go

package executor
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler"
"gitlink.org.cn/cloudream/common/utils/http2"
"gitlink.org.cn/cloudream/common/utils/serder"
)
type sugonHeader struct {
Token string `json:"token"`
}
func (c *HttpClient) CreateSugonInstance(token string, config map[string]interface{}) (string, error) {
targetURL, err := url.JoinPath(c.baseURL + "/ai/openapi/v2/instance-service/task")
if err != nil {
return "", err
}
header := sugonHeader{
Token: token,
}
body, err := json.Marshal(config)
resp, err := http2.PostJSON(targetURL, http2.RequestParam{
Body: body,
Header: header,
})
if err != nil {
return "", err
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading response body: %w", err)
}
contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, http2.ContentTypeJSON) {
var codeResp response[any]
if err := serder.JSONToObject(bodyBytes, &codeResp); err != nil {
return "", fmt.Errorf("parsing response: %w", err)
}
if codeResp.Code == "0" {
return codeResp.Data.(string), nil
}
return "", codeResp.ToError()
}
return "", fmt.Errorf("unknow response content type: %s", contType)
}
type GetInstanceIDReq struct {
InstanceServiceName string `json:"instanceServiceName"`
TaskType string `json:"taskType"`
Start int `json:"start"`
Limit int `json:"limit"`
Status string `json:"status"`
Sort string `json:"sort"`
}
type instanceService struct {
ID string `json:"id"`
Status string `json:"status"`
}
type GetInstanceIDResp struct {
Code string `json:"code"`
Msg string `json:"msg"`
Data []instanceService `json:"data"`
}
func (c *HttpClient) GetInstanceID(token string, instanceName string) (string, string, error) {
targetURL, err := url.JoinPath(c.baseURL + "/ai/openapi/v2/instance-service/task")
if err != nil {
return "", "", err
}
header := sugonHeader{
Token: token,
}
req := GetInstanceIDReq{
InstanceServiceName: instanceName,
//TaskType: "ssh",
Start: 0,
Limit: 20,
Sort: "desc",
}
resp, err := http2.GetJSON(targetURL, http2.RequestParam{
Body: req,
Header: header,
})
if err != nil {
return "", "", err
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", "", fmt.Errorf("reading response body: %w", err)
}
contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, http2.ContentTypeJSON) {
var codeResp GetInstanceIDResp
if err := serder.JSONToObject(bodyBytes, &codeResp); err != nil {
return "", "", fmt.Errorf("parsing response: %w", err)
}
if codeResp.Code != "0" {
return "", "", err
}
if len(codeResp.Data) > 0 {
return codeResp.Data[0].ID, codeResp.Data[0].Status, nil
}
return "", "", err
}
return "", "", fmt.Errorf("unknow response content type: %s", contType)
}
type GetInstanceUrlResp struct {
ContainerPortInfoList []containerPortInfoList `json:"containerPortInfoList"`
}
type containerPortInfoList struct {
AccessUrl string `json:"accessUrl"`
}
func (c *HttpClient) GetInstanceUrl(token string, instanceID string) (string, error) {
path := "/ai/openapi/v2/instance-service/" + instanceID + "/detail"
targetURL, err := url.JoinPath(c.baseURL + path)
if err != nil {
return "", err
}
header := sugonHeader{
Token: token,
}
resp, err := http2.GetJSON(targetURL, http2.RequestParam{
Header: header,
})
if err != nil {
return "", err
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading response body: %w", err)
}
contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, http2.ContentTypeJSON) {
var codeResp response[GetInstanceUrlResp]
if err := serder.JSONToObject(bodyBytes, &codeResp); err != nil {
return "", fmt.Errorf("parsing response: %w", err)
}
if codeResp.Code != "0" {
return "", codeResp.ToError()
}
if len(codeResp.Data.ContainerPortInfoList) > 0 {
return codeResp.Data.ContainerPortInfoList[0].AccessUrl, nil
}
return "", codeResp.ToError()
}
return "", fmt.Errorf("unknow response content type: %s", contType)
}
func (c *HttpClient) OperateSugonInstance(token string, instanceID string, operate string) (string, error) {
var resp *http.Response
header := sugonHeader{
Token: token,
}
switch operate {
case schsdk.RunECS:
path := "/ai/openapi/v2/instance-service/task/actions/restart" + "?instanceServiceId=" + instanceID
targetURL, err := url.JoinPath(c.baseURL + path)
if err != nil {
return "", err
}
resp, err = http2.PostJSON(targetURL, http2.RequestParam{
Header: header,
})
if err != nil {
return "", err
}
case schsdk.PauseECS:
path := "/ai/openapi/v2/instance-service/task/actions/stop" + "?ids=" + instanceID
targetURL, err := url.JoinPath(c.baseURL + path)
if err != nil {
return "", err
}
resp, err = http2.PostJSON(targetURL, http2.RequestParam{
Header: header,
})
if err != nil {
return "", err
}
case schsdk.DestroyECS:
path := "/ai/openapi/v2/instance-service/task" + "?ids=" + instanceID
targetURL, err := url.JoinPath(c.baseURL + path)
if err != nil {
return "", err
}
resp, err = http2.DeleteJSON(targetURL, http2.RequestParam{
Header: header,
})
if err != nil {
return "", err
}
default:
return "", fmt.Errorf("unknow operate")
}
contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, http2.ContentTypeJSON) {
var codeResp response[any]
if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
return "", fmt.Errorf("parsing response: %w", err)
}
if codeResp.Code == "0" {
return codeResp.Code, nil
}
return "", codeResp.ToError()
}
return "", fmt.Errorf("unknow response content type: %s", contType)
}
type runCommandReq struct {
ID string `json:"id"`
StartScriptActionScope string `json:"startScriptActionScope"`
StartScriptContent string `json:"startScriptContent"`
}
func (c *HttpClient) RunCommand(token string, instanceID string, content string) (string, error) {
targetURL, err := url.JoinPath(c.baseURL + "/ai/openapi/v2/instance-service/task/actions/execute-script")
if err != nil {
return "", err
}
header := sugonHeader{
Token: token,
}
req := runCommandReq{
ID: instanceID,
StartScriptActionScope: "header",
StartScriptContent: content,
}
resp, err := http2.PostJSON(targetURL, http2.RequestParam{
Header: header,
Body: req,
})
if err != nil {
return "", err
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading response body: %w", err)
}
//logger.Info("run command result: " + string(bodyBytes))
contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, http2.ContentTypeJSON) {
var codeResp response[any]
if err := serder.JSONToObject(bodyBytes, &codeResp); err != nil {
return "", fmt.Errorf("parsing response: %w", err)
}
if codeResp.Code == "0" {
return codeResp.Code, nil
}
return "", codeResp.ToError()
}
return "", fmt.Errorf("unknow response content type: %s", contType)
}
type previewFileReq struct {
Path string `json:"path"`
Force string `json:"force"`
StartIndex int `json:"startIndex"`
}
type previewFileResp struct {
Content string `json:"content"`
}
func (c *HttpClient) PreviewFile(token string, path string) (string, error) {
// 查询文件绝对路径
//fileUrl := c.baseURL + "/openapi/v2/file/list?limit=1000&start=0"
//filePath, err2 := c.getFileList(token, fileUrl, path)
//if err2 != nil {
// return "", err2
//}
targetURL, err := url.JoinPath(c.baseURL + "/openapi/v2/file/preview")
if err != nil {
return "", err
}
header := sugonHeader{
Token: token,
}
req := previewFileReq{
Path: path,
Force: "default",
StartIndex: 0,
}
resp, err := http2.PostForm(targetURL, http2.RequestParam{
Header: header,
Body: req,
})
if err != nil {
return "", err
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading response body: %w", err)
}
contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, http2.ContentTypeJSON) {
var codeResp response[previewFileResp]
if err := serder.JSONToObject(bodyBytes, &codeResp); err != nil {
return "", fmt.Errorf("parsing response: %w", err)
}
if codeResp.Code == "0" {
return codeResp.Data.Content, nil
}
return "", codeResp.ToError()
}
return "", fmt.Errorf("unknow response content type: %s", contType)
}
type fileListResp struct {
FileList []fileInfo `json:"fileList"`
}
type fileInfo struct {
Path string `json:"path"`
}
func (c *HttpClient) getFileList(token string, targetURL string, fileName string) (string, error) {
header := sugonHeader{
Token: token,
}
resp, err := http2.GetJSON(targetURL, http2.RequestParam{
Header: header,
})
if err != nil {
return "", err
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading response body: %w", err)
}
contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, http2.ContentTypeJSON) {
var codeResp response[fileListResp]
if err := serder.JSONToObject(bodyBytes, &codeResp); err != nil {
return "", fmt.Errorf("parsing response: %w", err)
}
if codeResp.Code != "0" {
return "", codeResp.ToError()
}
if len(codeResp.Data.FileList) > 0 {
for _, file := range codeResp.Data.FileList {
if strings.Contains(file.Path, fileName) {
return file.Path, nil
}
}
return "", fmt.Errorf("file not found")
}
}
return "", fmt.Errorf("unknow response content type: %s", contType)
}