diff --git a/pkgs/distlock/internal/acquire_actor.go b/pkgs/distlock/internal/acquire_actor.go index 35fd1a0..a26a62a 100644 --- a/pkgs/distlock/internal/acquire_actor.go +++ b/pkgs/distlock/internal/acquire_actor.go @@ -173,8 +173,6 @@ func (a *AcquireActor) doAcquiring() error { return err } - logger.Std.Infof("wait to: %d", index) - // 等待本地状态同步到最新 // TODO 配置等待时间 err = a.providersActor.WaitLocalIndexTo(ctx, index) @@ -190,7 +188,6 @@ func (a *AcquireActor) doAcquiring() error { // 测试锁,并获得锁数据 reqData, err := a.providersActor.TestLockRequestAndMakeData(req.Request) - logger.Std.Infof("6") if err != nil { req.LastErr = err continue diff --git a/pkgs/logger/utils.go b/pkgs/logger/utils.go index a11b618..04d9c50 100644 --- a/pkgs/logger/utils.go +++ b/pkgs/logger/utils.go @@ -11,24 +11,23 @@ type structFormatter struct { } func (f *structFormatter) String() string { - typ := reflect.TypeOf(f.val) - val := reflect.ValueOf(f.val) - - kind := typ.Kind() + realVal := reflect.ValueOf(f.val) + for { + kind := realVal.Type().Kind() + + if kind == reflect.Struct { + sb := strings.Builder{} + f.structString(realVal, &sb) + return sb.String() + } - if kind == reflect.Struct { - sb := strings.Builder{} - f.structString(val, &sb) - return sb.String() - } + if kind == reflect.Pointer { + realVal = realVal.Elem() + continue + } - if kind == reflect.Pointer { - sb := strings.Builder{} - f.structString(val.Elem(), &sb) - return sb.String() + return fmt.Sprintf("%v", f.val) } - - return fmt.Sprintf("%v", f.val) } func (f *structFormatter) structString(val reflect.Value, strBuilder *strings.Builder) { @@ -94,8 +93,7 @@ func (f *structFormatter) structString(val reflect.Value, strBuilder *strings.Bu // FormatStruct 输出结构体的内容。 // 1. 数组类型只会输出长度 -// 2. 内部的结构体的内容不会再输出 -// 3. 支持参数是一层的指针 +// 2. 内部的结构体的内容不会再输出,包括embeded字段 func FormatStruct(val any) any { return &structFormatter{ val: val, diff --git a/sdks/pcm/models.go b/sdks/pcm/models.go new file mode 100644 index 0000000..1123eb4 --- /dev/null +++ b/sdks/pcm/models.go @@ -0,0 +1,36 @@ +package pcmsdk + +import schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler" + +type Participant struct { + ID schsdk.SlwNodeID `json:"id"` + Name string `json:"name"` + Type string `json:"type"` +} + +type Image struct { + ImageID schsdk.SlwNodeImageID `json:"imageID"` + ImageName string `json:"imageName"` + ImageStatus string `json:"imageStatus"` +} + +type ResourceID string + +type Resource struct { + ParticipantID schsdk.SlwNodeID `json:"participantID"` + ParticipantName string `json:"participantName"` + SpecName string `json:"specName"` + SpecID ResourceID `json:"specId"` + SpecPrice float64 `json:"specPrice"` +} + +type TaskID string + +type TaskStatus string + +const ( + TaskStatusPending TaskStatus = "Pending" + TaskStatusRunning TaskStatus = "Running" + TaskStatusSuccess TaskStatus = "Success" + TaskStatuFailed TaskStatus = "Failed" +) diff --git a/sdks/pcm/pcm.go b/sdks/pcm/pcm.go index 417acd8..6aba911 100644 --- a/sdks/pcm/pcm.go +++ b/sdks/pcm/pcm.go @@ -4,27 +4,29 @@ import ( "fmt" "net/url" "strings" + "time" + "gitlink.org.cn/cloudream/common/sdks" schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler" - uopsdk "gitlink.org.cn/cloudream/common/sdks/unifyops" myhttp "gitlink.org.cn/cloudream/common/utils/http" "gitlink.org.cn/cloudream/common/utils/serder" ) -const CORRECT_CODE int = 200 +const CodeOK int = 200 type UploadImageReq struct { - SlwNodeID uopsdk.SlwNodeID `json:"slwNodeID"` + SlwNodeID schsdk.SlwNodeID `json:"slwNodeID"` ImagePath string `json:"imagePath"` } type UploadImageResp struct { Result string `json:"result"` - ImageID uopsdk.SlwNodeImageID `json:"imageID"` + ImageID schsdk.SlwNodeImageID `json:"imageID"` } +// TODO func (c *Client) UploadImage(req UploadImageReq) (*UploadImageResp, error) { - url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/uploadImage") + url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/uploadImage") if err != nil { return nil, err } @@ -43,7 +45,7 @@ func (c *Client) UploadImage(req UploadImageReq) (*UploadImageResp, error) { return nil, fmt.Errorf("parsing response: %w", err) } - if codeResp.Code == CORRECT_CODE { + if codeResp.Code == CodeOK { return &codeResp.Data, nil } @@ -53,200 +55,285 @@ func (c *Client) UploadImage(req UploadImageReq) (*UploadImageResp, error) { return nil, fmt.Errorf("unknow response content type: %s", contType) } +type GetParticipantsResp struct { + Participants []Participant +} + +func (c *Client) GetParticipants() (*GetParticipantsResp, error) { + type Resp struct { + Code int `json:"code"` + Message string `json:"message"` + Participants []Participant `json:"participants"` + } + + url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/uploadImage") + if err != nil { + return nil, err + } + rawResp, err := myhttp.GetJSON(url, myhttp.RequestParam{}) + if err != nil { + return nil, err + } + + resp, err := myhttp.ParseJSONResponse[Resp](rawResp) + if err != nil { + return nil, err + } + + if resp.Code != CodeOK { + return nil, &sdks.CodeMessageError{ + Code: fmt.Sprintf("%d", resp.Code), + Message: resp.Message, + } + } + + return &GetParticipantsResp{ + Participants: resp.Participants, + }, nil +} + type GetImageListReq struct { - SlwNodeID int64 `json:"slwNodeID"` + PartID schsdk.SlwNodeID `json:"partId"` } type GetImageListResp struct { - ImageIDs []int64 `json:"imageIDs"` + Images []Image } func (c *Client) GetImageList(req GetImageListReq) (*GetImageListResp, error) { - url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/getImageList") + type Resp struct { + Success bool `json:"success"` + Images []Image `json:"images"` + ErrorMsg string `json:"errorMsg"` + } + + url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/getImageList") if err != nil { return nil, err } - resp, err := myhttp.PostJSON(url, myhttp.RequestParam{ + rawResp, err := myhttp.GetJSON(url, myhttp.RequestParam{ Body: req, }) if err != nil { return nil, err } - contType := resp.Header.Get("Content-Type") - if strings.Contains(contType, myhttp.ContentTypeJSON) { - - var codeResp response[GetImageListResp] - if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { - return nil, fmt.Errorf("parsing response: %w", err) - } - - if codeResp.Code == CORRECT_CODE { - return &codeResp.Data, nil - } + resp, err := myhttp.ParseJSONResponse[Resp](rawResp) + if err != nil { + return nil, err + } - return nil, codeResp.ToError() + if !resp.Success { + return nil, fmt.Errorf(resp.ErrorMsg) } - return nil, fmt.Errorf("unknow response content type: %s", contType) + return &GetImageListResp{ + Images: resp.Images, + }, nil } type DeleteImageReq struct { - SlwNodeID int64 `json:"slwNodeID"` - PCMJobID int64 `json:"pcmJobID"` + PartID schsdk.SlwNodeID `json:"partID"` + ImageID schsdk.SlwNodeImageID `json:"imageID"` } -type DeleteImageResp struct { - Result string `json:"result"` -} +func (c *Client) DeleteImage(req DeleteImageReq) error { + type Resp struct { + Success bool `json:"success"` + ErrorMsg string `json:"errorMsg"` + } -func (c *Client) DeleteImage(req DeleteImageReq) (*DeleteImageResp, error) { - url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/deleteImage") + url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/deleteImage") if err != nil { - return nil, err + return err } - resp, err := myhttp.PostJSON(url, myhttp.RequestParam{ + rawResp, err := myhttp.PostJSON(url, myhttp.RequestParam{ Body: req, }) if err != nil { - return nil, err + return err } - contType := resp.Header.Get("Content-Type") - if strings.Contains(contType, myhttp.ContentTypeJSON) { - - var codeResp response[DeleteImageResp] - if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { - return nil, fmt.Errorf("parsing response: %w", err) - } - - if codeResp.Code == CORRECT_CODE { - return &codeResp.Data, nil - } + resp, err := myhttp.ParseJSONResponse[Resp](rawResp) + if err != nil { + return err + } - return nil, codeResp.ToError() + if !resp.Success { + return fmt.Errorf(resp.ErrorMsg) } - return nil, fmt.Errorf("unknow response content type: %s", contType) + return nil } -type ScheduleTaskReq struct { - SlwNodeID uopsdk.SlwNodeID `json:"slwNodeID"` - Envs []schsdk.EnvVar `json:"envs"` - ImageID uopsdk.SlwNodeImageID `json:"imageID"` - CMDLine string `json:"cmdLine"` +type SubmitTaskReq struct { + PartID schsdk.SlwNodeID `json:"partId"` + ImageID schsdk.SlwNodeImageID `json:"imageId"` + ResourceID ResourceID `json:"resourceId"` + CMD string `json:"cmd"` + Params []schsdk.KVPair `json:"params"` + Envs []schsdk.KVPair `json:"envs"` } -type ScheduleTaskResp struct { - Result string `json:"result"` - PCMJobID int64 `json:"pcmJobID"` +type SubmitTaskResp struct { + TaskID TaskID } -func (c *Client) ScheduleTask(req ScheduleTaskReq) (*ScheduleTaskResp, error) { - url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/scheduleTask") +func (c *Client) SubmitTask(req SubmitTaskReq) (*SubmitTaskResp, error) { + type Resp struct { + Success bool `json:"success"` + TaskID TaskID `json:"taskId"` + ErrorMsg string `json:"errorMsg"` + } + + url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/submitTask") if err != nil { return nil, err } - resp, err := myhttp.PostJSON(url, myhttp.RequestParam{ + rawResp, err := myhttp.PostJSON(url, myhttp.RequestParam{ Body: req, }) if err != nil { return nil, err } - contType := resp.Header.Get("Content-Type") - if strings.Contains(contType, myhttp.ContentTypeJSON) { - - var codeResp response[ScheduleTaskResp] - if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { - return nil, fmt.Errorf("parsing response: %w", err) - } - - if codeResp.Code == CORRECT_CODE { - return &codeResp.Data, nil - } + resp, err := myhttp.ParseJSONResponse[Resp](rawResp) + if err != nil { + return nil, err + } - return nil, codeResp.ToError() + if !resp.Success { + return nil, fmt.Errorf(resp.ErrorMsg) } - return nil, fmt.Errorf("unknow response content type: %s", contType) + return &SubmitTaskResp{ + TaskID: resp.TaskID, + }, nil } -type GetTaskStatusReq struct { - SlwNodeID uopsdk.SlwNodeID `json:"slwNodeID"` - PCMJobID int64 `json:"pcmJobID"` +type GetTaskReq struct { + PartID schsdk.SlwNodeID `json:"partId"` + TaskID TaskID `json:"taskId"` } -type GetTaskStatusResp struct { - Result string `json:"result"` - Status string `json:"status"` +type GetTaskResp struct { + TaskStatus TaskStatus + TaskName string + StartedAt time.Time + CompletedAt time.Time } -func (c *Client) GetTaskStatus(req GetTaskStatusReq) (*GetTaskStatusResp, error) { - url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/getTaskStatus") +func (c *Client) GetTask(req GetTaskReq) (*GetTaskResp, error) { + type Resp struct { + Success bool `json:"success"` + Task struct { + TaskID TaskID `json:"taskId"` + TaskStatus TaskStatus `json:"taskStatus"` + TaskName string `json:"taskName"` + StartedAt serder.TimestampSecond `json:"startedAt"` + CompletedAt serder.TimestampSecond `json:"completedAt"` + } `json:"task"` + ErrorMsg string `json:"errorMsg"` + } + + url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/getTask") if err != nil { return nil, err } - resp, err := myhttp.PostJSON(url, myhttp.RequestParam{ + rawResp, err := myhttp.GetJSON(url, myhttp.RequestParam{ Body: req, }) if err != nil { return nil, err } - contType := resp.Header.Get("Content-Type") - if strings.Contains(contType, myhttp.ContentTypeJSON) { + resp, err := myhttp.ParseJSONResponse[Resp](rawResp) + if err != nil { + return nil, err + } - var codeResp response[GetTaskStatusResp] - if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { - return nil, fmt.Errorf("parsing response: %w", err) - } + if !resp.Success { + return nil, fmt.Errorf(resp.ErrorMsg) + } - if codeResp.Code == CORRECT_CODE { - return &codeResp.Data, nil - } + return &GetTaskResp{ + TaskStatus: resp.Task.TaskStatus, + TaskName: resp.Task.TaskName, + StartedAt: time.Time(resp.Task.StartedAt), + CompletedAt: time.Time(resp.Task.CompletedAt), + }, nil +} - return nil, codeResp.ToError() +type DeleteTaskReq struct { + PartID schsdk.SlwNodeID `json:"partId"` + TaskID TaskID `json:"taskId"` +} + +func (c *Client) DeleteTask(req DeleteTaskReq) error { + type Resp struct { + Success bool `json:"success"` + ErrorMsg string `json:"errorMsg"` } - return nil, fmt.Errorf("unknow response content type: %s", contType) + url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/deleteTask") + if err != nil { + return err + } + rawResp, err := myhttp.PostJSON(url, myhttp.RequestParam{ + Body: req, + }) + if err != nil { + return err + } + + resp, err := myhttp.ParseJSONResponse[Resp](rawResp) + if err != nil { + return err + } + + if !resp.Success { + return fmt.Errorf(resp.ErrorMsg) + } + + return nil } -type DeleteTaskReq struct { - SlwNodeID int64 `json:"slwNodeID"` - PCMJobID int64 `json:"pcmJobID"` +type GetResourceSpecs struct { + PartID schsdk.SlwNodeID `json:"partId"` } -type DeleteTaskResp struct { - Result string `json:"result"` +type GetResourceSpecsResp struct { + Resources []Resource } -func (c *Client) DeleteTask(req DeleteTaskReq) (*DeleteTaskResp, error) { - url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/deleteTask") +func (c *Client) GetResourceSpecs(req GetImageListReq) (*GetResourceSpecsResp, error) { + type Resp struct { + Success bool `json:"success"` + ResourceSpecs []Resource `json:"resourceSpecs"` + ErrorMsg string `json:"errorMsg"` + } + + url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/getResourceSpecs") if err != nil { return nil, err } - resp, err := myhttp.PostJSON(url, myhttp.RequestParam{ + rawResp, err := myhttp.GetJSON(url, myhttp.RequestParam{ Body: req, }) if err != nil { return nil, err } - contType := resp.Header.Get("Content-Type") - if strings.Contains(contType, myhttp.ContentTypeJSON) { - - var codeResp response[DeleteTaskResp] - if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { - return nil, fmt.Errorf("parsing response: %w", err) - } - - if codeResp.Code == CORRECT_CODE { - return &codeResp.Data, nil - } + resp, err := myhttp.ParseJSONResponse[Resp](rawResp) + if err != nil { + return nil, err + } - return nil, codeResp.ToError() + if !resp.Success { + return nil, fmt.Errorf(resp.ErrorMsg) } - return nil, fmt.Errorf("unknow response content type: %s", contType) + return &GetResourceSpecsResp{ + Resources: resp.ResourceSpecs, + }, nil } diff --git a/sdks/pcm/pcm_test.go b/sdks/pcm/pcm_test.go new file mode 100644 index 0000000..d16775f --- /dev/null +++ b/sdks/pcm/pcm_test.go @@ -0,0 +1,58 @@ +package pcmsdk + +import ( + "testing" + "time" + + . "github.com/smartystreets/goconvey/convey" + schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler" +) + +func Test_SubmitTask(t *testing.T) { + Convey("提交任务,查询任务", t, func() { + cli := NewClient(&Config{ + URL: "http://localhost:8889", + }) + + submitResp, err := cli.SubmitTask(SubmitTaskReq{ + PartID: 1711652475901054976, + ImageID: "1d1769857cd64c03928c8a1a4ee4a23f", + ResourceID: "6388d3c27f654fa5b11439a3d6098dbc", + CMD: "echo $asd", + Envs: []schsdk.KVPair{{ + Key: "asd", + Value: "hello", + }}, + Params: []schsdk.KVPair{}, + }) + So(err, ShouldBeNil) + + t.Logf("taskID: %s", submitResp.TaskID) + + taskResp, err := cli.GetTask(GetTaskReq{ + PartID: 1711652475901054976, + TaskID: submitResp.TaskID, + }) + So(err, ShouldBeNil) + + <-time.After(time.Second * 3) + + t.Logf("taskName: %s, taskStatus: %s, startedAt: %v", taskResp.TaskName, taskResp.TaskStatus, taskResp.StartedAt) + }) + +} + +func Test_GetImageList(t *testing.T) { + Convey("查询镜像列表", t, func() { + cli := NewClient(&Config{ + URL: "http://localhost:8889", + }) + + getReps, err := cli.GetImageList(GetImageListReq{ + PartID: 1711652475901054976, + }) + So(err, ShouldBeNil) + + t.Logf("imageList: %v", getReps.Images) + }) +} diff --git a/sdks/scheduler/models.go b/sdks/scheduler/models.go index 9af19ea..b0db970 100644 --- a/sdks/scheduler/models.go +++ b/sdks/scheduler/models.go @@ -23,6 +23,10 @@ type JobSetID string type ImageID string +type SlwNodeID int64 + +type SlwNodeImageID string + type JobSetInfo struct { Jobs []JobInfo `json:"jobs"` } @@ -111,11 +115,11 @@ type ImageJobFileInfo struct { type JobRuntimeInfo struct { Command string `json:"command"` - Envs []EnvVar `json:"envs"` + Envs []KVPair `json:"envs"` } -type EnvVar struct { - Var string `json:"var"` +type KVPair struct { + Key string `json:"key"` Value string `json:"value"` } diff --git a/sdks/storage/storage.go b/sdks/storage/storage.go index f8c7a5f..c8038e3 100644 --- a/sdks/storage/storage.go +++ b/sdks/storage/storage.go @@ -88,6 +88,7 @@ func (c *Client) StorageCreatePackage(req StorageCreatePackageReq) (*StorageCrea } type StorageGetInfoReq struct { + UserID int64 `json:"userID"` StorageID int64 `json:"storageID"` } type StorageGetInfoResp struct { @@ -103,7 +104,7 @@ func (c *Client) StorageGetInfo(req StorageGetInfoReq) (*StorageGetInfoResp, err } resp, err := myhttp.GetForm(url, myhttp.RequestParam{ - Body: req, + Query: req, }) if err != nil { return nil, err diff --git a/sdks/unifyops/models.go b/sdks/unifyops/models.go index a805bd9..8f8c2b9 100644 --- a/sdks/unifyops/models.go +++ b/sdks/unifyops/models.go @@ -3,6 +3,7 @@ package uopsdk import ( "gitlink.org.cn/cloudream/common/pkgs/mq" "gitlink.org.cn/cloudream/common/pkgs/types" + schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler" "gitlink.org.cn/cloudream/common/utils/serder" ) @@ -17,16 +18,12 @@ const ( ResourceTypeMemory ResourceType = "MEMORY" ) -type SlwNodeID int64 - -type SlwNodeImageID int64 - type SlwNode struct { - ID SlwNodeID `json:"ID"` - Name string `json:"name"` - SlwRegionID int64 `json:"slwRegionID"` - StgNodeID int64 `json:"stgNodeID"` - StorageID int64 `json:"StorageID"` + ID schsdk.SlwNodeID `json:"id"` + Name string `json:"name"` + SlwRegionID int64 `json:"slwRegionID"` + StgNodeID int64 `json:"stgNodeID"` + StorageID int64 `json:"StorageID"` } type ResourceData interface { @@ -48,19 +45,19 @@ type ResourceDataBase struct{} func (d *ResourceDataBase) Noop() {} -type DetailType[T any] struct { +type UnitValue[T any] struct { Unit string `json:"unit"` Value T `json:"value"` } type CPUResourceData struct { ResourceDataBase - Name ResourceType `json:"name" union:"CPU"` - Total DetailType[int64] `json:"total"` - Available DetailType[int64] `json:"available"` + Name ResourceType `json:"name" union:"CPU"` + Total UnitValue[int64] `json:"total"` + Available UnitValue[int64] `json:"available"` } -func NewCPUResourceData(total DetailType[int64], available DetailType[int64]) *CPUResourceData { +func NewCPUResourceData(total UnitValue[int64], available UnitValue[int64]) *CPUResourceData { return &CPUResourceData{ Name: ResourceTypeCPU, Total: total, @@ -70,12 +67,12 @@ func NewCPUResourceData(total DetailType[int64], available DetailType[int64]) *C type NPUResourceData struct { ResourceDataBase - Name ResourceType `json:"name" union:"NPU"` - Total DetailType[int64] `json:"total"` - Available DetailType[int64] `json:"available"` + Name ResourceType `json:"name" union:"NPU"` + Total UnitValue[int64] `json:"total"` + Available UnitValue[int64] `json:"available"` } -func NewNPUResourceData(total DetailType[int64], available DetailType[int64]) *NPUResourceData { +func NewNPUResourceData(total UnitValue[int64], available UnitValue[int64]) *NPUResourceData { return &NPUResourceData{ Name: ResourceTypeNPU, Total: total, @@ -85,12 +82,12 @@ func NewNPUResourceData(total DetailType[int64], available DetailType[int64]) *N type GPUResourceData struct { ResourceDataBase - Name ResourceType `json:"name" union:"GPU"` - Total DetailType[int64] `json:"total"` - Available DetailType[int64] `json:"available"` + Name ResourceType `json:"name" union:"GPU"` + Total UnitValue[int64] `json:"total"` + Available UnitValue[int64] `json:"available"` } -func NewGPUResourceData(total DetailType[int64], available DetailType[int64]) *GPUResourceData { +func NewGPUResourceData(total UnitValue[int64], available UnitValue[int64]) *GPUResourceData { return &GPUResourceData{ Name: ResourceTypeGPU, Total: total, @@ -100,12 +97,12 @@ func NewGPUResourceData(total DetailType[int64], available DetailType[int64]) *G type MLUResourceData struct { ResourceDataBase - Name ResourceType `json:"name" union:"MLU"` - Total DetailType[int64] `json:"total"` - Available DetailType[int64] `json:"available"` + Name ResourceType `json:"name" union:"MLU"` + Total UnitValue[int64] `json:"total"` + Available UnitValue[int64] `json:"available"` } -func NewMLUResourceData(total DetailType[int64], available DetailType[int64]) *MLUResourceData { +func NewMLUResourceData(total UnitValue[int64], available UnitValue[int64]) *MLUResourceData { return &MLUResourceData{ Name: ResourceTypeMLU, Total: total, @@ -115,12 +112,12 @@ func NewMLUResourceData(total DetailType[int64], available DetailType[int64]) *M type StorageResourceData struct { ResourceDataBase - Name ResourceType `json:"name" union:"STORAGE"` - Total DetailType[float64] `json:"total"` - Available DetailType[float64] `json:"available"` + Name ResourceType `json:"name" union:"STORAGE"` + Total UnitValue[float64] `json:"total"` + Available UnitValue[float64] `json:"available"` } -func NewStorageResourceData(total DetailType[float64], available DetailType[float64]) *StorageResourceData { +func NewStorageResourceData(total UnitValue[float64], available UnitValue[float64]) *StorageResourceData { return &StorageResourceData{ Name: ResourceTypeStorage, Total: total, @@ -130,12 +127,12 @@ func NewStorageResourceData(total DetailType[float64], available DetailType[floa type MemoryResourceData struct { ResourceDataBase - Name ResourceType `json:"name" union:"MEMORY"` - Total DetailType[float64] `json:"total"` - Available DetailType[float64] `json:"available"` + Name ResourceType `json:"name" union:"MEMORY"` + Total UnitValue[float64] `json:"total"` + Available UnitValue[float64] `json:"available"` } -func NewMemoryResourceData(total DetailType[float64], available DetailType[float64]) *MemoryResourceData { +func NewMemoryResourceData(total UnitValue[float64], available UnitValue[float64]) *MemoryResourceData { return &MemoryResourceData{ Name: ResourceTypeMemory, Total: total, diff --git a/sdks/unifyops/unifyops.go b/sdks/unifyops/unifyops.go index 55d3d30..75a8649 100644 --- a/sdks/unifyops/unifyops.go +++ b/sdks/unifyops/unifyops.go @@ -5,17 +5,14 @@ import ( "net/url" "strings" + schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler" myhttp "gitlink.org.cn/cloudream/common/utils/http" "gitlink.org.cn/cloudream/common/utils/serder" ) const CORRECT_CODE int = 200 -type GetAllSlwNodeInfoResp struct { - Nodes []SlwNode `json:"nodes"` -} - -func (c *Client) GetAllSlwNodeInfo() (*GetAllSlwNodeInfoResp, error) { +func (c *Client) GetAllSlwNodeInfo() ([]SlwNode, error) { url, err := url.JoinPath(c.baseURL, "/cmdb/resApi/getSlwNodeInfo") if err != nil { return nil, err @@ -27,13 +24,13 @@ func (c *Client) GetAllSlwNodeInfo() (*GetAllSlwNodeInfoResp, error) { contType := resp.Header.Get("Content-Type") if strings.Contains(contType, myhttp.ContentTypeJSON) { - var codeResp response[GetAllSlwNodeInfoResp] + var codeResp response[[]SlwNode] if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { return nil, fmt.Errorf("parsing response: %w", err) } if codeResp.Code == CORRECT_CODE { - return &codeResp.Data, nil + return codeResp.Data, nil } return nil, codeResp.ToError() @@ -43,7 +40,7 @@ func (c *Client) GetAllSlwNodeInfo() (*GetAllSlwNodeInfoResp, error) { } type GetOneResourceDataReq struct { - SlwNodeID SlwNodeID `json:"nodeId"` + SlwNodeID schsdk.SlwNodeID `json:"nodeId"` } func (c *Client) GetCPUData(node GetOneResourceDataReq) (*CPUResourceData, error) { @@ -250,15 +247,10 @@ func (c *Client) GetIndicatorData(node GetOneResourceDataReq) (*[]ResourceData, return nil, codeResp.ToError() } - mapToObjOpt := serder.MapToObjectOption{ - UnionTypes: []serder.TaggedUnionType{ - ResourceDataTaggedTypeUnion, - }, - } var ret []ResourceData for _, mp := range codeResp.Data { var data ResourceData - err := serder.MapToObject(mp, &data, mapToObjOpt) + err := serder.MapToObject(mp, &data) if err != nil { return nil, err } diff --git a/sdks/unifyops/unifyops_test.go b/sdks/unifyops/unifyops_test.go index c770c78..16dc52b 100644 --- a/sdks/unifyops/unifyops_test.go +++ b/sdks/unifyops/unifyops_test.go @@ -17,43 +17,43 @@ func Test_UnifyOps(t *testing.T) { So(err, ShouldBeNil) cpuData, err := cli.GetCPUData(GetOneResourceDataReq{ - SlwNodeID: slwNodeInfos.Nodes[0].ID, + SlwNodeID: slwNodeInfos[0].ID, }) So(err, ShouldBeNil) fmt.Printf("cpuData: %v\n", cpuData) gpuData, err := cli.GetGPUData(GetOneResourceDataReq{ - SlwNodeID: slwNodeInfos.Nodes[0].ID, + SlwNodeID: slwNodeInfos[0].ID, }) So(err, ShouldBeNil) fmt.Printf("gpuData: %v\n", gpuData) npuData, err := cli.GetNPUData(GetOneResourceDataReq{ - SlwNodeID: slwNodeInfos.Nodes[0].ID, + SlwNodeID: slwNodeInfos[0].ID, }) So(err, ShouldBeNil) fmt.Printf("npuData: %v\n", npuData) mluData, err := cli.GetMLUData(GetOneResourceDataReq{ - SlwNodeID: slwNodeInfos.Nodes[0].ID, + SlwNodeID: slwNodeInfos[0].ID, }) So(err, ShouldBeNil) fmt.Printf("mluData: %v\n", mluData) storageData, err := cli.GetStorageData(GetOneResourceDataReq{ - SlwNodeID: slwNodeInfos.Nodes[0].ID, + SlwNodeID: slwNodeInfos[0].ID, }) So(err, ShouldBeNil) fmt.Printf("storageData: %v\n", storageData) memoryData, err := cli.GetMemoryData(GetOneResourceDataReq{ - SlwNodeID: slwNodeInfos.Nodes[0].ID, + SlwNodeID: slwNodeInfos[0].ID, }) So(err, ShouldBeNil) fmt.Printf("memoryData: %v\n", memoryData) indicatorData, err := cli.GetIndicatorData(GetOneResourceDataReq{ - SlwNodeID: slwNodeInfos.Nodes[0].ID, + SlwNodeID: slwNodeInfos[0].ID, }) So(err, ShouldBeNil) fmt.Printf("indicatorData: %v\n", indicatorData) diff --git a/utils/http/http.go b/utils/http/http.go index b0505f3..463bd37 100644 --- a/utils/http/http.go +++ b/utils/http/http.go @@ -1,6 +1,7 @@ package http import ( + "bytes" "fmt" "io" "mime/multipart" @@ -9,6 +10,7 @@ import ( "strings" "gitlink.org.cn/cloudream/common/pkgs/iterator" + "gitlink.org.cn/cloudream/common/utils/math" "gitlink.org.cn/cloudream/common/utils/serder" ) @@ -120,7 +122,13 @@ func ParseJSONResponse[TBody any](resp *http.Response) (TBody, error) { return ret, nil } - return ret, fmt.Errorf("unknow response content type: %s, status: %d", contType, resp.StatusCode) + cont, err := io.ReadAll(resp.Body) + if err != nil { + return ret, fmt.Errorf("unknow response content type: %s, status: %d", contType, resp.StatusCode) + } + strCont := string(cont) + + return ret, fmt.Errorf("unknow response content type: %s, status: %d, body(prefix): %s", contType, resp.StatusCode, strCont[:math.Min(len(strCont), 200)]) } type MultiPartRequestParam struct { @@ -273,7 +281,13 @@ func prepareJSONBody(req *http.Request, body any) error { return nil } - req.Body = serder.ObjectToJSONStream(body) + data, err := serder.ObjectToJSON(body) + if err != nil { + return err + } + + req.ContentLength = int64(len(data)) + req.Body = io.NopCloser(bytes.NewReader(data)) return nil } @@ -297,7 +311,9 @@ func prepareFormBody(req *http.Request, body any) error { values.Add(k, fmt.Sprintf("%v", v)) } - req.Body = io.NopCloser(strings.NewReader(values.Encode())) + data := values.Encode() + req.Body = io.NopCloser(strings.NewReader(data)) + req.ContentLength = int64(len(data)) return nil } diff --git a/utils/serder/types.go b/utils/serder/types.go new file mode 100644 index 0000000..e6517a9 --- /dev/null +++ b/utils/serder/types.go @@ -0,0 +1,43 @@ +package serder + +import ( + "fmt" + "strconv" + "time" +) + +type TimestampSecond time.Time + +func (t *TimestampSecond) MarshalJSON() ([]byte, error) { + raw := time.Time(*t) + return []byte(fmt.Sprintf("%d", raw.Unix())), nil +} + +func (t *TimestampSecond) UnmarshalJSON(data []byte) error { + var timestamp int64 + var err error + if timestamp, err = strconv.ParseInt(string(data), 10, 64); err != nil { + return err + } + + *t = TimestampSecond(time.Unix(timestamp, 0)) + return nil +} + +type TimestampMilliSecond time.Time + +func (t *TimestampMilliSecond) MarshalJSON() ([]byte, error) { + raw := time.Time(*t) + return []byte(fmt.Sprintf("%d", raw.UnixMilli())), nil +} + +func (t *TimestampMilliSecond) UnmarshalJSON(data []byte) error { + var timestamp int64 + var err error + if timestamp, err = strconv.ParseInt(string(data), 10, 64); err != nil { + return err + } + + *t = TimestampMilliSecond(time.UnixMilli(timestamp)) + return nil +} diff --git a/utils/serder/types_test.go b/utils/serder/types_test.go new file mode 100644 index 0000000..c376cf8 --- /dev/null +++ b/utils/serder/types_test.go @@ -0,0 +1,35 @@ +package serder + +import ( + "encoding/json" + "testing" + "time" + + . "github.com/smartystreets/goconvey/convey" +) + +func Test_Timestamp(t *testing.T) { + Convey("秒级时间戳", t, func() { + str := "1698894747" + + var ts TimestampSecond + + err := json.Unmarshal([]byte(str), &ts) + So(err, ShouldBeNil) + + t := time.Time(ts) + So(t.Unix(), ShouldEqual, 1698894747) + }) + + Convey("毫秒级时间戳", t, func() { + str := "1698895130651" + + var ts TimestampMilliSecond + + err := json.Unmarshal([]byte(str), &ts) + So(err, ShouldBeNil) + + t := time.Time(ts) + So(t.UnixMilli(), ShouldEqual, 1698895130651) + }) +}