diff --git a/tencentcloud/basic_test.go b/tencentcloud/basic_test.go index 3ff1cbf47d..232640f754 100644 --- a/tencentcloud/basic_test.go +++ b/tencentcloud/basic_test.go @@ -425,6 +425,7 @@ data "tencentcloud_instances" "instance" { locals { cvm_id = data.tencentcloud_instances.instance.instance_list.0.instance_id cvm_az = "` + defaultAZone + `" + cvm_private_ip = data.tencentcloud_instances.instance.instance_list.0.private_ip } ` diff --git a/tencentcloud/data_source_tc_clb_attachments_test.go b/tencentcloud/data_source_tc_clb_attachments_test.go index 97255c9ade..fc269c742c 100644 --- a/tencentcloud/data_source_tc_clb_attachments_test.go +++ b/tencentcloud/data_source_tc_clb_attachments_test.go @@ -32,7 +32,7 @@ const testAccTencentCloudDataSourceClbServerAttachments = instanceCommonTestCase resource "tencentcloud_clb_instance" "foo" { network_type = "OPEN" clb_name = var.instance_name - vpc_id = var.vpc_id + vpc_id = var.cvm_vpc_id } resource "tencentcloud_clb_listener" "foo" { diff --git a/tencentcloud/data_source_tc_clb_target_groups_test.go b/tencentcloud/data_source_tc_clb_target_groups_test.go index 6c9c5f8b92..2cff2d50df 100644 --- a/tencentcloud/data_source_tc_clb_target_groups_test.go +++ b/tencentcloud/data_source_tc_clb_target_groups_test.go @@ -12,7 +12,7 @@ const ( targetGroupResource = "tencentcloud_clb_target_group.test" ) -func TestAccTencentCloudDataSourceClbTargetGroup(t *testing.T) { +func TestAccTencentCloudClbTargetGroupDataSource(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -53,10 +53,11 @@ func TestAccTencentCloudDataSourceClbTargetGroup(t *testing.T) { }) } -const tareGetGroupBase = ` +const tareGetGroupBase = defaultVpcSubnets + ` resource "tencentcloud_clb_instance" "clb_basic" { network_type = "OPEN" clb_name = "tf-clb-rule-basic" + vpc_id = local.vpc_id } resource "tencentcloud_clb_listener" "listener_basic" { @@ -78,13 +79,14 @@ resource "tencentcloud_clb_listener_rule" "rule_basic" { resource "tencentcloud_clb_target_group" "test"{ target_group_name = "test-target-keep-1" + vpc_id = local.vpc_id } resource "tencentcloud_clb_target_group_attachment" "group" { clb_id = tencentcloud_clb_instance.clb_basic.id listener_id = tencentcloud_clb_listener.listener_basic.listener_id rule_id = tencentcloud_clb_listener_rule.rule_basic.rule_id - targrt_group_id = tencentcloud_clb_target_group.test.id + target_group_id = tencentcloud_clb_target_group.test.id } ` diff --git a/tencentcloud/resource_tc_alb_server_attachment.go b/tencentcloud/resource_tc_alb_server_attachment.go index b864ef57c8..d331c890ca 100644 --- a/tencentcloud/resource_tc_alb_server_attachment.go +++ b/tencentcloud/resource_tc_alb_server_attachment.go @@ -132,7 +132,7 @@ func resourceTencentCloudAlbServerAttachmentCreate(d *schema.ResourceData, meta for _, inst_ := range d.Get("backends").(*schema.Set).List() { inst := inst_.(map[string]interface{}) - request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["port"], inst["weight"])) + request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["eni_ip"], inst["port"], inst["weight"])) } err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { @@ -277,7 +277,7 @@ func resourceTencentCloudAlbServerAttachementRemove(d *schema.ResourceData, meta } for _, inst_ := range remove { inst := inst_.(map[string]interface{}) - request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["port"], inst["weight"])) + request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["eni_ip"], inst["port"], inst["weight"])) } err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { @@ -325,7 +325,7 @@ func resourceTencentCloudAlbServerAttachementAdd(d *schema.ResourceData, meta in for _, inst_ := range add { inst := inst_.(map[string]interface{}) - request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["port"], inst["weight"])) + request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["eni_ip"], inst["port"], inst["weight"])) } err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { requestId := "" diff --git a/tencentcloud/resource_tc_alb_server_attachment_test.go b/tencentcloud/resource_tc_alb_server_attachment_test.go index e219b04221..870c002da1 100644 --- a/tencentcloud/resource_tc_alb_server_attachment_test.go +++ b/tencentcloud/resource_tc_alb_server_attachment_test.go @@ -12,7 +12,7 @@ import ( ) func TestAccTencentCloudAlbServerAttachmentTcp(t *testing.T) { - t.Parallel() + t.Skipf("Deprecated resource TestAccTencentCloudAlbServerAttachmentTcp, skip testing") resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -42,7 +42,7 @@ func TestAccTencentCloudAlbServerAttachmentTcp(t *testing.T) { } func TestAccTencentCloudAlbServerAttachmentHttp(t *testing.T) { - t.Parallel() + t.Skipf("Deprecated resource TestAccTencentCloudAlbServerAttachmentTcp, skip testing") resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, diff --git a/tencentcloud/resource_tc_clb_attachment.go b/tencentcloud/resource_tc_clb_attachment.go index b1a5a7f0b9..11996d69e7 100644 --- a/tencentcloud/resource_tc_clb_attachment.go +++ b/tencentcloud/resource_tc_clb_attachment.go @@ -85,8 +85,13 @@ func resourceTencentCloudClbServerAttachment() *schema.Resource { Schema: map[string]*schema.Schema{ "instance_id": { Type: schema.TypeString, - Required: true, - Description: "Id of the backend server.", + Optional: true, + Description: "CVM Instance Id of the backend server, conflict with `eni_ip` but must specify one of them.", + }, + "eni_ip": { + Type: schema.TypeString, + Optional: true, + Description: "Eni IP address of the backend server, conflict with `instance_id` but must specify one of them.", }, "port": { Type: schema.TypeInt, @@ -147,7 +152,7 @@ func resourceTencentCloudClbServerAttachmentCreate(d *schema.ResourceData, meta break } inst := insList[index].(map[string]interface{}) - request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["port"], inst["weight"])) + request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["eni_ip"], inst["port"], inst["weight"])) } err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { @@ -220,7 +225,7 @@ func resourceTencentCloudClbServerAttachmentDelete(d *schema.ResourceData, meta break } inst := insList[index].(map[string]interface{}) - request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["port"], inst["weight"])) + request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["eni_ip"], inst["port"], inst["weight"])) } err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { @@ -318,9 +323,9 @@ func resourceTencentCloudClbServerAttachmentAdd(d *schema.ResourceData, meta int } } - for _, inst_ := range add { - inst := inst_.(map[string]interface{}) - request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["port"], inst["weight"])) + for _, v := range add { + inst := v.(map[string]interface{}) + request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["eni_ip"], inst["port"], inst["weight"])) } err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { requestId := "" @@ -432,21 +437,44 @@ func resourceTencentCloudClbServerAttachmentRead(d *schema.ResourceData, meta in //this may cause problems when there are members in two dimensions array //need to read state of the tfstate file to clear the relationships //in this situation, import action is not supported + // TL,DR: just update partial targets which this resource declared. stateTargets := d.Get("targets").(*schema.Set) if stateTargets.Len() != 0 { //the old state exist //create a new attachment with state - exactTargets := make([]*clb.Backend, 0) - for _, v := range onlineTargets { - if stateTargets.Contains(map[string]interface{}{ - "weight": int(*v.Weight), - "port": int(*v.Port), - "instance_id": *v.InstanceId, - }) { - exactTargets = append(exactTargets, v) + exactTargets := make([]interface{}, 0) + for i := range onlineTargets { + v := onlineTargets[i] + if *v.Type == "CVM" && v.InstanceId != nil { + target := map[string]interface{}{ + "weight": int(*v.Weight), + "port": int(*v.Port), + "instance_id": *v.InstanceId, + } + if stateTargets.Contains(target) { + exactTargets = append(exactTargets, map[string]interface{}{ + "weight": int(*v.Weight), + "port": int(*v.Port), + "instance_id": *v.InstanceId, + }) + } + + } else if len(v.PrivateIpAddresses) > 0 && *v.PrivateIpAddresses[0] != "" { + target := map[string]interface{}{ + "weight": int(*v.Weight), + "port": int(*v.Port), + "eni_ip": *v.PrivateIpAddresses[0], + } + if stateTargets.Contains(target) { + exactTargets = append(exactTargets, map[string]interface{}{ + "weight": int(*v.Weight), + "port": int(*v.Port), + "eni_ip": *v.PrivateIpAddresses[0], + }) + } } } - _ = d.Set("targets", flattenBackendList(exactTargets)) + _ = d.Set("targets", exactTargets) } else { _ = d.Set("targets", flattenBackendList(onlineTargets)) } @@ -466,7 +494,7 @@ func getRemoveCandidates(ctx context.Context, clbService ClbService, clbId strin for _, item := range remove { target := item.(map[string]interface{}) - if targetGroupContainsInstance(existTargetGroups, target["instance_id"].(string)) { + if targetGroupContainsInstance(existTargetGroups, target["instance_id"]) || targetGroupContainsEni(existTargetGroups, target["eni_ip"]) { removeCandidates = append(removeCandidates, target) } } @@ -474,14 +502,42 @@ func getRemoveCandidates(ctx context.Context, clbService ClbService, clbId strin return removeCandidates } -func targetGroupContainsInstance(targets []*clb.Backend, instanceId string) (contains bool) { +func targetGroupContainsInstance(targets []*clb.Backend, instanceId interface{}) (contains bool) { contains = false + id, ok := instanceId.(string) + if !ok || id == "" { + return + } for _, target := range targets { - if instanceId == *target.InstanceId { - log.Printf("[WARN] Instance %s applied.", instanceId) + if target.InstanceId == nil { + continue + } + if id == *target.InstanceId { + log.Printf("[WARN] Instance %s applied.", id) return true } } - log.Printf("[WARN] Instance %s not exist, skip deregister.", instanceId) + log.Printf("[WARN] Instance %s not exist, skip deregister.", id) + + return +} + +func targetGroupContainsEni(targets []*clb.Backend, eniIp interface{}) (contains bool) { + contains = false + ip, ok := eniIp.(string) + if !ok || ip == "" { + return + } + for _, target := range targets { + if len(target.PrivateIpAddresses) > 0 && target.PrivateIpAddresses[0] != nil { + continue + } + if ip == *target.PrivateIpAddresses[0] { + log.Printf("[WARN] IP %s applied.", ip) + return true + } + } + log.Printf("[WARN] IP %s not exist, skip deregister.", ip) + return } diff --git a/tencentcloud/resource_tc_clb_attachment_test.go b/tencentcloud/resource_tc_clb_attachment_test.go index 48084e76e5..24c9b8be87 100644 --- a/tencentcloud/resource_tc_clb_attachment_test.go +++ b/tencentcloud/resource_tc_clb_attachment_test.go @@ -199,7 +199,7 @@ resource "tencentcloud_clb_attachment" "foo" { } ` -const testAccClbServerAttachment_tcp_update = instanceCommonTestCase + ` +const testAccClbServerAttachment_tcp_update = instanceCommonTestCase + presetCVM + ` data "tencentcloud_ssl_certificates" "foo" { name = "keep" } @@ -208,6 +208,7 @@ resource "tencentcloud_clb_instance" "foo" { network_type = "OPEN" clb_name = "tf-clb-attach-tcp-test" vpc_id = var.cvm_vpc_id + snat_pro = true } resource "tencentcloud_clb_listener" "foo" { @@ -229,14 +230,14 @@ resource "tencentcloud_clb_attachment" "foo" { listener_id = tencentcloud_clb_listener.foo.listener_id targets { - instance_id = tencentcloud_instance.default.id + eni_ip = local.cvm_private_ip port = 23 weight = 50 } } ` -const testAccClbServerAttachment_tcp_update_ssl = instanceCommonTestCase + ` +const testAccClbServerAttachment_tcp_update_ssl = instanceCommonTestCase + presetCVM + ` data "tencentcloud_ssl_certificates" "foo" { name = "keep" } @@ -245,6 +246,7 @@ resource "tencentcloud_clb_instance" "foo" { network_type = "OPEN" clb_name = "tf-clb-attach-tcp-ssl" vpc_id = var.cvm_vpc_id + snat_pro = true } # This is will force new as expected @@ -263,15 +265,16 @@ resource "tencentcloud_clb_attachment" "foo" { clb_id = tencentcloud_clb_instance.foo.id listener_id = tencentcloud_clb_listener.foo.listener_id + # cross network target targets { - instance_id = tencentcloud_instance.default.id + eni_ip = local.cvm_private_ip port = 23 weight = 50 } } ` -const testAccClbServerAttachment_http = instanceCommonTestCase + ` +const testAccClbServerAttachment_http = instanceCommonTestCase + presetCVM + ` resource "tencentcloud_clb_instance" "foo" { network_type = "OPEN" clb_name = "tf-clb-attach-http-test" diff --git a/tencentcloud/resource_tc_clb_instance_test.go b/tencentcloud/resource_tc_clb_instance_test.go index 92d59131ea..e5d2db45e2 100644 --- a/tencentcloud/resource_tc_clb_instance_test.go +++ b/tencentcloud/resource_tc_clb_instance_test.go @@ -22,7 +22,7 @@ const OpenClbName = "tf-clb-open" const OpenClbNameUpdate = "tf-clb-update-open" func init() { - // -sweep-run=tencentcloud_clb_instance + // go test -v ./tencentcloud -sweep=ap-guangzhou -sweep-run=tencentcloud_clb_instance resource.AddTestSweepers("tencentcloud_clb_instance", &resource.Sweeper{ Name: "tencentcloud_clb_instance", F: testSweepClbInstance, diff --git a/tencentcloud/resource_tc_clb_listener_test.go b/tencentcloud/resource_tc_clb_listener_test.go index 461688f512..c55bd40cbe 100644 --- a/tencentcloud/resource_tc_clb_listener_test.go +++ b/tencentcloud/resource_tc_clb_listener_test.go @@ -602,6 +602,7 @@ resource "tencentcloud_clb_listener" "listener_tcp"{ session_expire_time = 60 scheduler = "WRR" health_check_type = "TCP" + health_check_port = 333 } ` diff --git a/tencentcloud/service_tencentcloud_clb.go b/tencentcloud/service_tencentcloud_clb.go index 31e4e89f66..a6f661835b 100644 --- a/tencentcloud/service_tencentcloud_clb.go +++ b/tencentcloud/service_tencentcloud_clb.go @@ -522,7 +522,7 @@ func (me *ClbService) DeleteAttachmentById(ctx context.Context, clbId string, li request.LoadBalancerId = &clbId for _, inst_ := range targets { inst := inst_.(map[string]interface{}) - request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["port"], inst["weight"])) + request.Targets = append(request.Targets, clbNewTarget(inst["instance_id"], inst["eni_ip"], inst["port"], inst["weight"])) } if locationId != "" { request.LocationId = &locationId @@ -1006,29 +1006,38 @@ func waitForTaskFinish(requestId string, meta *clb.Client) (err error) { func flattenBackendList(list []*clb.Backend) (mapping []map[string]interface{}) { result := make([]map[string]interface{}, 0, len(list)) - for _, v := range list { + for i := range list { + v := list[i] target := map[string]interface{}{ - "instance_id": v.InstanceId, - "port": v.Port, - "weight": v.Weight, + "port": v.Port, + "weight": v.Weight, + } + if *v.Type == "ENI" && len(v.PrivateIpAddresses) > 0 { + target["eni_ip"] = v.PrivateIpAddresses[0] + } else { + target["instance_id"] = v.InstanceId } result = append(result, target) } return result } -func clbNewTarget(instanceId, port, weight interface{}) *clb.Target { - id := instanceId.(string) +func clbNewTarget(instanceId, eniIp, port, weight interface{}) *clb.Target { p := int64(port.(int)) - bk := clb.Target{ - InstanceId: &id, - Port: &p, + target := clb.Target{ + Port: &p, + } + if id, ok := instanceId.(string); ok && id != "" { + target.InstanceId = &id + } + if ip, ok := eniIp.(string); ok && ip != "" { + target.EniIp = &ip } if w, ok := weight.(int); ok { weight64 := int64(w) - bk.Weight = &weight64 + target.Weight = &weight64 } - return &bk + return &target } func (me *ClbService) CreateTargetGroup(ctx context.Context, targetGroupName string, vpcId string, port uint64, diff --git a/website/docs/r/clb_attachment.html.markdown b/website/docs/r/clb_attachment.html.markdown index b5f1c9bf38..055d8b2bb0 100644 --- a/website/docs/r/clb_attachment.html.markdown +++ b/website/docs/r/clb_attachment.html.markdown @@ -38,8 +38,9 @@ The following arguments are supported: The `targets` object supports the following: -* `instance_id` - (Required, String) Id of the backend server. * `port` - (Required, Int) Port of the backend server. Valid value ranges: (0~65535). +* `eni_ip` - (Optional, String) Eni IP address of the backend server, conflict with `instance_id` but must specify one of them. +* `instance_id` - (Optional, String) CVM Instance Id of the backend server, conflict with `eni_ip` but must specify one of them. * `weight` - (Optional, Int) Forwarding weight of the backend service. Valid value ranges: (0~100). defaults to `10`. ## Attributes Reference