diff --git a/builder/googlecompute/config.go b/builder/googlecompute/config.go index bb189b19d..13446a092 100644 --- a/builder/googlecompute/config.go +++ b/builder/googlecompute/config.go @@ -31,6 +31,7 @@ type Config struct { MachineType string `mapstructure:"machine_type"` Metadata map[string]string `mapstructure:"metadata"` Network string `mapstructure:"network"` + Subnetwork string `mapstructure:"subnetwork"` Address string `mapstructure:"address"` Preemptible bool `mapstructure:"preemptible"` SourceImage string `mapstructure:"source_image"` @@ -38,6 +39,7 @@ type Config struct { RawStateTimeout string `mapstructure:"state_timeout"` Tags []string `mapstructure:"tags"` UseInternalIP bool `mapstructure:"use_internal_ip"` + Region string `mapstructure:"region"` Zone string `mapstructure:"zone"` account accountFile @@ -125,6 +127,11 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { errs = packer.MultiErrorAppend( errs, errors.New("a zone must be specified")) } + if c.Region == "" && len(c.Zone) > 2 { + // get region from Zone + region := c.Zone[:len(c.Zone)-2] + c.Region = region + } stateTimeout, err := time.ParseDuration(c.RawStateTimeout) if err != nil { diff --git a/builder/googlecompute/driver.go b/builder/googlecompute/driver.go index 495c1e092..1789a988a 100644 --- a/builder/googlecompute/driver.go +++ b/builder/googlecompute/driver.go @@ -47,8 +47,10 @@ type InstanceConfig struct { Metadata map[string]string Name string Network string + Subnetwork string Address string Preemptible bool Tags []string + Region string Zone string } diff --git a/builder/googlecompute/driver_gce.go b/builder/googlecompute/driver_gce.go index 91d04255f..f163b744f 100644 --- a/builder/googlecompute/driver_gce.go +++ b/builder/googlecompute/driver_gce.go @@ -215,6 +215,25 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) { return nil, err } + // 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 + 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(d.projectId, c.Region, c.Subnetwork).Do() + if err != nil { + return nil, err + } + subnetworkSelfLink = subnetwork.SelfLink + } + // If given a regional ip, get it accessconfig := compute.AccessConfig{ Name: "AccessConfig created by Packer", @@ -235,9 +254,10 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) { // Build up the metadata metadata := make([]*compute.MetadataItems, len(c.Metadata)) for k, v := range c.Metadata { + vCopy := v metadata = append(metadata, &compute.MetadataItems{ Key: k, - Value: &v, + Value: &vCopy, }) } @@ -268,6 +288,7 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) { &accessconfig, }, Network: network.SelfLink, + Subnetwork: subnetworkSelfLink, }, }, Scheduling: &compute.Scheduling{ diff --git a/builder/googlecompute/step_create_instance.go b/builder/googlecompute/step_create_instance.go index f3f16a09f..3f6874f6a 100644 --- a/builder/googlecompute/step_create_instance.go +++ b/builder/googlecompute/step_create_instance.go @@ -59,9 +59,11 @@ func (s *StepCreateInstance) Run(state multistep.StateBag) multistep.StepAction Metadata: config.getInstanceMetadata(sshPublicKey), Name: name, Network: config.Network, + Subnetwork: config.Subnetwork, Address: config.Address, Preemptible: config.Preemptible, Tags: config.Tags, + Region: config.Region, Zone: config.Zone, })