增加参数传递

This commit is contained in:
somunslotus 2025-09-01 17:10:40 +08:00
parent a80a1221aa
commit a9be49e470
19 changed files with 416 additions and 180 deletions

View File

@ -1,9 +1,45 @@
#FROM 172.20.32.187/pipeline-service/pipeline-convert:running
FROM ccr.ccs.tencentyun.com/somunslotus/pipeline-covert:running
WORKDIR /app
RUN go build
COPY ./remote-task-excutor-cli /app/remote-task-excutor-cli
#COPY ./internal/config/config.yaml /usr/local/argo-pipeline-manager/
RUN chmod a+x /app/remote-task-excutor-cli
ENTRYPOINT ["/app/remote-task-excutor-cli"]
##FROM ccr.ccs.tencentyun.com/somunslotus/pipeline-covert:running
#WORKDIR /app
#RUN go build -o remote-task-excutor-cli
#COPY ./remote-task-excutor-cli /app/remote-task-excutor-cli
##COPY ./internal/config/config.yaml /usr/local/argo-pipeline-manager/
#RUN chmod a+x /app/remote-task-excutor-cli
#ENTRYPOINT ["/app/remote-task-excutor-cli", "run"]
# 第一阶段:构建阶段
FROM 172.20.32.187/pipeline-service/golang:1.24.5-alpine3.22 AS builder
WORKDIR /app
# 先复制依赖文件,利用缓存
COPY go.mod go.sum ./
# 复制源代码
COPY . .
#RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go env -w GOPROXY=http://172.20.32.233:30005/repository/hnxjy-goproxy/
RUN go mod tidy && go mod download
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -o remote-task-executor-cli
# 第二阶段:运行阶段
FROM 172.20.32.187/pipeline-service/pipeline-convert:running
WORKDIR /app
# 从构建阶段复制可执行文件
COPY --from=builder /app/remote-task-executor-cli /app/
# 设置执行权限
RUN chmod a+x /app/remote-task-executor-cli
# 设置非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD /app/remote-task-executor-cli healthcheck || exit 1
# 入口点
ENTRYPOINT ["/app/remote-task-executor-cli", "run"]

10
build-image.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
tag=$(date +'%Y%m%d%H%M')
image=172.20.32.187/pipeline-service/remote-task-cli:${tag}
docker build -t ${image} .
docker push ${image}
docker tag ${image} ccr.ccs.tencentyun.com/somunslotus/remote-task-cli:${tag}
docker push ccr.ccs.tencentyun.com/somunslotus/remote-task-cli:${tag}

View File

@ -2,6 +2,7 @@ package cmd
import (
"github.com/spf13/cobra"
"os"
)
var rootCmd = &cobra.Command{
@ -12,6 +13,6 @@ var rootCmd = &cobra.Command{
func Execute() {
if err := rootCmd.Execute(); err != nil {
panic(err)
os.Exit(2)
}
}

View File

@ -6,12 +6,14 @@ import (
"fmt"
"github.com/spf13/cobra"
"log"
"os"
"remote-task-excutor-cli/pkg/config"
"remote-task-excutor-cli/pkg/models"
"remote-task-excutor-cli/pkg/runners"
"remote-task-excutor-cli/pkg/service/auth"
"remote-task-excutor-cli/pkg/service/preparation"
"remote-task-excutor-cli/pkg/service/task"
"strings"
"time"
)
@ -19,7 +21,7 @@ var runCmd = &cobra.Command{
Use: "run",
Short: "Run an remote ML task",
Long: `Execute an remote ML task with specified parameters`,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
// 创建参数结构体
fmt.Println("run called, args is", args)
runConfig, err := parseParams()
@ -67,10 +69,11 @@ var runCmd = &cobra.Command{
if err := runner.RunTask(ctx, runConfig); err != nil {
fmt.Println("Workflow failed with error:", err)
return
return err
}
fmt.Println("Workflow started successfully!")
return nil
},
}
@ -79,7 +82,7 @@ func printParams(config *models.RunConfig) {
fmt.Println("Starting remote ML task with configuration:")
fmt.Printf("Code Config: %s\n", config.CodeConfig)
fmt.Printf("Resource: %s\n", config.Resource)
fmt.Printf("Image: %s\n", config.Image)
fmt.Printf("Image: %d\n", config.Image)
fmt.Printf("Command: %s\n", config.Command)
fmt.Printf("Dataset: %s\n", config.Dataset)
fmt.Printf("Model Name: %s\n", config.ModelName)
@ -104,12 +107,17 @@ func parseParams() (*models.RunConfig, error) {
var r models.ResourceConfig
var d models.DataResourceConfig
var m models.DataResourceConfig
var rs models.RunConfig
var rs []string
if err := json.Unmarshal([]byte(codeConfig), &c); err != nil {
return nil, fmt.Errorf("failed to unmarshal codeConfig:%s, error:%v", codeConfig, err)
}
// 生成临时路径
tempDir, err := os.MkdirTemp("", "code-*")
if err != nil {
return nil, fmt.Errorf("failed to create temp dir:%s, error:%v", tempDir, err)
}
c.MountPath = tempDir
if err := json.Unmarshal([]byte(resource), &r); err != nil {
return nil, fmt.Errorf("failed to unmarshal resourceConfig:%s, error:%v", resource, err)
}
@ -118,14 +126,21 @@ func parseParams() (*models.RunConfig, error) {
return nil, fmt.Errorf("failed to unmarshal datasetConfig:%s, error:%v", dataset, err)
}
if err := json.Unmarshal([]byte(modelName), &m); err != nil {
return nil, fmt.Errorf("failed to unmarshal commandConfig:%s, error:%v", modelName, err)
if modelName != "" {
if err := json.Unmarshal([]byte(modelName), &m); err != nil {
return nil, fmt.Errorf("failed to unmarshal commandConfig:%s, error:%v", modelName, err)
}
}
if err := json.Unmarshal([]byte(runArgs), &rs); err != nil {
return nil, fmt.Errorf("failed to unmarshal runArgsConfig:%s, error:%v", runArgs, err)
}
params, err := ParseRunArgs(rs)
if err != nil {
return nil, fmt.Errorf("failed to parse runArgsConfig:%s, error:%v", runArgs, err)
}
return &models.RunConfig{
CodeConfig: c,
Resource: r,
@ -133,11 +148,32 @@ func parseParams() (*models.RunConfig, error) {
Command: command,
Dataset: d,
ModelName: m,
RunArgs: rs.RunArgs,
RunArgs: params,
TaskOutput: taskOutput,
}, nil
}
// ParseRunArgs 解析运行参数字符串为键值对
func ParseRunArgs(input []string) (map[string]string, error) {
result := make(map[string]string)
if len(input) == 0 {
return result, nil
}
for _, i := range input {
kv := strings.Split(i, "=")
if len(kv) != 2 {
return nil, fmt.Errorf("failed to parse runArgs: %s", i)
}
key := strings.TrimPrefix(strings.TrimSpace(kv[0]), "--")
value := strings.TrimSpace(kv[1])
result[key] = value
}
return result, nil
}
func init() {
rootCmd.AddCommand(runCmd)
@ -150,8 +186,8 @@ func init() {
runCmd.Flags().IntVarP(&image, "image", "i", 0,
"运行镜像 (required)")
runCmd.Flags().IntVarP(&image, "resource_type", "i", 0,
"资源类型 (required)")
runCmd.Flags().StringVarP(&resourceType, "resource_type", "t", "",
"资源类型")
runCmd.Flags().StringVarP(&command, "command", "m", "",
"启动命令 (required)")

13
go.mod
View File

@ -1,6 +1,8 @@
module remote-task-excutor-cli
go 1.24.5
go 1.24
toolchain go1.24.5
require (
github.com/go-git/go-git/v5 v5.16.2
@ -8,7 +10,7 @@ require (
github.com/nacos-group/nacos-sdk-go/v2 v2.3.2
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.9.1
golang.org/x/sync v0.13.0
golang.org/x/sync v0.15.0
)
require (
@ -52,12 +54,13 @@ require (
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-containerregistry v0.20.6 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@ -82,12 +85,12 @@ require (
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.1.0 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.56.3 // indirect
google.golang.org/protobuf v1.33.0 // indirect
google.golang.org/protobuf v1.36.3 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect

10
go.sum
View File

@ -227,6 +227,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-containerregistry v0.20.6 h1:cvWX87UxxLgaH76b4hIvya6Dzz9qHB31qAwjAohdSTU=
github.com/google/go-containerregistry v0.20.6/go.mod h1:T0x8MuoAoKX/873bkeSfLD2FAkwCDf9/HZgsFJ02E2Y=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@ -270,6 +272,8 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
@ -518,6 +522,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -572,6 +578,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@ -734,6 +742,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

12
main.go
View File

@ -1,9 +1,21 @@
package main
import (
"fmt"
"os"
"remote-task-excutor-cli/cmd"
)
func main() {
os.Setenv("HTTP_PROXY", "http://172.20.32.233:3128")
os.Setenv("HTTPS_PROXY", "http://172.20.32.233:3128")
os.Setenv("NO_PROXY", "172.20.32.0/24")
fmt.Println("===== Environment Variables =====")
fmt.Printf("HTTP_PROXY: %s\n", os.Getenv("HTTP_PROXY"))
fmt.Printf("HTTPS_PROXY: %s\n", os.Getenv("HTTPS_PROXY"))
fmt.Printf("http_proxy: %s\n", os.Getenv("http_proxy"))
fmt.Printf("https_proxy: %s\n", os.Getenv("https_proxy"))
cmd.Execute()
//fmt.Println("Hello, world!")
}

View File

@ -11,6 +11,7 @@ import (
"net/url"
"os"
"path/filepath"
"strings"
"time"
)
@ -97,7 +98,7 @@ func (c *HTTPClient) PostJSON(path string, data interface{}) ([]byte, error) {
if err != nil {
return nil, err
}
fmt.Println("request url, body is :", fullURL, string(jsonData))
req, err := http.NewRequest("POST", fullURL, bytes.NewBuffer(jsonData))
if err != nil {
return nil, err
@ -129,6 +130,7 @@ func (c *HTTPClient) PostJSON(path string, data interface{}) ([]byte, error) {
// files 参数现在支持每个字段名对应多个文件路径
func (c *HTTPClient) UploadFiles(
path string,
filesPrefix string,
files map[string][]string, // 字段名 -> 多个文件路径
formFields map[string]string, // 额外表单字段
) ([]byte, error) {
@ -147,7 +149,12 @@ func (c *HTTPClient) UploadFiles(
}
defer file.Close()
part, err := writer.CreateFormFile(fieldName, filepath.Base(filePath))
relativePath, err := removePathPrefix(filePath, filesPrefix)
if err != nil {
return nil, err
}
part, err := writer.CreateFormFile(fieldName, url.PathEscape(relativePath))
if err != nil {
return nil, fmt.Errorf("为文件 %s 创建表单字段失败: %w", filePath, err)
}
@ -213,6 +220,31 @@ func (c *HTTPClient) UploadFiles(
return io.ReadAll(resp.Body)
}
func removePathPrefix(fullPath, prefix string) (string, error) {
// 使用系统文件分隔符标准化路径
prefix = filepath.Clean(prefix) + string(filepath.Separator)
fullPath = filepath.Clean(fullPath)
// 检查路径是否有指定的前缀
if strings.HasPrefix(fullPath, prefix) {
// 返回去除前缀的路径
return fullPath[len(prefix):], nil
}
// 如果不匹配,返回原始路径(或者可以根据需要返回错误)
return "", fmt.Errorf("错误的filepath和prefix, filepath:%v, prefix:%v", fullPath, prefix)
}
func (c *HTTPClient) encodeFilepath(paths []string) []string {
var result []string
for _, path := range paths {
// 编码文件路径,使用urlencoded编码
encodedPath := url.PathEscape(path)
result = append(result, encodedPath)
}
fmt.Println("encodeFilepath result: ", result)
return result
}
// DownloadFile 下载文件到本地路径(支持大文件流式处理)
// localPath保存文件的本地路径包含文件名
// queryParams可选查询参数
@ -262,9 +294,12 @@ func (c *HTTPClient) DownloadFile(path, localPath string, queryParams ...map[str
}
}
os.MkdirAll(localPath, 0755)
filename := extractFilenameFromDisposition(resp.Header.Get("Content-Disposition"))
if filename == "" {
filename = filepath.Join(localPath, "file.zip")
} else {
filename = filepath.Join(localPath, filename)
}
// 创建本地文件
outFile, err := os.Create(filename)

View File

@ -39,6 +39,7 @@ type APIConfig struct {
Username string `json:"username" yaml:"username"`
Password string `json:"password" yaml:"password"`
BaseURL string `json:"baseUrl" yaml:"baseUrl"`
TestURL string `json:"testUrl" yaml:"testUrl"`
TokenTTL int `json:"tokenTtl" yaml:"tokenTtl"` // token 有效期(秒)
Timeout int `json:"timeout" yaml:"timeout"`
}
@ -54,6 +55,16 @@ type ConfigReader struct {
group string
}
var DefaultApiConfig = &APIConfig{
AuthURL: "jcc-admin/admin/login",
Username: "hnxjy-super",
Password: "h1n2x3j4y5@",
BaseURL: "https://jcc.jointcloud.net/",
TestURL: "",
TokenTTL: 0,
Timeout: 10,
}
// NewConfigReader 创建新的 Nacos 配置读取器
func NewConfigReader(ctx context.Context, cfg NacosConfig) (*ConfigReader, error) {
// 创建 ServerConfig
@ -67,7 +78,7 @@ func NewConfigReader(ctx context.Context, cfg NacosConfig) (*ConfigReader, error
// 创建 ClientConfig
clientConfig := constant.ClientConfig{
NamespaceId: cfg.NamespaceID,
NamespaceId: "",
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogDir: cfg.LogDir,
@ -109,34 +120,34 @@ func NewConfigReader(ctx context.Context, cfg NacosConfig) (*ConfigReader, error
// loadConfig 从Nacos加载配置带上下文
func (r *ConfigReader) loadConfig(ctx context.Context) error {
// 使用上下文限制超时
content, err := r.client.GetConfig(vo.ConfigParam{
DataId: r.dataID,
Group: r.group,
})
if err != nil {
return errors.Wrap(err, "获取Nacos配置失败")
}
if content == "" {
return errors.New("从Nacos获取的配置为空")
}
var apiCfg APIConfig
if err := json.Unmarshal([]byte(content), &apiCfg); err != nil {
return errors.Wrapf(err, "解析配置失败: %s", content)
}
// 设置默认值
if apiCfg.TokenTTL == 0 {
apiCfg.TokenTTL = 3600 // 默认1小时
}
// 更新配置
r.cfgMutex.Lock()
r.apiCfg = &apiCfg
r.cfgMutex.Unlock()
//content, err := r.client.GetConfig(vo.ConfigParam{
// DataId: r.dataID,
// Group: r.group,
//})
//
//if err != nil {
// return errors.Wrap(err, "获取Nacos配置失败")
//}
//
//if content == "" {
// return errors.New("从Nacos获取的配置为空")
//}
//
//var apiCfg APIConfig
//if err := yaml.Unmarshal([]byte(content), &apiCfg); err != nil {
// return errors.Wrapf(err, "解析配置失败: %s", content)
//}
//
//// 设置默认值
//if apiCfg.TokenTTL == 0 {
// apiCfg.TokenTTL = 3600 // 默认1小时
//}
//
//// 更新配置
//r.cfgMutex.Lock()
//r.apiCfg = &apiCfg
//r.cfgMutex.Unlock()
r.apiCfg = DefaultApiConfig
return nil
}

View File

@ -10,15 +10,15 @@ type AuthResponse struct {
// AuthData 认证数据主体
type AuthData struct {
TokenHead string `json:"tokenHead"`
ExpiresIn int `json:"expiresIn"` // 注意:改为整型
ExpiresIn string `json:"expiresIn"`
JsmUserInfo UserInfo `json:"jsmUserInfo"`
TokenTimeout int `json:"tokenTimeout"` // 注意:改为整型
TokenTimeout string `json:"tokenTimeout"`
Token string `json:"token"`
}
// UserInfo 用户信息
type UserInfo struct {
Code int `json:"code"` // 注意:改为整型
Code string `json:"code"` // 注意:改为整型
Message string `json:"message"`
Data UserData `json:"data"`
}

View File

@ -1,40 +1,13 @@
package models
import (
"fmt"
"strings"
)
// RunConfig 包含所有运行参数
type RunConfig struct {
CodeConfig CodeConfig `json:"code_config"`
Resource ResourceConfig `json:"resource"`
Image int `json:"image"`
Command string `json:"command"`
RunArgs []string `json:"run_args"`
RunArgs map[string]string `json:"run_args"`
Dataset DataResourceConfig `json:"dataset"`
ModelName DataResourceConfig `json:"model_name"`
TaskOutput string `json:"task_output"`
}
// ParseRunArgs 解析运行参数字符串为键值对
func ParseRunArgs(input string) (map[string]string, error) {
result := make(map[string]string)
if input == "" {
return result, nil
}
pairs := strings.Split(input, ",")
for _, pair := range pairs {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return nil, fmt.Errorf("invalid key-value pair: %s", pair)
}
key := strings.TrimSpace(kv[0])
value := strings.TrimSpace(kv[1])
result[key] = value
}
return result, nil
}

View File

@ -37,11 +37,11 @@ type BucketID int
type StorageID int
type PackageCreateLoadInfo struct {
UserID int `json:"userID" binding:"required"`
BucketID int `json:"bucketID" binding:"required"`
Name string `json:"name" binding:"required"`
LoadTo int `json:"loadTo"`
LoadToPath []string `json:"loadToPath"`
UserID int `json:"userID" binding:"required"`
BucketID int `json:"bucketID" binding:"required"`
Name string `json:"name" binding:"required"`
//LoadTo int `json:"loadTo"`
//LoadToPath []string `json:"loadToPath"`
}
type PackageCreateResponse struct {
@ -208,3 +208,8 @@ type BindResultSet struct {
BindDatasetID int `json:"bind_dataset_id"`
BindModelID int `json:"bind_model_id"`
}
type UploadFileConfig struct {
FilePrefix string
Files []string
}

View File

@ -27,7 +27,7 @@ type Job struct {
// JobFiles 表示任务关联的文件
type JobFiles struct {
Dataset FileBinding `json:"dataset"`
Model FileBinding `json:"model"`
Model FileBinding `json:"model,omitempty"`
Image ImageBinding `json:"image"`
}
@ -118,8 +118,8 @@ type TaskDetailResponse struct {
type TaskDetailData struct {
Name string `json:"name"` // 任务名称
Description string `json:"description"` // 任务描述
StartTime time.Time `json:"startTime"` // 开始时间
EndTime time.Time `json:"endTime"` // 结束时间
StartTime string `json:"startTime"` // 开始时间
EndTime string `json:"endTime"` // 结束时间
Strategy int `json:"strategy"` // 策略
SynergyStatus int `json:"synergyStatus"` // 协同状态
ClusterInfos []ClusterItem `json:"clusterInfos"` // 集群信息列表

View File

@ -28,12 +28,12 @@ func (r *taskRunner) RunTask(ctx context.Context, config *models.RunConfig) erro
if err != nil {
return err
}
fmt.Println("获取token成功")
clusterID, err := r.authService.GetClusterID(ctx, "openI")
if err != nil {
return err
}
fmt.Println("获取clusterID成功", clusterID)
// 数据准备
bindResultSet, err := r.preparationService.PrepareAll(ctx, authData, config, clusterID)
if err != nil {
@ -44,13 +44,18 @@ func (r *taskRunner) RunTask(ctx context.Context, config *models.RunConfig) erro
if err != nil {
return err
}
fmt.Println("任务提交成功,开始查询任务状态")
time.Sleep(5 * time.Second)
go r.RecordLogFile(ctx, authData, jobSetID)
// 轮询任务状态
err = r.PollTaskStatusWithBackoff(ctx, authData, jobSetID)
resp, err := r.PollTaskStatusWithBackoff(ctx, authData, jobSetID)
if err != nil {
return err
}
if resp.Data.SubTaskInfos[0].Status != "Completed" {
return fmt.Errorf("远程任务执行失败:")
}
// 获取任务结果
err = r.taskRunService.GetTaskResult(ctx, authData, config.TaskOutput, jobSetID)
if err != nil {
@ -60,11 +65,21 @@ func (r *taskRunner) RunTask(ctx context.Context, config *models.RunConfig) erro
return nil
}
func (r *taskRunner) PollTaskStatusWithBackoff(ctx context.Context, authData *models.AuthData, jobSetID string) error {
func (r *taskRunner) RecordLogFile(ctx context.Context, authData *models.AuthData, jobSetID string) error {
for {
content, _ := r.taskRunService.GetTaskLogs(ctx, authData, jobSetID)
if len(content) == 0 {
time.Sleep(5 * time.Second)
}
fmt.Println("get log content is ", content)
}
}
func (r *taskRunner) PollTaskStatusWithBackoff(ctx context.Context, authData *models.AuthData, jobSetID string) (*models.TaskDetailResponse, error) {
const (
baseInterval = 5 * time.Second
maxInterval = 1 * time.Minute
maxAttempts = 10 // 最多尝试10次
maxAttempts = 5 // 最多尝试10次
)
var (
@ -73,26 +88,26 @@ func (r *taskRunner) PollTaskStatusWithBackoff(ctx context.Context, authData *mo
)
for {
attemptCount++
if attemptCount > maxAttempts {
return fmt.Errorf("超出最大查询次数(%d)", maxAttempts)
return nil, fmt.Errorf("超出最大查询次数(%d)", maxAttempts)
}
// 检查上下文是否被取消
if ctx.Err() != nil {
return ctx.Err()
return nil, ctx.Err()
}
// 获取任务状态
status, err := r.taskRunService.GetTaskStatus(ctx, authData, jobSetID)
if err != nil {
attemptCount++
// 指数回退
backoff = min(backoff*2, maxInterval)
sleepTime := backoff + time.Duration(rand.Int63n(int64(backoff/2))) // 随机抖动避免同步
fmt.Printf("任务查询失败(%s), 将在 %s 后重试\n", err, sleepTime)
select {
case <-ctx.Done():
return ctx.Err()
return nil, ctx.Err()
case <-time.After(sleepTime):
continue
}
@ -103,17 +118,17 @@ func (r *taskRunner) PollTaskStatusWithBackoff(ctx context.Context, authData *mo
// 检查任务状态
switch {
case IsCompleted(status):
fmt.Println("任务成功完成!")
return nil
case IsCompleted(status.Data.SubTaskInfos[0].Status):
fmt.Println("任务成功完成!, 完成状态:", status)
return status, nil
default:
fmt.Println("任务运行中: %s", status)
fmt.Println("任务运行中: ", status)
}
// 等待下一次轮询
select {
case <-ctx.Done():
return ctx.Err()
return nil, ctx.Err()
case <-time.After(baseInterval):
}
}

View File

@ -29,7 +29,8 @@ func NewTokenService(cfg *config.APIConfig) service.AuthService {
authURL: cfg.AuthURL,
username: cfg.Username,
password: cfg.Password,
httpClient: client.NewHTTPClient(cfg.AuthURL, time.Second*10),
httpClient: client.NewHTTPClient(cfg.BaseURL, time.Duration(cfg.Timeout)*time.Second),
authData: &models.AuthData{},
}
}
@ -81,7 +82,11 @@ func (ts *TokenService) GetClusterID(ctx context.Context, label string) (string,
// 查询集群ID
ts.httpClient.Headers["Authorization"] = "Bearer " + token.Token
resp, err := ts.httpClient.Get("/pcm/v1/adapter/cluster/getClusterBaseInfo", nil)
params := map[string]string{
"pageNum": "1",
"pageSize": "30",
}
resp, err := ts.httpClient.Get("/pcm/v1/adapter/cluster/getClusterBaseInfo", params)
if err != nil {
return "", err
}

View File

@ -22,7 +22,7 @@ type PreparationService interface {
type TaskService interface {
SubmitTask(ctx context.Context, authData *models.AuthData, config *models.RunConfig,
clusterID string, bindResultSet *models.BindResultSet) (string, error)
GetTaskStatus(ctx context.Context, authData *models.AuthData, jobSetID string) (string, error)
GetTaskStatus(ctx context.Context, authData *models.AuthData, jobSetID string) (*models.TaskDetailResponse, error)
GetTaskResult(ctx context.Context, authData *models.AuthData, path string, jobSetID string) error
GetTaskLogs(ctx context.Context, authData *models.AuthData, jobSetID string) (string, error)
}

View File

@ -28,10 +28,12 @@ const (
ImageType = "image"
CodeType = "code"
BindingType = "binding"
TaskBindingType = "Binding"
ImageCategory = "image"
RootPath = "/"
ImageClassifyType = "image_classification"
PytorchType = "pytorch"
CreateResourceUri = "/apis/jsm//app/submit"
)
type preparationService struct {
@ -57,7 +59,10 @@ func (s *preparationService) PrepareAll(ctx context.Context, authData *models.Au
codeChan := make(chan result, 1)
datasetChan := make(chan result, 1)
modelChan := make(chan result, 1)
var modelChan chan result
if config.ModelName.Path != "" {
modelChan = make(chan result, 1)
}
// 并发执行代码准备
errGroup.Go(func() error {
@ -73,19 +78,26 @@ func (s *preparationService) PrepareAll(ctx context.Context, authData *models.Au
return err
})
// 并发执行模型准备
errGroup.Go(func() error {
id, err := s.PrepareModel(ctx, authData, config.ModelName, clusterID)
modelChan <- result{id, err}
return err
})
if config.ModelName.Path != "" {
errGroup.Go(func() error {
id, err := s.PrepareModel(ctx, authData, config.ModelName, clusterID)
modelChan <- result{id, err}
return err
})
}
// 等待所有任务完成
if err := errGroup.Wait(); err != nil {
// 有错误发生,但我们需要收集所有结果
codeRes := <-codeChan
datasetRes := <-datasetChan
modelRes := <-modelChan
var modelRes result
if modelChan != nil {
modelRes = <-modelChan
} else {
modelRes = result{id: 0, err: nil} // 默认值
}
return &models.BindResultSet{
BindCodeID: codeRes.id,
@ -97,7 +109,12 @@ func (s *preparationService) PrepareAll(ctx context.Context, authData *models.Au
// 所有任务成功完成
codeRes := <-codeChan
datasetRes := <-datasetChan
modelRes := <-modelChan
var modelRes result
if modelChan != nil {
modelRes = <-modelChan
} else {
modelRes = result{id: 0, err: nil}
}
return &models.BindResultSet{
BindCodeID: codeRes.id,
@ -124,31 +141,52 @@ func aggregateErrors(errs ...error) error {
func (s *preparationService) PrepareCode(ctx context.Context, authData *models.AuthData, config *models.RunConfig,
clusterID string) (int, error) {
fmt.Println("开始准备代码")
resul, err := s.uploadCode(ctx, authData, config.CodeConfig)
if err != nil {
return 0, err
}
return s.bindCode(ctx, authData, config, resul, clusterID)
fmt.Println("代码上传成功,开始代码定版")
id, err := s.bindCode(ctx, authData, config, resul, clusterID)
if err != nil {
return 0, err
}
fmt.Println("代码定版成功")
return id, nil
}
func (s *preparationService) PrepareDataset(ctx context.Context, authData *models.AuthData, config models.DataResourceConfig,
clusterID string) (int, error) {
fmt.Println("开始准备数据集")
// 1 上传数据集到数据集仓库
result, err := s.uploadFiles(ctx, authData, config, DatasetType)
if err != nil {
return 0, fmt.Errorf("上传数据集失败: %w", err)
}
fmt.Println("数据集上传成功,开始数据集定版")
//2 绑定数据集到用户的bucket
return s.bindDataset(ctx, authData, config, result, clusterID)
id, err := s.bindDataset(ctx, authData, config, result, clusterID)
if err != nil {
return 0, err
}
fmt.Println("数据集定版成功")
return id, nil
}
func (s *preparationService) PrepareModel(ctx context.Context, authData *models.AuthData, config models.DataResourceConfig,
clusterID string) (int, error) {
fmt.Println("开始准备模型")
result, err := s.uploadFiles(ctx, authData, config, ModelType)
if err != nil {
return 0, fmt.Errorf("上传模型失败: %w", err)
}
return s.bindModel(ctx, authData, config, result, clusterID)
fmt.Println("模型上传成功,开始模型定版")
id, err := s.bindModel(ctx, authData, config, result, clusterID)
if err != nil {
return 0, err
}
fmt.Println("模型定版成功")
return id, nil
}
func (s *preparationService) bindCode(ctx context.Context, authData *models.AuthData, config *models.RunConfig,
@ -187,7 +225,8 @@ func (s *preparationService) bindCode(ctx context.Context, authData *models.Auth
},
}
s.httpClient.Headers["Authorization"] = "Bearer " + authData.Token
resp, err := s.httpClient.PostJSON("/app/submit", request)
resp, err := s.httpClient.PostJSON(CreateResourceUri, request)
fmt.Println("代码绑定结果:", string(resp))
if err != nil {
return 0, fmt.Errorf("绑定代码失败: %w", err)
}
@ -196,7 +235,7 @@ func (s *preparationService) bindCode(ctx context.Context, authData *models.Auth
func (s *preparationService) getStartCommandObjectID(config *models.RunConfig, uploadResult *models.PackageCreateResponse) (int, error) {
for _, file := range uploadResult.Data.Objects {
if (RootPath + strings.Trim(config.Command, " ")) == file.Path {
if (strings.Trim(config.Command, " ")) == file.Path {
return file.ObjectID, nil
}
}
@ -235,7 +274,8 @@ func (s *preparationService) bindModel(ctx context.Context, authData *models.Aut
},
}
s.httpClient.Headers["Authorization"] = "Bearer " + authData.Token
resp, err := s.httpClient.PostJSON("/app/submit", request)
resp, err := s.httpClient.PostJSON(CreateResourceUri, request)
fmt.Println("模型绑定结果:", string(resp))
if err != nil {
return 0, fmt.Errorf("绑定模型失败: %w", err)
}
@ -244,7 +284,7 @@ func (s *preparationService) bindModel(ctx context.Context, authData *models.Aut
func (s *preparationService) uploadFiles(ctx context.Context, authData *models.AuthData, config models.DataResourceConfig, uploadType string) (*models.PackageCreateResponse, error) {
// 1 获取数据集路径下的所有文件 遍历config.MountPath下的所有文件获取路径和文件名组成文件map[string][]string
files, err := GetAllFiles(config.MountPath)
filesConfig, err := GetAllFiles(config.MountPath)
if err != nil {
return nil, fmt.Errorf("获取路径下的所有文件失败: %w", err)
}
@ -259,19 +299,20 @@ func (s *preparationService) uploadFiles(ctx context.Context, authData *models.A
Name: config.Name + "-" + GenerateUniqueID(),
}
return s.doUpload(ctx, authData, files, info)
return s.doUpload(ctx, authData, filesConfig, info)
}
func (s *preparationService) doUpload(ctx context.Context, authData *models.AuthData, files []string, info models.PackageCreateLoadInfo) (*models.PackageCreateResponse, error) {
func (s *preparationService) doUpload(ctx context.Context, authData *models.AuthData, filesConfig *models.UploadFileConfig, info models.PackageCreateLoadInfo) (*models.PackageCreateResponse, error) {
infoJson, err := json.Marshal(info)
if err != nil {
return nil, fmt.Errorf("序列化PackageCreateLoadInfo失败: %w", err)
}
s.httpClient.Headers["Authorization"] = "Bearer " + authData.Token
resp, err := s.httpClient.UploadFiles("package/createLoad",
resp, err := s.httpClient.UploadFiles("/apis/jcs/package/createLoad",
filesConfig.FilePrefix,
map[string][]string{
"files": s.encodeFilepath(files),
"files": filesConfig.Files, //s.encodeFilepath(files),
},
map[string]string{
"info": string(infoJson),
@ -285,6 +326,9 @@ func (s *preparationService) doUpload(ctx context.Context, authData *models.Auth
if err != nil {
return nil, fmt.Errorf("解析上传结果失败: %w", err)
}
if result.Code != "OK" {
return nil, fmt.Errorf("上传失败:%v-%v", result.Code, result.Message)
}
return &result, nil
}
@ -300,7 +344,7 @@ func (s *preparationService) uploadCode(ctx context.Context, authData *models.Au
info := models.PackageCreateLoadInfo{
UserID: authData.JsmUserInfo.Data.UserID,
BucketID: authData.JsmUserInfo.Data.Buckets.Code,
Name: config.CodeRepoName + "-" + GenerateUniqueID(),
Name: "code" + "-" + GenerateUniqueID(),
}
return s.doUpload(ctx, authData, files, info)
}
@ -354,7 +398,8 @@ func (s *preparationService) bindDataset(ctx context.Context, authData *models.A
},
}
s.httpClient.Headers["Authorization"] = "Bearer " + authData.Token
resp, err := s.httpClient.PostJSON("/app/submit", request)
resp, err := s.httpClient.PostJSON(CreateResourceUri, request)
fmt.Println("数据集绑定结果:", string(resp))
if err != nil {
return 0, fmt.Errorf("绑定数据集失败: %w", err)
}
@ -373,7 +418,7 @@ func (s *preparationService) getBindingID(response []byte) (int, error) {
}
if result.BindingID <= 0 {
return 0, fmt.Errorf("绑定数据集失败: %s", tmp.Message)
return 0, fmt.Errorf("绑定资源失败: %s", tmp.Message)
}
return result.BindingID, nil
@ -412,7 +457,7 @@ func getObjectIDS(uploadResult *models.PackageCreateResponse) []int {
}
// GetAllFiles 获取指定目录下的所有文件绝对路径
func GetAllFiles(rootDir string) ([]string, error) {
func GetAllFiles(rootDir string) (*models.UploadFileConfig, error) {
// 获取绝对路径
absRoot, err := filepath.Abs(rootDir)
if err != nil {
@ -426,6 +471,11 @@ func GetAllFiles(rootDir string) ([]string, error) {
return fmt.Errorf("访问路径 %s 失败: %w", path, err)
}
// 排除 .git 目录及其所有内容
if info.IsDir() && info.Name() == ".git" {
return filepath.SkipDir // 跳过整个目录
}
if !info.IsDir() {
// 确保路径是绝对路径
absPath, err := filepath.Abs(path)
@ -441,7 +491,10 @@ func GetAllFiles(rootDir string) ([]string, error) {
return nil, fmt.Errorf("遍历目录失败: %w", err)
}
return files, nil
return &models.UploadFileConfig{
FilePrefix: rootDir,
Files: files,
}, nil
}
func (s *preparationService) encodeFilepath(paths []string) []string {

View File

@ -38,12 +38,13 @@ func (s *taskService) SubmitTask(ctx context.Context, authData *models.AuthData,
clusterID string, bindResultSet *models.BindResultSet) (string, error) {
submitTaskReq := s.buildSubmitTaskReq(ctx, authData, config, clusterID, bindResultSet)
s.httpClient.Headers["Authorization"] = "Bearer " + authData.Token
fmt.Printf("任务提交参数:%+v", submitTaskReq)
resp, err := s.httpClient.PostJSON("/jsm/jobSet/submit", submitTaskReq)
if err != nil {
fmt.Println("Submit task failed: ", err)
return "", err
}
fmt.Println("提交任务结果:", string(resp))
var submitTaskResp models.SubmitTaskResponse
if err := json.Unmarshal(resp, &submitTaskResp); err != nil {
fmt.Println("Submit task response unmarshal failed: ", err)
@ -53,34 +54,41 @@ func (s *taskService) SubmitTask(ctx context.Context, authData *models.AuthData,
fmt.Println("Submit task failed: ", submitTaskResp.Code)
return "", fmt.Errorf("submit task failed: %s", submitTaskResp.Code)
}
fmt.Println("Submit task result: ", resp)
fmt.Println("Submit task result: ", string(resp))
return submitTaskResp.Data.JobSetID, nil
}
func (s *taskService) GetTaskStatus(ctx context.Context, authData *models.AuthData, jobSetID string) (string, error) {
func (s *taskService) GetTaskStatus(ctx context.Context, authData *models.AuthData, jobSetID string) (*models.TaskDetailResponse, error) {
s.httpClient.Headers["Authorization"] = "Bearer " + authData.Token
params := map[string]string{
JobSetIDKey: jobSetID,
LocalJobIDKey: MainTaskID,
}
resp, err := s.httpClient.Get("/jsm/jobMgr/detail", params)
if err != nil {
fmt.Println("Get task status failed: ", err)
return "", err
}
var taskStatus models.TaskDetailResponse
if err := json.Unmarshal(resp, &taskStatus); err != nil {
fmt.Println("Get task status response unmarshal failed: ", err)
return "", err
}
for {
resp, err := s.httpClient.Get("/jsm/jobMgr/detail", params)
if err != nil {
fmt.Println("Get task status failed: ", err)
return nil, err
}
if taskStatus.Code != ResponseOK {
fmt.Println("Get task status failed: ", taskStatus.Code)
return "", fmt.Errorf("get task status failed: code: %s, message: %s", taskStatus.Code, taskStatus.Message)
var taskStatus models.TaskDetailResponse
if err := json.Unmarshal(resp, &taskStatus); err != nil {
fmt.Println("Get task status response unmarshal failed: ", err)
return nil, err
}
if taskStatus.Code != ResponseOK {
fmt.Println("Get task status failed: ", taskStatus.Code)
return nil, fmt.Errorf("get task status failed: code: %s, message: %s", taskStatus.Code, taskStatus.Message)
}
fmt.Println("Get task status result: ", string(resp))
if len(taskStatus.Data.SubTaskInfos) == 0 {
time.Sleep(5 * time.Second)
continue
}
return &taskStatus, nil
}
fmt.Println("Get task status result: ", resp)
return taskStatus.Data.SubTaskInfos[0].Status, nil
}
func (s *taskService) GetTaskLogs(ctx context.Context, authData *models.AuthData, jobSetID string) (string, error) {
@ -98,6 +106,7 @@ func (s *taskService) GetTaskLogs(ctx context.Context, authData *models.AuthData
var taskLogResponse models.TaskLogResponse
if err := json.Unmarshal(resp, &taskLogResponse); err != nil {
fmt.Println("Get task logs response unmarshal failed: ", err)
return "", err
}
@ -125,6 +134,7 @@ func (s *taskService) GetTaskResult(ctx context.Context, authData *models.AuthDa
fmt.Println("Unarchive task result failed: ", err)
return err
}
// 删除filename文件
if err := os.Remove(filename); err != nil {
fmt.Println("Remove task result failed: ", err)
@ -137,8 +147,8 @@ func (s *taskService) GetTaskResult(ctx context.Context, authData *models.AuthDa
func (s *taskService) downloadTaskResult(ctx context.Context, authData *models.AuthData, path string, packageID int) (string, error) {
s.httpClient.Headers["Authorization"] = "Bearer " + authData.Token
params := map[string]string{
"packageId": fmt.Sprintf("%s", packageID),
"userId": fmt.Sprintf("%s", authData.JsmUserInfo.Data.UserID),
"packageID": fmt.Sprintf("%d", packageID),
"userID": fmt.Sprintf("%d", authData.JsmUserInfo.Data.UserID),
}
filename, err := s.httpClient.DownloadFile("/jcs/v1/package/download", path, params)
if err != nil {
@ -153,31 +163,52 @@ func (s *taskService) getTaskResultDetail(ctx context.Context, authData *models.
s.httpClient.Headers["Authorization"] = "Bearer " + authData.Token
queryTaskResultReq := models.TaskQueryRequest{
JobSetID: jobSetID,
LocalJobID: DataReturnTaskID,
LocalJobID: MainTaskID,
}
resp, err := s.httpClient.PostJSON("/jsm/jobMgr/result", queryTaskResultReq)
if err != nil {
fmt.Println("Get task result details failed: ", err)
return nil, err
maxAttemps := 3
attemps := 0
for {
resp, err := s.httpClient.PostJSON("/jsm/jobMgr/result", queryTaskResultReq)
fmt.Println("get result details resp:", string(resp))
if err != nil {
fmt.Println("Get task result details failed: ", err)
return nil, err
}
var taskResultDetails models.TaskResultDetailResponse
if err := json.Unmarshal(resp, &taskResultDetails); err != nil {
fmt.Println("Get task result details response unmarshal failed: ", err)
return nil, err
}
if taskResultDetails.Code != ResponseOK {
if taskResultDetails.Message == "query pcm job: record not found" {
time.Sleep(5 * time.Second)
continue
} else {
if attemps > maxAttemps {
fmt.Println("Get task result details failed: ", taskResultDetails.Code)
return nil, fmt.Errorf("get task result details failed: %s", taskResultDetails.Code)
}
attemps++
time.Sleep(5 * time.Second)
}
}
if taskResultDetails.Data.PcmJobData.Status == "failed" { // && taskResultDetails.Data.PcmJobData.ErrorMsg == "data return job id is empty" {
time.Sleep(5 * time.Second)
continue
}
return &taskResultDetails.Data, nil
}
var taskResultDetails models.TaskResultDetailResponse
if err := json.Unmarshal(resp, &taskResultDetails); err != nil {
fmt.Println("Get task result details response unmarshal failed: ", err)
return nil, err
}
if taskResultDetails.Code != ResponseOK {
fmt.Println("Get task result details failed: ", taskResultDetails.Code)
return nil, fmt.Errorf("get task result details failed: %s", taskResultDetails.Code)
}
return &taskResultDetails.Data, nil
}
func (s *taskService) buildSubmitTaskReq(ctx context.Context, authData *models.AuthData, config *models.RunConfig,
clusterID string, bindResultSet *models.BindResultSet) models.SubtaskRequest {
return models.SubtaskRequest{
UserID: authData.JsmUserInfo.Data.UserID,
JobSetInfo: models.JobSetInfo{
@ -189,15 +220,15 @@ func (s *taskService) buildSubmitTaskReq(ctx context.Context, authData *models.A
Type: AITaskType,
Files: &models.JobFiles{
Dataset: models.FileBinding{
Type: preparation.DatasetType,
Type: preparation.TaskBindingType,
BindingID: bindResultSet.BindDatasetID,
},
Model: models.FileBinding{
Type: preparation.ModelType,
Type: preparation.TaskBindingType,
BindingID: bindResultSet.BindModelID,
},
Image: models.ImageBinding{
Type: preparation.ImageType,
Type: "Image",
ImageID: config.Image,
},
},
@ -207,11 +238,11 @@ func (s *taskService) buildSubmitTaskReq(ctx context.Context, authData *models.A
{
ClusterID: clusterID,
Runtime: models.Runtime{
Envs: nil,
Params: nil,
Envs: config.RunArgs,
Params: config.RunArgs,
},
Code: models.CodeInfo{
Type: preparation.CodeType,
Type: preparation.TaskBindingType,
BindingID: bindResultSet.BindCodeID,
},
Resources: config.Resource.Resources,
@ -226,7 +257,7 @@ func (s *taskService) buildSubmitTaskReq(ctx context.Context, authData *models.A
{
TargetJobID: MainTaskID,
InputParams: models.InputParams{
PackageName: "name",
PackageName: "Name",
ClusterID: "ClusterID",
Output: "Output",
},

Binary file not shown.