Skip to content

Commit

Permalink
Add interconnect_attachment to router_interface
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
Ty Larrabee authored and modular-magician committed May 24, 2019
1 parent 07011ca commit b7b79b7
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 23 deletions.
48 changes: 39 additions & 9 deletions google/resource_compute_router_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func resourceComputeRouterInterface() *schema.Resource {
State: resourceComputeRouterInterfaceImportState,
},

CustomizeDiff: routerInterfaceDiffOneOfCheck,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Expand All @@ -33,11 +35,18 @@ func resourceComputeRouterInterface() *schema.Resource {
},
"vpn_tunnel": {
Type: schema.TypeString,
Required: true,
ConflictsWith: []string{"interconnect_attachment"},
Optional: true,
ForceNew: true,
DiffSuppressFunc: linkDiffSuppress,
},
"interconnect_attachment": {
Type: schema.TypeString,
ConflictsWith: []string{"vpn_tunnel"},
Optional: true,
ForceNew: true,
DiffSuppressFunc: linkDiffSuppress,
},

"ip_range": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -102,16 +111,26 @@ func resourceComputeRouterInterfaceCreate(d *schema.ResourceData, meta interface
}
}

vpnTunnel, err := getVpnTunnelLink(config, project, region, d.Get("vpn_tunnel").(string))
if err != nil {
return err
iface := &compute.RouterInterface{Name: ifaceName}

if ipVal, ok := d.GetOk("ip_range"); ok {
iface.IpRange = ipVal.(string)
}

iface := &compute.RouterInterface{Name: ifaceName,
LinkedVpnTunnel: vpnTunnel}
if vpnVal, ok := d.GetOk("vpn_tunnel"); ok {
vpnTunnel, err := getVpnTunnelLink(config, project, region, vpnVal.(string))
if err != nil {
return err
}
iface.LinkedVpnTunnel = vpnTunnel
}

if v, ok := d.GetOk("ip_range"); ok {
iface.IpRange = v.(string)
if icVal, ok := d.GetOk("interconnect_attachment"); ok {
interconnectAttachment, err := getInterconnectAttachmentLink(config, project, region, icVal.(string))
if err != nil {
return err
}
iface.LinkedInterconnectAttachment = interconnectAttachment
}

log.Printf("[INFO] Adding interface %s", ifaceName)
Expand Down Expand Up @@ -170,6 +189,7 @@ func resourceComputeRouterInterfaceRead(d *schema.ResourceData, meta interface{}
if iface.Name == ifaceName {
d.SetId(fmt.Sprintf("%s/%s/%s", region, routerName, ifaceName))
d.Set("vpn_tunnel", iface.LinkedVpnTunnel)
d.Set("interconnect_attachment", iface.LinkedInterconnectAttachment)
d.Set("ip_range", iface.IpRange)
d.Set("region", region)
d.Set("project", project)
Expand Down Expand Up @@ -271,3 +291,13 @@ func resourceComputeRouterInterfaceImportState(d *schema.ResourceData, meta inte

return []*schema.ResourceData{d}, nil
}

func routerInterfaceDiffOneOfCheck(d *schema.ResourceDiff, meta interface{}) error {
_, ipOk := d.GetOk("ip_range")
_, vpnOk := d.GetOk("vpn_tunnel")
_, icOk := d.GetOk("interconnect_attachment")
if !(ipOk || vpnOk || icOk) {
return fmt.Errorf("Each interface requires one linked resource or an ip range, or both.")
}
return nil
}
97 changes: 86 additions & 11 deletions google/resource_compute_router_interface_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,29 @@ func TestAccComputeRouterInterface_basic(t *testing.T) {
})
}

func TestAccComputeRouterInterface_withTunnel(t *testing.T) {
t.Parallel()

testId := acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeRouterInterfaceDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeRouterInterfaceWithTunnel(testId),
Check: testAccCheckComputeRouterInterfaceExists(
"google_compute_router_interface.foobar"),
},
{
ResourceName: "google_compute_router_interface.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckComputeRouterInterfaceDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)

Expand Down Expand Up @@ -208,25 +231,70 @@ func testAccComputeRouterInterfaceBasic(testId string) string {
asn = 64514
}
}
resource "google_compute_vpn_tunnel" "foobar" {
name = "router-interface-test-%s"
region = "${google_compute_forwarding_rule.foobar_udp4500.region}"
target_vpn_gateway = "${google_compute_vpn_gateway.foobar.self_link}"
shared_secret = "unguessable"
peer_ip = "8.8.8.8"
router = "${google_compute_router.foobar.name}"
}
resource "google_compute_router_interface" "foobar" {
name = "router-interface-test-%s"
router = "${google_compute_router.foobar.name}"
region = "${google_compute_router.foobar.region}"
ip_range = "169.254.3.1/30"
vpn_tunnel = "${google_compute_vpn_tunnel.foobar.name}"
}
`, testId, testId, testId, testId, testId, testId, testId, testId, testId, testId)
`, testId, testId, testId, testId, testId, testId, testId, testId, testId)
}

func testAccComputeRouterInterfaceKeepRouter(testId string) string {
return fmt.Sprintf(`
resource "google_compute_network" "foobar" {
name = "router-interface-test-%s"
}
resource "google_compute_subnetwork" "foobar" {
name = "router-interface-test-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 = "router-interface-test-%s"
region = "${google_compute_subnetwork.foobar.region}"
}
resource "google_compute_vpn_gateway" "foobar" {
name = "router-interface-test-%s"
network = "${google_compute_network.foobar.self_link}"
region = "${google_compute_subnetwork.foobar.region}"
}
resource "google_compute_forwarding_rule" "foobar_esp" {
name = "router-interface-test-%s-1"
region = "${google_compute_vpn_gateway.foobar.region}"
ip_protocol = "ESP"
ip_address = "${google_compute_address.foobar.address}"
target = "${google_compute_vpn_gateway.foobar.self_link}"
}
resource "google_compute_forwarding_rule" "foobar_udp500" {
name = "router-interface-test-%s-2"
region = "${google_compute_forwarding_rule.foobar_esp.region}"
ip_protocol = "UDP"
port_range = "500-500"
ip_address = "${google_compute_address.foobar.address}"
target = "${google_compute_vpn_gateway.foobar.self_link}"
}
resource "google_compute_forwarding_rule" "foobar_udp4500" {
name = "router-interface-test-%s-3"
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
ip_protocol = "UDP"
port_range = "4500-4500"
ip_address = "${google_compute_address.foobar.address}"
target = "${google_compute_vpn_gateway.foobar.self_link}"
}
resource "google_compute_router" "foobar"{
name = "router-interface-test-%s"
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
network = "${google_compute_network.foobar.self_link}"
bgp {
asn = 64514
}
}
`, testId, testId, testId, testId, testId, testId, testId, testId)
}

func testAccComputeRouterInterfaceWithTunnel(testId string) string {
return fmt.Sprintf(`
resource "google_compute_network" "foobar" {
name = "router-interface-test-%s"
Expand Down Expand Up @@ -285,5 +353,12 @@ func testAccComputeRouterInterfaceKeepRouter(testId string) string {
peer_ip = "8.8.8.8"
router = "${google_compute_router.foobar.name}"
}
`, testId, testId, testId, testId, testId, testId, testId, testId, testId)
resource "google_compute_router_interface" "foobar" {
name = "router-interface-test-%s"
router = "${google_compute_router.foobar.name}"
region = "${google_compute_router.foobar.region}"
ip_range = "169.254.3.1/30"
vpn_tunnel = "${google_compute_vpn_tunnel.foobar.name}"
}
`, testId, testId, testId, testId, testId, testId, testId, testId, testId, testId)
}
2 changes: 1 addition & 1 deletion google/resource_compute_vpn_tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ var invalidPeerAddrs = []struct {
}

func getVpnTunnelLink(config *Config, project string, region string, tunnel string) (string, error) {
if !strings.HasPrefix(tunnel, "https://www.googleapis.com/compute/") {
if !strings.Contains(tunnel, "/") {
// Tunnel value provided is just the name, lookup the tunnel SelfLink
tunnelData, err := config.clientCompute.VpnTunnels.Get(
project, region, tunnel).Do()
Expand Down
13 changes: 13 additions & 0 deletions google/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,16 @@ func paginatedListRequest(baseUrl string, config *Config, flattener func(map[str

return ls, nil
}

func getInterconnectAttachmentLink(config *Config, project, region, ic string) (string, error) {
if !strings.Contains(ic, "/") {
icData, err := config.clientCompute.InterconnectAttachments.Get(
project, region, ic).Do()
if err != nil {
return "", fmt.Errorf("Error reading interconnect attachment: %s", err)
}
ic = icData.SelfLink
}

return ic, nil
}
14 changes: 12 additions & 2 deletions website/docs/r/compute_router_interface.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,24 @@ 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.

* `vpn_tunnel` - (Required) The name or resource link to the VPN tunnel this
interface will be linked 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.

- - -

* `ip_range` - (Optional) 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.

* `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.

* `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.

* `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.

Expand Down

0 comments on commit b7b79b7

Please sign in to comment.