diff --git a/.changelog/3469.txt b/.changelog/3469.txt new file mode 100644 index 0000000000..ea2658ec82 --- /dev/null +++ b/.changelog/3469.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +tencentcloud_cam_message_receiver +``` \ No newline at end of file diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index ebd12166c9..95a03b6958 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -1564,6 +1564,7 @@ func Provider() *schema.Provider { "tencentcloud_cam_set_policy_version_config": cam.ResourceTencentCloudCamSetPolicyVersionConfig(), "tencentcloud_cam_user_permission_boundary_attachment": cam.ResourceTencentCloudCamUserPermissionBoundaryAttachment(), "tencentcloud_cam_role_permission_boundary_attachment": cam.ResourceTencentCloudCamRolePermissionBoundaryAttachment(), + "tencentcloud_cam_message_receiver": cam.ResourceTencentCloudCamMessageReceiver(), "tencentcloud_organization_quit_organization_operation": tco.ResourceTencentCloudOrganizationQuitOrganizationOperation(), "tencentcloud_ciam_user_group": ciam.ResourceTencentCloudCiamUserGroup(), "tencentcloud_ciam_user_store": ciam.ResourceTencentCloudCiamUserStore(), diff --git a/tencentcloud/services/cam/resource_tc_cam_message_receiver.go b/tencentcloud/services/cam/resource_tc_cam_message_receiver.go new file mode 100644 index 0000000000..16c77c202e --- /dev/null +++ b/tencentcloud/services/cam/resource_tc_cam_message_receiver.go @@ -0,0 +1,250 @@ +package cam + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + camv20190116 "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam/v20190116" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func ResourceTencentCloudCamMessageReceiver() *schema.Resource { + return &schema.Resource{ + Create: resourceTencentCloudCamMessageReceiverCreate, + Read: resourceTencentCloudCamMessageReceiverRead, + Delete: resourceTencentCloudCamMessageReceiverDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Username of the message recipient.", + }, + + "remark": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Recipient's notes.", + }, + + "country_code": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The international area code for mobile phone numbers is 86 for domestic areas.", + }, + + "phone_number": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Mobile phone number, for example: 132****2492.", + }, + + "email": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Email address, for example: 57*****@qq.com.", + }, + + // computed + "uid": { + Type: schema.TypeInt, + Computed: true, + Description: "UID.", + }, + + "is_receiver_owner": { + Type: schema.TypeInt, + Computed: true, + Description: "Whether it is the primary contact person.", + }, + + "phone_flag": { + Type: schema.TypeInt, + Computed: true, + Description: "Whether the mobile phone number is verified.", + }, + + "email_flag": { + Type: schema.TypeInt, + Computed: true, + Description: "Whether the email is verified.", + }, + + "wechat_flag": { + Type: schema.TypeInt, + Computed: true, + Description: "Whether WeChat is allowed to receive notifications.", + }, + + "uin": { + Type: schema.TypeInt, + Computed: true, + Description: "Account uin.", + }, + }, + } +} + +func resourceTencentCloudCamMessageReceiverCreate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_cam_message_receiver.create")() + defer tccommon.InconsistentCheck(d, meta)() + + var ( + logId = tccommon.GetLogId(tccommon.ContextNil) + ctx = tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + request = camv20190116.NewCreateMessageReceiverRequest() + name string + ) + + if v, ok := d.GetOk("name"); ok { + request.Name = helper.String(v.(string)) + name = v.(string) + } + + if v, ok := d.GetOk("remark"); ok { + request.Remark = helper.String(v.(string)) + } + + if v, ok := d.GetOk("country_code"); ok { + request.CountryCode = helper.String(v.(string)) + } + + if v, ok := d.GetOk("phone_number"); ok { + request.PhoneNumber = helper.String(v.(string)) + } + + if v, ok := d.GetOk("email"); ok { + request.Email = helper.String(v.(string)) + } + + reqErr := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCamV20190116Client().CreateMessageReceiverWithContext(ctx, request) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + } + + if result == nil || result.Response == nil { + return resource.NonRetryableError(fmt.Errorf("Create cam message receiver failed, Response is nil.")) + } + + return nil + }) + + if reqErr != nil { + log.Printf("[CRITAL]%s create cam message receiver failed, reason:%+v", logId, reqErr) + return reqErr + } + + d.SetId(name) + return resourceTencentCloudCamMessageReceiverRead(d, meta) +} + +func resourceTencentCloudCamMessageReceiverRead(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_cam_message_receiver.read")() + defer tccommon.InconsistentCheck(d, meta)() + + var ( + logId = tccommon.GetLogId(tccommon.ContextNil) + ctx = tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + service = CamService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + name = d.Id() + ) + + respData, err := service.DescribeCamMessageReceiverById(ctx, name) + if err != nil { + return err + } + + if respData == nil { + log.Printf("[WARN]%s resource `tencentcloud_cam_message_receiver` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + d.SetId("") + return nil + } + + if respData.Name != nil { + _ = d.Set("name", respData.Name) + } + + if respData.Remark != nil { + _ = d.Set("remark", respData.Remark) + } + + if respData.PhoneNumber != nil { + _ = d.Set("phone_number", respData.PhoneNumber) + } + + if respData.Email != nil { + _ = d.Set("email", respData.Email) + } + + if respData.Uid != nil { + _ = d.Set("uid", respData.Uid) + } + + if respData.IsReceiverOwner != nil { + _ = d.Set("is_receiver_owner", respData.IsReceiverOwner) + } + + if respData.PhoneFlag != nil { + _ = d.Set("phone_flag", respData.PhoneFlag) + } + + if respData.EmailFlag != nil { + _ = d.Set("email_flag", respData.EmailFlag) + } + + if respData.WechatFlag != nil { + _ = d.Set("wechat_flag", respData.WechatFlag) + } + + if respData.Uin != nil { + _ = d.Set("uin", respData.Uin) + } + + return nil +} + +func resourceTencentCloudCamMessageReceiverDelete(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_cam_message_receiver.delete")() + defer tccommon.InconsistentCheck(d, meta)() + + var ( + logId = tccommon.GetLogId(tccommon.ContextNil) + ctx = tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + request = camv20190116.NewDeleteMessageReceiverRequest() + name = d.Id() + ) + + request.Name = &name + reqErr := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCamV20190116Client().DeleteMessageReceiverWithContext(ctx, request) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + } + + return nil + }) + + if reqErr != nil { + log.Printf("[CRITAL]%s delete cam message receiver failed, reason:%+v", logId, reqErr) + return reqErr + } + + return nil +} diff --git a/tencentcloud/services/cam/resource_tc_cam_message_receiver.md b/tencentcloud/services/cam/resource_tc_cam_message_receiver.md new file mode 100644 index 0000000000..1b233b5f39 --- /dev/null +++ b/tencentcloud/services/cam/resource_tc_cam_message_receiver.md @@ -0,0 +1,27 @@ +Provides a resource to create a CAM message receiver + +~> **NOTE:** For security reasons, the CAM will return the `email` and `phone_number` parameter values in encrypted form. Please use the `ignore_changes` function in Terraform's `lifecycle` to include these two parameters. + +Example Usage + +```hcl +resource "tencentcloud_cam_message_receiver" "example" { + name = "tf-example" + remark = "remark." + country_code = "86" + phone_number = "18123456789" + email = "demo@qq.com" + + lifecycle { + ignore_changes = [ email, phone_number ] + } +} +``` + +Import + +CAM message receiver can be imported using the id, e.g. + +``` +terraform import tencentcloud_cam_message_receiver.example tf-example +``` diff --git a/tencentcloud/services/cam/resource_tc_cam_message_receiver_test.go b/tencentcloud/services/cam/resource_tc_cam_message_receiver_test.go new file mode 100644 index 0000000000..e38119373b --- /dev/null +++ b/tencentcloud/services/cam/resource_tc_cam_message_receiver_test.go @@ -0,0 +1,47 @@ +package cam_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" +) + +func TestAccTencentCloudCamMessageReceiverResource_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + tcacctest.AccPreCheck(t) + }, + Providers: tcacctest.AccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCamMessageReceiver, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("tencentcloud_cam_message_receiver.example", "id"), + resource.TestCheckResourceAttrSet("tencentcloud_cam_message_receiver.example", "name"), + resource.TestCheckResourceAttrSet("tencentcloud_cam_message_receiver.example", "remark"), + resource.TestCheckResourceAttrSet("tencentcloud_cam_message_receiver.example", "country_code"), + resource.TestCheckResourceAttrSet("tencentcloud_cam_message_receiver.example", "phone_number"), + resource.TestCheckResourceAttrSet("tencentcloud_cam_message_receiver.example", "email"), + ), + }, + { + ResourceName: "tencentcloud_cam_message_receiver.example", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +const testAccCamMessageReceiver = ` +resource "tencentcloud_cam_message_receiver" "example" { + name = "tf-example" + remark = "remark." + country_code = "86" + phone_number = "18123456789" + email = "demo@qq.com" +} +` diff --git a/tencentcloud/services/cam/service_tencentcloud_cam.go b/tencentcloud/services/cam/service_tencentcloud_cam.go index a149159615..cf27ae61ef 100644 --- a/tencentcloud/services/cam/service_tencentcloud_cam.go +++ b/tencentcloud/services/cam/service_tencentcloud_cam.go @@ -2032,3 +2032,69 @@ func (me *CamService) DescribeCamRoleDetailByFilter(ctx context.Context, param m ret = response.Response return } + +func (me *CamService) DescribeCamMessageReceiverById(ctx context.Context, name string) (ret *cam.Receiver, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := cam.NewListReceiverRequest() + response := cam.NewListReceiverResponse() + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + var ( + offset uint64 = 0 + limit uint64 = 200 + receivers []*cam.Receiver + ) + + for { + request.Offset = &offset + request.Limit = &limit + + errRet = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + ratelimit.Check(request.GetAction()) + result, e := me.client.UseCamV20190116Client().ListReceiver(request) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + } + + if result == nil || result.Response == nil { + return resource.NonRetryableError(fmt.Errorf("Describe receiver failed, Response is nil.")) + } + + response = result + return nil + }) + + if errRet != nil { + log.Printf("[CRITAL]%s describe receiver failed, reason:%+v", logId, errRet) + return nil, errRet + } + + if len(response.Response.Receivers) < 1 { + break + } + + receivers = append(receivers, response.Response.Receivers...) + if len(response.Response.Receivers) < int(limit) { + break + } + + offset += limit + } + + for _, item := range receivers { + if item.Name != nil && *item.Name == name { + ret = item + break + } + } + + return +}