diff --git a/.changelog/6766.txt b/.changelog/6766.txt new file mode 100644 index 00000000000..4db240b2703 --- /dev/null +++ b/.changelog/6766.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +compute: added subnetwork and private_ip_address arguments to resource_compute_router_interface +``` diff --git a/google/resource_compute_router_interface.go b/google/resource_compute_router_interface.go index 4c4615cf303..26d08f4a7e9 100644 --- a/google/resource_compute_router_interface.go +++ b/google/resource_compute_router_interface.go @@ -42,28 +42,44 @@ func resourceComputeRouterInterface() *schema.Resource { }, "vpn_tunnel": { Type: schema.TypeString, - ConflictsWith: []string{"interconnect_attachment"}, Optional: true, ForceNew: true, DiffSuppressFunc: compareSelfLinkOrResourceName, - AtLeastOneOf: []string{"vpn_tunnel", "interconnect_attachment", "ip_range"}, - Description: `The name or resource link to the VPN tunnel this interface will be linked to. Changing this forces a new interface to be created. Only one of vpn_tunnel and interconnect_attachment can be specified.`, + AtLeastOneOf: []string{"ip_range", "interconnect_attachment", "subnetwork", "vpn_tunnel"}, + ConflictsWith: []string{"interconnect_attachment", "subnetwork"}, + Description: `The name or resource link to the VPN tunnel this interface will be linked to. Changing this forces a new interface to be created. Only one of vpn_tunnel, interconnect_attachment or subnetwork can be specified.`, }, "interconnect_attachment": { Type: schema.TypeString, - ConflictsWith: []string{"vpn_tunnel"}, Optional: true, ForceNew: true, DiffSuppressFunc: compareSelfLinkOrResourceName, - AtLeastOneOf: []string{"vpn_tunnel", "interconnect_attachment", "ip_range"}, - Description: `The name or resource link to the VLAN interconnect for this interface. Changing this forces a new interface to be created. Only one of vpn_tunnel and interconnect_attachment can be specified.`, + AtLeastOneOf: []string{"ip_range", "interconnect_attachment", "subnetwork", "vpn_tunnel"}, + ConflictsWith: []string{"subnetwork", "vpn_tunnel"}, + Description: `The name or resource link to the VLAN interconnect for this interface. Changing this forces a new interface to be created. Only one of interconnect_attachment, subnetwork or vpn_tunnel can be specified.`, }, "ip_range": { Type: schema.TypeString, Optional: true, ForceNew: true, - AtLeastOneOf: []string{"vpn_tunnel", "interconnect_attachment", "ip_range"}, - Description: `IP address and range of the interface. The IP range must be in the RFC3927 link-local IP space. Changing this forces a new interface to be created.`, + Computed: true, + AtLeastOneOf: []string{"ip_range", "interconnect_attachment", "subnetwork", "vpn_tunnel"}, + Description: `The IP address and range of the interface. The IP range must be in the RFC3927 link-local IP space. Changing this forces a new interface to be created.`, + }, + "private_ip_address": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The regional private internal IP address that is used to establish BGP sessions to a VM instance acting as a third-party Router Appliance. Changing this forces a new interface to be created.`, + }, + "subnetwork": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + AtLeastOneOf: []string{"ip_range", "interconnect_attachment", "subnetwork", "vpn_tunnel"}, + ConflictsWith: []string{"interconnect_attachment", "vpn_tunnel"}, + Description: `The URI of the subnetwork resource that this interface belongs to, which must be in the same region as the Cloud Router. Changing this forces a new interface to be created. Only one of subnetwork, interconnect_attachment or vpn_tunnel can be specified.`, }, "project": { Type: schema.TypeString, @@ -72,7 +88,6 @@ func resourceComputeRouterInterface() *schema.Resource { ForceNew: true, Description: `The ID of the project in which this interface's router belongs. If it is not provided, the provider project is used. Changing this forces a new interface to be created.`, }, - "region": { Type: schema.TypeString, Optional: true, @@ -85,7 +100,7 @@ func resourceComputeRouterInterface() *schema.Resource { Type: schema.TypeString, Optional: true, ForceNew: true, - Description: `The name of the interface that is redundant to this interface.`, + Description: `The name of the interface that is redundant to this interface. Changing this forces a new interface to be created.`, }, }, UseJSONNumber: true, @@ -144,8 +159,12 @@ func resourceComputeRouterInterfaceCreate(d *schema.ResourceData, meta interface iface.RedundantInterface = riVal.(string) } - if ipVal, ok := d.GetOk("ip_range"); ok { - iface.IpRange = ipVal.(string) + if ipRangeVal, ok := d.GetOk("ip_range"); ok { + iface.IpRange = ipRangeVal.(string) + } + + if privateIpVal, ok := d.GetOk("private_ip_address"); ok { + iface.PrivateIpAddress = privateIpVal.(string) } if vpnVal, ok := d.GetOk("vpn_tunnel"); ok { @@ -164,6 +183,10 @@ func resourceComputeRouterInterfaceCreate(d *schema.ResourceData, meta interface iface.LinkedInterconnectAttachment = interconnectAttachment } + if subVal, ok := d.GetOk("subnetwork"); ok { + iface.Subnetwork = subVal.(string) + } + log.Printf("[INFO] Adding interface %s", ifaceName) ifaces = append(ifaces, iface) patchRouter := &compute.Router{ @@ -231,6 +254,12 @@ func resourceComputeRouterInterfaceRead(d *schema.ResourceData, meta interface{} if err := d.Set("ip_range", iface.IpRange); err != nil { return fmt.Errorf("Error setting ip_range: %s", err) } + if err := d.Set("private_ip_address", iface.PrivateIpAddress); err != nil { + return fmt.Errorf("Error setting private_ip_address: %s", err) + } + if err := d.Set("subnetwork", iface.Subnetwork); err != nil { + return fmt.Errorf("Error setting subnetwork: %s", err) + } if err := d.Set("region", region); err != nil { return fmt.Errorf("Error setting region: %s", err) } diff --git a/google/resource_compute_router_interface_test.go b/google/resource_compute_router_interface_test.go index fc53cccde8a..b4c4900ec37 100644 --- a/google/resource_compute_router_interface_test.go +++ b/google/resource_compute_router_interface_test.go @@ -82,6 +82,29 @@ func TestAccComputeRouterInterface_withTunnel(t *testing.T) { }) } +func TestAccComputeRouterInterface_withPrivateIpAddress(t *testing.T) { + t.Parallel() + + routerName := fmt.Sprintf("tf-test-router-%s", randString(t, 10)) + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRouterInterfaceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRouterInterfaceWithPrivateIpAddress(routerName), + Check: testAccCheckComputeRouterInterfaceExists( + t, "google_compute_router_interface.foobar"), + }, + { + ResourceName: "google_compute_router_interface.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckComputeRouterInterfaceDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { config := googleProviderConfig(t) @@ -435,3 +458,42 @@ resource "google_compute_router_interface" "foobar" { } `, routerName, routerName, routerName, routerName, routerName, routerName, routerName, routerName) } + +func testAccComputeRouterInterfaceWithPrivateIpAddress(routerName string) string { + return fmt.Sprintf(` +resource "google_compute_network" "foobar" { + name = "tf-test-%s" +} + +resource "google_compute_subnetwork" "foobar" { + name = "tf-test-router-interface-subnetwork-%s" + network = google_compute_network.foobar.self_link + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" +} + +resource "google_compute_address" "foobar" { + name = "%s-addr" + region = google_compute_subnetwork.foobar.region + subnetwork = google_compute_subnetwork.foobar.id + address_type = "INTERNAL" +} + +resource "google_compute_router" "foobar" { + name = "%s" + region = google_compute_subnetwork.foobar.region + network = google_compute_network.foobar.self_link + bgp { + asn = 64514 + } +} + +resource "google_compute_router_interface" "foobar" { + name = "%s" + router = google_compute_router.foobar.name + region = google_compute_router.foobar.region + subnetwork = google_compute_subnetwork.foobar.self_link + private_ip_address = google_compute_address.foobar.address +} +`, routerName, routerName, routerName, routerName, routerName) +} diff --git a/website/docs/r/compute_router_interface.html.markdown b/website/docs/r/compute_router_interface.html.markdown index 921cc31636b..1c81ffcd998 100644 --- a/website/docs/r/compute_router_interface.html.markdown +++ b/website/docs/r/compute_router_interface.html.markdown @@ -34,9 +34,7 @@ The following arguments are supported: * `router` - (Required) The name of the router this interface will be attached to. Changing this forces a new interface to be created. -In addition to the above required fields, a router interface must have specified -either `ip_range` or exactly one of `vpn_tunnel` or `interconnect_attachment`, -or both. +In addition to the above required fields, a router interface must have specified either `ip_range` or exactly one of `vpn_tunnel`, `interconnect_attachment` or `subnetwork`, or both. - - - @@ -45,23 +43,29 @@ or both. * `vpn_tunnel` - (Optional) The name or resource link to the VPN tunnel this interface will be linked to. Changing this forces a new interface to be created. Only - one of `vpn_tunnel` and `interconnect_attachment` can be specified. + one of `vpn_tunnel`, `interconnect_attachment` or `subnetwork` can be specified. * `interconnect_attachment` - (Optional) The name or resource link to the - VLAN interconnect for this interface. Changing this forces a new interface to - be created. Only one of `vpn_tunnel` and `interconnect_attachment` can be - specified. + VLAN interconnect for this interface. Changing this forces a new interface to + be created. Only one of `vpn_tunnel`, `interconnect_attachment` or `subnetwork` can be specified. * `redundant_interface` - (Optional) The name of the interface that is redundant to - this interface. Changing this forces a new interface to - be created. + this interface. Changing this forces a new interface to be created. -* `project` - (Optional) The ID of the project in which this interface's router belongs. If it - is not provided, the provider project is used. Changing this forces a new interface to be created. +* `project` - (Optional) The ID of the project in which this interface's router belongs. + If it is not provided, the provider project is used. Changing this forces a new interface to be created. -* `region` - (Optional) The region this interface's router sits in. If not specified, - the project region will be used. Changing this forces a new interface to be - created. +* `subnetwork` - (Optional) The URI of the subnetwork resource that this interface + belongs to, which must be in the same region as the Cloud Router. When you establish a BGP session to a VM instance using this interface, the VM instance must belong to the same subnetwork as the subnetwork specified here. Changing this forces a new interface to be created. Only one of `vpn_tunnel`, `interconnect_attachment` or `subnetwork` can be specified. + +* `private_ip_address` - (Optional) The regional private internal IP address that is used + to establish BGP sessions to a VM instance acting as a third-party Router Appliance. Changing this forces a new interface to be created. + +* `project` - (Optional) The ID of the project in which this interface's routerbelongs. + If it is not provided, the provider project is used. Changing this forces a new interface to be created. + +* `region` - (Optional) The region this interface's router sits in. + If not specified, the project region will be used. Changing this forces a new interface to be created. ## Attributes Reference