From f230f00726f865fda9bb11a7b27531b048b09dc1 Mon Sep 17 00:00:00 2001 From: Rickard von Essen Date: Wed, 21 Jun 2017 15:13:53 +0200 Subject: [PATCH] googlecompute: Allow using URL's for network and subnetwork If full server URL's is used in subnetwork we can skip reading from the network API. This is usefull when you can launch instances in a shared network but don't have access to do GET on the network resources. Closes: #5018 --- builder/googlecompute/driver_gce.go | 68 +++++++++++++------ .../docs/builders/googlecompute.html.md | 11 ++- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/builder/googlecompute/driver_gce.go b/builder/googlecompute/driver_gce.go index 7addec698..fe3987a1a 100644 --- a/builder/googlecompute/driver_gce.go +++ b/builder/googlecompute/driver_gce.go @@ -10,6 +10,7 @@ import ( "fmt" "log" "net/http" + "net/url" "runtime" "strings" "time" @@ -297,33 +298,56 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) { } // TODO(mitchellh): deprecation warnings - // Get the network - if c.NetworkProjectId == "" { - c.NetworkProjectId = d.projectId - } - d.ui.Message(fmt.Sprintf("Loading network: %s", c.Network)) - network, err := d.service.Networks.Get(c.NetworkProjectId, c.Network).Do() - if err != nil { - return nil, err - } + networkSelfLink := "" + subnetworkSelfLink := "" - // Subnetwork - // Validate Subnetwork config now that we have some info about the network - if !network.AutoCreateSubnetworks && len(network.Subnetworks) > 0 { - // Network appears to be in "custom" mode, so a subnetwork is required - if c.Subnetwork == "" { - return nil, fmt.Errorf("a subnetwork must be specified") + if u, err := url.Parse(c.Network); err == nil && (u.Scheme == "https" || u.Scheme == "http") { + // Network is a full server URL + // Parse out Network and NetworkProjectId from URL + // https://www.googleapis.com/compute/v1/projects//global/networks/ + networkSelfLink = c.Network + parts := strings.Split(u.String(), "/") + if len(parts) >= 10 { + c.NetworkProjectId = parts[6] + c.Network = parts[9] } } - // Get the subnetwork - subnetworkSelfLink := "" - if c.Subnetwork != "" { - d.ui.Message(fmt.Sprintf("Loading subnetwork: %s for region: %s", c.Subnetwork, c.Region)) - subnetwork, err := d.service.Subnetworks.Get(c.NetworkProjectId, c.Region, c.Subnetwork).Do() + if u, err := url.Parse(c.Subnetwork); err == nil && (u.Scheme == "https" || u.Scheme == "http") { + // Subnetwork is a full server URL + subnetworkSelfLink = c.Subnetwork + } + + // If subnetwork is ID's and not full service URL's look them up. + if subnetworkSelfLink == "" { + + // Get the network + if c.NetworkProjectId == "" { + c.NetworkProjectId = d.projectId + } + d.ui.Message(fmt.Sprintf("Loading network: %s", c.Network)) + network, err := d.service.Networks.Get(c.NetworkProjectId, c.Network).Do() if err != nil { return nil, err } - subnetworkSelfLink = subnetwork.SelfLink + networkSelfLink = network.SelfLink + + // Subnetwork + // Validate Subnetwork config now that we have some info about the network + if !network.AutoCreateSubnetworks && len(network.Subnetworks) > 0 { + // Network appears to be in "custom" mode, so a subnetwork is required + if c.Subnetwork == "" { + return nil, fmt.Errorf("a subnetwork must be specified") + } + } + // Get the subnetwork + if c.Subnetwork != "" { + d.ui.Message(fmt.Sprintf("Loading subnetwork: %s for region: %s", c.Subnetwork, c.Region)) + subnetwork, err := d.service.Subnetworks.Get(c.NetworkProjectId, c.Region, c.Subnetwork).Do() + if err != nil { + return nil, err + } + subnetworkSelfLink = subnetwork.SelfLink + } } var accessconfig *compute.AccessConfig @@ -381,7 +405,7 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) { NetworkInterfaces: []*compute.NetworkInterface{ { AccessConfigs: []*compute.AccessConfig{accessconfig}, - Network: network.SelfLink, + Network: networkSelfLink, Subnetwork: subnetworkSelfLink, }, }, diff --git a/website/source/docs/builders/googlecompute.html.md b/website/source/docs/builders/googlecompute.html.md index 6ee7bbc59..7fe6de1b7 100644 --- a/website/source/docs/builders/googlecompute.html.md +++ b/website/source/docs/builders/googlecompute.html.md @@ -203,7 +203,7 @@ builder. - `metadata` (object of key/value strings) - Metadata applied to the launched instance. -- `network` (string) - The Google Compute network to use for the +- `network` (string) - The Google Compute network id or URL to use for the launched instance. Defaults to `"default"`. - `network_project_id` (string) - The project ID for the network and subnetwork @@ -244,11 +244,10 @@ builder. - `state_timeout` (string) - The time to wait for instance state changes. Defaults to `"5m"`. -- `subnetwork` (string) - The Google Compute subnetwork to use for the launched - instance. Only required if the `network` has been created with custom - subnetting. - Note, the region of the subnetwork must match the `region` or `zone` in - which the VM is launched. +- `subnetwork` (string) - The Google Compute subnetwork id or URL to use for + the launched instance. Only required if the `network` has been created with + custom subnetting. Note, the region of the subnetwork must match the `region` + or `zone` in which the VM is launched. - `tags` (array of strings)