Skip to content

Commit fe13803

Browse files
RouterBgpPeer BFD support (#3258) (#10487)
Signed-off-by: Modular Magician <[email protected]>
1 parent 026524f commit fe13803

File tree

4 files changed

+405
-9
lines changed

4 files changed

+405
-9
lines changed

.changelog/3258.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
compute: Added `bfd` to `google_compute_router_peer`
3+
```

google/resource_compute_router_bgp_peer_test.go

+140
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,49 @@ func TestAccComputeRouterPeer_enable(t *testing.T) {
112112
})
113113
}
114114

115+
func TestAccComputeRouterPeer_bfd(t *testing.T) {
116+
t.Parallel()
117+
118+
routerName := fmt.Sprintf("tf-test-router-%s", randString(t, 10))
119+
vcrTest(t, resource.TestCase{
120+
PreCheck: func() { testAccPreCheck(t) },
121+
Providers: testAccProviders,
122+
CheckDestroy: testAccCheckComputeRouterPeerDestroyProducer(t),
123+
Steps: []resource.TestStep{
124+
{
125+
Config: testAccComputeRouterPeerBasic(routerName),
126+
Check: testAccCheckComputeRouterPeerExists(
127+
t, "google_compute_router_peer.foobar"),
128+
},
129+
{
130+
ResourceName: "google_compute_router_peer.foobar",
131+
ImportState: true,
132+
ImportStateVerify: true,
133+
},
134+
{
135+
Config: testAccComputeRouterPeerBfd(routerName, "DISABLED"),
136+
Check: testAccCheckComputeRouterPeerExists(
137+
t, "google_compute_router_peer.foobar"),
138+
},
139+
{
140+
ResourceName: "google_compute_router_peer.foobar",
141+
ImportState: true,
142+
ImportStateVerify: true,
143+
},
144+
{
145+
Config: testAccComputeRouterPeerBasic(routerName),
146+
Check: testAccCheckComputeRouterPeerExists(
147+
t, "google_compute_router_peer.foobar"),
148+
},
149+
{
150+
ResourceName: "google_compute_router_peer.foobar",
151+
ImportState: true,
152+
ImportStateVerify: true,
153+
},
154+
},
155+
})
156+
}
157+
115158
func testAccCheckComputeRouterPeerDestroyProducer(t *testing.T) func(s *terraform.State) error {
116159
return func(s *terraform.State) error {
117160
config := googleProviderConfig(t)
@@ -675,3 +718,100 @@ resource "google_compute_router_peer" "foobar" {
675718
}
676719
`, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName, enable)
677720
}
721+
722+
func testAccComputeRouterPeerBfd(routerName, bfdMode string) string {
723+
return fmt.Sprintf(`
724+
resource "google_compute_network" "foobar" {
725+
name = "%s-net"
726+
auto_create_subnetworks = false
727+
}
728+
729+
resource "google_compute_subnetwork" "foobar" {
730+
name = "%s-subnet"
731+
network = google_compute_network.foobar.self_link
732+
ip_cidr_range = "10.0.0.0/16"
733+
region = "us-central1"
734+
}
735+
736+
resource "google_compute_address" "foobar" {
737+
name = "%s"
738+
region = google_compute_subnetwork.foobar.region
739+
}
740+
741+
resource "google_compute_vpn_gateway" "foobar" {
742+
name = "%s-gateway"
743+
network = google_compute_network.foobar.self_link
744+
region = google_compute_subnetwork.foobar.region
745+
}
746+
747+
resource "google_compute_forwarding_rule" "foobar_esp" {
748+
name = "%s-frfr1"
749+
region = google_compute_vpn_gateway.foobar.region
750+
ip_protocol = "ESP"
751+
ip_address = google_compute_address.foobar.address
752+
target = google_compute_vpn_gateway.foobar.self_link
753+
}
754+
755+
resource "google_compute_forwarding_rule" "foobar_udp500" {
756+
name = "%s-fr2"
757+
region = google_compute_forwarding_rule.foobar_esp.region
758+
ip_protocol = "UDP"
759+
port_range = "500-500"
760+
ip_address = google_compute_address.foobar.address
761+
target = google_compute_vpn_gateway.foobar.self_link
762+
}
763+
764+
resource "google_compute_forwarding_rule" "foobar_udp4500" {
765+
name = "%s-fr3"
766+
region = google_compute_forwarding_rule.foobar_udp500.region
767+
ip_protocol = "UDP"
768+
port_range = "4500-4500"
769+
ip_address = google_compute_address.foobar.address
770+
target = google_compute_vpn_gateway.foobar.self_link
771+
}
772+
773+
resource "google_compute_router" "foobar" {
774+
name = "%s"
775+
region = google_compute_forwarding_rule.foobar_udp500.region
776+
network = google_compute_network.foobar.self_link
777+
bgp {
778+
asn = 64514
779+
}
780+
}
781+
782+
resource "google_compute_vpn_tunnel" "foobar" {
783+
name = "%s"
784+
region = google_compute_forwarding_rule.foobar_udp4500.region
785+
target_vpn_gateway = google_compute_vpn_gateway.foobar.self_link
786+
shared_secret = "unguessable"
787+
peer_ip = "8.8.8.8"
788+
router = google_compute_router.foobar.name
789+
}
790+
791+
resource "google_compute_router_interface" "foobar" {
792+
name = "%s"
793+
router = google_compute_router.foobar.name
794+
region = google_compute_router.foobar.region
795+
ip_range = "169.254.3.1/30"
796+
vpn_tunnel = google_compute_vpn_tunnel.foobar.name
797+
}
798+
799+
resource "google_compute_router_peer" "foobar" {
800+
name = "%s"
801+
router = google_compute_router.foobar.name
802+
region = google_compute_router.foobar.region
803+
ip_address = "169.254.3.1"
804+
peer_ip_address = "169.254.3.2"
805+
peer_asn = 65515
806+
advertised_route_priority = 100
807+
interface = google_compute_router_interface.foobar.name
808+
809+
bfd {
810+
min_receive_interval = 2000
811+
min_transmit_interval = 2000
812+
multiplier = 6
813+
session_initialization_mode = "%s"
814+
}
815+
}
816+
`, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName, bfdMode)
817+
}

google/resource_compute_router_peer.go

+194
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,55 @@ CIDR-formatted string.`,
140140
Where there is more than one matching route of maximum
141141
length, the routes with the lowest priority value win.`,
142142
},
143+
"bfd": {
144+
Type: schema.TypeList,
145+
Computed: true,
146+
Optional: true,
147+
Description: `BFD configuration for the BGP peering.`,
148+
MaxItems: 1,
149+
Elem: &schema.Resource{
150+
Schema: map[string]*schema.Schema{
151+
"session_initialization_mode": {
152+
Type: schema.TypeString,
153+
Required: true,
154+
ValidateFunc: validation.StringInSlice([]string{"ACTIVE", "DISABLED", "PASSIVE"}, false),
155+
Description: `The BFD session initialization mode for this BGP peer.
156+
If set to 'ACTIVE', the Cloud Router will initiate the BFD session
157+
for this BGP peer. If set to 'PASSIVE', the Cloud Router will wait
158+
for the peer router to initiate the BFD session for this BGP peer.
159+
If set to 'DISABLED', BFD is disabled for this BGP peer. Possible values: ["ACTIVE", "DISABLED", "PASSIVE"]`,
160+
},
161+
"min_receive_interval": {
162+
Type: schema.TypeInt,
163+
Optional: true,
164+
Description: `The minimum interval, in milliseconds, between BFD control packets
165+
received from the peer router. The actual value is negotiated
166+
between the two routers and is equal to the greater of this value
167+
and the transmit interval of the other router. If set, this value
168+
must be between 1000 and 30000.`,
169+
Default: 1000,
170+
},
171+
"min_transmit_interval": {
172+
Type: schema.TypeInt,
173+
Optional: true,
174+
Description: `The minimum interval, in milliseconds, between BFD control packets
175+
transmitted to the peer router. The actual value is negotiated
176+
between the two routers and is equal to the greater of this value
177+
and the corresponding receive interval of the other router. If set,
178+
this value must be between 1000 and 30000.`,
179+
Default: 1000,
180+
},
181+
"multiplier": {
182+
Type: schema.TypeInt,
183+
Optional: true,
184+
Description: `The number of consecutive BFD packets that must be missed before
185+
BFD declares that a peer is unavailable. If set, the value must
186+
be a value between 5 and 16.`,
187+
Default: 5,
188+
},
189+
},
190+
},
191+
},
143192
"enable": {
144193
Type: schema.TypeBool,
145194
Optional: true,
@@ -252,6 +301,12 @@ func resourceComputeRouterBgpPeerCreate(d *schema.ResourceData, meta interface{}
252301
} else if v, ok := d.GetOkExists("advertised_ip_ranges"); ok || !reflect.DeepEqual(v, advertisedIpRangesProp) {
253302
obj["advertisedIpRanges"] = advertisedIpRangesProp
254303
}
304+
bfdProp, err := expandNestedComputeRouterBgpPeerBfd(d.Get("bfd"), d, config)
305+
if err != nil {
306+
return err
307+
} else if v, ok := d.GetOkExists("bfd"); !isEmptyValue(reflect.ValueOf(bfdProp)) && (ok || !reflect.DeepEqual(v, bfdProp)) {
308+
obj["bfd"] = bfdProp
309+
}
255310
enableProp, err := expandNestedComputeRouterBgpPeerEnable(d.Get("enable"), d, config)
256311
if err != nil {
257312
return err
@@ -393,6 +448,9 @@ func resourceComputeRouterBgpPeerRead(d *schema.ResourceData, meta interface{})
393448
if err := d.Set("management_type", flattenNestedComputeRouterBgpPeerManagementType(res["managementType"], d, config)); err != nil {
394449
return fmt.Errorf("Error reading RouterBgpPeer: %s", err)
395450
}
451+
if err := d.Set("bfd", flattenNestedComputeRouterBgpPeerBfd(res["bfd"], d, config)); err != nil {
452+
return fmt.Errorf("Error reading RouterBgpPeer: %s", err)
453+
}
396454
if err := d.Set("enable", flattenNestedComputeRouterBgpPeerEnable(res["enable"], d, config)); err != nil {
397455
return fmt.Errorf("Error reading RouterBgpPeer: %s", err)
398456
}
@@ -458,6 +516,12 @@ func resourceComputeRouterBgpPeerUpdate(d *schema.ResourceData, meta interface{}
458516
} else if v, ok := d.GetOkExists("advertised_ip_ranges"); ok || !reflect.DeepEqual(v, advertisedIpRangesProp) {
459517
obj["advertisedIpRanges"] = advertisedIpRangesProp
460518
}
519+
bfdProp, err := expandNestedComputeRouterBgpPeerBfd(d.Get("bfd"), d, config)
520+
if err != nil {
521+
return err
522+
} else if v, ok := d.GetOkExists("bfd"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, bfdProp)) {
523+
obj["bfd"] = bfdProp
524+
}
461525
enableProp, err := expandNestedComputeRouterBgpPeerEnable(d.Get("enable"), d, config)
462526
if err != nil {
463527
return err
@@ -679,6 +743,80 @@ func flattenNestedComputeRouterBgpPeerManagementType(v interface{}, d *schema.Re
679743
return v
680744
}
681745

746+
func flattenNestedComputeRouterBgpPeerBfd(v interface{}, d *schema.ResourceData, config *Config) interface{} {
747+
if v == nil {
748+
return nil
749+
}
750+
original := v.(map[string]interface{})
751+
if len(original) == 0 {
752+
return nil
753+
}
754+
transformed := make(map[string]interface{})
755+
transformed["session_initialization_mode"] =
756+
flattenNestedComputeRouterBgpPeerBfdSessionInitializationMode(original["sessionInitializationMode"], d, config)
757+
transformed["min_transmit_interval"] =
758+
flattenNestedComputeRouterBgpPeerBfdMinTransmitInterval(original["minTransmitInterval"], d, config)
759+
transformed["min_receive_interval"] =
760+
flattenNestedComputeRouterBgpPeerBfdMinReceiveInterval(original["minReceiveInterval"], d, config)
761+
transformed["multiplier"] =
762+
flattenNestedComputeRouterBgpPeerBfdMultiplier(original["multiplier"], d, config)
763+
return []interface{}{transformed}
764+
}
765+
func flattenNestedComputeRouterBgpPeerBfdSessionInitializationMode(v interface{}, d *schema.ResourceData, config *Config) interface{} {
766+
return v
767+
}
768+
769+
func flattenNestedComputeRouterBgpPeerBfdMinTransmitInterval(v interface{}, d *schema.ResourceData, config *Config) interface{} {
770+
// Handles the string fixed64 format
771+
if strVal, ok := v.(string); ok {
772+
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
773+
return intVal
774+
}
775+
}
776+
777+
// number values are represented as float64
778+
if floatVal, ok := v.(float64); ok {
779+
intVal := int(floatVal)
780+
return intVal
781+
}
782+
783+
return v // let terraform core handle it otherwise
784+
}
785+
786+
func flattenNestedComputeRouterBgpPeerBfdMinReceiveInterval(v interface{}, d *schema.ResourceData, config *Config) interface{} {
787+
// Handles the string fixed64 format
788+
if strVal, ok := v.(string); ok {
789+
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
790+
return intVal
791+
}
792+
}
793+
794+
// number values are represented as float64
795+
if floatVal, ok := v.(float64); ok {
796+
intVal := int(floatVal)
797+
return intVal
798+
}
799+
800+
return v // let terraform core handle it otherwise
801+
}
802+
803+
func flattenNestedComputeRouterBgpPeerBfdMultiplier(v interface{}, d *schema.ResourceData, config *Config) interface{} {
804+
// Handles the string fixed64 format
805+
if strVal, ok := v.(string); ok {
806+
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
807+
return intVal
808+
}
809+
}
810+
811+
// number values are represented as float64
812+
if floatVal, ok := v.(float64); ok {
813+
intVal := int(floatVal)
814+
return intVal
815+
}
816+
817+
return v // let terraform core handle it otherwise
818+
}
819+
682820
func flattenNestedComputeRouterBgpPeerEnable(v interface{}, d *schema.ResourceData, config *Config) interface{} {
683821
if v == nil {
684822
return true
@@ -760,6 +898,62 @@ func expandNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(v interface{}
760898
return v, nil
761899
}
762900

901+
func expandNestedComputeRouterBgpPeerBfd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
902+
l := v.([]interface{})
903+
if len(l) == 0 || l[0] == nil {
904+
return nil, nil
905+
}
906+
raw := l[0]
907+
original := raw.(map[string]interface{})
908+
transformed := make(map[string]interface{})
909+
910+
transformedSessionInitializationMode, err := expandNestedComputeRouterBgpPeerBfdSessionInitializationMode(original["session_initialization_mode"], d, config)
911+
if err != nil {
912+
return nil, err
913+
} else if val := reflect.ValueOf(transformedSessionInitializationMode); val.IsValid() && !isEmptyValue(val) {
914+
transformed["sessionInitializationMode"] = transformedSessionInitializationMode
915+
}
916+
917+
transformedMinTransmitInterval, err := expandNestedComputeRouterBgpPeerBfdMinTransmitInterval(original["min_transmit_interval"], d, config)
918+
if err != nil {
919+
return nil, err
920+
} else if val := reflect.ValueOf(transformedMinTransmitInterval); val.IsValid() && !isEmptyValue(val) {
921+
transformed["minTransmitInterval"] = transformedMinTransmitInterval
922+
}
923+
924+
transformedMinReceiveInterval, err := expandNestedComputeRouterBgpPeerBfdMinReceiveInterval(original["min_receive_interval"], d, config)
925+
if err != nil {
926+
return nil, err
927+
} else if val := reflect.ValueOf(transformedMinReceiveInterval); val.IsValid() && !isEmptyValue(val) {
928+
transformed["minReceiveInterval"] = transformedMinReceiveInterval
929+
}
930+
931+
transformedMultiplier, err := expandNestedComputeRouterBgpPeerBfdMultiplier(original["multiplier"], d, config)
932+
if err != nil {
933+
return nil, err
934+
} else if val := reflect.ValueOf(transformedMultiplier); val.IsValid() && !isEmptyValue(val) {
935+
transformed["multiplier"] = transformedMultiplier
936+
}
937+
938+
return transformed, nil
939+
}
940+
941+
func expandNestedComputeRouterBgpPeerBfdSessionInitializationMode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
942+
return v, nil
943+
}
944+
945+
func expandNestedComputeRouterBgpPeerBfdMinTransmitInterval(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
946+
return v, nil
947+
}
948+
949+
func expandNestedComputeRouterBgpPeerBfdMinReceiveInterval(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
950+
return v, nil
951+
}
952+
953+
func expandNestedComputeRouterBgpPeerBfdMultiplier(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
954+
return v, nil
955+
}
956+
763957
func expandNestedComputeRouterBgpPeerEnable(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
764958
if v == nil {
765959
return nil, nil

0 commit comments

Comments
 (0)