diff --git a/sdks/storage/bucket.go b/sdks/storage/bucket.go new file mode 100644 index 0000000..a4183a2 --- /dev/null +++ b/sdks/storage/bucket.go @@ -0,0 +1,86 @@ +package cdssdk + +import ( + "net/url" + + "gitlink.org.cn/cloudream/common/consts/errorcode" + myhttp "gitlink.org.cn/cloudream/common/utils/http" +) + +type BucketService struct { + *Client +} + +func (c *Client) Bucket() *BucketService { + return &BucketService{c} +} + +const BucketCreatePath = "/bucket/create" + +type BucketCreateReq struct { + UserID UserID `json:"userID" binding:"required"` + BucketName string `json:"bucketName" binding:"required"` +} + +type BucketCreateResp struct { + BucketID BucketID `json:"bucketID"` +} + +func (c *BucketService) Create(req BucketCreateReq) (*BucketCreateResp, error) { + url, err := url.JoinPath(c.baseURL, BucketCreatePath) + if err != nil { + return nil, err + } + + resp, err := myhttp.PostJSON(url, myhttp.RequestParam{ + Body: req, + }) + if err != nil { + return nil, err + } + + codeResp, err := myhttp.ParseJSONResponse[response[BucketCreateResp]](resp) + if err != nil { + return nil, err + } + + if codeResp.Code == errorcode.OK { + return &codeResp.Data, nil + } + + return nil, codeResp.ToError() +} + +const BucketDeletePath = "/bucket/delete" + +type BucketDeleteReq struct { + UserID UserID `json:"userID" binding:"required"` + BucketID BucketID `json:"bucketID" binding:"required"` +} + +type BucketDeleteResp struct{} + +func (c *BucketService) Delete(req BucketDeleteReq) (*BucketDeleteResp, error) { + url, err := url.JoinPath(c.baseURL, BucketDeletePath) + if err != nil { + return nil, err + } + + resp, err := myhttp.PostJSON(url, myhttp.RequestParam{ + Body: req, + }) + if err != nil { + return nil, err + } + + codeResp, err := myhttp.ParseJSONResponse[response[BucketDeleteResp]](resp) + if err != nil { + return nil, err + } + + if codeResp.Code == errorcode.OK { + return &codeResp.Data, nil + } + + return nil, codeResp.ToError() +} diff --git a/sdks/storage/cache.go b/sdks/storage/cache.go index a6866a1..e7574dd 100644 --- a/sdks/storage/cache.go +++ b/sdks/storage/cache.go @@ -7,7 +7,7 @@ import ( myhttp "gitlink.org.cn/cloudream/common/utils/http" ) -var CacheMovePackagePath = "/cache/movePackage" +const CacheMovePackagePath = "/cache/movePackage" type CacheMovePackageReq struct { UserID UserID `json:"userID"` diff --git a/sdks/storage/models.go b/sdks/storage/models.go index 577479b..e4cc3d8 100644 --- a/sdks/storage/models.go +++ b/sdks/storage/models.go @@ -112,6 +112,8 @@ type Object struct { Size int64 `db:"Size" json:"size,string"` FileHash string `db:"FileHash" json:"fileHash"` Redundancy Redundancy `db:"Redundancy" json:"redundancy"` + CreateTime time.Time `db:"CreateTime" json:"createTime"` + UpdateTime time.Time `db:"UpdateTime" json:"updateTime"` } type Node struct { @@ -132,6 +134,12 @@ type PinnedObject struct { CreateTime time.Time `db:"CreateTime" json:"createTime"` } +type Bucket struct { + BucketID BucketID `db:"BucketID" json:"bucketID"` + Name string `db:"Name" json:"name"` + CreatorID UserID `db:"CreatorID" json:"creatorID"` +} + type NodePackageCachingInfo struct { NodeID NodeID `json:"nodeID"` FileSize int64 `json:"fileSize"` diff --git a/sdks/storage/object.go b/sdks/storage/object.go index 81fb5d7..abbefd4 100644 --- a/sdks/storage/object.go +++ b/sdks/storage/object.go @@ -7,17 +7,95 @@ import ( "strings" "gitlink.org.cn/cloudream/common/consts/errorcode" + "gitlink.org.cn/cloudream/common/pkgs/iterator" myhttp "gitlink.org.cn/cloudream/common/utils/http" "gitlink.org.cn/cloudream/common/utils/serder" ) +type ObjectService struct { + *Client +} + +func (c *Client) Object() *ObjectService { + return &ObjectService{ + Client: c, + } +} + +const ObjectUploadPath = "/object/upload" + +type ObjectUploadReq struct { + ObjectUploadInfo + Files UploadObjectIterator `json:"-"` +} + +type ObjectUploadInfo struct { + UserID UserID `json:"userID" binding:"required"` + PackageID PackageID `json:"packageID" binding:"required"` + NodeAffinity *NodeID `json:"nodeAffinity"` +} + +type IterObjectUpload struct { + Path string + File io.ReadCloser +} + +type UploadObjectIterator = iterator.Iterator[*IterObjectUpload] + +type ObjectUploadResp struct{} + +func (c *ObjectService) Upload(req ObjectUploadReq) (*ObjectUploadResp, error) { + url, err := url.JoinPath(c.baseURL, ObjectUploadPath) + if err != nil { + return nil, err + } + + infoJSON, err := serder.ObjectToJSON(req) + if err != nil { + return nil, fmt.Errorf("upload info to json: %w", err) + } + + resp, err := myhttp.PostMultiPart(url, myhttp.MultiPartRequestParam{ + Form: map[string]string{"info": string(infoJSON)}, + Files: iterator.Map(req.Files, func(src *IterObjectUpload) (*myhttp.IterMultiPartFile, error) { + return &myhttp.IterMultiPartFile{ + FieldName: "files", + FileName: src.Path, + File: src.File, + }, nil + }), + }) + if err != nil { + return nil, err + } + + contType := resp.Header.Get("Content-Type") + if strings.Contains(contType, myhttp.ContentTypeJSON) { + var codeResp response[ObjectUploadResp] + if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { + return nil, fmt.Errorf("parsing response: %w", err) + } + + if codeResp.Code == errorcode.OK { + return &codeResp.Data, nil + } + + return nil, codeResp.ToError() + } + + return nil, fmt.Errorf("unknow response content type: %s", contType) + +} + +const ObjectDownloadPath = "/object/download" + type ObjectDownloadReq struct { UserID int64 `json:"userID"` ObjectID int64 `json:"objectID"` } -func (c *Client) ObjectDownload(req ObjectDownloadReq) (io.ReadCloser, error) { - url, err := url.JoinPath(c.baseURL, "/object/download") +func (c *ObjectService) Download(req ObjectDownloadReq) (io.ReadCloser, error) { + url, err := url.JoinPath(c.baseURL, ObjectDownloadPath) if err != nil { return nil, err } @@ -47,7 +125,7 @@ func (c *Client) ObjectDownload(req ObjectDownloadReq) (io.ReadCloser, error) { return nil, fmt.Errorf("unknow response content type: %s", contType) } -var ObjectGetPackageObjectsPath = "/object/getPackageObjects" +const ObjectGetPackageObjectsPath = "/object/getPackageObjects" type ObjectGetPackageObjectsReq struct { UserID UserID `json:"userID"` @@ -57,7 +135,7 @@ type ObjectGetPackageObjectsResp struct { Objects []Object `json:"objects"` } -func (c *Client) ObjectGetPackageObjects(req ObjectGetPackageObjectsReq) (*ObjectGetPackageObjectsResp, error) { +func (c *ObjectService) GetPackageObjects(req ObjectGetPackageObjectsReq) (*ObjectGetPackageObjectsResp, error) { url, err := url.JoinPath(c.baseURL, ObjectGetPackageObjectsPath) if err != nil { return nil, err diff --git a/sdks/storage/package.go b/sdks/storage/package.go index c264a21..26a8931 100644 --- a/sdks/storage/package.go +++ b/sdks/storage/package.go @@ -2,16 +2,24 @@ package cdssdk import ( "fmt" - "io" "net/url" "strings" "gitlink.org.cn/cloudream/common/consts/errorcode" - "gitlink.org.cn/cloudream/common/pkgs/iterator" myhttp "gitlink.org.cn/cloudream/common/utils/http" "gitlink.org.cn/cloudream/common/utils/serder" ) +type PackageService struct { + *Client +} + +func (c *Client) Package() *PackageService { + return &PackageService{c} +} + +const PackageGetPath = "/package/get" + type PackageGetReq struct { UserID UserID `json:"userID"` PackageID PackageID `json:"packageID"` @@ -20,8 +28,8 @@ type PackageGetResp struct { Package } -func (c *Client) PackageGet(req PackageGetReq) (*PackageGetResp, error) { - url, err := url.JoinPath(c.baseURL, "/package/get") +func (c *PackageService) Get(req PackageGetReq) (*PackageGetResp, error) { + url, err := url.JoinPath(c.baseURL, PackageGetPath) if err != nil { return nil, err } @@ -45,66 +53,41 @@ func (c *Client) PackageGet(req PackageGetReq) (*PackageGetResp, error) { return nil, codeResp.ToError() } -type PackageUploadReq struct { - UserID UserID `json:"userID"` - BucketID BucketID `json:"bucketID"` - Name string `json:"name"` - NodeAffinity *NodeID `json:"nodeAffinity"` - Files PackageUploadFileIterator `json:"-"` -} +const PackageCreatePath = "/package/create" -type IterPackageUploadFile struct { - Path string - File io.ReadCloser +type PackageCreateReq struct { + UserID UserID `json:"userID"` + BucketID BucketID `json:"bucketID"` + Name string `json:"name"` } -type PackageUploadFileIterator = iterator.Iterator[*IterPackageUploadFile] - -type PackageUploadResp struct { +type PackageCreateResp struct { PackageID PackageID `json:"packageID,string"` } -func (c *Client) PackageUpload(req PackageUploadReq) (*PackageUploadResp, error) { - url, err := url.JoinPath(c.baseURL, "/package/upload") +func (s *PackageService) Create(req PackageCreateReq) (*PackageCreateResp, error) { + url, err := url.JoinPath(s.baseURL, PackageCreatePath) if err != nil { return nil, err } - infoJSON, err := serder.ObjectToJSON(req) - if err != nil { - return nil, fmt.Errorf("package info to json: %w", err) - } - - resp, err := myhttp.PostMultiPart(url, myhttp.MultiPartRequestParam{ - Form: map[string]string{"info": string(infoJSON)}, - Files: iterator.Map(req.Files, func(src *IterPackageUploadFile) (*myhttp.IterMultiPartFile, error) { - return &myhttp.IterMultiPartFile{ - FieldName: "files", - FileName: src.Path, - File: src.File, - }, nil - }), + resp, 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[PackageUploadResp] - if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { - return nil, fmt.Errorf("parsing response: %w", err) - } - - if codeResp.Code == errorcode.OK { - return &codeResp.Data, nil - } - - return nil, codeResp.ToError() + codeResp, err := myhttp.ParseJSONResponse[response[PackageCreateResp]](resp) + if err != nil { + return nil, err } - return nil, fmt.Errorf("unknow response content type: %s", contType) + if codeResp.Code == errorcode.OK { + return &codeResp.Data, nil + } + return nil, codeResp.ToError() } type PackageDeleteReq struct { @@ -112,7 +95,7 @@ type PackageDeleteReq struct { PackageID PackageID `json:"packageID"` } -func (c *Client) PackageDelete(req PackageDeleteReq) error { +func (c *PackageService) Delete(req PackageDeleteReq) error { url, err := url.JoinPath(c.baseURL, "/package/delete") if err != nil { return err @@ -152,7 +135,7 @@ type PackageGetCachedNodesResp struct { PackageCachingInfo } -func (c *Client) PackageGetCachedNodes(req PackageGetCachedNodesReq) (*PackageGetCachedNodesResp, error) { +func (c *PackageService) GetCachedNodes(req PackageGetCachedNodesReq) (*PackageGetCachedNodesResp, error) { url, err := url.JoinPath(c.baseURL, "/package/getCachedNodes") if err != nil { return nil, err @@ -190,7 +173,7 @@ type PackageGetLoadedNodesResp struct { NodeIDs []NodeID `json:"nodeIDs"` } -func (c *Client) PackageGetLoadedNodes(req PackageGetLoadedNodesReq) (*PackageGetLoadedNodesResp, error) { +func (c *PackageService) GetLoadedNodes(req PackageGetLoadedNodesReq) (*PackageGetLoadedNodesResp, error) { url, err := url.JoinPath(c.baseURL, "/package/getLoadedNodes") if err != nil { return nil, err diff --git a/sdks/storage/storage_test.go b/sdks/storage/storage_test.go index dc6b13f..5521a47 100644 --- a/sdks/storage/storage_test.go +++ b/sdks/storage/storage_test.go @@ -23,16 +23,24 @@ func Test_PackageGet(t *testing.T) { } pkgName := uuid.NewString() - upResp, err := cli.PackageUpload(PackageUploadReq{ + createResp, err := cli.Package().Create(PackageCreateReq{ UserID: 1, BucketID: 1, Name: pkgName, + }) + So(err, ShouldBeNil) + + _, err = cli.Object().Upload(ObjectUploadReq{ + ObjectUploadInfo: ObjectUploadInfo{ + UserID: 1, + PackageID: createResp.PackageID, + }, Files: iterator.Array( - &IterPackageUploadFile{ + &IterObjectUpload{ Path: "test", File: io.NopCloser(bytes.NewBuffer(fileData)), }, - &IterPackageUploadFile{ + &IterObjectUpload{ Path: "test2", File: io.NopCloser(bytes.NewBuffer(fileData)), }, @@ -40,18 +48,18 @@ func Test_PackageGet(t *testing.T) { }) So(err, ShouldBeNil) - getResp, err := cli.PackageGet(PackageGetReq{ + getResp, err := cli.Package().Get(PackageGetReq{ UserID: 1, - PackageID: upResp.PackageID, + PackageID: createResp.PackageID, }) So(err, ShouldBeNil) - So(getResp.PackageID, ShouldEqual, upResp.PackageID) + So(getResp.PackageID, ShouldEqual, createResp.PackageID) So(getResp.Package.Name, ShouldEqual, pkgName) - err = cli.PackageDelete(PackageDeleteReq{ + err = cli.Package().Delete(PackageDeleteReq{ UserID: 1, - PackageID: upResp.PackageID, + PackageID: createResp.PackageID, }) So(err, ShouldBeNil) }) @@ -69,17 +77,27 @@ func Test_Object(t *testing.T) { } nodeAff := NodeID(2) - upResp, err := cli.PackageUpload(PackageUploadReq{ - UserID: 1, - BucketID: 1, - Name: uuid.NewString(), - NodeAffinity: &nodeAff, + + pkgName := uuid.NewString() + createResp, err := cli.Package().Create(PackageCreateReq{ + UserID: 1, + BucketID: 1, + Name: pkgName, + }) + So(err, ShouldBeNil) + + _, err = cli.Object().Upload(ObjectUploadReq{ + ObjectUploadInfo: ObjectUploadInfo{ + UserID: 1, + PackageID: createResp.PackageID, + NodeAffinity: &nodeAff, + }, Files: iterator.Array( - &IterPackageUploadFile{ + &IterObjectUpload{ Path: "test", File: io.NopCloser(bytes.NewBuffer(fileData)), }, - &IterPackageUploadFile{ + &IterObjectUpload{ Path: "test2", File: io.NopCloser(bytes.NewBuffer(fileData)), }, @@ -98,9 +116,9 @@ func Test_Object(t *testing.T) { // So(downFileData, ShouldResemble, fileData) // downFs.Close() - err = cli.PackageDelete(PackageDeleteReq{ + err = cli.Package().Delete(PackageDeleteReq{ UserID: 1, - PackageID: upResp.PackageID, + PackageID: createResp.PackageID, }) So(err, ShouldBeNil) }) @@ -117,16 +135,25 @@ func Test_Storage(t *testing.T) { fileData[i] = byte(i) } - upResp, err := cli.PackageUpload(PackageUploadReq{ + pkgName := uuid.NewString() + createResp, err := cli.Package().Create(PackageCreateReq{ UserID: 1, BucketID: 1, - Name: uuid.NewString(), + Name: pkgName, + }) + So(err, ShouldBeNil) + + _, err = cli.Object().Upload(ObjectUploadReq{ + ObjectUploadInfo: ObjectUploadInfo{ + UserID: 1, + PackageID: createResp.PackageID, + }, Files: iterator.Array( - &IterPackageUploadFile{ + &IterObjectUpload{ Path: "test", File: io.NopCloser(bytes.NewBuffer(fileData)), }, - &IterPackageUploadFile{ + &IterObjectUpload{ Path: "test2", File: io.NopCloser(bytes.NewBuffer(fileData)), }, @@ -136,14 +163,14 @@ func Test_Storage(t *testing.T) { _, err = cli.StorageLoadPackage(StorageLoadPackageReq{ UserID: 1, - PackageID: upResp.PackageID, + PackageID: createResp.PackageID, StorageID: 1, }) So(err, ShouldBeNil) - err = cli.PackageDelete(PackageDeleteReq{ + err = cli.Package().Delete(PackageDeleteReq{ UserID: 1, - PackageID: upResp.PackageID, + PackageID: createResp.PackageID, }) So(err, ShouldBeNil) }) @@ -160,16 +187,25 @@ func Test_Cache(t *testing.T) { fileData[i] = byte(i) } - upResp, err := cli.PackageUpload(PackageUploadReq{ + pkgName := uuid.NewString() + createResp, err := cli.Package().Create(PackageCreateReq{ UserID: 1, BucketID: 1, - Name: uuid.NewString(), + Name: pkgName, + }) + So(err, ShouldBeNil) + + _, err = cli.Object().Upload(ObjectUploadReq{ + ObjectUploadInfo: ObjectUploadInfo{ + UserID: 1, + PackageID: createResp.PackageID, + }, Files: iterator.Array( - &IterPackageUploadFile{ + &IterObjectUpload{ Path: "test.txt", File: io.NopCloser(bytes.NewBuffer(fileData)), }, - &IterPackageUploadFile{ + &IterObjectUpload{ Path: "test2.txt", File: io.NopCloser(bytes.NewBuffer(fileData)), }, @@ -179,14 +215,14 @@ func Test_Cache(t *testing.T) { _, err = cli.CacheMovePackage(CacheMovePackageReq{ UserID: 1, - PackageID: upResp.PackageID, + PackageID: createResp.PackageID, NodeID: 1, }) So(err, ShouldBeNil) - err = cli.PackageDelete(PackageDeleteReq{ + err = cli.Package().Delete(PackageDeleteReq{ UserID: 1, - PackageID: upResp.PackageID, + PackageID: createResp.PackageID, }) So(err, ShouldBeNil) }) @@ -197,14 +233,14 @@ func Test_GetNodeInfos(t *testing.T) { cli := NewClient(&Config{ URL: "http://localhost:7890", }) - resp1, err := cli.PackageGetCachedNodes(PackageGetCachedNodesReq{ + resp1, err := cli.Package().GetCachedNodes(PackageGetCachedNodesReq{ PackageID: 11, UserID: 1, }) So(err, ShouldBeNil) fmt.Printf("resp1: %v\n", resp1) - resp2, err := cli.PackageGetLoadedNodes(PackageGetLoadedNodesReq{ + resp2, err := cli.Package().GetLoadedNodes(PackageGetLoadedNodesReq{ PackageID: 11, UserID: 1, })