Skip to content

Commit 0dcdb37

Browse files
authored
feat: clb - support snat pro and snat ips (#1114)
1 parent c1e62af commit 0dcdb37

9 files changed

+735
-27
lines changed

tencentcloud/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ Cloud Load Balancer(CLB)
244244
tencentcloud_clb_log_set
245245
tencentcloud_clb_log_topic
246246
tencentcloud_clb_customized_config
247+
tencentcloud_clb_snat_ip
247248
248249
Cloud Object Storage(COS)
249250
Data Source
@@ -966,6 +967,7 @@ func Provider() terraform.ResourceProvider {
966967
"tencentcloud_clb_log_set": resourceTencentCloudClbLogSet(),
967968
"tencentcloud_clb_log_topic": resourceTencentCloudClbLogTopic(),
968969
"tencentcloud_clb_customized_config": resourceTencentCloudClbCustomizedConfig(),
970+
"tencentcloud_clb_snat_ip": resourceTencentCloudClbSnatIp(),
969971
"tencentcloud_container_cluster": resourceTencentCloudContainerCluster(),
970972
"tencentcloud_container_cluster_instance": resourceTencentCloudContainerClusterInstance(),
971973
"tencentcloud_kubernetes_cluster": resourceTencentCloudTkeCluster(),

tencentcloud/resource_tc_clb_instance.go

Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ import (
152152
"log"
153153
"sync"
154154

155+
"github.com/hashicorp/terraform-plugin-sdk/helper/hashcode"
156+
155157
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
156158
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
157159
"github.com/pkg/errors"
@@ -253,6 +255,30 @@ func resourceTencentCloudClbInstance() *schema.Resource {
253255
Computed: true,
254256
Description: "Vpc information of backend services are attached the CLB instance. Only supports `OPEN` CLBs.",
255257
},
258+
"snat_pro": {
259+
Type: schema.TypeBool,
260+
Optional: true,
261+
Description: "Indicates whether Binding IPs of other VPCs feature switch.",
262+
},
263+
"snat_ips": {
264+
Type: schema.TypeList,
265+
Optional: true,
266+
Description: "Snat Ip List, required with `snat_pro=true`. NOTE: This argument cannot be read and modified here because dynamic ip is untraceable, please import resource `tencentcloud_clb_snat_ip` to handle fixed ips.",
267+
Elem: &schema.Resource{
268+
Schema: map[string]*schema.Schema{
269+
"ip": {
270+
Type: schema.TypeString,
271+
Optional: true,
272+
Description: "Snat IP address, If set to empty will auto allocated.",
273+
},
274+
"subnet_id": {
275+
Type: schema.TypeString,
276+
Required: true,
277+
Description: "Snat subnet ID.",
278+
},
279+
},
280+
},
281+
},
256282
"tags": {
257283
Type: schema.TypeMap,
258284
Optional: true,
@@ -366,6 +392,24 @@ func resourceTencentCloudClbInstanceCreate(d *schema.ResourceData, meta interfac
366392
request.AddressIPVersion = helper.String(v.(string))
367393
}
368394

395+
if v, ok := d.GetOk("snat_pro"); ok {
396+
request.SnatPro = helper.Bool(v.(bool))
397+
}
398+
399+
if v, ok := d.Get("snat_ips").([]interface{}); ok && len(v) > 0 {
400+
for i := range v {
401+
item := v[i].(map[string]interface{})
402+
subnetId := item["subnet_id"].(string)
403+
snatIp := &clb.SnatIp{
404+
SubnetId: &subnetId,
405+
}
406+
if v, ok := item["ip"].(string); ok && v != "" {
407+
snatIp.Ip = &v
408+
}
409+
request.SnatIps = append(request.SnatIps, snatIp)
410+
}
411+
}
412+
369413
v, ok := d.GetOk("internet_charge_type")
370414
bv, bok := d.GetOk("internet_bandwidth_max_out")
371415
pv, pok := d.GetOk("bandwidth_package_id")
@@ -613,6 +657,10 @@ func resourceTencentCloudClbInstanceRead(d *schema.ResourceData, meta interface{
613657
_ = d.Set("log_set_id", instance.LogSetId)
614658
_ = d.Set("log_topic_id", instance.LogTopicId)
615659

660+
if _, ok := d.GetOk("snat_pro"); ok {
661+
_ = d.Set("snat_pro", instance.SnatPro)
662+
}
663+
616664
tcClient := meta.(*TencentCloudClient).apiV3Conn
617665
tagService := &TagService{client: tcClient}
618666
tags, err := tagService.DescribeResourceTags(ctx, "clb", "clb", tcClient.Region, d.Id())
@@ -631,15 +679,19 @@ func resourceTencentCloudClbInstanceUpdate(d *schema.ResourceData, meta interfac
631679
defer clbActionMu.Unlock()
632680

633681
logId := getLogId(contextNil)
682+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
634683

635684
d.Partial(true)
636685

637686
clbId := d.Id()
687+
request := clb.NewModifyLoadBalancerAttributesRequest()
688+
request.LoadBalancerId = helper.String(clbId)
638689
clbName := ""
639690
targetRegionInfo := clb.TargetRegionInfo{}
640691
internet := clb.InternetAccessible{}
641692
changed := false
642693
isLoadBalancerPassToTgt := false
694+
snatPro := d.Get("snat_pro").(bool)
643695

644696
if d.HasChange("clb_name") {
645697
changed = true
@@ -651,6 +703,7 @@ func resourceTencentCloudClbInstanceUpdate(d *schema.ResourceData, meta interfac
651703
if flag {
652704
return fmt.Errorf("[CHECK][CLB instance][Update] check: Same CLB name %s exists!", clbName)
653705
}
706+
request.LoadBalancerName = helper.String(clbName)
654707
}
655708

656709
if d.HasChange("target_region_info_region") || d.HasChange("target_region_info_vpc_id") {
@@ -664,6 +717,7 @@ func resourceTencentCloudClbInstanceUpdate(d *schema.ResourceData, meta interfac
664717
Region: &region,
665718
VpcId: &vpcId,
666719
}
720+
request.TargetRegionInfo = &targetRegionInfo
667721
}
668722

669723
if d.HasChange("internet_charge_type") || d.HasChange("internet_bandwidth_max_out") {
@@ -679,28 +733,25 @@ func resourceTencentCloudClbInstanceUpdate(d *schema.ResourceData, meta interfac
679733
if bandwidth > 0 {
680734
internet.InternetMaxBandwidthOut = helper.IntInt64(bandwidth)
681735
}
736+
request.InternetChargeInfo = &internet
682737
}
683738

684739
if d.HasChange("load_balancer_pass_to_target") {
685740
changed = true
686741
isLoadBalancerPassToTgt = d.Get("load_balancer_pass_to_target").(bool)
742+
request.LoadBalancerPassToTarget = &isLoadBalancerPassToTgt
743+
}
744+
745+
if d.HasChange("snat_pro") {
746+
changed = true
747+
request.SnatPro = &snatPro
748+
}
749+
750+
if d.HasChange("snat_ips") {
751+
return fmt.Errorf("`snat_ips`")
687752
}
688753

689754
if changed {
690-
request := clb.NewModifyLoadBalancerAttributesRequest()
691-
request.LoadBalancerId = helper.String(clbId)
692-
if d.HasChange("clb_name") {
693-
request.LoadBalancerName = helper.String(clbName)
694-
}
695-
if d.HasChange("target_region_info_region") || d.HasChange("target_region_info_vpc_id") {
696-
request.TargetRegionInfo = &targetRegionInfo
697-
}
698-
if d.HasChange("internet_charge_type") || d.HasChange("internet_bandwidth_max_out") {
699-
request.InternetChargeInfo = &internet
700-
}
701-
if d.HasChange("load_balancer_pass_to_target") {
702-
request.LoadBalancerPassToTarget = &isLoadBalancerPassToTgt
703-
}
704755
err := resource.Retry(writeRetryTimeout, func() *resource.RetryError {
705756
response, e := meta.(*TencentCloudClient).apiV3Conn.UseClbClient().ModifyLoadBalancerAttributes(request)
706757
if e != nil {
@@ -720,18 +771,6 @@ func resourceTencentCloudClbInstanceUpdate(d *schema.ResourceData, meta interfac
720771
log.Printf("[CRITAL]%s update CLB instance failed, reason:%+v", logId, err)
721772
return err
722773
}
723-
if d.HasChange("clb_name") {
724-
d.SetPartial("clb_name")
725-
}
726-
if d.HasChange("clb_vips") {
727-
d.SetPartial("clb_vips")
728-
}
729-
if d.HasChange("target_region_info_region") {
730-
d.SetPartial("target_region_info_region")
731-
}
732-
if d.HasChange("target_region_info_vpc_id") {
733-
d.SetPartial("target_region_info_vpc_id")
734-
}
735774
}
736775

737776
if d.HasChange("security_groups") {
@@ -794,7 +833,7 @@ func resourceTencentCloudClbInstanceUpdate(d *schema.ResourceData, meta interfac
794833
return err
795834
}
796835
}
797-
ctx := context.WithValue(context.TODO(), logIdKey, logId)
836+
798837
if d.HasChange("tags") {
799838

800839
oldValue, newValue := d.GetChange("tags")
@@ -875,3 +914,15 @@ func checkSameName(name string, meta interface{}) (flag bool, errRet error) {
875914
errRet = err
876915
return
877916
}
917+
918+
func snatIpSetInitFn(i interface{}) int {
919+
item := i.(map[string]interface{})
920+
subnet := item["subnet_id"].(string)
921+
allocatedIp := item["allocated_snat_ip"].(string)
922+
ip, ok := item["ip"].(string)
923+
924+
if !ok || ip == "" {
925+
ip = allocatedIp
926+
}
927+
return hashcode.String(subnet + ip)
928+
}

tencentcloud/resource_tc_clb_instance_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
)
1414

1515
const BasicClbName = "tf-clb-basic"
16+
const SnatClbName = "tf-clb-snat"
1617
const InternalClbName = "tf-clb-internal"
1718
const InternalClbNameUpdate = "tf-clb-update-internal"
1819
const SingleClbName = "single-open-clb"
@@ -136,6 +137,27 @@ func TestAccTencentCloudClbInstance_open(t *testing.T) {
136137
})
137138
}
138139

140+
func TestAccTencentCloudClbInstance_snat(t *testing.T) {
141+
t.Parallel()
142+
143+
resource.Test(t, resource.TestCase{
144+
PreCheck: func() { testAccPreCheck(t) },
145+
Providers: testAccProviders,
146+
CheckDestroy: testAccCheckClbInstanceDestroy,
147+
Steps: []resource.TestStep{
148+
{
149+
Config: testAccClbInstance_snat,
150+
Check: resource.ComposeTestCheckFunc(
151+
testAccCheckClbInstanceExists("tencentcloud_clb_instance.clb_basic"),
152+
resource.TestCheckResourceAttr("tencentcloud_clb_instance.clb_basic", "network_type", "OPEN"),
153+
resource.TestCheckResourceAttr("tencentcloud_clb_instance.clb_basic", "clb_name", SnatClbName),
154+
resource.TestCheckResourceAttr("tencentcloud_clb_instance.clb_basic", "snat_pro", "true"),
155+
),
156+
},
157+
},
158+
})
159+
}
160+
139161
func TestAccTencentCloudClbInstance_internal(t *testing.T) {
140162
t.Parallel()
141163

@@ -310,6 +332,35 @@ resource "tencentcloud_clb_instance" "clb_basic" {
310332
}
311333
`
312334

335+
const testAccClbInstance_snat = `
336+
data "tencentcloud_vpc_instances" "gz3vpc" {
337+
name = "Default-"
338+
is_default = true
339+
}
340+
341+
data "tencentcloud_vpc_subnets" "gz3" {
342+
vpc_id = data.tencentcloud_vpc_instances.gz3vpc.instance_list.0.vpc_id
343+
}
344+
345+
locals {
346+
keep_clb_subnets = [for subnet in data.tencentcloud_vpc_subnets.gz3.instance_list: lookup(subnet, "subnet_id") if lookup(subnet, "name") == "keep-clb-sub"]
347+
subnets = [for subnet in data.tencentcloud_vpc_subnets.gz3.instance_list: lookup(subnet, "subnet_id") ]
348+
subnet_for_clb_snat = concat(local.keep_clb_subnets, local.subnets)
349+
}
350+
351+
resource "tencentcloud_clb_instance" "clb_basic" {
352+
network_type = "OPEN"
353+
clb_name = "` + SnatClbName + `"
354+
snat_pro = true
355+
snat_ips {
356+
subnet_id = local.subnet_for_clb_snat.0
357+
}
358+
snat_ips {
359+
subnet_id = local.subnet_for_clb_snat.1
360+
}
361+
}
362+
`
363+
313364
const testAccClbInstance_internal = `
314365
variable "availability_zone" {
315366
default = "ap-guangzhou-3"

0 commit comments

Comments
 (0)