alicloud/resource_alicloud_router_interface.go (335 lines of code) (raw):
package alicloud
import (
"time"
"github.com/denverdino/aliyungo/common"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
"github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func resourceAlicloudRouterInterface() *schema.Resource {
return &schema.Resource{
Create: resourceAlicloudRouterInterfaceCreate,
Read: resourceAlicloudRouterInterfaceRead,
Update: resourceAlicloudRouterInterfaceUpdate,
Delete: resourceAlicloudRouterInterfaceDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"opposite_region": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"router_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(VRouter), string(VBR)}, false),
ForceNew: true,
DiffSuppressFunc: routerInterfaceAcceptsideDiffSuppressFunc,
},
"router_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"role": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(InitiatingSide), string(AcceptingSide)}, false),
ForceNew: true,
},
"specification": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(GetAllRouterInterfaceSpec(), false),
DiffSuppressFunc: routerInterfaceAcceptsideDiffSuppressFunc,
},
"name": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(2, 128),
},
"description": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(2, 256),
},
"health_check_source_ip": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: routerInterfaceVBRTypeDiffSuppressFunc,
},
"health_check_target_ip": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: routerInterfaceVBRTypeDiffSuppressFunc,
},
"instance_charge_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: PostPaid,
ValidateFunc: validation.StringInSlice([]string{string(common.PrePaid), string(common.PostPaid)}, false),
},
"period": {
Type: schema.TypeInt,
Optional: true,
DiffSuppressFunc: PostPaidDiffSuppressFunc,
ValidateFunc: validation.Any(
validation.IntBetween(1, 9),
validation.IntInSlice([]int{12, 24, 36})),
},
"access_point_id": {
Type: schema.TypeString,
Computed: true,
Deprecated: "Attribute 'opposite_access_point_id' has been deprecated from version 1.11.0.",
},
"opposite_access_point_id": {
Type: schema.TypeString,
Optional: true,
Deprecated: "Attribute 'opposite_access_point_id' has been deprecated from version 1.11.0.",
},
"opposite_router_type": {
Type: schema.TypeString,
Computed: true,
Deprecated: "Attribute 'opposite_router_type' has been deprecated from version 1.11.0. Use resource alicloud_router_interface_connection's 'opposite_router_type' instead.",
},
"opposite_router_id": {
Type: schema.TypeString,
Computed: true,
Deprecated: "Attribute 'opposite_router_id' has been deprecated from version 1.11.0. Use resource alicloud_router_interface_connection's 'opposite_router_id' instead.",
},
"opposite_interface_id": {
Type: schema.TypeString,
Computed: true,
Deprecated: "Attribute 'opposite_interface_id' has been deprecated from version 1.11.0. Use resource alicloud_router_interface_connection's 'opposite_interface_id' instead.",
},
"opposite_interface_owner_id": {
Type: schema.TypeString,
Computed: true,
Deprecated: "Attribute 'opposite_interface_owner_id' has been deprecated from version 1.11.0. Use resource alicloud_router_interface_connection's 'opposite_interface_owner_id' instead.",
},
},
}
}
func resourceAlicloudRouterInterfaceCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
vpcService := VpcService{client}
request, err := buildAlicloudRouterInterfaceCreateArgs(d, meta)
if err != nil {
return WrapError(err)
}
raw, err := client.WithVpcClient(func(vpcClient *vpc.Client) (interface{}, error) {
return vpcClient.CreateRouterInterface(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, "alicloud_router_interface", request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*vpc.CreateRouterInterfaceResponse)
d.SetId(response.RouterInterfaceId)
if err := vpcService.WaitForRouterInterface(d.Id(), client.RegionId, Idle, 300); err != nil {
return WrapError(err)
}
return resourceAlicloudRouterInterfaceUpdate(d, meta)
}
func resourceAlicloudRouterInterfaceUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
d.Partial(true)
request, attributeUpdate, err := buildAlicloudRouterInterfaceModifyAttrArgs(d, meta)
if err != nil {
return WrapError(err)
}
request.RegionId = client.RegionId
if attributeUpdate {
raw, err := client.WithVpcClient(func(vpcClient *vpc.Client) (interface{}, error) {
return vpcClient.ModifyRouterInterfaceAttribute(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
}
if d.HasChange("specification") && !d.IsNewResource() {
d.SetPartial("specification")
request := vpc.CreateModifyRouterInterfaceSpecRequest()
request.RegionId = string(client.Region)
request.RouterInterfaceId = d.Id()
request.Spec = d.Get("specification").(string)
raw, err := client.WithVpcClient(func(vpcClient *vpc.Client) (interface{}, error) {
return vpcClient.ModifyRouterInterfaceSpec(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
}
d.Partial(false)
return resourceAlicloudRouterInterfaceRead(d, meta)
}
func resourceAlicloudRouterInterfaceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
vpcService := VpcService{client}
object, err := vpcService.DescribeRouterInterface(d.Id(), client.RegionId)
if err != nil {
if NotFoundError(err) {
d.SetId("")
return nil
}
}
d.Set("role", object.Role)
d.Set("specification", object.Spec)
d.Set("name", object.Name)
d.Set("router_id", object.RouterId)
d.Set("router_type", object.RouterType)
d.Set("description", object.Description)
d.Set("access_point_id", object.AccessPointId)
d.Set("opposite_region", object.OppositeRegionId)
d.Set("opposite_router_type", object.OppositeRouterType)
d.Set("opposite_router_id", object.OppositeRouterId)
d.Set("opposite_interface_id", object.OppositeInterfaceId)
d.Set("opposite_interface_owner_id", object.OppositeInterfaceOwnerId)
d.Set("health_check_source_ip", object.HealthCheckSourceIp)
d.Set("health_check_target_ip", object.HealthCheckTargetIp)
if object.ChargeType == "Prepaid" {
d.Set("instance_charge_type", PrePaid)
//period, err := computePeriodByUnit(object.CreationTime, object.EndTime, d.Get("period").(int), "Month")
//if err != nil {
// return WrapError(err)
//}
//d.Set("period", period)
} else {
d.Set("instance_charge_type", PostPaid)
}
return nil
}
func resourceAlicloudRouterInterfaceDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
vpcService := VpcService{client}
if object, err := vpcService.DescribeRouterInterface(d.Id(), client.RegionId); err != nil {
if NotFoundError(err) {
return nil
}
return WrapError(err)
} else if object.Status == string(Active) {
if err := vpcService.DeactivateRouterInterface(d.Id()); err != nil {
return WrapError(err)
}
}
request := vpc.CreateDeleteRouterInterfaceRequest()
request.RegionId = string(client.Region)
request.RouterInterfaceId = d.Id()
request.ClientToken = buildClientToken(request.GetActionName())
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
args := *request
raw, err := client.WithVpcClient(func(vpcClient *vpc.Client) (interface{}, error) {
return vpcClient.DeleteRouterInterface(&args)
})
if err != nil {
if IsExpectedErrors(err, []string{"IncorrectStatus", "DependencyViolation.RouterInterfaceReferedByRouteEntry", "OperationConflict"}) {
time.Sleep(5 * time.Second)
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
return nil
})
if err != nil {
if IsExpectedErrors(err, []string{"InvalidInstanceId.NotFound"}) {
return nil
}
WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
return WrapError(vpcService.WaitForRouterInterface(d.Id(), client.RegionId, Deleted, DefaultLongTimeout))
}
func buildAlicloudRouterInterfaceCreateArgs(d *schema.ResourceData, meta interface{}) (*vpc.CreateRouterInterfaceRequest, error) {
client := meta.(*connectivity.AliyunClient)
ecsService := EcsService{client}
oppositeRegion := d.Get("opposite_region").(string)
if err := ecsService.JudgeRegionValidation("opposite_region", oppositeRegion); err != nil {
return nil, WrapError(err)
}
request := vpc.CreateCreateRouterInterfaceRequest()
request.RegionId = client.RegionId
request.RouterType = d.Get("router_type").(string)
request.RouterId = d.Get("router_id").(string)
request.Role = d.Get("role").(string)
request.Spec = d.Get("specification").(string)
request.InstanceChargeType = d.Get("instance_charge_type").(string)
if request.InstanceChargeType == string(PrePaid) {
period := d.Get("period").(int)
request.Period = requests.NewInteger(period)
request.PricingCycle = string(Month)
if period > 9 {
request.Period = requests.NewInteger(period / 12)
request.PricingCycle = string(Year)
}
request.AutoPay = requests.NewBoolean(true)
}
request.OppositeRegionId = oppositeRegion
// Accepting side router interface spec only be Negative and router type only be VRouter.
if request.Role == string(AcceptingSide) {
request.Spec = string(Negative)
request.RouterType = string(VRouter)
} else {
if request.Spec == "" {
return request, WrapError(Error("'specification': required field is not set when role is %s.", InitiatingSide))
}
}
// Get VBR access point
if request.RouterType == string(VBR) {
describeVirtualBorderRoutersRequest := vpc.CreateDescribeVirtualBorderRoutersRequest()
values := []string{request.RouterId}
filters := []vpc.DescribeVirtualBorderRoutersFilter{{
Key: "VbrId",
Value: &values,
}}
describeVirtualBorderRoutersRequest.Filter = &filters
raw, err := client.WithVpcClient(func(vpcClient *vpc.Client) (interface{}, error) {
return vpcClient.DescribeVirtualBorderRouters(describeVirtualBorderRoutersRequest)
})
if err != nil {
return request, WrapErrorf(err, DefaultErrorMsg, "alicloud_router_interface", request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*vpc.DescribeVirtualBorderRoutersResponse)
if response.TotalCount > 0 {
request.AccessPointId = response.VirtualBorderRouterSet.VirtualBorderRouterType[0].AccessPointId
}
}
request.ClientToken = buildClientToken(request.GetActionName())
return request, nil
}
func buildAlicloudRouterInterfaceModifyAttrArgs(d *schema.ResourceData, meta interface{}) (*vpc.ModifyRouterInterfaceAttributeRequest, bool, error) {
sourceIp, sourceOk := d.GetOk("health_check_source_ip")
targetIp, targetOk := d.GetOk("health_check_target_ip")
if sourceOk && !targetOk || !sourceOk && targetOk {
return nil, false, WrapError(Error("The 'health_check_source_ip' and 'health_check_target_ip' should be specified or not at one time."))
}
request := vpc.CreateModifyRouterInterfaceAttributeRequest()
request.RouterInterfaceId = d.Id()
attributeUpdate := false
if d.HasChange("health_check_source_ip") {
d.SetPartial("health_check_source_ip")
request.HealthCheckSourceIp = sourceIp.(string)
request.HealthCheckTargetIp = targetIp.(string)
attributeUpdate = true
}
if d.HasChange("health_check_target_ip") {
d.SetPartial("health_check_target_ip")
request.HealthCheckTargetIp = targetIp.(string)
request.HealthCheckSourceIp = sourceIp.(string)
attributeUpdate = true
}
if d.HasChange("name") {
d.SetPartial("name")
request.Name = d.Get("name").(string)
attributeUpdate = true
}
if d.HasChange("description") {
d.SetPartial("description")
request.Description = d.Get("description").(string)
attributeUpdate = true
}
return request, attributeUpdate, nil
}