pipeline-convert/templates/data-export/utils/utils.go

285 lines
7.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package utils
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
const (
K8SHost = "http://ci4s-gateway-service.argo:8082"
// K8SHost = "http://172.20.32.98:8082"
mountPrefix = "argo-workflow"
CodeOK = 200
Gataway = "mmp"
Admin = "fanshuai"
Password = "h1n2x3j4y5@"
GetTokenUri = "auth/loginByKey"
AutoExportType = "auto_export"
)
type TokenRequest struct {
Name string `json:"username"`
Password string `json:"key"`
}
type TokenResponse struct {
Code int `json:"code"`
Msg interface{} `json:"msg"`
Data struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
} `json:"data"`
}
type UploadRequest struct {
Path string `json:"path"`
UUID string `json:"uuid"`
}
type UploadResponse struct {
Msg string `json:"msg"`
Code int `json:"code"`
Data []struct {
FileName string `json:"fileName"`
FileSize string `json:"fileSize"`
Url string `json:"url"`
} `json:"data"`
}
type DataDetail struct {
Id string `json:"id"`
IdInt int `json:"id_str"`
Name string `json:"name"`
Owner string `json:"owner"`
Identifier string `json:"identifier"`
}
type DataVersionVos struct {
FileName string `json:"file_name"`
FileSize string `json:"file_size"`
Url string `json:"url"`
}
func ParseDataDetail(data string) (*DataDetail, error) {
var dataDetail DataDetail
if err := json.Unmarshal([]byte(data), &dataDetail); err != nil {
return nil, err
}
id, err := strconv.Atoi(dataDetail.Id)
if err != nil {
return nil, err
}
dataDetail.IdInt = id
return &dataDetail, nil
}
func GetToken(url string, name string, password string) (string, error) {
tokenReq := TokenRequest{
Name: name,
Password: password,
}
data, err := json.Marshal(tokenReq)
resp, err := SendPost(&http.Client{Timeout: time.Second * 5}, url, data, "")
if err != nil {
fmt.Println("SendPost error:", err)
return "", err
}
var tokenResp TokenResponse
err = json.Unmarshal(resp, &tokenResp)
if err != nil {
fmt.Println("Decode error:", err)
return "", err
}
if tokenResp.Code != CodeOK {
fmt.Println("get token Code error:", tokenResp.Code)
return "", fmt.Errorf("get token code error: %d, msg: %s", tokenResp.Code, tokenResp.Msg)
}
fmt.Println("get token success, token is:", tokenResp.Data.AccessToken)
return tokenResp.Data.AccessToken, nil
}
func getDatasetMinioPath(mountPath string) (string, error) {
podName := os.Getenv("POD_NAME")
namespace := os.Getenv("POD_NAMESPACE")
// 使用k8s go client客户端获取pod挂载的pvc
config, err := rest.InClusterConfig()
if err != nil {
fmt.Printf("get config err:%v\n", err)
return "", err
}
// 创建Kubernetes客户端
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
fmt.Errorf("create kubernetes client err:%v\n", err)
return "", err
}
fmt.Println("namespace is:", namespace)
fmt.Println("podName is:", podName)
pod, err := clientset.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
if err != nil {
fmt.Errorf("get pod err:%v\n", err)
return "", err
}
var volumeMounts []corev1.VolumeMount
for _, c := range pod.Spec.Containers {
if c.Name == "main" {
volumeMounts = c.VolumeMounts
}
}
if len(volumeMounts) == 0 {
return "", fmt.Errorf("no pvc found for pod %s", podName)
}
subPath := ""
for _, m := range volumeMounts {
if m.MountPath == mountPath {
subPath = m.SubPath
break
}
}
fmt.Println("subpath is ", subPath)
parts := strings.SplitN(subPath, "argo-workflow/", 2)
if len(parts) < 2 {
fmt.Println("The string does not contain 'argo-workflow/'")
return "", fmt.Errorf("invalid subPath %s", subPath)
}
// parts[1] 将包含 "argo-workflow/" 后的部分
fmt.Println("minio path:", parts[1])
return parts[1], nil
}
func UploadData(url, accessToken string, mountPath string) (*UploadResponse, error) {
// uuid 为当前的时间戳转换为字符串
uuid := fmt.Sprintf("%d", time.Now().UnixMilli())
respBody, err := uploadData(url, uuid, accessToken, mountPath)
if err != nil {
fmt.Println("uploadData error:", err)
return nil, err
}
var uploadResp UploadResponse
err = json.Unmarshal(respBody, &uploadResp)
if err != nil {
fmt.Println("Decode error:", err)
return nil, err
}
if uploadResp.Code != CodeOK {
fmt.Println("upload data Code error:", uploadResp.Code)
return nil, fmt.Errorf("upload data code error: %d, msg is %s", uploadResp.Code, uploadResp.Msg)
}
return &uploadResp, nil
}
func SendPost(client *http.Client, url string, data []byte, token string) ([]byte, error) {
body := bytes.NewBuffer(data)
req, err := http.NewRequest(http.MethodPost, url, body)
if err != nil {
fmt.Println("NewRequest error:", err)
return nil, err
}
fmt.Println("url is :", url)
fmt.Println("data is :", string(data))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
fmt.Println("Do error:, url is :", err, url)
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("StatusCode error:", resp.StatusCode)
return nil, err
}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("ReadAll error:", err)
return nil, err
}
return respBody, nil
}
// uploadData 上传数据到平台服务, 上传的文件从mountPath中获取 使用multipart/form-data方式上传
// 返回值是上传成功后的响应数据
func uploadData(url string, uuid string, accessToken string, mountPath string) ([]byte, error) {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
// mounPath 是一个目录,需要遍历目录下的文件进行上传
files, err := filepath.Glob(mountPath + "/*")
if err != nil {
fmt.Println("获取文件列表失败:", err)
return nil, err
}
for _, file := range files {
part, err := writer.CreateFormFile("file", filepath.Base(file))
if err != nil {
fmt.Println("创建form file失败:", err)
return nil, err
}
f, err := os.Open(file)
if err != nil {
fmt.Println("打开文件失败:", err)
return nil, err
}
defer f.Close()
_, err = io.Copy(part, f)
if err != nil {
fmt.Println("写入文件失败:", err)
return nil, err
}
}
// 写入uuid参数
err = writer.WriteField("uuid", uuid)
if err != nil {
fmt.Println("写入uuid参数失败:", err)
return nil, err
}
writer.Close()
req, err := http.NewRequest(http.MethodPost, url, body)
if err != nil {
fmt.Println("NewRequest error:", err)
return nil, err
}
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println("Do error:", err)
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("StatusCode error:", resp.StatusCode)
return nil, err
}
// 解析响应数据, 不用ReadAll, 因为已经deprecate
respBody, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("ReadAll error:", err)
return nil, err
}
return respBody, err
}