diff --git a/builtin/providers/google/resource_compute_instance.go b/builtin/providers/google/resource_compute_instance.go index cdcf19a27..efa780300 100644 --- a/builtin/providers/google/resource_compute_instance.go +++ b/builtin/providers/google/resource_compute_instance.go @@ -145,6 +145,12 @@ func resourceComputeInstance() *schema.Resource { ForceNew: true, }, + "subnetwork_project": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "name": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -485,6 +491,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err // Load up the name of this network_interface networkName := d.Get(prefix + ".network").(string) subnetworkName := d.Get(prefix + ".subnetwork").(string) + subnetworkProject := d.Get(prefix + ".subnetwork_project").(string) address := d.Get(prefix + ".address").(string) var networkLink, subnetworkLink string @@ -500,8 +507,11 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err } else { region := getRegionFromZone(d.Get("zone").(string)) + if subnetworkProject == "" { + subnetworkProject = project + } subnetwork, err := config.clientCompute.Subnetworks.Get( - project, region, subnetworkName).Do() + subnetworkProject, region, subnetworkName).Do() if err != nil { return fmt.Errorf( "Error referencing subnetwork '%s' in region '%s': %s", @@ -726,11 +736,12 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error } networkInterfaces = append(networkInterfaces, map[string]interface{}{ - "name": iface.Name, - "address": iface.NetworkIP, - "network": d.Get(fmt.Sprintf("network_interface.%d.network", i)), - "subnetwork": d.Get(fmt.Sprintf("network_interface.%d.subnetwork", i)), - "access_config": accessConfigs, + "name": iface.Name, + "address": iface.NetworkIP, + "network": d.Get(fmt.Sprintf("network_interface.%d.network", i)), + "subnetwork": d.Get(fmt.Sprintf("network_interface.%d.subnetwork", i)), + "subnetwork_project": d.Get(fmt.Sprintf("network_interface.%d.subnetwork_project", i)), + "access_config": accessConfigs, }) } } diff --git a/builtin/providers/google/resource_compute_instance_test.go b/builtin/providers/google/resource_compute_instance_test.go index ecc6fd20b..62683509a 100644 --- a/builtin/providers/google/resource_compute_instance_test.go +++ b/builtin/providers/google/resource_compute_instance_test.go @@ -2,6 +2,7 @@ package google import ( "fmt" + "os" "regexp" "strings" "testing" @@ -418,6 +419,31 @@ func TestAccComputeInstance_subnet_custom(t *testing.T) { }) } +func TestAccComputeInstance_subnet_xpn(t *testing.T) { + var instance compute.Instance + var instanceName = fmt.Sprintf("instance-test-%s", acctest.RandString(10)) + var xpn_host = os.Getenv("GOOGLE_XPN_HOST_PROJECT") + if xpn_host == "" { + t.Fatal("GOOGLE_XPN_HOST_PROJECT must be set for TestAccComputeInstance_subnet_xpn test") + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeInstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeInstance_subnet_xpn(instanceName, xpn_host), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceHasSubnet(&instance), + ), + }, + }, + }) +} + func TestAccComputeInstance_address_auto(t *testing.T) { var instance compute.Instance var instanceName = fmt.Sprintf("instance-test-%s", acctest.RandString(10)) @@ -1083,6 +1109,40 @@ func testAccComputeInstance_subnet_custom(instance string) string { }`, acctest.RandString(10), acctest.RandString(10), instance) } +func testAccComputeInstance_subnet_xpn(instance, xpn_host string) string { + return fmt.Sprintf(` + resource "google_compute_network" "inst-test-network" { + name = "inst-test-network-%s" + auto_create_subnetworks = false + project = "%s" + } + + resource "google_compute_subnetwork" "inst-test-subnetwork" { + name = "inst-test-subnetwork-%s" + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" + network = "${google_compute_network.inst-test-network.self_link}" + project = "%s" + } + + resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "n1-standard-1" + zone = "us-central1-a" + + disk { + image = "debian-8-jessie-v20160803" + } + + network_interface { + subnetwork = "${google_compute_subnetwork.inst-test-subnetwork.name}" + subnetwork_project = "${google_compute_subnetwork.inst-test-subnetwork.project}" + access_config { } + } + + }`, acctest.RandString(10), xpn_host, acctest.RandString(10), xpn_host, instance) +} + func testAccComputeInstance_address_auto(instance string) string { return fmt.Sprintf(` resource "google_compute_network" "inst-test-network" { diff --git a/website/source/docs/providers/google/r/compute_instance.html.markdown b/website/source/docs/providers/google/r/compute_instance.html.markdown index 3f869a061..7b7031817 100644 --- a/website/source/docs/providers/google/r/compute_instance.html.markdown +++ b/website/source/docs/providers/google/r/compute_instance.html.markdown @@ -141,10 +141,13 @@ The `network_interface` block supports: * `network` - (Optional) The name or self_link of the network to attach this interface to. Either `network` or `subnetwork` must be provided. -* `subnetwork` - (Optional) the name of the subnetwork to attach this interface +* `subnetwork` - (Optional) The name of the subnetwork to attach this interface 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. + * `address` - (Optional) The private IP address to assign to the instance. If empty, the address will be automatically assigned.