diff --git a/bucket_inventory.go b/bucket_inventory.go new file mode 100644 index 0000000..17ed781 --- /dev/null +++ b/bucket_inventory.go @@ -0,0 +1,134 @@ +package cos + +import ( + "context" + "encoding/xml" + "fmt" + "net/http" +) + +// Notice bucket_inventory only for test. can not use + +// BucketGetInventoryResult same struct to options +type BucketGetInventoryResult BucketPutInventoryOptions + +// BucketListInventoryConfiguartion same struct to options +type BucketListInventoryConfiguartion BucketPutInventoryOptions + +// BucketInventoryFilter ... +type BucketInventoryFilter struct { + Prefix string `xml:"Prefix,omitempty"` +} + +// BucketInventoryOptionalFields ... +type BucketInventoryOptionalFields struct { + XMLName xml.Name `xml:"OptionalFields,omitempty"` + BucketInventoryFields []string `xml:"Field,omitempty"` +} + +// BucketInventorySchedule ... +type BucketInventorySchedule struct { + Frequency string `xml:"Frequency"` +} + +// BucketInventoryEncryption ... +type BucketInventoryEncryption struct { + XMLName xml.Name `xml:"Encryption"` + SSECOS string `xml:"SSE-COS,omitempty"` +} + +// BucketInventoryDestinationContent ... +type BucketInventoryDestinationContent struct { + Bucket string `xml:"Bucket"` + AccountId string `xml:"AccountId,omitempty"` + Prefix string `xml:"Prefix,omitempty"` + Format string `xml:"Format"` + Encryption *BucketInventoryEncryption `xml:"Encryption,omitempty"` +} + +// BucketInventoryDestination ... +type BucketInventoryDestination struct { + XMLName xml.Name `xml:"Destination"` + BucketDestination *BucketInventoryDestinationContent `xml:"COSBucketDestination"` +} + +// BucketPutInventoryOptions ... +type BucketPutInventoryOptions struct { + XMLName xml.Name `xml:"InventoryConfiguration"` + ID string `xml:"Id"` + IsEnabled string `xml:"IsEnabled"` + IncludedObjectVersions string `xml:"IncludedObjectVersions"` + Filter *BucketInventoryFilter `xml:"Filter,omitempty"` + OptionalFields *BucketInventoryOptionalFields `xml:"OptionalFields,omitempty"` + Schedule *BucketInventorySchedule `xml:"Schedule"` + Destination *BucketInventoryDestination `xml:"Destination"` +} + +// ListBucketInventoryConfigResult result of ListBucketInventoryConfiguration +type ListBucketInventoryConfigResult struct { + XMLName xml.Name `xml:"ListInventoryConfigurationResult"` + InventoryConfigurations []BucketListInventoryConfiguartion `xml:"InventoryConfiguration,omitempty"` + IsTruncated bool `xml:"IsTruncated,omitempty"` + ContinuationToken string `xml:"ContinuationToken,omitempty"` + NextContinuationToken string `xml:"NextContinuationToken,omitempty"` +} + +// PutBucketInventory https://cloud.tencent.com/document/product/436/33707 +func (s *BucketService) PutBucketInventoryTest(ctx context.Context, id string, opt *BucketPutInventoryOptions) (*Response, error) { + u := fmt.Sprintf("/?inventory&id=%s", id) + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: u, + method: http.MethodPut, + body: opt, + } + resp, err := s.client.send(ctx, &sendOpt) + return resp, err + +} + +// GetBucketInventory https://cloud.tencent.com/document/product/436/33705 +func (s *BucketService) GetBucketInventoryTest(ctx context.Context, id string) (*BucketGetInventoryResult, *Response, error) { + u := fmt.Sprintf("/?inventory&id=%s", id) + var res BucketGetInventoryResult + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: u, + method: http.MethodGet, + result: &res, + } + resp, err := s.client.send(ctx, &sendOpt) + return &res, resp, err +} + +// DeleteBucketInventory https://cloud.tencent.com/document/product/436/33704 +func (s *BucketService) DeleteBucketInventoryTest(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("/?inventory&id=%s", id) + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: u, + method: http.MethodDelete, + } + resp, err := s.client.send(ctx, &sendOpt) + return resp, err +} + +// ListBucketInventoryConfigurations https://cloud.tencent.com/document/product/436/33706 +func (s *BucketService) ListBucketInventoryConfigurationsTest(ctx context.Context, token string) (*ListBucketInventoryConfigResult, *Response, error) { + var res ListBucketInventoryConfigResult + var u string + if token == "" { + u = "/?inventory" + } else { + u = fmt.Sprintf("/?inventory&continuation-token=%s", encodeURIComponent(token)) + } + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: u, + method: http.MethodGet, + result: &res, + } + resp, err := s.client.send(ctx, &sendOpt) + return &res, resp, err + +} diff --git a/bucket_logging.go b/bucket_logging.go new file mode 100644 index 0000000..d4ea513 --- /dev/null +++ b/bucket_logging.go @@ -0,0 +1,53 @@ +package cos + +import ( + "context" + "encoding/xml" + "net/http" +) + +// Notice bucket logging function is testing, can not use. + +// BucketLoggingEnabled main struct of logging +type BucketLoggingEnabled struct { + TargetBucket string `xml:"TargetBucket"` + TargetPrefix string `xml:"TargetPrefix"` +} + +// BucketPutLoggingOptions is the options of PutBucketLogging +type BucketPutLoggingOptions struct { + XMLName xml.Name `xml:"BucketLoggingStatus"` + LoggingEnabled *BucketLoggingEnabled `xml:"LoggingEnabled"` +} + +// BucketGetLoggingResult is the result of GetBucketLogging +type BucketGetLoggingResult struct { + XMLName xml.Name `xml:"BucketLoggingStatus"` + LoggingEnabled *BucketLoggingEnabled `xml:"LoggingEnabled"` +} + +// PutBucketLogging https://cloud.tencent.com/document/product/436/17054 +func (s *BucketService) PutBucketLoggingTest(ctx context.Context, opt *BucketPutLoggingOptions) (*Response, error) { + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?logging", + method: http.MethodPut, + body: opt, + } + resp, err := s.client.send(ctx, &sendOpt) + return resp, err +} + +// GetBucketLogging https://cloud.tencent.com/document/product/436/17053 +func (s *BucketService) GetBucketLoggingTest(ctx context.Context) (*BucketGetLoggingResult, *Response, error) { + var res BucketGetLoggingResult + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?logging", + method: http.MethodGet, + result: &res, + } + resp, err := s.client.send(ctx, &sendOpt) + return &res, resp, err + +} diff --git a/bucket_replication.go b/bucket_replication.go new file mode 100644 index 0000000..d0a1a9a --- /dev/null +++ b/bucket_replication.go @@ -0,0 +1,73 @@ +package cos + +import ( + "context" + "encoding/xml" + "net/http" +) + +// ReplicationDestination is the sub struct of BucketReplicationRule +type ReplicationDestination struct { + Bucket string `xml:"Bucket"` + StorageClass string `xml:"StorageClass,omitempty"` +} + +// BucketReplicationRule is the main param of replication +type BucketReplicationRule struct { + ID string `xml:"ID,omitempty"` + Status string `xml:"Status"` + Prefix string `xml:"Prefix"` + Destination *ReplicationDestination `xml:"Destination"` +} + +// PutBucketReplicationOptions is the options of PutBucketReplication +type PutBucketReplicationOptions struct { + XMLName xml.Name `xml:"ReplicationConfiguration"` + Role string `xml:"Role"` + Rule []BucketReplicationRule `xml:"Rule"` +} + +// GetBucketReplicationResult is the result of GetBucketReplication +type GetBucketReplicationResult struct { + XMLName xml.Name `xml:"ReplicationConfiguration"` + Role string `xml:"Role"` + Rule []BucketReplicationRule `xml:"Rule"` +} + +// PutBucketReplication https://cloud.tencent.com/document/product/436/19223 +func (s *BucketService) PutBucketReplication(ctx context.Context, opt *PutBucketReplicationOptions) (*Response, error) { + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?replication", + method: http.MethodPut, + body: opt, + } + resp, err := s.client.send(ctx, &sendOpt) + return resp, err + +} + +// GetBucketReplication https://cloud.tencent.com/document/product/436/19222 +func (s *BucketService) GetBucketReplication(ctx context.Context) (*GetBucketReplicationResult, *Response, error) { + var res GetBucketReplicationResult + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?replication", + method: http.MethodGet, + result: &res, + } + resp, err := s.client.send(ctx, &sendOpt) + return &res, resp, err + +} + +// DeleteBucketReplication https://cloud.tencent.com/document/product/436/19221 +func (s *BucketService) DeleteBucketReplication(ctx context.Context) (*Response, error) { + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?replication", + method: http.MethodDelete, + } + resp, err := s.client.send(ctx, &sendOpt) + return resp, err +} diff --git a/bucket_version.go b/bucket_version.go new file mode 100644 index 0000000..b74527b --- /dev/null +++ b/bucket_version.go @@ -0,0 +1,45 @@ +package cos + +import ( + "context" + "encoding/xml" + "net/http" +) + +// BucketPutVersionOptions is the options of PutBucketVersioning +type BucketPutVersionOptions struct { + XMLName xml.Name `xml:"VersioningConfiguration"` + Status string `xml:"Status"` +} + +// BucketGetVersionResult is the result of GetBucketVersioning +type BucketGetVersionResult struct { + XMLName xml.Name `xml:"VersioningConfiguration"` + Status string `xml:"Status"` +} + +// PutVersion https://cloud.tencent.com/document/product/436/19889 +// Status has Suspended\Enabled +func (s *BucketService) PutVersioning(ctx context.Context, opt *BucketPutVersionOptions) (*Response, error) { + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?versioning", + method: http.MethodPut, + body: opt, + } + resp, err := s.client.send(ctx, &sendOpt) + return resp, err +} + +// GetVersion https://cloud.tencent.com/document/product/436/19888 +func (s *BucketService) GetVersioning(ctx context.Context) (*BucketGetVersionResult, *Response, error) { + var res BucketGetVersionResult + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?versioning", + method: http.MethodGet, + result: &res, + } + resp, err := s.client.send(ctx, &sendOpt) + return &res, resp, err +} diff --git a/costesting/ci_test.go b/costesting/ci_test.go index 2db4e04..90a7e67 100644 --- a/costesting/ci_test.go +++ b/costesting/ci_test.go @@ -185,6 +185,100 @@ func (s *CosTestSuite) TestPutGetDeleteCORS() { assert.Equal(s.T(), 1, len(v.Rules), "GetBucketCORS wrong number rules") } +func (s *CosTestSuite) TestVersionAndReplication() { + opt := &cos.BucketPutVersionOptions{ + // Enabled or Suspended, the versioning once opened can not close. + Status: "Enabled", + } + _, err := s.Client.Bucket.PutVersioning(context.Background(), opt) + assert.Nil(s.T(), err, "PutVersioning Failed") + v, _, err := s.Client.Bucket.GetVersioning(context.Background()) + assert.Nil(s.T(), err, "GetVersioning Failed") + assert.Equal(s.T(), "Enabled", v.Status, "Get Wrong Version status") + + repOpt := &cos.PutBucketReplicationOptions{ + // qcs::cam::uin/[UIN]:uin/[Subaccount] + Role: "qcs::cam::uin/2779643970:uin/2779643970", + Rule: []cos.BucketReplicationRule{ + { + ID: "1", + // Enabled or Disabled + Status: "Enabled", + Destination: &cos.ReplicationDestination{ + // qcs::cos:[Region]::[Bucketname-Appid] + Bucket: "qcs::cos:ap-beijing::alanbj-1251668577", + }, + }, + }, + } + + _, err = s.Client.Bucket.PutBucketReplication(context.Background(), repOpt) + assert.Nil(s.T(), err, "PutBucketReplication Failed") + vr, _, err := s.Client.Bucket.GetBucketReplication(context.Background()) + assert.Nil(s.T(), err, "GetBucketReplication Failed") + for _, r := range vr.Rule { + assert.Equal(s.T(), "Enabled", r.Status, "Get Wrong Version status") + assert.Equal(s.T(), "qcs::cos:ap-beijing::alanbj-1251668577", r.Destination.Bucket, "Get Wrong Version status") + + } + _, err = s.Client.Bucket.DeleteBucketReplication(context.Background()) + assert.Nil(s.T(), err, "DeleteBucketReplication Failed") +} + +func (s *CosTestSuite) TestBucketInventory() { + id := "test1" + opt := &cos.BucketPutInventoryOptions{ + ID: id, + // True or False + IsEnabled: "True", + IncludedObjectVersions: "All", + Filter: &cos.BucketInventoryFilter{ + Prefix: "test", + }, + OptionalFields: &cos.BucketInventoryOptionalFields{ + BucketInventoryFields: []string{ + "Size", "LastModifiedDate", + }, + }, + Schedule: &cos.BucketInventorySchedule{ + // Weekly or Daily + Frequency: "Daily", + }, + Destination: &cos.BucketInventoryDestination{ + BucketDestination: &cos.BucketInventoryDestinationContent{ + Bucket: "qcs::cos:ap-guangzhou::alangz-1251668577", + Format: "CSV", + }, + }, + } + _, err := s.Client.Bucket.PutBucketInventory(context.Background(), id, opt) + assert.Nil(s.T(), err, "PutBucketInventory Failed") + v, _, err := s.Client.Bucket.GetBucketInventory(context.Background(), id) + assert.Nil(s.T(), err, "GetBucketInventory Failed") + assert.Equal(s.T(), "test1", v.ID, "Get Wrong inventory id") + assert.Equal(s.T(), "True", v.IsEnabled, "Get Wrong inventory isenabled") + assert.Equal(s.T(), "qcs::cos:ap-guangzhou::alangz-1251668577", v.Destination.BucketDestination.Bucket, "Get Wrong inventory isenabled") + + _, err = s.Client.Bucket.DeleteBucketInventory(context.Background(), id) + assert.Nil(s.T(), err, "DeleteBucketInventory Failed") + +} + +func (s *CosTestSuite) TestBucketLogging() { + opt := &cos.BucketPutLoggingOptions{ + LoggingEnabled: &cos.BucketLoggingEnabled{ + // The bucket must same region. + TargetBucket: "alangz-1251668577", + }, + } + _, err := s.Client.Bucket.PutBucketLogging(context.Background(), opt) + assert.Nil(s.T(), err, "PutBucketLogging Failed") + v, _, err := s.Client.Bucket.GetBucketLogging(context.Background()) + assert.Nil(s.T(), err, "GetBucketLogging Failed") + assert.Equal(s.T(), "alangz-1251668577", v.LoggingEnabled.TargetBucket, "Get Wrong Version status") + +} + func (s *CosTestSuite) TestPutGetDeleteLifeCycle() { lc := &cos.BucketPutLifecycleOptions{ Rules: []cos.BucketLifecycleRule{ @@ -351,7 +445,7 @@ func (s *CosTestSuite) TestPutObjectRestore() { Tier: "Expedited", }, } - resp, _ := s.Client.Object.PutRestore(context.Background(), name, opt) + resp, _ := s.Client.Object.PostRestore(context.Background(), name, opt) retCode := resp.StatusCode if retCode != 200 && retCode != 202 && retCode != 409 { right := false diff --git a/example/bucket/deleteReplication.go b/example/bucket/deleteReplication.go new file mode 100644 index 0000000..9f9794b --- /dev/null +++ b/example/bucket/deleteReplication.go @@ -0,0 +1,36 @@ +package main + +import ( + "context" + "net/url" + "os" + + "net/http" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func main() { + u, _ := url.Parse("https://alanbj-1251668577.cos.ap-beijing.myqcloud.com") + b := &cos.BaseURL{ + BucketURL: u, + } + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + _, err := c.Bucket.DeleteBucketReplication(context.Background()) + if err != nil { + panic(err) + } +} diff --git a/example/bucket/getReplication.go b/example/bucket/getReplication.go new file mode 100644 index 0000000..8e77474 --- /dev/null +++ b/example/bucket/getReplication.go @@ -0,0 +1,41 @@ +package main + +import ( + "context" + "fmt" + "net/url" + "os" + + "net/http" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func main() { + u, _ := url.Parse("https://alanbj-1251668577.cos.ap-beijing.myqcloud.com") + b := &cos.BaseURL{ + BucketURL: u, + } + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + v, _, err := c.Bucket.GetBucketReplication(context.Background()) + if err != nil { + panic(err) + } + for _, r := range v.Rule { + + fmt.Printf("%s, %s\n", r.Status, r.ID) + } +} diff --git a/example/bucket/getVersioning.go b/example/bucket/getVersioning.go new file mode 100644 index 0000000..f9a1aae --- /dev/null +++ b/example/bucket/getVersioning.go @@ -0,0 +1,39 @@ +package main + +import ( + "context" + "fmt" + "net/url" + "os" + + "net/http" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func main() { + u, _ := url.Parse("https://alanbj-1251668577.cos.ap-beijing.myqcloud.com") + b := &cos.BaseURL{ + BucketURL: u, + } + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + v, _, err := c.Bucket.GetVersioning(context.Background()) + if err != nil { + panic(err) + } + + fmt.Printf("status is %s \n", v.Status) +} diff --git a/example/bucket/putReplication.go b/example/bucket/putReplication.go new file mode 100644 index 0000000..c0b99a4 --- /dev/null +++ b/example/bucket/putReplication.go @@ -0,0 +1,51 @@ +package main + +import ( + "context" + "net/url" + "os" + + "net/http" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func main() { + u, _ := url.Parse("https://alanbj-1251668577.cos.ap-beijing.myqcloud.com") + b := &cos.BaseURL{ + BucketURL: u, + } + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + opt := &cos.PutBucketReplicationOptions{ + // qcs::cam::uin/[UIN]:uin/[Subaccount] + Role: "qcs::cam::uin/2779643970:uin/2779643970", + Rule: []cos.BucketReplicationRule{ + { + ID: "1", + // Enabled or Disabled + Status: "Enabled", + Destination: &cos.ReplicationDestination{ + // qcs::cos:[Region]::[Bucketname-Appid] + Bucket: "qcs::cos:ap-guangzhou::alangz-1251668577", + }, + }, + }, + } + _, err := c.Bucket.PutBucketReplication(context.Background(), opt) + if err != nil { + panic(err) + } +} diff --git a/example/bucket/putVersioning.go b/example/bucket/putVersioning.go new file mode 100644 index 0000000..5b35a21 --- /dev/null +++ b/example/bucket/putVersioning.go @@ -0,0 +1,41 @@ +package main + +import ( + "context" + "net/url" + "os" + + "net/http" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func main() { + u, _ := url.Parse("https://alanbj-1251668577.cos.ap-beijing.myqcloud.com") + b := &cos.BaseURL{ + BucketURL: u, + } + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + opt := &cos.BucketPutVersionOptions{ + // Enabled or Suspended, the versioning once opened can not close. + Status: "Enabled", + } + + _, err := c.Bucket.PutVersioning(context.Background(), opt) + if err != nil { + panic(err) + } +} diff --git a/object.go b/object.go index c91b6e6..452dd65 100644 --- a/object.go +++ b/object.go @@ -123,6 +123,7 @@ type ObjectPutHeaderOptions struct { ContentDisposition string `header:"Content-Disposition,omitempty" url:"-"` ContentEncoding string `header:"Content-Encoding,omitempty" url:"-"` ContentType string `header:"Content-Type,omitempty" url:"-"` + ContentMD5 string `header:"Content-MD5,omitempty" url:"-"` ContentLength int `header:"Content-Length,omitempty" url:"-"` Expect string `header:"Expect,omitempty" url:"-"` Expires string `header:"Expires,omitempty" url:"-"`