Skip to content

Commit

Permalink
feat(vpc): [123456789] support reserve ip address (#2972)
Browse files Browse the repository at this point in the history
* support reserve ip address

* add changelog

---------

Co-authored-by: mikatong <[email protected]>
  • Loading branch information
tongyiming and mikatong authored Nov 23, 2024
1 parent 76a060b commit 3a7177f
Show file tree
Hide file tree
Showing 13 changed files with 1,673 additions and 101 deletions.
3 changes: 3 additions & 0 deletions .changelog/2972.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
tencentcloud_reserve_ip_address
```
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1034
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudaudit v1.0.1033
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cls v1.0.970
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1038
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1045
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.1014
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cwp v1.0.762
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cynosdb v1.0.692
Expand Down Expand Up @@ -96,7 +96,7 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tse v1.0.857
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tsf v1.0.674
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.860
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.1018
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.1045
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1037
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/wedata v1.0.792
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/wss v1.0.199
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -928,10 +928,12 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1034 h1:T7e
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1034/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1036 h1:B3GO+IBOrjrq8sN5bT9e8GMHWguHkyyGdNEos6cp5cE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1036/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1038 h1:tB3DLzyQXavvGTI+JUvEcuYh0EtTn1rvh9W6xxFHL38=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1038/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1037 h1:cXerqxVAnEhEryXYgeBVFAJR8zjG2AsPWVnLtqJfkmY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1037/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1038 h1:tB3DLzyQXavvGTI+JUvEcuYh0EtTn1rvh9W6xxFHL38=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1038/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1045 h1:3vvovAezER+/2FycWT4Wplkis3y3OHsRg2mDfcv08MI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1045/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/controlcenter v1.0.993 h1:WlPgXldQCxt7qi5Xrc6j6zTrsXWzN5BcOGs7Irq7fwQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/controlcenter v1.0.993/go.mod h1:Z9U8zNtyuyKhjS0698wqsrG/kLx1TQ5CEixXBwVe7xY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/csip v1.0.860 h1:F3esKBIT3HW9+7Gt8cVgf8X06VdGIczpgLBUECzSEzU=
Expand Down Expand Up @@ -1054,6 +1056,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.860 h1:vW2NgAH
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.860/go.mod h1:uCkDh/AW/tb8JGq5b2kqLjqZuhCFR+6oTsq1SrrvT44=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.1018 h1:+ATJA5XAYJVLRm0IjPhl6UlyXc2eh7FTJ+I42uSz0B4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.1018/go.mod h1:LmBUb+v6kdY+Jr+VRsU28SF8H5ga7Tqh+wpoVYmSofw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.1045 h1:7+rfyxftJ/C85yMQfs7ALj0RHkSlyboMj6gqCVKYa58=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.1045/go.mod h1:yn4I7fSwpiM6ltjqksS1JtZZAHkZ35ywN+kLm6AJPzc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.833 h1:avaBlZ+Qqv7bfMg/u0jlRsbEBbE18CfqKWbfGc84PLg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.833/go.mod h1:fUWG217b//46Oa3VXxC5mgeYeewVAbF+lc81uET89EM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1037 h1:sgHOHqVFcO266dnoh0KJ0CoxrRglRZYKW78iBh41Giw=
Expand Down
1 change: 1 addition & 0 deletions tencentcloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2164,6 +2164,7 @@ func Provider() *schema.Provider {
"tencentcloud_vpc_peer_connect_manager": vpc.ResourceTencentCloudVpcPeerConnectManager(),
"tencentcloud_vpc_peer_connect_accept_operation": vpc.ResourceTencentCloudVpcPeerConnectAcceptOperation(),
"tencentcloud_vpc_peer_connect_reject_operation": vpc.ResourceTencentCloudVpcPeerConnectRejectOperation(),
"tencentcloud_reserve_ip_address": vpc.ResourceTencentCloudReserveIpAddress(),
"tencentcloud_csip_risk_center": csip.ResourceTencentCloudCsipRiskCenter(),
"tencentcloud_organization_org_share_unit_member": tco.ResourceTencentCloudOrganizationOrgShareUnitMember(),
"tencentcloud_organization_org_share_unit": tco.ResourceTencentCloudOrganizationOrgShareUnit(),
Expand Down
335 changes: 335 additions & 0 deletions tencentcloud/services/vpc/resource_tc_reserve_ip_address.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
package vpc

import (
"context"
"fmt"
"log"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"

tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common"
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
svctag "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/tag"
)

func ResourceTencentCloudReserveIpAddress() *schema.Resource {
return &schema.Resource{
Create: resourceTencentCloudReserveIpAddressCreate,
Read: resourceTencentCloudReserveIpAddressRead,
Update: resourceTencentCloudReserveIpAddressUpdate,
Delete: resourceTencentCloudReserveIpAddressDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"vpc_id": {
Type: schema.TypeString,
Required: true,
Description: "VPC unique ID.",
},

"ip_address": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Specify the reserved IP address of the intranet for which the IP application is requested.",
},

"subnet_id": {
Type: schema.TypeString,
Optional: true,
Description: "Subnet ID.",
},

"name": {
Type: schema.TypeString,
Optional: true,
Description: "The IP name is reserved for the intranet.",
},

"description": {
Type: schema.TypeString,
Optional: true,
Description: "The IP description is retained on the intranet.",
},

"tags": {
Type: schema.TypeMap,
Optional: true,
Description: "Tags.",
},
"reserve_ip_id": {
Type: schema.TypeString,
Computed: true,
Description: "Reserve ip ID.",
},
"resource_id": {
Type: schema.TypeString,
Computed: true,
Description: "The intranet retains the resource instance ID bound to the IPs.",
},
"ip_type": {
Type: schema.TypeInt,
Computed: true,
Description: "Ip type for product application.",
},
"state": {
Type: schema.TypeString,
Computed: true,
Description: "Binding status.",
},
"created_time": {
Type: schema.TypeString,
Computed: true,
Description: "Created time.",
},
},
}
}

func resourceTencentCloudReserveIpAddressCreate(d *schema.ResourceData, meta interface{}) error {
defer tccommon.LogElapsed("resource.tencentcloud_reserve_ip_address.create")()
defer tccommon.InconsistentCheck(d, meta)()

logId := tccommon.GetLogId(tccommon.ContextNil)

ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta)

var (
vpcId string
reserveIpId string
)
var (
request = vpc.NewCreateReserveIpAddressesRequest()
response = vpc.NewCreateReserveIpAddressesResponse()
)

if v, ok := d.GetOk("vpc_id"); ok {
vpcId = v.(string)
request.VpcId = helper.String(vpcId)
}

if v, ok := d.GetOk("ip_address"); ok {
ipAddress := v.(string)
request.IpAddresses = append(request.IpAddresses, helper.String(ipAddress))
} else {
request.IpAddressCount = helper.IntUint64(1)
}

if v, ok := d.GetOk("subnet_id"); ok {
request.SubnetId = helper.String(v.(string))
}

if v, ok := d.GetOk("name"); ok {
request.Name = helper.String(v.(string))
}

if v, ok := d.GetOk("description"); ok {
request.Description = helper.String(v.(string))
}

err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError {
result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVpcClient().CreateReserveIpAddressesWithContext(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 len(result.Response.ReserveIpAddressSet) > 0 {
reserveIpId = *result.Response.ReserveIpAddressSet[0].ReserveIpId
}
return nil
})
if err != nil {
log.Printf("[CRITAL]%s create reserve ip addresses failed, reason:%+v", logId, err)
return err
}

_ = response

if tags := helper.GetTags(d, "tags"); len(tags) > 0 {
tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn()
tagService := svctag.NewTagService(tcClient)
resourceName := tccommon.BuildTagResourceName("vpc", "rsvip", tcClient.Region, reserveIpId)
if err := tagService.ModifyTags(ctx, resourceName, tags, nil); err != nil {
return err
}
}

d.SetId(strings.Join([]string{vpcId, reserveIpId}, tccommon.FILED_SP))

return resourceTencentCloudReserveIpAddressRead(d, meta)
}

func resourceTencentCloudReserveIpAddressRead(d *schema.ResourceData, meta interface{}) error {
defer tccommon.LogElapsed("resource.tencentcloud_reserve_ip_address.read")()
defer tccommon.InconsistentCheck(d, meta)()

logId := tccommon.GetLogId(tccommon.ContextNil)

ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta)

service := VpcService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()}

idSplit := strings.Split(d.Id(), tccommon.FILED_SP)
if len(idSplit) != 2 {
return fmt.Errorf("id is broken,%s", d.Id())
}
reserveIpId := idSplit[1]

respData, err := service.DescribeReserveIpAddressesById(ctx, reserveIpId)
if err != nil {
return err
}

if respData == nil {
d.SetId("")
log.Printf("[WARN]%s resource `reserve_ip_addresses` [%s] not found, please check if it has been deleted.\n", logId, d.Id())
return nil
}
if len(respData.ReserveIpAddressSet) < 1 {
d.SetId("")
log.Printf("[WARN]%s resource `reserve_ip_addresses` [%s] not found, please check if it has been deleted.\n", logId, d.Id())
return nil
}
reserveIpAddress := respData.ReserveIpAddressSet[0]

_ = d.Set("vpc_id", reserveIpAddress.VpcId)
_ = d.Set("ip_address", reserveIpAddress.ReserveIpAddress)
_ = d.Set("name", reserveIpAddress.Name)
_ = d.Set("description", reserveIpAddress.Description)
_ = d.Set("reserve_ip_id", reserveIpAddress.ReserveIpId)
_ = d.Set("resource_id", reserveIpAddress.ResourceId)
_ = d.Set("ip_type", reserveIpAddress.IpType)
_ = d.Set("state", reserveIpAddress.State)
_ = d.Set("created_time", reserveIpAddress.CreatedTime)

tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn()
tagService := svctag.NewTagService(meta.(tccommon.ProviderMeta).GetAPIV3Conn())
tags, err := tagService.DescribeResourceTags(ctx, "vpc", "rsvip", tcClient.Region, reserveIpId)
if err != nil {
return err
}
_ = d.Set("tags", tags)
_ = reserveIpId
return nil
}

func resourceTencentCloudReserveIpAddressUpdate(d *schema.ResourceData, meta interface{}) error {
defer tccommon.LogElapsed("resource.tencentcloud_reserve_ip_address.update")()
defer tccommon.InconsistentCheck(d, meta)()

logId := tccommon.GetLogId(tccommon.ContextNil)

ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta)

immutableArgs := []string{"vpc_id", "ip_addresses", "subnet_id"}
for _, v := range immutableArgs {
if d.HasChange(v) {
return fmt.Errorf("argument `%s` cannot be changed", v)
}
}
idSplit := strings.Split(d.Id(), tccommon.FILED_SP)
if len(idSplit) != 2 {
return fmt.Errorf("id is broken,%s", d.Id())
}
vpcId := idSplit[0]
reserveIpId := idSplit[1]

needChange := false
mutableArgs := []string{"name", "description"}
for _, v := range mutableArgs {
if d.HasChange(v) {
needChange = true
break
}
}

if needChange {
request := vpc.NewModifyReserveIpAddressRequest()

request.VpcId = helper.String(vpcId)

request.ReserveIpId = helper.String(reserveIpId)

if v, ok := d.GetOk("name"); ok {
request.Name = helper.String(v.(string))
}

if v, ok := d.GetOk("description"); ok {
request.Description = helper.String(v.(string))
}

err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError {
result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVpcClient().ModifyReserveIpAddressWithContext(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 err != nil {
log.Printf("[CRITAL]%s update reserve ip addresses failed, reason:%+v", logId, err)
return err
}
}

if d.HasChange("tags") {
tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn()
tagService := svctag.NewTagService(tcClient)
oldTags, newTags := d.GetChange("tags")
replaceTags, deleteTags := svctag.DiffTags(oldTags.(map[string]interface{}), newTags.(map[string]interface{}))
resourceName := tccommon.BuildTagResourceName("vpc", "rsvip", tcClient.Region, reserveIpId)
if err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags); err != nil {
return err
}
}

return resourceTencentCloudReserveIpAddressRead(d, meta)
}

func resourceTencentCloudReserveIpAddressDelete(d *schema.ResourceData, meta interface{}) error {
defer tccommon.LogElapsed("resource.tencentcloud_reserve_ip_address.delete")()
defer tccommon.InconsistentCheck(d, meta)()

logId := tccommon.GetLogId(tccommon.ContextNil)
ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta)

idSplit := strings.Split(d.Id(), tccommon.FILED_SP)
if len(idSplit) != 2 {
return fmt.Errorf("id is broken,%s", d.Id())
}
vpcId := idSplit[0]
reserveIpId := idSplit[1]

var (
request = vpc.NewDeleteReserveIpAddressesRequest()
response = vpc.NewDeleteReserveIpAddressesResponse()
)

request.VpcId = helper.String(vpcId)
request.ReserveIpIds = []*string{&reserveIpId}

err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError {
result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVpcClient().DeleteReserveIpAddressesWithContext(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())
}
response = result
return nil
})
if err != nil {
log.Printf("[CRITAL]%s delete reserve ip addresses failed, reason:%+v", logId, err)
return err
}

_ = response
_ = reserveIpId
return nil
}
Loading

0 comments on commit 3a7177f

Please sign in to comment.