diff --git a/tencentcloud/resource_tc_cam_role.go b/tencentcloud/resource_tc_cam_role.go index 8101ec7f6d..7d0754a953 100644 --- a/tencentcloud/resource_tc_cam_role.go +++ b/tencentcloud/resource_tc_cam_role.go @@ -24,6 +24,9 @@ resource "tencentcloud_cam_role" "foo" { EOF description = "test" console_login = true + tags = { + test = "tf-cam-role", + } } ``` @@ -134,6 +137,11 @@ func resourceTencentCloudCamRole() *schema.Resource { Computed: true, Description: "The last update time of the CAM role.", }, + "tags": { + Type: schema.TypeMap, + Optional: true, + Description: "A list of tags used to associate different resources.", + }, }, } } @@ -216,6 +224,15 @@ func resourceTencentCloudCamRoleCreate(d *schema.ResourceData, meta interface{}) log.Printf("[CRITAL]%s read CAM role failed, reason:%s\n", logId, err.Error()) return err } + + //modify tags + if tags := helper.GetTags(d, "tags"); len(tags) > 0 { + tagService := TagService{client: meta.(*TencentCloudClient).apiV3Conn} + resourceName := BuildTagResourceName("cam", "role", "", roleId) + if err := tagService.ModifyTags(ctx, resourceName, tags, nil); err != nil { + return err + } + } time.Sleep(10 * time.Second) return resourceTencentCloudCamRoleRead(d, meta) } @@ -267,6 +284,15 @@ func resourceTencentCloudCamRoleRead(d *schema.ResourceData, meta interface{}) e } else { _ = d.Set("console_login", false) } + + //tags + tagService := TagService{client: meta.(*TencentCloudClient).apiV3Conn} + tags, err := tagService.DescribeResourceTags(ctx, "cam", "role", "", roleId) + if err != nil { + return err + } + _ = d.Set("tags", tags) + return nil } @@ -274,6 +300,7 @@ func resourceTencentCloudCamRoleUpdate(d *schema.ResourceData, meta interface{}) defer logElapsed("resource.tencentcloud_cam_role.update")() logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) d.Partial(true) @@ -343,6 +370,21 @@ func resourceTencentCloudCamRoleUpdate(d *schema.ResourceData, meta interface{}) d.Partial(false) + //tag + if d.HasChange("tags") { + oldInterface, newInterface := d.GetChange("tags") + replaceTags, deleteTags := diffTags(oldInterface.(map[string]interface{}), newInterface.(map[string]interface{})) + tagService := TagService{ + client: meta.(*TencentCloudClient).apiV3Conn, + } + resourceName := BuildTagResourceName("cam", "role", "", roleId) + err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags) + if err != nil { + return err + } + d.SetPartial("tags") + } + return resourceTencentCloudCamRoleRead(d, meta) } diff --git a/tencentcloud/resource_tc_cam_user.go b/tencentcloud/resource_tc_cam_user.go index 128f961a85..8ddf8e1e4c 100644 --- a/tencentcloud/resource_tc_cam_user.go +++ b/tencentcloud/resource_tc_cam_user.go @@ -15,6 +15,9 @@ resource "tencentcloud_cam_user" "foo" { email = "hello@test.com" country_code = "86" force_delete = true + tags = { + test = "tf-cam-user", + } } ``` @@ -135,6 +138,11 @@ func resourceTencentCloudCamUser() *schema.Resource { Computed: true, Description: "ID of the CAM user.", }, + "tags": { + Type: schema.TypeMap, + Optional: true, + Description: "A list of tags used to associate different resources.", + }, }, } } @@ -239,6 +247,16 @@ func resourceTencentCloudCamUserCreate(d *schema.ResourceData, meta interface{}) log.Printf("[CRITAL]%s wait for CAM user ready failed, reason:%s\n", logId, err.Error()) return err } + + //modify tags + if tags := helper.GetTags(d, "tags"); len(tags) > 0 { + tagService := TagService{client: meta.(*TencentCloudClient).apiV3Conn} + region := meta.(*TencentCloudClient).apiV3Conn.Region + resourceName := BuildTagResourceName("cam", "uin", region, helper.UInt64ToStr(*response.Response.Uin)) + if err := tagService.ModifyTags(ctx, resourceName, tags, nil); err != nil { + return err + } + } time.Sleep(10 * time.Second) return resourceTencentCloudCamUserRead(d, meta) } @@ -292,6 +310,15 @@ func resourceTencentCloudCamUserRead(d *schema.ResourceData, meta interface{}) e _ = d.Set("console_login", true) } + //tags + tagService := TagService{client: meta.(*TencentCloudClient).apiV3Conn} + region := meta.(*TencentCloudClient).apiV3Conn.Region + tags, err := tagService.DescribeResourceTags(ctx, "cam", "uin", region, helper.UInt64ToStr(*instance.Response.Uin)) + if err != nil { + return err + } + _ = d.Set("tags", tags) + return nil } @@ -299,6 +326,7 @@ func resourceTencentCloudCamUserUpdate(d *schema.ResourceData, meta interface{}) defer logElapsed("resource.tencentcloud_cam_user.update")() logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) userId := d.Id() @@ -362,6 +390,45 @@ func resourceTencentCloudCamUserUpdate(d *schema.ResourceData, meta interface{}) } } + //tag + if d.HasChange("tags") { + camService := CamService{ + client: meta.(*TencentCloudClient).apiV3Conn, + } + + var instance *cam.GetUserResponse + err := resource.Retry(readRetryTimeout, func() *resource.RetryError { + result, e := camService.DescribeUserById(ctx, userId) + if e != nil { + return retryError(e) + } + instance = result + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s read CAM user failed, reason:%s\n", logId, err.Error()) + return err + } + + if instance == nil || instance.Response == nil || instance.Response.Uid == nil { + d.SetId("") + return nil + } + + oldInterface, newInterface := d.GetChange("tags") + replaceTags, deleteTags := diffTags(oldInterface.(map[string]interface{}), newInterface.(map[string]interface{})) + tagService := TagService{ + client: meta.(*TencentCloudClient).apiV3Conn, + } + region := meta.(*TencentCloudClient).apiV3Conn.Region + resourceName := BuildTagResourceName("cam", "uin", region, helper.UInt64ToStr(*instance.Response.Uin)) + err = tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags) + if err != nil { + return err + } + d.SetPartial("tags") + } + return nil } diff --git a/website/docs/r/cam_role.html.markdown b/website/docs/r/cam_role.html.markdown index 5ef37f9107..33775bdfce 100644 --- a/website/docs/r/cam_role.html.markdown +++ b/website/docs/r/cam_role.html.markdown @@ -34,6 +34,9 @@ resource "tencentcloud_cam_role" "foo" { EOF description = "test" console_login = true + tags = { + test = "tf-cam-role", + } } ``` @@ -69,6 +72,7 @@ The following arguments are supported: * `name` - (Required, ForceNew) Name of CAM role. * `console_login` - (Optional, ForceNew) Indicates whether the CAM role can login or not. * `description` - (Optional) Description of the CAM role. +* `tags` - (Optional) A list of tags used to associate different resources. ## Attributes Reference diff --git a/website/docs/r/cam_user.html.markdown b/website/docs/r/cam_user.html.markdown index 814ad16d4b..e486c9229d 100644 --- a/website/docs/r/cam_user.html.markdown +++ b/website/docs/r/cam_user.html.markdown @@ -25,6 +25,9 @@ resource "tencentcloud_cam_user" "foo" { email = "hello@test.com" country_code = "86" force_delete = true + tags = { + test = "tf-cam-user", + } } ``` @@ -41,6 +44,7 @@ The following arguments are supported: * `password` - (Optional) The password of the CAM user. Password should be at least 8 characters and no more than 32 characters, includes uppercase letters, lowercase letters, numbers and special characters. Only required when `console_login` is true. If not set, a random password will be automatically generated. * `phone_num` - (Optional) Phone number of the CAM user. * `remark` - (Optional) Remark of the CAM user. +* `tags` - (Optional) A list of tags used to associate different resources. * `use_api` - (Optional) Indicate whether to generate the API secret key or not. ## Attributes Reference