From 2271a9ac67129357f53ae51350102202cd21384e Mon Sep 17 00:00:00 2001 From: Ujjwal Kumar Date: Fri, 18 Oct 2024 11:23:00 +0530 Subject: [PATCH] Added support for vpn gateway connection distribute traffic Distributing traffic across tunnels of route-based VPN gateway connections. You can now distribute traffic across tunnels with a status of up in a route-based VPN gateway connection. When creating or updating a route-based VPN gateway connection, set the distribute_traffic property to true (default is false). Existing connections will have the distribute_traffic property set to false --- go.mod | 2 +- go.sum | 4 +- ...ta_source_ibm_is_vpn_gateway_connection.go | 15 ++ ...urce_ibm_is_vpn_gateway_connection_test.go | 135 ++++++++++++ ...a_source_ibm_is_vpn_gateway_connections.go | 8 + ...rce_ibm_is_vpn_gateway_connections_test.go | 59 ++++++ ...urce_ibm_is_vpn_gateway_connection_test.go | 192 ++++++++++++++++++ ...resource_ibm_is_vpn_gateway_connections.go | 34 +++- .../d/is_vpn_gateway_connection.html.markdown | 2 +- .../is_vpn_gateway_connections.html.markdown | 1 + .../r/is_vpn_gateway_connection.html.markdown | 1 + 11 files changed, 446 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 0186684d47..49305bcf34 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/IBM/secrets-manager-go-sdk/v2 v2.0.7 github.com/IBM/vmware-go-sdk v0.1.2 github.com/IBM/vpc-beta-go-sdk v0.8.0 - github.com/IBM/vpc-go-sdk v0.58.0 + github.com/IBM/vpc-go-sdk v0.61.0 github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5 github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 github.com/akamai/AkamaiOPEN-edgegrid-golang/v5 v5.0.0 diff --git a/go.sum b/go.sum index 4209bfff05..0a902daf1a 100644 --- a/go.sum +++ b/go.sum @@ -194,8 +194,8 @@ github.com/IBM/vmware-go-sdk v0.1.2 h1:5lKWFyInWz9e2hwGsoFTEoLa1jYkD30SReN0fQ10w github.com/IBM/vmware-go-sdk v0.1.2/go.mod h1:2UGPBJju3jiv5VKKBBm9a5L6bzF/aJdKOKAzJ7HaOjA= github.com/IBM/vpc-beta-go-sdk v0.8.0 h1:cEPpv4iw3Ba5W2d0AWg3TIbKeJ8y1nPuUuibR5Jt9eE= github.com/IBM/vpc-beta-go-sdk v0.8.0/go.mod h1:hORgIyTFRzXrZIK9IohaWmCRBBlYiDRagsufi7M6akE= -github.com/IBM/vpc-go-sdk v0.58.0 h1:Slk1jkcV7tPnf0iECQV2Oja7W8Bom0z7k9M4fMBY4bI= -github.com/IBM/vpc-go-sdk v0.58.0/go.mod h1:swmxiYLT+OfBsBYqJWGeRd6NPmBk4u/het2PZdtzIaw= +github.com/IBM/vpc-go-sdk v0.61.0 h1:VXT8ZwOQtl15/RSInj9+Z4OQC/vhE/Owoauu128BO4M= +github.com/IBM/vpc-go-sdk v0.61.0/go.mod h1:swmxiYLT+OfBsBYqJWGeRd6NPmBk4u/het2PZdtzIaw= github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56 h1:vuquMR410psHNax14XKNWa0Ae/kYgWJcXi0IFuX60N0= diff --git a/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connection.go b/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connection.go index d45844768a..1bdfcb1274 100644 --- a/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connection.go +++ b/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connection.go @@ -86,6 +86,11 @@ func DataSourceIBMISVPNGatewayConnection() *schema.Resource { }, }, }, + "distribute_traffic": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether the traffic is distributed between the `up` tunnels of the VPN gateway connection when the VPC route's next hop is a VPN connection. If `false`, the traffic is only routed through the `up` tunnel with the lower `public_ip` address.", + }, "href": { Type: schema.TypeString, Computed: true, @@ -574,6 +579,10 @@ func setvpnGatewayConnectionIntfDatasourceData(d *schema.ResourceData, vpn_gatew if err = d.Set("resource_type", vpnGatewayConnection.ResourceType); err != nil { return fmt.Errorf("[ERROR] Error setting resource_type: %s", err) } + if err = d.Set("distribute_traffic", vpnGatewayConnection.DistributeTraffic); err != nil { + return fmt.Errorf("[ERROR] Error setting distribute_traffic: %s", err) + } + if err = d.Set("status", vpnGatewayConnection.Status); err != nil { return fmt.Errorf("[ERROR] Error setting status: %s", err) } @@ -678,6 +687,9 @@ func setvpnGatewayConnectionIntfDatasourceData(d *schema.ResourceData, vpn_gatew if err = d.Set("status", vpnGatewayConnection.Status); err != nil { return fmt.Errorf("[ERROR] Error setting status: %s", err) } + if err = d.Set("distribute_traffic", vpnGatewayConnection.DistributeTraffic); err != nil { + return fmt.Errorf("[ERROR] Error setting distribute_traffic: %s", err) + } if err := d.Set("status_reasons", resourceVPNGatewayConnectionFlattenLifecycleReasons(vpnGatewayConnection.StatusReasons)); err != nil { return fmt.Errorf("[ERROR] Error setting status_reasons: %s", err) } @@ -779,6 +791,9 @@ func setvpnGatewayConnectionIntfDatasourceData(d *schema.ResourceData, vpn_gatew if err = d.Set("status", vpnGatewayConnection.Status); err != nil { return fmt.Errorf("[ERROR] Error setting status: %s", err) } + if err = d.Set("distribute_traffic", vpnGatewayConnection.DistributeTraffic); err != nil { + return fmt.Errorf("[ERROR] Error setting distribute_traffic: %s", err) + } if err := d.Set("status_reasons", resourceVPNGatewayConnectionFlattenLifecycleReasons(vpnGatewayConnection.StatusReasons)); err != nil { return fmt.Errorf("[ERROR] Error setting status_reasons: %s", err) } diff --git a/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connection_test.go b/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connection_test.go index 60e4027d7c..6f2b7c9ee6 100644 --- a/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connection_test.go +++ b/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connection_test.go @@ -97,6 +97,94 @@ func TestAccIBMIsVPNGatewayConnectionDataSourceBasic(t *testing.T) { }, }) } +func TestAccIBMIsVPNGatewayConnectionDataSourceDistrbuteTraffic(t *testing.T) { + vpcname := fmt.Sprintf("tfvpnuat-vpc-%d", acctest.RandIntRange(100, 200)) + subnetname := fmt.Sprintf("tfvpnuat-subnet-%d", acctest.RandIntRange(100, 200)) + vpngwname := fmt.Sprintf("tfvpnuat-vpngw-%d", acctest.RandIntRange(100, 200)) + name := fmt.Sprintf("tfvpnuat-createname-%d", acctest.RandIntRange(100, 200)) + dt := true + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIsVPNGatewayConnectionDataSourceDistributeTrafficConfig(vpcname, subnetname, vpngwname, name, dt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "admin_state_up"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "authentication_mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.action"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.interval"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.timeout"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "peer_address"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "psk"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "status"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "distribute_traffic"), + ), + }, + { + Config: testAccCheckIBMIsVPNGatewayConnectionDataSourceDistributeTrafficConfig(vpcname, subnetname, vpngwname, name, dt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "admin_state_up"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "authentication_mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.action"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.interval"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.timeout"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "peer_address"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "psk"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "status"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example1", "distribute_traffic"), + ), + }, + { + Config: testAccCheckIBMIsVPNGatewayConnectionDataSourceDistributeTrafficConfig(vpcname, subnetname, vpngwname, name, dt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "admin_state_up"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "authentication_mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.action"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.interval"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.timeout"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "peer_address"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "psk"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "status"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example2", "distribute_traffic")), + }, + { + Config: testAccCheckIBMIsVPNGatewayConnectionDataSourceDistributeTrafficConfig(vpcname, subnetname, vpngwname, name, dt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "admin_state_up"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "authentication_mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.action"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.interval"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example", "dead_peer_detection.0.timeout"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "peer_address"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "psk"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "status"), + resource.TestCheckResourceAttrSet("data.ibm_is_vpn_gateway_connection.example3", "distribute_traffic"), + ), + }, + }, + }) +} func testAccCheckIBMIsVPNGatewayConnectionDataSourceConfigBasic(vpc, subnet, vpngwname, name string) string { return fmt.Sprintf(` @@ -143,3 +231,50 @@ func testAccCheckIBMIsVPNGatewayConnectionDataSourceConfigBasic(vpc, subnet, vpn } `, vpc, subnet, acc.ISZoneName, acc.ISCIDR, vpngwname, name) } + +func testAccCheckIBMIsVPNGatewayConnectionDataSourceDistributeTrafficConfig(vpc, subnet, vpngwname, name string, distributeTraffic bool) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "example" { + name = "%s" + + } + resource "ibm_is_subnet" "example" { + name = "%s" + vpc = ibm_is_vpc.example.id + zone = "%s" + ipv4_cidr_block = "%s" + + } + resource "ibm_is_vpn_gateway" "example" { + name = "%s" + subnet = ibm_is_subnet.example.id + mode = "policy" + + } + resource "ibm_is_vpn_gateway_connection" "example" { + name = "%s" + vpn_gateway = ibm_is_vpn_gateway.example.id + peer_address = "1.2.3.4" + peer_cidrs = [ibm_is_subnet.example.ipv4_cidr_block] + local_cidrs = [ibm_is_subnet.example.ipv4_cidr_block] + preshared_key = "VPNDemoPassword" + distribute_traffic = %t + } + data "ibm_is_vpn_gateway_connection" "example" { + vpn_gateway = ibm_is_vpn_gateway.example.id + vpn_gateway_connection = ibm_is_vpn_gateway_connection.example.gateway_connection + } + data "ibm_is_vpn_gateway_connection" "example1" { + vpn_gateway = ibm_is_vpn_gateway.example.id + vpn_gateway_connection_name = ibm_is_vpn_gateway_connection.example.name + } + data "ibm_is_vpn_gateway_connection" "example2" { + vpn_gateway_name = ibm_is_vpn_gateway.example.name + vpn_gateway_connection = ibm_is_vpn_gateway_connection.example.gateway_connection + } + data "ibm_is_vpn_gateway_connection" "example3" { + vpn_gateway_name = ibm_is_vpn_gateway.example.name + vpn_gateway_connection_name = ibm_is_vpn_gateway_connection.example.name + } + `, vpc, subnet, acc.ISZoneName, acc.ISCIDR, vpngwname, name, distributeTraffic) +} diff --git a/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connections.go b/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connections.go index ca77dc9826..cef607163f 100644 --- a/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connections.go +++ b/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connections.go @@ -67,6 +67,11 @@ func DataSourceIBMISVPNGatewayConnections() *schema.Resource { Computed: true, Description: "Interval for dead peer detection interval", }, + "distribute_traffic": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether the traffic is distributed between the `up` tunnels of the VPN gateway connection when the VPC route's next hop is a VPN connection. If `false`, the traffic is only routed through the `up` tunnel with the lower `public_ip` address.", + }, isVPNGatewayConnectionDeadPeerDetectionTimeout: { Type: schema.TypeInt, Computed: true, @@ -345,6 +350,7 @@ func getvpnGatewayConnectionIntfData(vpnGatewayConnectionIntf vpcv1.VPNGatewayCo } gatewayconnection["mode"] = vpnGatewayConnection.Mode gatewayconnection["name"] = vpnGatewayConnection.Name + gatewayconnection["distribute_traffic"] = vpnGatewayConnection.DistributeTraffic // breaking changes gatewayconnection["establish_mode"] = vpnGatewayConnection.EstablishMode @@ -399,6 +405,7 @@ func getvpnGatewayConnectionIntfData(vpnGatewayConnectionIntf vpcv1.VPNGatewayCo if vpnGatewayConnection.IkePolicy != nil { gatewayconnection["ike_policy"] = vpnGatewayConnection.IkePolicy.ID } + gatewayconnection["distribute_traffic"] = vpnGatewayConnection.DistributeTraffic if vpnGatewayConnection.IpsecPolicy != nil { gatewayconnection["ipsec_policy"] = vpnGatewayConnection.IpsecPolicy.ID @@ -455,6 +462,7 @@ func getvpnGatewayConnectionIntfData(vpnGatewayConnectionIntf vpcv1.VPNGatewayCo gatewayconnection[isVPNGatewayConnectionDeadPeerDetectionInterval] = vpnGatewayConnection.DeadPeerDetection.Interval gatewayconnection[isVPNGatewayConnectionDeadPeerDetectionTimeout] = vpnGatewayConnection.DeadPeerDetection.Timeout } + gatewayconnection["distribute_traffic"] = vpnGatewayConnection.DistributeTraffic gatewayconnection["href"] = vpnGatewayConnection.Href if vpnGatewayConnection.IkePolicy != nil { gatewayconnection["ike_policy"] = vpnGatewayConnection.IkePolicy.ID diff --git a/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connections_test.go b/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connections_test.go index fa504aaa12..7d44133e77 100644 --- a/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connections_test.go +++ b/ibm/service/vpc/data_source_ibm_is_vpn_gateway_connections_test.go @@ -35,6 +35,29 @@ func TestAccIBMISVpnGatewayConnectionsDataSource_basic(t *testing.T) { }, }) } +func TestAccIBMISVpnGatewayConnectionsDataSource_distributeTraffic(t *testing.T) { + var vpnGatewayConnection string + node := "data.ibm_is_vpn_gateway_connections.test1" + vpcname := fmt.Sprintf("tfvpnuat-vpc-%d", acctest.RandIntRange(100, 200)) + subnetname := fmt.Sprintf("tfvpnuat-subnet-%d", acctest.RandIntRange(100, 200)) + vpngwname := fmt.Sprintf("tfvpnuat-vpngw-%d", acctest.RandIntRange(100, 200)) + name := fmt.Sprintf("tfvpnuat-createname-%d", acctest.RandIntRange(100, 200)) + dt := true + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISVpnGatewayconnectionsDataSourceDistributeTrafficConfig(vpcname, subnetname, vpngwname, name, dt), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISVPNGatewayConnectionExists("ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection", vpnGatewayConnection), + resource.TestCheckResourceAttrSet(node, "connections.#"), + ), + }, + }, + }) +} func testAccCheckIBMISVpnGatewayconnectionsDataSourceConfig(vpc, subnet, vpngwname, name string) string { // status filter defaults to empty @@ -71,3 +94,39 @@ func testAccCheckIBMISVpnGatewayconnectionsDataSourceConfig(vpc, subnet, vpngwna }`, vpc, subnet, acc.ISZoneName, acc.ISCIDR, vpngwname, name) } +func testAccCheckIBMISVpnGatewayconnectionsDataSourceDistributeTrafficConfig(vpc, subnet, vpngwname, name string, distributeTraffic bool) string { + // status filter defaults to empty + return fmt.Sprintf(` + + data "ibm_resource_group" "rg" { + is_default = true + } + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + resource_group = data.ibm_resource_group.rg.id + } + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = "${ibm_is_vpc.testacc_vpc.id}" + zone = "%s" + ipv4_cidr_block = "%s" + resource_group = data.ibm_resource_group.rg.id + } + resource "ibm_is_vpn_gateway" "testacc_vpnGateway" { + name = "%s" + subnet = "${ibm_is_subnet.testacc_subnet.id}" + resource_group = data.ibm_resource_group.rg.id + + } + resource "ibm_is_vpn_gateway_connection" "testacc_VPNGatewayConnection" { + name = "%s" + vpn_gateway = "${ibm_is_vpn_gateway.testacc_vpnGateway.id}" + peer_address = "1.2.3.4" + preshared_key = "VPNDemoPassword" + distribute_traffic = %t + } + data "ibm_is_vpn_gateway_connections" "test1" { + vpn_gateway = ibm_is_vpn_gateway.testacc_vpnGateway.id + }`, vpc, subnet, acc.ISZoneName, acc.ISCIDR, vpngwname, name, distributeTraffic) + +} diff --git a/ibm/service/vpc/resource_ibm_is_vpn_gateway_connection_test.go b/ibm/service/vpc/resource_ibm_is_vpn_gateway_connection_test.go index eda71335be..85798aa4a5 100644 --- a/ibm/service/vpc/resource_ibm_is_vpn_gateway_connection_test.go +++ b/ibm/service/vpc/resource_ibm_is_vpn_gateway_connection_test.go @@ -451,6 +451,198 @@ func TestAccIBMISVPNGatewayConnection_admin_state(t *testing.T) { }, }) } + +// distribute_traffic +func TestAccIBMISVPNGatewayConnection_routeDistributeTraffic(t *testing.T) { + var VPNGatewayConnection string + vpcname1 := fmt.Sprintf("tfvpngc-vpc-%d", acctest.RandIntRange(100, 200)) + subnetname1 := fmt.Sprintf("tfvpngc-subnet-%d", acctest.RandIntRange(100, 200)) + vpnname1 := fmt.Sprintf("tfvpngc-vpn-%d", acctest.RandIntRange(100, 200)) + name1 := fmt.Sprintf("tfvpngc-createname-%d", acctest.RandIntRange(100, 200)) + + vpcname2 := fmt.Sprintf("tfvpngc-vpc-%d", acctest.RandIntRange(100, 200)) + subnetname2 := fmt.Sprintf("tfvpngc-subnet-%d", acctest.RandIntRange(100, 200)) + vpnname2 := fmt.Sprintf("tfvpngc-vpn-%d", acctest.RandIntRange(100, 200)) + name2 := fmt.Sprintf("tfvpngc-createname-%d", acctest.RandIntRange(100, 200)) + updname2 := fmt.Sprintf("tfvpngc-updatename-%d", acctest.RandIntRange(100, 200)) + dt := true + dt2 := false + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISVPNGatewayConnectionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISVPNGatewayConnectionRouteDistributeTrafficConfig(vpcname1, subnetname1, vpnname1, name1, vpcname2, subnetname2, vpnname2, name2, dt), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISVPNGatewayConnectionExists("ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", VPNGatewayConnection), + resource.TestCheckResourceAttr( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "name", name1), + resource.TestCheckResourceAttr( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "mode", "route"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "action"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "admin_state_up"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "authentication_mode"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "created_at"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "establish_mode"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "href"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "id"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "interval"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "preshared_key"), + resource.TestCheckResourceAttr( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "resource_type", "vpn_gateway_connection"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "status"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "distribute_traffic"), + resource.TestCheckResourceAttr( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "distribute_traffic", fmt.Sprintf("%t", dt)), + ), + }, + { + Config: testAccCheckIBMISVPNGatewayConnectionRouteDistributeTrafficUpdate(vpcname1, subnetname1, vpnname1, name1, vpcname2, subnetname2, vpnname2, updname2, dt2), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISVPNGatewayConnectionExists("ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection2", VPNGatewayConnection), + resource.TestCheckResourceAttr( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection2", "name", updname2), + resource.TestCheckResourceAttr( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection2", "mode", "route"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "action"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "admin_state_up"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "authentication_mode"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "created_at"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "establish_mode"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "href"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "id"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "interval"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "preshared_key"), + resource.TestCheckResourceAttr( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "resource_type", "vpn_gateway_connection"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "status"), + resource.TestCheckResourceAttrSet( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "distribute_traffic"), + resource.TestCheckResourceAttr( + "ibm_is_vpn_gateway_connection.testacc_VPNGatewayConnection1", "distribute_traffic", fmt.Sprintf("%t", dt2)), + ), + }, + }, + }) +} + +func testAccCheckIBMISVPNGatewayConnectionRouteDistributeTrafficConfig(vpc1, subnet1, vpnname1, name1, vpc2, subnet2, vpnname2, name2 string, distributeTraffic bool) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc1" { + name = "%s" + } + resource "ibm_is_subnet" "testacc_subnet1" { + name = "%s" + vpc = "${ibm_is_vpc.testacc_vpc1.id}" + zone = "%s" + ipv4_cidr_block = "%s" + } + resource "ibm_is_vpn_gateway" "testacc_VPNGateway1" { + name = "%s" + subnet = "${ibm_is_subnet.testacc_subnet1.id}" + mode = "route" + } + resource "ibm_is_vpn_gateway_connection" "testacc_VPNGatewayConnection1" { + name = "%s" + vpn_gateway = "${ibm_is_vpn_gateway.testacc_VPNGateway1.id}" + peer_address = "${ibm_is_vpn_gateway.testacc_VPNGateway1.public_ip_address}" + preshared_key = "VPNDemoPassword" + } + resource "ibm_is_vpc" "testacc_vpc2" { + name = "%s" + } + resource "ibm_is_subnet" "testacc_subnet2" { + name = "%s" + vpc = "${ibm_is_vpc.testacc_vpc2.id}" + zone = "%s" + ipv4_cidr_block = "%s" + } + resource "ibm_is_vpn_gateway" "testacc_VPNGateway2" { + name = "%s" + subnet = "${ibm_is_subnet.testacc_subnet2.id}" + mode = "route" + } + resource "ibm_is_vpn_gateway_connection" "testacc_VPNGatewayConnection2" { + name = "%s" + vpn_gateway = "${ibm_is_vpn_gateway.testacc_VPNGateway2.id}" + peer_address = "${ibm_is_vpn_gateway.testacc_VPNGateway2.public_ip_address}" + preshared_key = "VPNDemoPassword" + distribute_traffic = %t + } + `, vpc1, subnet1, acc.ISZoneName, acc.ISCIDR, vpnname1, name1, vpc2, subnet2, acc.ISZoneName, acc.ISCIDR, vpnname2, name2, distributeTraffic) + +} + +func testAccCheckIBMISVPNGatewayConnectionRouteDistributeTrafficUpdate(vpc1, subnet1, vpnname1, name1, vpc2, subnet2, vpnname2, name2 string, distributeTraffic bool) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc1" { + name = "%s" + } + resource "ibm_is_subnet" "testacc_subnet1" { + name = "%s" + vpc = "${ibm_is_vpc.testacc_vpc1.id}" + zone = "%s" + ipv4_cidr_block = "%s" + } + resource "ibm_is_vpn_gateway" "testacc_VPNGateway1" { + name = "%s" + subnet = "${ibm_is_subnet.testacc_subnet1.id}" + mode = "route" + } + resource "ibm_is_vpn_gateway_connection" "testacc_VPNGatewayConnection1" { + name = "%s" + vpn_gateway = "${ibm_is_vpn_gateway.testacc_VPNGateway1.id}" + peer_address = "${ibm_is_vpn_gateway.testacc_VPNGateway1.public_ip_address}" + preshared_key = "VPNDemoPassword" + } + resource "ibm_is_vpc" "testacc_vpc2" { + name = "%s" + } + resource "ibm_is_subnet" "testacc_subnet2" { + name = "%s" + vpc = "${ibm_is_vpc.testacc_vpc2.id}" + zone = "%s" + ipv4_cidr_block = "%s" + } + resource "ibm_is_vpn_gateway" "testacc_VPNGateway2" { + name = "%s" + subnet = "${ibm_is_subnet.testacc_subnet2.id}" + mode = "route" + } + resource "ibm_is_vpn_gateway_connection" "testacc_VPNGatewayConnection2" { + name = "%s" + vpn_gateway = "${ibm_is_vpn_gateway.testacc_VPNGateway2.id}" + peer_address = "${ibm_is_vpn_gateway.testacc_VPNGateway2.public_ip_address}" + preshared_key = "VPNDemoPassword" + distribute_traffic = %t + } + `, vpc1, subnet1, acc.ISZoneName, acc.ISCIDR, vpnname1, name1, vpc2, subnet2, acc.ISZoneName, acc.ISCIDR, vpnname2, name2, distributeTraffic) + +} + func TestAccIBMISVPNGatewayConnection_multiple(t *testing.T) { var VPNGatewayConnection string var VPNGatewayConnection2 string diff --git a/ibm/service/vpc/resource_ibm_is_vpn_gateway_connections.go b/ibm/service/vpc/resource_ibm_is_vpn_gateway_connections.go index 5fd2ffa895..32427bb008 100644 --- a/ibm/service/vpc/resource_ibm_is_vpn_gateway_connections.go +++ b/ibm/service/vpc/resource_ibm_is_vpn_gateway_connections.go @@ -86,6 +86,14 @@ func ResourceIBMISVPNGatewayConnection() *schema.Resource { Deprecated: "peer_address is deprecated, use peer instead", }, + // distribute traffic + "distribute_traffic": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Indicates whether the traffic is distributed between the `up` tunnels of the VPN gateway connection when the VPC route's next hop is a VPN connection. If `false`, the traffic is only routed through the `up` tunnel with the lower `public_ip` address.", + }, + // new breaking changes "establish_mode": &schema.Schema{ Type: schema.TypeString, @@ -616,7 +624,9 @@ func vpngwconCreate(d *schema.ResourceData, meta interface{}, name, gatewayID, p } else { vpnGatewayConnectionPrototypeModel.IpsecPolicy = nil } - + if distributeTrafficOk, ok := d.GetOkExists("distribute_traffic"); ok { + vpnGatewayConnectionPrototypeModel.DistributeTraffic = core.BoolPtr(distributeTrafficOk.(bool)) + } options := &vpcv1.CreateVPNGatewayConnectionOptions{ VPNGatewayID: &gatewayID, VPNGatewayConnectionPrototype: vpnGatewayConnectionPrototypeModel, @@ -726,6 +736,11 @@ func vpngwconUpdate(d *schema.ResourceData, meta interface{}, gID, gConnID strin ID: &gConnID, } vpnGatewayConnectionPatchModel := &vpcv1.VPNGatewayConnectionPatch{} + + if d.HasChange("distribute_traffic") { + vpnGatewayConnectionPatchModel.DistributeTraffic = core.BoolPtr(d.Get("distribute_traffic").(bool)) + } + if d.HasChange(isVPNGatewayConnectionName) { name := d.Get(isVPNGatewayConnectionName).(string) vpnGatewayConnectionPatchModel.Name = &name @@ -1206,6 +1221,11 @@ func setvpnGatewayConnectionIntfResource(d *schema.ResourceData, vpn_gateway_id if err = d.Set("mode", vpnGatewayConnection.Mode); err != nil { return fmt.Errorf("[ERROR] Error setting mode: %s", err) } + if !core.IsNil(vpnGatewayConnection.DistributeTraffic) { + if err = d.Set("distribute_traffic", vpnGatewayConnection.DistributeTraffic); err != nil { + return fmt.Errorf("Error setting distribute_traffic: %s", err) + } + } if err = d.Set("name", vpnGatewayConnection.Name); err != nil { return fmt.Errorf("[ERROR] Error setting name: %s", err) } @@ -1282,7 +1302,11 @@ func setvpnGatewayConnectionIntfResource(d *schema.ResourceData, vpn_gateway_id if err = d.Set("created_at", flex.DateTimeToString(vpnGatewayConnection.CreatedAt)); err != nil { return fmt.Errorf("[ERROR] Error setting created_at: %s", err) } - + if !core.IsNil(vpnGatewayConnection.DistributeTraffic) { + if err = d.Set("distribute_traffic", vpnGatewayConnection.DistributeTraffic); err != nil { + return fmt.Errorf("Error setting distribute_traffic: %s", err) + } + } if vpnGatewayConnection.DeadPeerDetection != nil { d.Set(isVPNGatewayConnectionDeadPeerDetectionAction, vpnGatewayConnection.DeadPeerDetection.Action) d.Set(isVPNGatewayConnectionDeadPeerDetectionInterval, vpnGatewayConnection.DeadPeerDetection.Interval) @@ -1378,7 +1402,11 @@ func setvpnGatewayConnectionIntfResource(d *schema.ResourceData, vpn_gateway_id if err = d.Set("created_at", flex.DateTimeToString(vpnGatewayConnection.CreatedAt)); err != nil { return fmt.Errorf("[ERROR] Error setting created_at: %s", err) } - + if !core.IsNil(vpnGatewayConnection.DistributeTraffic) { + if err = d.Set("distribute_traffic", vpnGatewayConnection.DistributeTraffic); err != nil { + return fmt.Errorf("Error setting distribute_traffic: %s", err) + } + } if vpnGatewayConnection.DeadPeerDetection != nil { d.Set(isVPNGatewayConnectionDeadPeerDetectionAction, vpnGatewayConnection.DeadPeerDetection.Action) d.Set(isVPNGatewayConnectionDeadPeerDetectionInterval, vpnGatewayConnection.DeadPeerDetection.Interval) diff --git a/website/docs/d/is_vpn_gateway_connection.html.markdown b/website/docs/d/is_vpn_gateway_connection.html.markdown index 00cc804950..afe9f2fd52 100644 --- a/website/docs/d/is_vpn_gateway_connection.html.markdown +++ b/website/docs/d/is_vpn_gateway_connection.html.markdown @@ -58,7 +58,7 @@ In addition to all argument references listed, you can access the following attr - `action` - (String) Dead Peer Detection actions. - `interval` - (Integer) Dead Peer Detection interval in seconds. - `timeout` - (Integer) Dead Peer Detection timeout in seconds. Must be at least the interval. - +- `distribute_traffic` - (Boolean) Indicates whether the traffic is distributed between the `up` tunnels of the VPN gateway connection when the VPC route's next hop is a VPN connection. If `false`, the traffic is only routed through the `up` tunnel with the lower `public_ip` address. Distributing traffic across tunnels of route-based VPN gateway connections. Traffic across tunnels can be distributed with a status of up in a route-based VPN gateway connection. When creating or updating a route-based VPN gateway connection, set the distribute_traffic property to true (default is false). Existing connections will have the `distribute_traffic` property set to false. - `establish_mode` - (String) The establish mode of the VPN gateway connection:- `bidirectional`: Either side of the VPN gateway can initiate IKE protocol negotiations or rekeying processes.- `peer_only`: Only the peer can initiate IKE protocol negotiations for this VPN gateway connection. Additionally, the peer is responsible for initiating the rekeying process after the connection is established. If rekeying does not occur, the VPN gateway connection will be brought down after its lifetime expires. - `href` - (String) The VPN connection's canonical URL. diff --git a/website/docs/d/is_vpn_gateway_connections.html.markdown b/website/docs/d/is_vpn_gateway_connections.html.markdown index 417abf9ef0..6272e5241e 100644 --- a/website/docs/d/is_vpn_gateway_connections.html.markdown +++ b/website/docs/d/is_vpn_gateway_connections.html.markdown @@ -43,6 +43,7 @@ In addition to all argument reference list, you can access the following attribu - `admin_state_up` - (String) The VPN gateway connection admin state. Default value is **true**. - `authentication_mode` - (String) The authentication mode. - `created_at`- (Timestamp) The date and time the VPN gateway connection was created. +- `distribute_traffic` - (Boolean) Indicates whether the traffic is distributed between the `up` tunnels of the VPN gateway connection when the VPC route's next hop is a VPN connection. If `false`, the traffic is only routed through the `up` tunnel with the lower `public_ip` address. Distributing traffic across tunnels of route-based VPN gateway connections. Traffic across tunnels can be distributed with a status of up in a route-based VPN gateway connection. When creating or updating a route-based VPN gateway connection, set the distribute_traffic property to true (default is false). Existing connections will have the `distribute_traffic` property set to false. - `establish_mode` - (String) The establish mode of the VPN gateway connection:- `bidirectional`: Either side of the VPN gateway can initiate IKE protocol negotiations or rekeying processes.- `peer_only`: Only the peer can initiate IKE protocol negotiations for this VPN gateway connection. Additionally, the peer is responsible for initiating the rekeying process after the connection is established. If rekeying does not occur, the VPN gateway connection will be brought down after its lifetime expires. - `id` - (String) The ID of the VPN gateway connection. - `ike_policy` - (String) The VPN gateway connection IKE Policy. diff --git a/website/docs/r/is_vpn_gateway_connection.html.markdown b/website/docs/r/is_vpn_gateway_connection.html.markdown index 9231e6ddcf..92c84c6ade 100644 --- a/website/docs/r/is_vpn_gateway_connection.html.markdown +++ b/website/docs/r/is_vpn_gateway_connection.html.markdown @@ -107,6 +107,7 @@ Review the argument references that you can specify for your resource. - `action` - (Optional, String) Dead peer detection actions. Supported values are **restart**, **clear**, **hold**, or **none**. Default value is `restart`. - `admin_state_up` - (Optional, Bool) The VPN gateway connection status. Default value is **false**. If set to false, the VPN gateway connection is shut down. +- `distribute_traffic` - (Optional, Bool) Indicates whether the traffic is distributed between the `up` tunnels of the VPN gateway connection when the VPC route's next hop is a VPN connection. If `false`, the traffic is only routed through the `up` tunnel with the lower `public_ip` address. Distributing traffic across tunnels of route-based VPN gateway connections. Traffic across tunnels can be distributed with a status of up in a route-based VPN gateway connection. When creating or updating a route-based VPN gateway connection, set the distribute_traffic property to true (default is false). Existing connections will have the `distribute_traffic` property set to false. - `establish_mode` - (Optional, String) The establish mode of the VPN gateway connection:- `bidirectional`: Either side of the VPN gateway can initiate IKE protocol negotiations or rekeying processes.- `peer_only`: Only the peer can initiate IKE protocol negotiations for this VPN gateway connection. Additionally, the peer is responsible for initiating the rekeying process after the connection is established. If rekeying does not occur, the VPN gateway connection will be brought down after its lifetime expires. - `ike_policy` - (Optional, String) The ID of the IKE policy. Updating value from ID to `""` or making it `null` or removing it will remove the existing policy. - `interval` - (Optional, Integer) Dead peer detection interval in seconds. Default value is 2.