Allow specifying project for source images in GCE
Within GCE, images may be shared across projects. Prior to this commit, there was no way to inform the GCE builder that a source image belonged to a specific project. This adds an optional 'source_image_project_id' key to the GCE builder config.
This commit is contained in:
parent
70cc555133
commit
8f237b7b94
|
@ -16,25 +16,26 @@ import (
|
||||||
type Config struct {
|
type Config struct {
|
||||||
common.PackerConfig `mapstructure:",squash"`
|
common.PackerConfig `mapstructure:",squash"`
|
||||||
|
|
||||||
BucketName string `mapstructure:"bucket_name"`
|
BucketName string `mapstructure:"bucket_name"`
|
||||||
ClientSecretsFile string `mapstructure:"client_secrets_file"`
|
ClientSecretsFile string `mapstructure:"client_secrets_file"`
|
||||||
DiskSizeGb int64 `mapstructure:"disk_size"`
|
DiskSizeGb int64 `mapstructure:"disk_size"`
|
||||||
ImageName string `mapstructure:"image_name"`
|
ImageName string `mapstructure:"image_name"`
|
||||||
ImageDescription string `mapstructure:"image_description"`
|
ImageDescription string `mapstructure:"image_description"`
|
||||||
InstanceName string `mapstructure:"instance_name"`
|
InstanceName string `mapstructure:"instance_name"`
|
||||||
MachineType string `mapstructure:"machine_type"`
|
MachineType string `mapstructure:"machine_type"`
|
||||||
Metadata map[string]string `mapstructure:"metadata"`
|
Metadata map[string]string `mapstructure:"metadata"`
|
||||||
Network string `mapstructure:"network"`
|
Network string `mapstructure:"network"`
|
||||||
Passphrase string `mapstructure:"passphrase"`
|
Passphrase string `mapstructure:"passphrase"`
|
||||||
PrivateKeyFile string `mapstructure:"private_key_file"`
|
PrivateKeyFile string `mapstructure:"private_key_file"`
|
||||||
ProjectId string `mapstructure:"project_id"`
|
ProjectId string `mapstructure:"project_id"`
|
||||||
SourceImage string `mapstructure:"source_image"`
|
SourceImage string `mapstructure:"source_image"`
|
||||||
SSHUsername string `mapstructure:"ssh_username"`
|
SourceImageProjectId string `mapstructure:"source_image_project_id"`
|
||||||
SSHPort uint `mapstructure:"ssh_port"`
|
SSHUsername string `mapstructure:"ssh_username"`
|
||||||
RawSSHTimeout string `mapstructure:"ssh_timeout"`
|
SSHPort uint `mapstructure:"ssh_port"`
|
||||||
RawStateTimeout string `mapstructure:"state_timeout"`
|
RawSSHTimeout string `mapstructure:"ssh_timeout"`
|
||||||
Tags []string `mapstructure:"tags"`
|
RawStateTimeout string `mapstructure:"state_timeout"`
|
||||||
Zone string `mapstructure:"zone"`
|
Tags []string `mapstructure:"tags"`
|
||||||
|
Zone string `mapstructure:"zone"`
|
||||||
|
|
||||||
clientSecrets *clientSecrets
|
clientSecrets *clientSecrets
|
||||||
instanceName string
|
instanceName string
|
||||||
|
@ -103,21 +104,22 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||||
|
|
||||||
// Process Templates
|
// Process Templates
|
||||||
templates := map[string]*string{
|
templates := map[string]*string{
|
||||||
"bucket_name": &c.BucketName,
|
"bucket_name": &c.BucketName,
|
||||||
"client_secrets_file": &c.ClientSecretsFile,
|
"client_secrets_file": &c.ClientSecretsFile,
|
||||||
"image_name": &c.ImageName,
|
"image_name": &c.ImageName,
|
||||||
"image_description": &c.ImageDescription,
|
"image_description": &c.ImageDescription,
|
||||||
"instance_name": &c.InstanceName,
|
"instance_name": &c.InstanceName,
|
||||||
"machine_type": &c.MachineType,
|
"machine_type": &c.MachineType,
|
||||||
"network": &c.Network,
|
"network": &c.Network,
|
||||||
"passphrase": &c.Passphrase,
|
"passphrase": &c.Passphrase,
|
||||||
"private_key_file": &c.PrivateKeyFile,
|
"private_key_file": &c.PrivateKeyFile,
|
||||||
"project_id": &c.ProjectId,
|
"project_id": &c.ProjectId,
|
||||||
"source_image": &c.SourceImage,
|
"source_image": &c.SourceImage,
|
||||||
"ssh_username": &c.SSHUsername,
|
"source_image_project_id": &c.SourceImageProjectId,
|
||||||
"ssh_timeout": &c.RawSSHTimeout,
|
"ssh_username": &c.SSHUsername,
|
||||||
"state_timeout": &c.RawStateTimeout,
|
"ssh_timeout": &c.RawSSHTimeout,
|
||||||
"zone": &c.Zone,
|
"state_timeout": &c.RawStateTimeout,
|
||||||
|
"zone": &c.Zone,
|
||||||
}
|
}
|
||||||
|
|
||||||
for n, ptr := range templates {
|
for n, ptr := range templates {
|
||||||
|
|
|
@ -23,10 +23,15 @@ type Driver interface {
|
||||||
WaitForInstance(state, zone, name string) <-chan error
|
WaitForInstance(state, zone, name string) <-chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
Name string
|
||||||
|
ProjectId string
|
||||||
|
}
|
||||||
|
|
||||||
type InstanceConfig struct {
|
type InstanceConfig struct {
|
||||||
Description string
|
Description string
|
||||||
DiskSizeGb int64
|
DiskSizeGb int64
|
||||||
Image string
|
Image Image
|
||||||
MachineType string
|
MachineType string
|
||||||
Metadata map[string]string
|
Metadata map[string]string
|
||||||
Name string
|
Name string
|
||||||
|
|
|
@ -134,7 +134,7 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the image
|
// Get the image
|
||||||
d.ui.Message(fmt.Sprintf("Loading image: %s", c.Image))
|
d.ui.Message(fmt.Sprintf("Loading image: %s in project %s", c.Image.Name, c.Image.ProjectId))
|
||||||
image, err := d.getImage(c.Image)
|
image, err := d.getImage(c.Image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -229,17 +229,17 @@ func (d *driverGCE) WaitForInstance(state, zone, name string) <-chan error {
|
||||||
return errCh
|
return errCh
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driverGCE) getImage(name string) (image *compute.Image, err error) {
|
func (d *driverGCE) getImage(img Image) (image *compute.Image, err error) {
|
||||||
projects := []string{d.projectId, "centos-cloud", "coreos-cloud", "debian-cloud", "google-containers", "opensuse-cloud", "rhel-cloud", "suse-cloud", "windows-cloud"}
|
projects := []string{img.ProjectId, "centos-cloud", "coreos-cloud", "debian-cloud", "google-containers", "opensuse-cloud", "rhel-cloud", "suse-cloud", "windows-cloud"}
|
||||||
for _, project := range projects {
|
for _, project := range projects {
|
||||||
image, err = d.service.Images.Get(project, name).Do()
|
image, err = d.service.Images.Get(project, img.Name).Do()
|
||||||
if err == nil && image != nil && image.SelfLink != "" {
|
if err == nil && image != nil && image.SelfLink != "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
image = nil
|
image = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = fmt.Errorf("Image %s could not be found in any of these projects: %s", name, projects)
|
err = fmt.Errorf("Image %s could not be found in any of these projects: %s", img.Name, projects)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,14 @@ type StepCreateInstance struct {
|
||||||
instanceName string
|
instanceName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config *Config) getImage() (Image) {
|
||||||
|
project := config.ProjectId
|
||||||
|
if config.SourceImageProjectId != "" {
|
||||||
|
project = config.SourceImageProjectId
|
||||||
|
}
|
||||||
|
return Image{Name: config.SourceImage, ProjectId: project}
|
||||||
|
}
|
||||||
|
|
||||||
// Run executes the Packer build step that creates a GCE instance.
|
// Run executes the Packer build step that creates a GCE instance.
|
||||||
func (s *StepCreateInstance) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *StepCreateInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
|
@ -29,7 +37,7 @@ func (s *StepCreateInstance) Run(state multistep.StateBag) multistep.StepAction
|
||||||
errCh, err := driver.RunInstance(&InstanceConfig{
|
errCh, err := driver.RunInstance(&InstanceConfig{
|
||||||
Description: "New instance created by Packer",
|
Description: "New instance created by Packer",
|
||||||
DiskSizeGb: config.DiskSizeGb,
|
DiskSizeGb: config.DiskSizeGb,
|
||||||
Image: config.SourceImage,
|
Image: config.getImage(),
|
||||||
MachineType: config.MachineType,
|
MachineType: config.MachineType,
|
||||||
Metadata: map[string]string{
|
Metadata: map[string]string{
|
||||||
"sshKeys": fmt.Sprintf("%s:%s", config.SSHUsername, sshPublicKey),
|
"sshKeys": fmt.Sprintf("%s:%s", config.SSHUsername, sshPublicKey),
|
||||||
|
|
Loading…
Reference in New Issue