From 77037bed2c6298490612b95c9465e168d64fc196 Mon Sep 17 00:00:00 2001 From: zbikmarc Date: Thu, 12 Jan 2017 15:05:13 +0100 Subject: [PATCH] providers/google: Add subnetwork_project field to enable cross-project networking in instance templates (#11110) * Add subnetwork_project field to allow for XPN in GCE instance templates * Missing os import * Removing unneeded check * fix formatting * Add subnetwork_project to read --- .../resource_compute_instance_template.go | 18 +++++- ...resource_compute_instance_template_test.go | 63 ++++++++++++++++++- .../r/compute_instance_template.html.markdown | 5 +- 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/builtin/providers/google/resource_compute_instance_template.go b/builtin/providers/google/resource_compute_instance_template.go index da0708b3b6..9b9798dc21 100644 --- a/builtin/providers/google/resource_compute_instance_template.go +++ b/builtin/providers/google/resource_compute_instance_template.go @@ -203,6 +203,12 @@ func resourceComputeInstanceTemplate() *schema.Resource { ForceNew: true, }, + "subnetwork_project": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "access_config": &schema.Schema{ Type: schema.TypeList, Optional: true, @@ -406,14 +412,16 @@ func buildNetworks(d *schema.ResourceData, meta interface{}) ([]*compute.Network for i := 0; i < networksCount; i++ { prefix := fmt.Sprintf("network_interface.%d", i) - var networkName, subnetworkName string + var networkName, subnetworkName, subnetworkProject string if v, ok := d.GetOk(prefix + ".network"); ok { networkName = v.(string) } if v, ok := d.GetOk(prefix + ".subnetwork"); ok { subnetworkName = v.(string) } - + if v, ok := d.GetOk(prefix + ".subnetwork_project"); ok { + subnetworkProject = v.(string) + } if networkName == "" && subnetworkName == "" { return nil, fmt.Errorf("network or subnetwork must be provided") } @@ -435,8 +443,11 @@ func buildNetworks(d *schema.ResourceData, meta interface{}) ([]*compute.Network if err != nil { return nil, err } + if subnetworkProject == "" { + subnetworkProject = project + } subnetwork, err := config.clientCompute.Subnetworks.Get( - project, region, subnetworkName).Do() + subnetworkProject, region, subnetworkName).Do() if err != nil { return nil, fmt.Errorf( "Error referencing subnetwork '%s' in region '%s': %s", @@ -639,6 +650,7 @@ func flattenNetworkInterfaces(networkInterfaces []*compute.NetworkInterface) ([] subnetworkUrl := strings.Split(networkInterface.Subnetwork, "/") networkInterfaceMap["subnetwork"] = subnetworkUrl[len(subnetworkUrl)-1] region = subnetworkUrl[len(subnetworkUrl)-3] + networkInterfaceMap["subnetwork_project"] = subnetworkUrl[len(subnetworkUrl)-5] } if networkInterface.AccessConfigs != nil { diff --git a/builtin/providers/google/resource_compute_instance_template_test.go b/builtin/providers/google/resource_compute_instance_template_test.go index 642e0e57fe..e287d32e2c 100644 --- a/builtin/providers/google/resource_compute_instance_template_test.go +++ b/builtin/providers/google/resource_compute_instance_template_test.go @@ -2,6 +2,7 @@ package google import ( "fmt" + "os" "strings" "testing" @@ -115,6 +116,27 @@ func TestAccComputeInstanceTemplate_subnet_custom(t *testing.T) { }) } +func TestAccComputeInstanceTemplate_subnet_xpn(t *testing.T) { + var instanceTemplate compute.InstanceTemplate + var xpn_host = os.Getenv("GOOGLE_XPN_HOST_PROJECT") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeInstanceTemplateDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeInstanceTemplate_subnet_xpn(xpn_host), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceTemplateExists( + "google_compute_instance_template.foobar", &instanceTemplate), + testAccCheckComputeInstanceTemplateSubnetwork(&instanceTemplate), + ), + }, + }, + }) +} + func TestAccComputeInstanceTemplate_metadata_startup_script(t *testing.T) { var instanceTemplate compute.InstanceTemplate @@ -467,6 +489,45 @@ resource "google_compute_instance_template" "foobar" { } }`, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10)) +func testAccComputeInstanceTemplate_subnet_xpn(xpn_host string) string { + return fmt.Sprintf(` + resource "google_compute_network" "network" { + name = "network-%s" + auto_create_subnetworks = false + project = "%s" + } + + resource "google_compute_subnetwork" "subnetwork" { + name = "subnetwork-%s" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = "${google_compute_network.network.self_link}" + project = "%s" + } + + resource "google_compute_instance_template" "foobar" { + name = "instance-test-%s" + machine_type = "n1-standard-1" + region = "us-central1" + + disk { + source_image = "debian-8-jessie-v20160803" + auto_delete = true + disk_size_gb = 10 + boot = true + } + + network_interface { + subnetwork = "${google_compute_subnetwork.subnetwork.name}" + subnetwork_project = "${google_compute_subnetwork.subnetwork.project}" + } + + metadata { + foo = "bar" + } + }`, acctest.RandString(10), xpn_host, acctest.RandString(10), xpn_host, acctest.RandString(10)) +} + var testAccComputeInstanceTemplate_startup_script = fmt.Sprintf(` resource "google_compute_instance_template" "foobar" { name = "instance-test-%s" @@ -486,6 +547,6 @@ resource "google_compute_instance_template" "foobar" { network_interface{ network = "default" } - + metadata_startup_script = "echo 'Hello'" }`, acctest.RandString(10)) diff --git a/website/source/docs/providers/google/r/compute_instance_template.html.markdown b/website/source/docs/providers/google/r/compute_instance_template.html.markdown index 201abc3333..796cb4e907 100644 --- a/website/source/docs/providers/google/r/compute_instance_template.html.markdown +++ b/website/source/docs/providers/google/r/compute_instance_template.html.markdown @@ -138,7 +138,7 @@ The following arguments are supported: * `metadata_startup_script` - (Optional) An alternative to using the startup-script metadata key, mostly to match the compute_instance resource. - This replaces the startup-script metadata key on the created instance and + This replaces the startup-script metadata key on the created instance and thus the two mechanisms are not allowed to be used simultaneously. * `network_interface` - (Required) Networks to attach to instances created from @@ -208,6 +208,9 @@ The `network_interface` block supports: to. The subnetwork must exist in the same `region` this instance will be created in. Either `network` or `subnetwork` must be provided. +* `subnetwork_project` - (Optional) The project in which the subnetwork belongs. + If it is not provided, the provider project is used. + * `access_config` - (Optional) Access configurations, i.e. IPs via which this instance can be accessed via the Internet. Omit to ensure that the instance is not accessible from the Internet (this means that ssh provisioners will