Skip to content

Commit fb4ead0

Browse files
authored
Merge pull request #684 from tencentcloudstack/feat/cos-object-tags
Feat/cos object tags
2 parents 274fbe2 + 89f1fbe commit fb4ead0

File tree

4 files changed

+169
-0
lines changed

4 files changed

+169
-0
lines changed

tencentcloud/resource_tc_cos_bucket_object.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ func resourceTencentCloudCosBucketObject() *schema.Resource {
105105
Optional: true,
106106
Description: "Specifies what content encodings have been applied to the object and thus what decoding mechanisms must be applied to obtain the media-type referenced by the Content-Type header field.",
107107
},
108+
"tags": {
109+
Type: schema.TypeMap,
110+
Optional: true,
111+
Description: "Tag of the object.",
112+
},
108113
"content_type": {
109114
Type: schema.TypeString,
110115
Optional: true,
@@ -192,6 +197,22 @@ func resourceTencentCloudCosBucketObjectCreate(d *schema.ResourceData, meta inte
192197
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n",
193198
logId, "put object", request.String(), response.String())
194199

200+
if v, ok := d.GetOk("tags"); ok {
201+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
202+
service := CosService{
203+
client: meta.(*TencentCloudClient).apiV3Conn,
204+
}
205+
tags := make(map[string]string)
206+
207+
for key, val := range v.(map[string]interface{}) {
208+
tags[key] = val.(string)
209+
}
210+
211+
if err := service.SetObjectTags(ctx, bucket, key, tags); err != nil {
212+
log.Printf("[WARN] set object tags error, skip processing")
213+
}
214+
}
215+
195216
d.SetId(bucket + key)
196217
return resourceTencentCloudCosBucketObjectRead(d, meta)
197218
}
@@ -228,6 +249,18 @@ func resourceTencentCloudCosBucketObjectRead(d *schema.ResourceData, meta interf
228249
_ = d.Set("storage_class", response.StorageClass)
229250
}
230251

252+
var tags map[string]string
253+
tags, err = cosService.GetObjectTags(ctx, bucket, key)
254+
if err != nil {
255+
if awsError, ok := err.(awserr.RequestFailure); ok && awsError.StatusCode() == 404 {
256+
log.Printf("[WARN]%s tags in object (%s) of bucket (%s) not found, error code (404)", logId, key, bucket)
257+
d.SetId("")
258+
return nil
259+
}
260+
return err
261+
}
262+
err = d.Set("tags", tags)
263+
231264
return nil
232265
}
233266

@@ -267,6 +300,17 @@ func resourceTencentCloudCosBucketObjectUpdate(d *schema.ResourceData, meta inte
267300
}
268301
}
269302

303+
if d.HasChange("tags") {
304+
v := d.Get("tags").(map[string]interface{})
305+
tags := make(map[string]string)
306+
for key, val := range v {
307+
tags[key] = val.(string)
308+
}
309+
if err := cosService.SetObjectTags(ctx, bucket, key, tags); err != nil {
310+
return err
311+
}
312+
}
313+
270314
return nil
271315
}
272316

tencentcloud/resource_tc_cos_bucket_object_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,26 @@ func TestAccTencentCloudCosBucketObject_content(t *testing.T) {
7070
})
7171
}
7272

73+
func TestAccTencentCloudCosBucketObject_tags(t *testing.T) {
74+
t.Parallel()
75+
76+
resource.Test(t, resource.TestCase{
77+
PreCheck: func() { testAccPreCheck(t) },
78+
Providers: testAccProviders,
79+
CheckDestroy: testAccCheckCosBucketObjectDestroy,
80+
Steps: []resource.TestStep{
81+
{
82+
Config: testAccCosBucketObject_tags(appid),
83+
Check: resource.ComposeAggregateTestCheckFunc(
84+
testAccCheckCosBucketObjectExists("tencentcloud_cos_bucket_object.object_with_tags"),
85+
resource.TestCheckResourceAttr("tencentcloud_cos_bucket_object.object_with_tags", "tags.test", "test"),
86+
resource.TestCheckResourceAttr("tencentcloud_cos_bucket_object.object_with_tags", "tags.hello", "world"),
87+
),
88+
},
89+
},
90+
})
91+
}
92+
7393
func TestAccTencentCloudCosBucketObject_storageClass(t *testing.T) {
7494
t.Parallel()
7595

@@ -192,6 +212,25 @@ resource "tencentcloud_cos_bucket_object" "object_content" {
192212
`, acctest.RandInt(), appid)
193213
}
194214

215+
func testAccCosBucketObject_tags(appid string) string {
216+
return fmt.Sprintf(`
217+
resource "tencentcloud_cos_bucket" "object_bucket" {
218+
bucket = "tf-bucket-%d-%s"
219+
}
220+
221+
resource "tencentcloud_cos_bucket_object" "object_with_tags" {
222+
bucket = tencentcloud_cos_bucket.object_bucket.bucket
223+
key = "tf-object-tags"
224+
content = "aaaaaaaaaaaaaaaa"
225+
content_type = "binary/octet-stream"
226+
tags = {
227+
test = "test"
228+
hello = "world"
229+
}
230+
}
231+
`, acctest.RandInt(), appid)
232+
}
233+
195234
func testAccCosBucketObject_storageClass(appid string) string {
196235
return fmt.Sprintf(`
197236
resource "tencentcloud_cos_bucket" "object_bucket" {

tencentcloud/service_tencentcloud_cos.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,91 @@ func (me *CosService) GetBucketTags(ctx context.Context, bucket string) (map[str
674674
return tags, nil
675675
}
676676

677+
func (me *CosService) GetObjectTags(ctx context.Context, bucket string, key string) (map[string]string, error) {
678+
logId := getLogId(ctx)
679+
680+
req := &s3.GetObjectTaggingInput{
681+
Bucket: &bucket,
682+
Key: &key,
683+
}
684+
685+
ratelimit.Check("GetObjectTagging")
686+
resp, err := me.client.UseCosClient().GetObjectTagging(req)
687+
if err != nil {
688+
if awsErr, ok := err.(awserr.Error); !ok || awsErr.Code() != "404" {
689+
return nil, nil
690+
}
691+
692+
log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%v]",
693+
logId, "get object tags", req.String(), err)
694+
return nil, err
695+
}
696+
697+
tags := make(map[string]string, len(resp.TagSet))
698+
699+
for _, tag := range resp.TagSet {
700+
tags[*tag.Key] = *tag.Value
701+
}
702+
703+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]",
704+
logId, "get tags", req.String(), resp.String())
705+
706+
return tags, nil
707+
}
708+
709+
// SetObjectTags same as delete Bucket Tags
710+
func (me *CosService) SetObjectTags(ctx context.Context, bucket string, key string, tags map[string]string) error {
711+
logId := getLogId(ctx)
712+
713+
deleteReq := &s3.DeleteObjectTaggingInput{
714+
Bucket: aws.String(bucket),
715+
Key: aws.String(key),
716+
}
717+
718+
ratelimit.Check("DeleteObjectTagging")
719+
720+
deleteResp, err := me.client.UseCosClient().DeleteObjectTagging(deleteReq)
721+
if err != nil {
722+
log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]",
723+
logId, "delete olg object tags", deleteReq.String(), err)
724+
return err
725+
}
726+
727+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]",
728+
logId, "delete olg object tags", deleteReq.String(), deleteResp.String())
729+
730+
if len(tags) == 0 {
731+
return nil
732+
}
733+
734+
putReq := &s3.PutObjectTaggingInput{
735+
Key: aws.String(key),
736+
Bucket: aws.String(bucket),
737+
Tagging: new(s3.Tagging),
738+
}
739+
740+
for k, v := range tags {
741+
putReq.Tagging.TagSet = append(putReq.Tagging.TagSet, &s3.Tag{
742+
Key: aws.String(k),
743+
Value: aws.String(v),
744+
})
745+
}
746+
747+
ratelimit.Check("PutObjectTagging")
748+
749+
resp, err := me.client.UseCosClient().PutObjectTagging(putReq)
750+
if err != nil {
751+
log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%v]",
752+
logId, "put new object tags", deleteReq.String(), err)
753+
return err
754+
}
755+
756+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]",
757+
logId, "put new object tags", putReq.String(), resp.String())
758+
759+
return nil
760+
}
761+
677762
func (me *CosService) PutBucketPolicy(ctx context.Context, bucket, policy string) (errRet error) {
678763
logId := getLogId(ctx)
679764

website/docs/r/cos_bucket_object.html.markdown

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ The following arguments are supported:
5353
* `etag` - (Optional) The ETag generated for the object (an MD5 sum of the object content).
5454
* `source` - (Optional) The path to the source file being uploaded to the bucket.
5555
* `storage_class` - (Optional) Object storage type, Available values include `STANDARD`, `STANDARD_IA` and `ARCHIVE`.
56+
* `tags` - (Optional) Tag of the object.
5657

5758
## Attributes Reference
5859

0 commit comments

Comments
 (0)