From 7165cc5360275f3756b22bf6788c99ecf9b52923 Mon Sep 17 00:00:00 2001 From: nickyinluo Date: Fri, 19 Apr 2024 18:03:14 +0800 Subject: [PATCH 1/2] feat(postgresql): [xxx]support new resource. --- ...eadonly_group_network_access_attachment.go | 291 ++++++++++++++++++ ...eadonly_group_network_access_attachment.md | 69 +++++ ...ly_group_network_access_attachment_test.go | 234 ++++++++++++++ .../service_tencentcloud_postgresql.go | 121 +++++++- 4 files changed, 714 insertions(+), 1 deletion(-) create mode 100644 tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.go create mode 100644 tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.md create mode 100644 tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment_test.go diff --git a/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.go b/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.go new file mode 100644 index 0000000000..d884ba8bd3 --- /dev/null +++ b/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.go @@ -0,0 +1,291 @@ +package postgresql + +import ( + "context" + "fmt" + "log" + "strings" + "time" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + svctag "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/tag" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + postgresql "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/postgres/v20170312" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachment() *schema.Resource { + return &schema.Resource{ + Create: resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentCreate, + Read: resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentRead, + Delete: resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "db_instance_id": { + Required: true, + ForceNew: true, + Type: schema.TypeString, + Description: "Master database instance ID.", + }, + + "read_only_group_id": { + Required: true, + ForceNew: true, + Type: schema.TypeString, + Description: "RO group identifier.", + }, + + "vpc_id": { + Required: true, + ForceNew: true, + Type: schema.TypeString, + Description: "Unified VPC ID.", + }, + + "subnet_id": { + Required: true, + ForceNew: true, + Type: schema.TypeString, + Description: "Subnet ID.", + }, + + "is_assign_vip": { + Required: true, + ForceNew: true, + Type: schema.TypeBool, + Description: "Whether to manually assign the VIP. Valid values:true (manually assign), false (automatically assign).", + }, + + "vip": { + Optional: true, + Computed: true, + ForceNew: true, + Type: schema.TypeString, + Description: "Target VIP.", + }, + + "tags": { + Type: schema.TypeMap, + Optional: true, + Description: "Tag description list.", + }, + }, + } +} + +func resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentCreate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_postgresql_readonly_group_network_access_attachment.create")() + + logId := tccommon.GetLogId(tccommon.ContextNil) + + var ( + request = postgresql.NewCreateReadOnlyGroupNetworkAccessRequest() + dbInstanceId string + roGroupId string + vpcId string + vip string + port string + isUserAssign bool + ) + if v, ok := d.GetOk("db_instance_id"); ok { + dbInstanceId = v.(string) + } + + if v, ok := d.GetOk("readonly_group_id"); ok { + request.ReadOnlyGroupId = helper.String(v.(string)) + roGroupId = v.(string) + } + + if v, ok := d.GetOk("vpc_id"); ok { + request.VpcId = helper.String(v.(string)) + vpcId = v.(string) + } + + if v, ok := d.GetOk("subnet_id"); ok { + request.SubnetId = helper.String(v.(string)) + } + + if v, ok := d.GetOkExists("is_assign_vip"); ok { + request.IsAssignVip = helper.Bool(v.(bool)) + isUserAssign = v.(bool) + } + + if v, ok := d.GetOk("vip"); ok { + request.Vip = helper.String(v.(string)) + vip = v.(string) + } + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UsePostgresqlClient().CreateReadOnlyGroupNetworkAccess(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 err != nil { + log.Printf("[CRITAL]%s create postgresql ReadonlyGroupNetworkAccessAttachment failed, reason:%+v", logId, err) + return err + } + + id := strings.Join([]string{dbInstanceId, roGroupId, vpcId, vip, port}, tccommon.FILED_SP) + + service := PostgresqlService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + conf := tccommon.BuildStateChangeConf([]string{}, []string{"opened"}, 180*tccommon.ReadRetryTimeout, time.Second, service.PostgresqlReadonlyGroupNetworkAccessAttachmentStateRefreshFunc(id, []string{})) + + var ret interface{} + var e error + if ret, e = conf.WaitForState(); e != nil { + return e + } else { + object := ret.(*postgresql.DBInstanceNetInfo) + // fill out the port and vip + if object != nil { + if isUserAssign { + // find the port + if *object.VpcId == vpcId && *object.Ip == vip { + port = helper.UInt64ToStr(*object.Port) + } + } else { + // find the port and vip when is_assign_vip is false + if *object.VpcId == vpcId { + port = helper.UInt64ToStr(*object.Port) + vip = *object.Ip + } + } + } + } + + id = strings.Join([]string{dbInstanceId, roGroupId, vpcId, vip, port}, tccommon.FILED_SP) + d.SetId(id) + + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + if tags := helper.GetTags(d, "tags"); len(tags) > 0 { + tagService := svctag.NewTagService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + region := meta.(tccommon.ProviderMeta).GetAPIV3Conn().Region + resourceName := fmt.Sprintf("qcs::postgres:%s:uin/:dbInstanceId/%s", region, d.Id()) + if err := tagService.ModifyTags(ctx, resourceName, tags, nil); err != nil { + return err + } + } + + return resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentRead(d, meta) +} + +func resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentRead(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_postgresql_readonly_group_network_access_attachment.read")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + service := PostgresqlService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) != 5 { + return fmt.Errorf("id is broken,%s, location:%s", d.Id(), "resource.tencentcloud_postgresql_readonly_group_network_access_attachment.read") + } + + dbInstanceId := idSplit[0] + roGroupId := idSplit[1] + vpcId := idSplit[2] + vip := idSplit[3] + port := idSplit[4] + + ReadonlyGroupNetworkAccessAttachment, err := service.DescribePostgresqlReadonlyGroupNetworkAccessAttachmentById(ctx, dbInstanceId, roGroupId) + if err != nil { + return err + } + + if ReadonlyGroupNetworkAccessAttachment == nil { + d.SetId("") + log.Printf("[WARN]%s resource `PostgresqlReadonlyGroupNetworkAccessAttachment` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil + } + + if ReadonlyGroupNetworkAccessAttachment.MasterDBInstanceId != nil { + _ = d.Set("db_instance_id", ReadonlyGroupNetworkAccessAttachment.MasterDBInstanceId) + } + + if ReadonlyGroupNetworkAccessAttachment.ReadOnlyGroupId != nil { + _ = d.Set("readonly_group_id", ReadonlyGroupNetworkAccessAttachment.ReadOnlyGroupId) + } + + if ReadonlyGroupNetworkAccessAttachment.VpcId != nil { + _ = d.Set("vpc_id", ReadonlyGroupNetworkAccessAttachment.VpcId) + } + + if ReadonlyGroupNetworkAccessAttachment.SubnetId != nil { + _ = d.Set("subnet_id", ReadonlyGroupNetworkAccessAttachment.SubnetId) + } + + if vip == "" { + // That's mean isUserAssign is false and need to set vip assigned by system + if ReadonlyGroupNetworkAccessAttachment.DBInstanceNetInfo != nil { + for _, info := range ReadonlyGroupNetworkAccessAttachment.DBInstanceNetInfo { + if *info.VpcId == vpcId && helper.UInt64ToStr(*info.Port) == port { + if info.Ip != nil { + vip = *info.Ip + log.Printf("[DEBUG]%s the id:[%s]'s filed vip[%s] updated successfully!\n", logId, d.Id(), vip) + break + } + } + } + } + // update the vip into unique id + id := strings.Join([]string{dbInstanceId, roGroupId, vpcId, vip, port}, tccommon.FILED_SP) + d.SetId(id) + } + _ = d.Set("vip", vip) + + tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + tagService := svctag.NewTagService(tcClient) + tags, err := tagService.DescribeResourceTags(ctx, "postgres", "dbInstanceId", tcClient.Region, d.Id()) + if err != nil { + return err + } + _ = d.Set("tags", tags) + + return nil +} + +func resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentDelete(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_postgresql_readonly_group_network_access_attachment.delete")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + service := PostgresqlService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) != 5 { + return fmt.Errorf("id is broken,%s", d.Id()) + } + + var subnetId string + roGroupId := idSplit[1] + vpcId := idSplit[2] + vip := idSplit[3] + if v, ok := d.GetOk("subnet_id"); ok { + subnetId = v.(string) + } + + if err := service.DeletePostgresqlReadonlyGroupNetworkAccessAttachmentById(ctx, roGroupId, vpcId, subnetId, vip); err != nil { + return err + } + + conf := tccommon.BuildStateChangeConf([]string{}, []string{"closed"}, 180*tccommon.ReadRetryTimeout, time.Second, service.PostgresqlReadonlyGroupNetworkAccessAttachmentStateRefreshFunc(d.Id(), []string{})) + + if _, e := conf.WaitForState(); e != nil { + return e + } + + return nil +} diff --git a/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.md b/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.md new file mode 100644 index 0000000000..32df4173e0 --- /dev/null +++ b/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.md @@ -0,0 +1,69 @@ +/* +Provides a resource to create a postgresql readonly_group_network_access_attachment + +Example Usage + +Vip assigned by system. + +```hcl +resource "tencentcloud_vpc" "vpc" { + cidr_block = "172.18.111.0/24" + name = "test-pg-network-vpc" +} +resource "tencentcloud_subnet" "subnet" { + availability_zone = var.default_az + cidr_block = "172.18.111.0/24" + name = "test-pg-network-sub1" + vpc_id = tencentcloud_vpc.vpc.id +} +locals { + my_vpc_id = tencentcloud_subnet.subnet.vpc_id + my_subnet_id = tencentcloud_subnet.subnet.id +} +resource "tencentcloud_postgresql_readonly_group" "group" { + master_db_instance_id = local.pgsql_id + name = "tf_test_postgresql_readonly_group" + project_id = 0 + vpc_id = local.my_vpc_id + subnet_id = local.my_subnet_id + replay_lag_eliminate = 1 + replay_latency_eliminate = 1 + max_replay_lag = 100 + max_replay_latency = 512 + min_delay_eliminate_reserve = 1 +} +resource "tencentcloud_postgresql_readonly_group_network_access_attachment" "readonly_group_network_access_attachment" { + db_instance_id = local.pgsql_id + readonly_group_id = tencentcloud_postgresql_readonly_group.group.id + vpc_id = local.my_vpc_id + subnet_id = local.my_subnet_id + is_assign_vip = false + tags = { + "createdBy" = "terraform" + } +} +``` + +Vip specified by user. + +```hcl +resource "tencentcloud_postgresql_readonly_group_network_access_attachment" "readonly_group_network_access_attachment" { + db_instance_id = local.pgsql_id + readonly_group_id = tencentcloud_postgresql_readonly_group.group.id + vpc_id = local.my_vpc_id + subnet_id = local.my_subnet_id + is_assign_vip = true + vip = "172.18.111.111" + tags = { + "createdBy" = "terraform" + } +} + +Import + +postgresql readonly_group_network_access_attachment can be imported using the id, e.g. + +``` +terraform import tencentcloud_postgresql_readonly_group_network_access_attachment.readonly_group_network_access_attachment db_instance_id#readonly_group_id#vpc_id#vip#port +``` +*/ \ No newline at end of file diff --git a/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment_test.go b/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment_test.go new file mode 100644 index 0000000000..6619b8be8d --- /dev/null +++ b/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment_test.go @@ -0,0 +1,234 @@ +package postgresql_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" + + tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + svcpostgresql "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/postgresql" +) + +const testAccReadonlyGroupNetworkAccessAttachmentObject = "tencentcloud_postgresql_readonly_group_network_access_attachment.readonly_group_network_access_attachment" + +func TestAccTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentResource_auto_assign(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + tcacctest.AccStepSetRegion(t, "ap-guangzhou") + tcacctest.AccPreCheck(t) + }, + Providers: tcacctest.AccProviders, + CheckDestroy: testAccCheckReadonlyGroupNetworkAccessAttachmentDestroy, + Steps: []resource.TestStep{ + { + PreConfig: func() { + tcacctest.AccStepSetRegion(t, "ap-guangzhou") + tcacctest.AccPreCheckCommon(t, tcacctest.ACCOUNT_TYPE_COMMON) + }, + Config: testAccPostgresqlReadonlyGroupNetworkAccessAttachment_auto_assign, + Check: resource.ComposeTestCheckFunc( + testAccCheckReadonlyGroupNetworkAccessAttachmentExists(testAccReadonlyGroupNetworkAccessAttachmentObject), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "db_instance_id"), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "readonly_group_id"), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "vpc_id"), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "subnet_id"), + resource.TestCheckResourceAttr(testAccReadonlyGroupNetworkAccessAttachmentObject, "is_assign_vip", "false"), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "vip"), + ), + }, + { + ResourceName: testAccReadonlyGroupNetworkAccessAttachmentObject, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"is_assign_vip"}, + }, + }, + }) +} + +func TestAccTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentResource_user_assign(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + tcacctest.AccStepSetRegion(t, "ap-guangzhou") + tcacctest.AccPreCheck(t) + }, + Providers: tcacctest.AccProviders, + CheckDestroy: testAccCheckReadonlyGroupNetworkAccessAttachmentDestroy, + Steps: []resource.TestStep{ + { + PreConfig: func() { + tcacctest.AccStepSetRegion(t, "ap-guangzhou") + tcacctest.AccPreCheckCommon(t, tcacctest.ACCOUNT_TYPE_COMMON) + }, + Config: testAccPostgresqlReadonlyGroupNetworkAccessAttachment_user_assign, + Check: resource.ComposeTestCheckFunc( + testAccCheckReadonlyGroupNetworkAccessAttachmentExists(testAccReadonlyGroupNetworkAccessAttachmentObject), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "db_instance_id"), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "readonly_group_id"), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "vpc_id"), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "subnet_id"), + resource.TestCheckResourceAttr(testAccReadonlyGroupNetworkAccessAttachmentObject, "is_assign_vip", "true"), + resource.TestCheckResourceAttrSet(testAccReadonlyGroupNetworkAccessAttachmentObject, "vip"), + ), + }, + { + ResourceName: testAccReadonlyGroupNetworkAccessAttachmentObject, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"is_assign_vip"}, + }, + }, + }) +} + +func testAccCheckReadonlyGroupNetworkAccessAttachmentDestroy(s *terraform.State) error { + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + service := svcpostgresql.NewPostgresqlService(tcacctest.AccProvider.Meta().(tccommon.ProviderMeta).GetAPIV3Conn()) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "tencentcloud_postgresql_readonly_group_network_access_attachment" { + continue + } + + object, err := service.DescribePostgresqlReadonlyGroupSpecificNetInfoById(ctx, rs.Primary.ID) + + if err != nil { + err, ok := err.(*sdkErrors.TencentCloudSDKError) + if ok && err.GetCode() == "ResourceNotFound.InstanceNotFoundError" { + // it is ok + return nil + } + return err + } + + if object != nil { + return fmt.Errorf("The tencentcloud_postgresql_readonly_group_network_access_attachment instance [%s] still exist.", rs.Primary.ID) + } + + } + return nil +} + +func testAccCheckReadonlyGroupNetworkAccessAttachmentExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + service := svcpostgresql.NewPostgresqlService(tcacctest.AccProvider.Meta().(tccommon.ProviderMeta).GetAPIV3Conn()) + + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("vpc attachment %s is not found", n) + } + if rs.Primary.ID == "" { + return fmt.Errorf("vpc attachment id is not set") + } + + object, err := service.DescribePostgresqlReadonlyGroupSpecificNetInfoById(ctx, rs.Primary.ID) + + if err != nil { + err, ok := err.(*sdkErrors.TencentCloudSDKError) + if ok && err.GetCode() == "ResourceNotFound.InstanceNotFoundError" { + // it is ok + return nil + } + return err + } + + if object == nil { + return fmt.Errorf("The tencentcloud_postgresql_readonly_group_network_access_attachment instance [%s] not found.", rs.Primary.ID) + } + + return nil + } +} + +const testAccPostgresqlInstanceForROGroupNetworkAccess = ` + variable "default_az" { + default = "ap-guangzhou-3" + } + + resource "tencentcloud_vpc" "vpc" { + cidr_block = "172.18.111.0/24" + name = "test-pg-network-vpc" + } + + resource "tencentcloud_subnet" "subnet" { + availability_zone = var.default_az + cidr_block = "172.18.111.0/24" + name = "test-pg-network-sub1" + vpc_id = tencentcloud_vpc.vpc.id + } + + resource "tencentcloud_postgresql_instance" "test" { + name = "example" + availability_zone = var.availability_zone + charge_type = "POSTPAID_BY_HOUR" + vpc_id = tencentcloud_vpc.vpc.id + subnet_id = tencentcloud_subnet.subnet.id + engine_version = "10.4" + root_user = "root123" + root_password = "Root123$" + charset = "UTF8" + project_id = 0 + memory = 2 + storage = 10 + + tags = { + test = "tf" + } + } + + locals { + my_vpc_id = tencentcloud_subnet.subnet.vpc_id + my_subnet_id = tencentcloud_subnet.subnet.id + pgsql_id = tencentcloud_postgresql_instance.test.id + } + + resource "tencentcloud_postgresql_readonly_group" "group" { + master_db_instance_id = local.pgsql_id + name = "tf_test_postgresql_readonly_group" + project_id = 0 + vpc_id = local.my_vpc_id + subnet_id = local.my_subnet_id + replay_lag_eliminate = 1 + replay_latency_eliminate = 1 + max_replay_lag = 100 + max_replay_latency = 512 + min_delay_eliminate_reserve = 1 + } +` + +const testAccPostgresqlReadonlyGroupNetworkAccessAttachment_auto_assign = testAccPostgresqlInstanceForROGroupNetworkAccess + ` +resource "tencentcloud_postgresql_readonly_group_network_access_attachment" "readonly_group_network_access_attachment" { + db_instance_id = local.pgsql_id + readonly_group_id = tencentcloud_postgresql_readonly_group.group.id + vpc_id = local.my_vpc_id + subnet_id = local.my_subnet_id + is_assign_vip = false + tags = { + "createdBy" = "terraform" + } + } +` + +const testAccPostgresqlReadonlyGroupNetworkAccessAttachment_user_assign = testAccPostgresqlInstanceForROGroupNetworkAccess + ` +resource "tencentcloud_postgresql_readonly_group_network_access_attachment" "readonly_group_network_access_attachment" { + db_instance_id = local.pgsql_id + readonly_group_id = tencentcloud_postgresql_readonly_group.group.id + vpc_id = local.my_vpc_id + subnet_id = local.my_subnet_id + is_assign_vip = true + vip = "172.18.111.111" + tags = { + "createdBy" = "terraform" + } +} +` diff --git a/tencentcloud/services/postgresql/service_tencentcloud_postgresql.go b/tencentcloud/services/postgresql/service_tencentcloud_postgresql.go index b6a01aef25..e2b3e136fe 100644 --- a/tencentcloud/services/postgresql/service_tencentcloud_postgresql.go +++ b/tencentcloud/services/postgresql/service_tencentcloud_postgresql.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "strconv" + "strings" "time" tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" @@ -1300,7 +1301,7 @@ func (me *PostgresqlService) PostgresqlDBInstanceNetworkAccessStateRefreshFunc(d } func (me *PostgresqlService) DescribePostgresqlReadonlyGroupNetInfosById(ctx context.Context, dbInstanceId, roGroupId string) (netInfos []*postgresql.DBInstanceNetInfo, errRet error) { - tccommon.LogElapsed("DescribePostgresqlReadonlyGroupNetInfoById called")() + tccommon.LogElapsed("DescribePostgresqlReadonlyGroupNetInfosById called")() logId := tccommon.GetLogId(ctx) paramMap := map[string]interface{}{ @@ -1856,3 +1857,121 @@ func (me *PostgresqlService) DeletePostgresqlBaseBackupById(ctx context.Context, return } + +func (me *PostgresqlService) DescribePostgresqlReadonlyGroupSpecificNetInfoById(ctx context.Context, id string) (dBInstanceNetInfo *postgresql.DBInstanceNetInfo, errRet error) { + tccommon.LogElapsed("DescribePostgresqlReadonlyGroupSpecificNetInfoById called") + idSplit := strings.Split(id, tccommon.FILED_SP) + if len(idSplit) != 5 { + return nil, fmt.Errorf("id is broken,%s, location:%s", id, "resource.tencentcloud_postgresql_readonly_group_network_access_attachment.read") + } + + dbInstanceId := idSplit[0] + roGroupId := idSplit[1] + vpcId := idSplit[2] + vip := idSplit[3] + port := idSplit[4] + + ret, err := me.DescribePostgresqlReadonlyGroupNetworkAccessAttachmentById(ctx, dbInstanceId, roGroupId) + if err != nil { + return nil, err + } + + if ret != nil { + for _, info := range ret.DBInstanceNetInfo { + // vpc, vip and port may empty before creating completed. + if (*info.VpcId == vpcId || vpcId == "") && (*info.Ip == vip || vip == "") && (helper.UInt64ToStr(*info.Port) == port || port == "") { + dBInstanceNetInfo = info + return + } + } + } + return nil, nil +} + +func (me *PostgresqlService) DescribePostgresqlReadonlyGroupNetworkAccessAttachmentById(ctx context.Context, dbInstanceId, roGroupId string) (roGroup *postgresql.ReadOnlyGroup, errRet error) { + logId := tccommon.GetLogId(ctx) + + paramMap := map[string]interface{}{ + "Filters": []*postgresql.Filter{ + { + Name: helper.String("db-master-instance-id"), + Values: []*string{helper.String(dbInstanceId)}, + }, + { + Name: helper.String("read-only-group-id"), + Values: []*string{helper.String(dbInstanceId)}, + }, + }, + } + + result, err := me.DescribePostgresqlReadonlyGroupsByFilter(ctx, paramMap) + if err != nil { + errRet = err + return + } + + if roGroupId != "" { + for _, group := range result { + if *group.ReadOnlyGroupId == roGroupId { + roGroup = group + + break + } + } + } else { + roGroup = result[0] + } + log.Printf("[DEBUG]%s DescribePostgresqlReadonlyGroupNetworkAccessAttachmentById dbInstanceId:[%s] roGroupId:[%s] success, result is roGroup:[%v], \n", logId, dbInstanceId, roGroupId, roGroup) + + return +} + +func (me *PostgresqlService) DeletePostgresqlReadonlyGroupNetworkAccessAttachmentById(ctx context.Context, readOnlyGroupId, vpcId, subnetId, vip string) (errRet error) { + logId := tccommon.GetLogId(ctx) + + request := postgresql.NewDeleteReadOnlyGroupNetworkAccessRequest() + request.ReadOnlyGroupId = &readOnlyGroupId + request.VpcId = &vpcId + request.SubnetId = &subnetId + request.Vip = &vip + + 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()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UsePostgresqlClient().DeleteReadOnlyGroupNetworkAccess(request) + if err != nil { + errRet = err + return + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + return +} + +func (me *PostgresqlService) PostgresqlReadonlyGroupNetworkAccessAttachmentStateRefreshFunc(id string, failStates []string) resource.StateRefreshFunc { + tccommon.LogElapsed("PostgresqlReadonlyGroupNetworkAccessAttachmentStateRefreshFunc called")() + return func() (interface{}, string, error) { + ctx := tccommon.ContextNil + + object, err := me.DescribePostgresqlReadonlyGroupSpecificNetInfoById(ctx, id) + + if err != nil { + err, ok := err.(*sdkErrors.TencentCloudSDKError) + if ok && err.GetCode() == "ResourceNotFound.InstanceNotFoundError" { + // it is ok + return nil, "", nil + } + return nil, "", err + } + if object == nil { + return &postgresql.DBInstanceNetInfo{}, "closed", nil + } + + return object, helper.PString(object.Status), nil + } +} From 335ce6eaf08efce9c0d135f00f083f21724fb5d0 Mon Sep 17 00:00:00 2001 From: nickyinluo Date: Mon, 22 Apr 2024 16:51:17 +0800 Subject: [PATCH 2/2] fix issue --- tencentcloud/provider.go | 1 + ...tc_postgresql_readonly_group_network_access_attachment.go | 5 +++-- .../services/postgresql/service_tencentcloud_postgresql.go | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index 0fe00be2c6..20ff2d83b1 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -1357,6 +1357,7 @@ func Provider() *schema.Provider { "tencentcloud_postgresql_modify_account_remark_operation": postgresql.ResourceTencentCloudPostgresqlModifyAccountRemarkOperation(), "tencentcloud_postgresql_modify_switch_time_period_operation": postgresql.ResourceTencentCloudPostgresqlModifySwitchTimePeriodOperation(), "tencentcloud_postgresql_instance_ha_config": postgresql.ResourceTencentCloudPostgresqlInstanceHAConfig(), + "tencentcloud_postgresql_readonly_group_network_access_attachment": postgresql.ResourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachment(), "tencentcloud_sqlserver_instance": sqlserver.ResourceTencentCloudSqlserverInstance(), "tencentcloud_sqlserver_db": sqlserver.ResourceTencentCloudSqlserverDB(), "tencentcloud_sqlserver_account": sqlserver.ResourceTencentCloudSqlserverAccount(), diff --git a/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.go b/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.go index d884ba8bd3..c2b69464a0 100644 --- a/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.go +++ b/tencentcloud/services/postgresql/resource_tc_postgresql_readonly_group_network_access_attachment.go @@ -16,7 +16,7 @@ import ( "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) -func resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachment() *schema.Resource { +func ResourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachment() *schema.Resource { return &schema.Resource{ Create: resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentCreate, Read: resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachmentRead, @@ -32,7 +32,7 @@ func resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachment() *schem Description: "Master database instance ID.", }, - "read_only_group_id": { + "readonly_group_id": { Required: true, ForceNew: true, Type: schema.TypeString, @@ -70,6 +70,7 @@ func resourceTencentCloudPostgresqlReadonlyGroupNetworkAccessAttachment() *schem "tags": { Type: schema.TypeMap, + ForceNew: true, Optional: true, Description: "Tag description list.", }, diff --git a/tencentcloud/services/postgresql/service_tencentcloud_postgresql.go b/tencentcloud/services/postgresql/service_tencentcloud_postgresql.go index e2b3e136fe..92e96178a7 100644 --- a/tencentcloud/services/postgresql/service_tencentcloud_postgresql.go +++ b/tencentcloud/services/postgresql/service_tencentcloud_postgresql.go @@ -1899,7 +1899,7 @@ func (me *PostgresqlService) DescribePostgresqlReadonlyGroupNetworkAccessAttachm }, { Name: helper.String("read-only-group-id"), - Values: []*string{helper.String(dbInstanceId)}, + Values: []*string{helper.String(roGroupId)}, }, }, }