From 6ae25f9806833adf5b53443c292aea0bb8a75ea2 Mon Sep 17 00:00:00 2001
From: Sean Malloy <spinelli85@gmail.com>
Date: Mon, 26 Mar 2018 21:55:16 -0500
Subject: [PATCH] Add support for creating instances on shared VPC networks

Adds a new configuration option network_project_id. This allows
setting the network project that will be used for the GCE instance.
See the below document for an overview of GCP shared VPC.

https://cloud.google.com/vpc/docs/shared-vpc
---
 README.md                                 | 1 +
 lib/vagrant-google/action/run_instance.rb | 6 ++++--
 lib/vagrant-google/config.rb              | 9 +++++++++
 test/unit/common/config_test.rb           | 2 +-
 4 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index ba5c9c8..0befe82 100644
--- a/README.md
+++ b/README.md
@@ -192,6 +192,7 @@ will pull the most recent CentOS 7 image. For more info, refer to
   e.g. 10/08/2015 13:15:15 is "i-2015081013-15637fda".
 * `network` - The name of the network to use for the instance.  Default is
  "default".
+* `network_project_id` - The ID of the GCP project for the network and subnetwork to use for the instance. Default is `google_project_id`.
 * `subnetwork` - The name of the subnetwork to use for the instance.
 * `tags` - An array of tags to apply to this instance.
 * `labels` - Custom key/value pairs of labels to add to the instance.
diff --git a/lib/vagrant-google/action/run_instance.rb b/lib/vagrant-google/action/run_instance.rb
index 2c44bde..3867cc6 100644
--- a/lib/vagrant-google/action/run_instance.rb
+++ b/lib/vagrant-google/action/run_instance.rb
@@ -51,6 +51,7 @@ def call(env) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
           disk_name           = zone_config.disk_name
           disk_type           = zone_config.disk_type
           network             = zone_config.network
+          network_project_id  = zone_config.network_project_id
           subnetwork          = zone_config.subnetwork
           metadata            = zone_config.metadata
           labels              = zone_config.labels
@@ -78,6 +79,7 @@ def call(env) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
           env[:ui].info(" -- Instance Group:  #{instance_group}")
           env[:ui].info(" -- Zone:            #{zone}") if zone
           env[:ui].info(" -- Network:         #{network}") if network
+          env[:ui].info(" -- Network Project: #{network_project_id}") if network_project_id
           env[:ui].info(" -- Subnetwork:      #{subnetwork}") if subnetwork
           env[:ui].info(" -- Metadata:        '#{metadata}'")
           env[:ui].info(" -- Labels:          '#{labels}'")
@@ -101,8 +103,8 @@ def call(env) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
 
           # Munge network configs
           if network != 'default'
-            network = "projects/#{project_id}/global/networks/#{network}"
-            subnetwork  = "projects/#{project_id}/regions/#{zone.split('-')[0..1].join('-')}/subnetworks/#{subnetwork}"
+            network = "projects/#{network_project_id}/global/networks/#{network}"
+            subnetwork  = "projects/#{network_project_id}/regions/#{zone.split('-')[0..1].join('-')}/subnetworks/#{subnetwork}"
           else
             network = "global/networks/default"
           end
diff --git a/lib/vagrant-google/config.rb b/lib/vagrant-google/config.rb
index 7820c0c..ecb881e 100644
--- a/lib/vagrant-google/config.rb
+++ b/lib/vagrant-google/config.rb
@@ -82,6 +82,11 @@ class Config < Vagrant.plugin("2", :config) # rubocop:disable Metrics/ClassLengt
       # @return [String]
       attr_accessor :network
 
+      # The name of the network_project_id
+      #
+      # @return [String]
+      attr_accessor :network_project_id
+
       # The name of the subnetwork
       #
       # @return [String]
@@ -169,6 +174,7 @@ def initialize(zone_specific=false)
         @metadata            = {}
         @name                = UNSET_VALUE
         @network             = UNSET_VALUE
+        @network_project_id  = UNSET_VALUE
         @subnetwork          = UNSET_VALUE
         @tags                = []
         @labels              = {}
@@ -289,6 +295,9 @@ def finalize! # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedC
         # Network defaults to 'default'
         @network = "default" if @network == UNSET_VALUE
 
+        # Network project id defaults to project_id
+        @network_project_id = @google_project_id if @network_project_id == UNSET_VALUE
+
         # Subnetwork defaults to nil
         @subnetwork = nil if @subnetwork == UNSET_VALUE
 
diff --git a/test/unit/common/config_test.rb b/test/unit/common/config_test.rb
index 1f81ece..4c14a57 100644
--- a/test/unit/common/config_test.rb
+++ b/test/unit/common/config_test.rb
@@ -55,7 +55,7 @@
     # each of these attributes to "foo" in isolation, and reads the value
     # and asserts the proper result comes back out.
     [:name, :image, :zone, :instance_ready_timeout, :machine_type, :disk_size, :disk_name, :disk_type,
-     :network, :metadata, :labels, :can_ip_forward, :external_ip, :autodelete_disk].each do |attribute|
+     :network, :network_project_id, :metadata, :labels, :can_ip_forward, :external_ip, :autodelete_disk].each do |attribute|
 
       it "should not default #{attribute} if overridden" do
         instance.send("#{attribute}=".to_sym, "foo")