Remove config interface. Make CreateImage function to accept config as list of config fields

This commit is contained in:
krisko 2019-05-05 17:12:30 +02:00
parent f2f6772aee
commit e96bda6466
No known key found for this signature in database
GPG Key ID: 172111170DC9A709
26 changed files with 317 additions and 377 deletions

View File

@ -9,7 +9,7 @@ import (
type Artifact struct {
image *Image
driver Driver
config *ConfigGCE
config *Config
}
// BuilderId returns the builder Id.

View File

@ -18,7 +18,7 @@ const BuilderId = "packer.googlecompute"
// Builder represents a Packer Builder.
type Builder struct {
config *ConfigGCE
config *Config
runner multistep.Runner
}

View File

@ -1,32 +1,259 @@
package googlecompute
import compute "google.golang.org/api/compute/v1"
import (
"errors"
"fmt"
"os"
"regexp"
"time"
// Configis the interface that has to be implemented to pass
//configuration for GCE. The Config interface exists mostly to allow a mock implementation
// to be used to test the steps.
type Config interface {
//GetImageDescription gets image desription for the image.
GetImageDescription() string
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
compute "google.golang.org/api/compute/v1"
)
//GetImageName gets image name for the image.
GetImageName() string
var reImageFamily = regexp.MustCompile(`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$`)
//GGetImageFamily gets image family for the image.
GetImageFamily() string
// Config is the configuration structure for the GCE builder. It stores
// both the publicly settable state as well as the privately generated
// state of the config object.
type Config struct {
common.PackerConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
//GetImageLabels gets list of labels for the image.
GetImageLabels() map[string]string
AccountFile string `mapstructure:"account_file"`
ProjectId string `mapstructure:"project_id"`
//GetImageDescription gets image desription for the image.
GetImageLicenses() []string
AcceleratorType string `mapstructure:"accelerator_type"`
AcceleratorCount int64 `mapstructure:"accelerator_count"`
Address string `mapstructure:"address"`
DisableDefaultServiceAccount bool `mapstructure:"disable_default_service_account"`
DiskName string `mapstructure:"disk_name"`
DiskSizeGb int64 `mapstructure:"disk_size"`
DiskType string `mapstructure:"disk_type"`
ImageName string `mapstructure:"image_name"`
ImageDescription string `mapstructure:"image_description"`
ImageEncryptionKey *compute.CustomerEncryptionKey `mapstructure:"image_encryption_key"`
ImageFamily string `mapstructure:"image_family"`
ImageLabels map[string]string `mapstructure:"image_labels"`
ImageLicenses []string `mapstructure:"image_licenses"`
InstanceName string `mapstructure:"instance_name"`
Labels map[string]string `mapstructure:"labels"`
MachineType string `mapstructure:"machine_type"`
Metadata map[string]string `mapstructure:"metadata"`
MinCpuPlatform string `mapstructure:"min_cpu_platform"`
Network string `mapstructure:"network"`
NetworkProjectId string `mapstructure:"network_project_id"`
OmitExternalIP bool `mapstructure:"omit_external_ip"`
OnHostMaintenance string `mapstructure:"on_host_maintenance"`
Preemptible bool `mapstructure:"preemptible"`
RawStateTimeout string `mapstructure:"state_timeout"`
Region string `mapstructure:"region"`
Scopes []string `mapstructure:"scopes"`
ServiceAccountEmail string `mapstructure:"service_account_email"`
SourceImage string `mapstructure:"source_image"`
SourceImageFamily string `mapstructure:"source_image_family"`
SourceImageProjectId string `mapstructure:"source_image_project_id"`
StartupScriptFile string `mapstructure:"startup_script_file"`
Subnetwork string `mapstructure:"subnetwork"`
Tags []string `mapstructure:"tags"`
UseInternalIP bool `mapstructure:"use_internal_ip"`
Zone string `mapstructure:"zone"`
//GetZone gets image zone for the image.
GetZone() string
//GetDiskName gets disk name for the image.
GetDiskName() string
//GetImageEncryptionKey gets image encryption key for the image.
GetImageEncryptionKey() *compute.CustomerEncryptionKey
Account AccountFile
stateTimeout time.Duration
imageAlreadyExists bool
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
c := new(Config)
c.ctx.Funcs = TemplateFuncs
err := config.Decode(c, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &c.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"run_command",
},
},
}, raws...)
if err != nil {
return nil, nil, err
}
var errs *packer.MultiError
// Set defaults.
if c.Network == "" && c.Subnetwork == "" {
c.Network = "default"
}
if c.NetworkProjectId == "" {
c.NetworkProjectId = c.ProjectId
}
if c.DiskSizeGb == 0 {
c.DiskSizeGb = 10
}
if c.DiskType == "" {
c.DiskType = "pd-standard"
}
if c.ImageDescription == "" {
c.ImageDescription = "Created by Packer"
}
if c.OnHostMaintenance == "MIGRATE" && c.Preemptible {
errs = packer.MultiErrorAppend(errs,
errors.New("on_host_maintenance must be TERMINATE when using preemptible instances."))
}
// Setting OnHostMaintenance Correct Defaults
// "MIGRATE" : Possible and default if Preemptible is false
// "TERMINATE": Required if Preemptible is true
if c.Preemptible {
c.OnHostMaintenance = "TERMINATE"
} else {
if c.OnHostMaintenance == "" {
c.OnHostMaintenance = "MIGRATE"
}
}
// Make sure user sets a valid value for on_host_maintenance option
if !(c.OnHostMaintenance == "MIGRATE" || c.OnHostMaintenance == "TERMINATE") {
errs = packer.MultiErrorAppend(errs,
errors.New("on_host_maintenance must be one of MIGRATE or TERMINATE."))
}
if c.ImageName == "" {
img, err := interpolate.Render("packer-{{timestamp}}", nil)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("Unable to parse image name: %s ", err))
} else {
c.ImageName = img
}
}
if len(c.ImageFamily) > 63 {
errs = packer.MultiErrorAppend(errs,
errors.New("Invalid image family: Must not be longer than 63 characters"))
}
if c.ImageFamily != "" {
if !reImageFamily.MatchString(c.ImageFamily) {
errs = packer.MultiErrorAppend(errs,
errors.New("Invalid image family: The first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash"))
}
}
if c.InstanceName == "" {
c.InstanceName = fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
}
if c.DiskName == "" {
c.DiskName = c.InstanceName
}
if c.MachineType == "" {
c.MachineType = "n1-standard-1"
}
if c.RawStateTimeout == "" {
c.RawStateTimeout = "5m"
}
if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
errs = packer.MultiErrorAppend(errs, es...)
}
// Process required parameters.
if c.ProjectId == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("a project_id must be specified"))
}
if c.Scopes == nil {
c.Scopes = []string{
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.full_control",
}
}
if c.SourceImage == "" && c.SourceImageFamily == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("a source_image or source_image_family must be specified"))
}
if c.Zone == "" {
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
}
err = c.CalcTimeout()
if err != nil {
errs = packer.MultiErrorAppend(errs, err)
}
if c.AccountFile != "" {
if err := ProcessAccountFile(&c.Account, c.AccountFile); err != nil {
errs = packer.MultiErrorAppend(errs, err)
}
}
if c.OmitExternalIP && c.Address != "" {
errs = packer.MultiErrorAppend(fmt.Errorf("you can not specify an external address when 'omit_external_ip' is true"))
}
if c.OmitExternalIP && !c.UseInternalIP {
errs = packer.MultiErrorAppend(fmt.Errorf("'use_internal_ip' must be true if 'omit_external_ip' is true"))
}
if c.AcceleratorCount > 0 && len(c.AcceleratorType) == 0 {
errs = packer.MultiErrorAppend(fmt.Errorf("'accelerator_type' must be set when 'accelerator_count' is more than 0"))
}
if c.AcceleratorCount > 0 && c.OnHostMaintenance != "TERMINATE" {
errs = packer.MultiErrorAppend(fmt.Errorf("'on_host_maintenance' must be set to 'TERMINATE' when 'accelerator_count' is more than 0"))
}
// If DisableDefaultServiceAccount is provided, don't allow a value for ServiceAccountEmail
if c.DisableDefaultServiceAccount && c.ServiceAccountEmail != "" {
errs = packer.MultiErrorAppend(fmt.Errorf("you may not specify a 'service_account_email' when 'disable_default_service_account' is true"))
}
if c.StartupScriptFile != "" {
if _, err := os.Stat(c.StartupScriptFile); err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("startup_script_file: %v", err))
}
}
// Check for any errors.
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
}
return c, nil, nil
}
func (c *Config) CalcTimeout() error {
stateTimeout, err := time.ParseDuration(c.RawStateTimeout)
if err != nil {
return fmt.Errorf("Failed parsing state_timeout: %s", err)
}
c.stateTimeout = stateTimeout
return nil
}

View File

@ -1,291 +0,0 @@
package googlecompute
import (
"errors"
"fmt"
"os"
"regexp"
"time"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
compute "google.golang.org/api/compute/v1"
)
var reImageFamily = regexp.MustCompile(`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$`)
// Config is the configuration structure for the GCE builder. It stores
// both the publicly settable state as well as the privately generated
// state of the config object.
type ConfigGCE struct {
common.PackerConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
AccountFile string `mapstructure:"account_file"`
ProjectId string `mapstructure:"project_id"`
AcceleratorType string `mapstructure:"accelerator_type"`
AcceleratorCount int64 `mapstructure:"accelerator_count"`
Address string `mapstructure:"address"`
DisableDefaultServiceAccount bool `mapstructure:"disable_default_service_account"`
DiskName string `mapstructure:"disk_name"`
DiskSizeGb int64 `mapstructure:"disk_size"`
DiskType string `mapstructure:"disk_type"`
ImageName string `mapstructure:"image_name"`
ImageDescription string `mapstructure:"image_description"`
ImageFamily string `mapstructure:"image_family"`
ImageLabels map[string]string `mapstructure:"image_labels"`
ImageEncryptionKey *compute.CustomerEncryptionKey `mapstructure:"image_encryption_key"`
ImageLicenses []string `mapstructure:"image_licenses"`
InstanceName string `mapstructure:"instance_name"`
Labels map[string]string `mapstructure:"labels"`
MachineType string `mapstructure:"machine_type"`
Metadata map[string]string `mapstructure:"metadata"`
MinCpuPlatform string `mapstructure:"min_cpu_platform"`
Network string `mapstructure:"network"`
NetworkProjectId string `mapstructure:"network_project_id"`
OmitExternalIP bool `mapstructure:"omit_external_ip"`
OnHostMaintenance string `mapstructure:"on_host_maintenance"`
Preemptible bool `mapstructure:"preemptible"`
RawStateTimeout string `mapstructure:"state_timeout"`
Region string `mapstructure:"region"`
Scopes []string `mapstructure:"scopes"`
ServiceAccountEmail string `mapstructure:"service_account_email"`
SourceImage string `mapstructure:"source_image"`
SourceImageFamily string `mapstructure:"source_image_family"`
SourceImageProjectId string `mapstructure:"source_image_project_id"`
StartupScriptFile string `mapstructure:"startup_script_file"`
Subnetwork string `mapstructure:"subnetwork"`
Tags []string `mapstructure:"tags"`
UseInternalIP bool `mapstructure:"use_internal_ip"`
Zone string `mapstructure:"zone"`
Account AccountFile
stateTimeout time.Duration
imageAlreadyExists bool
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*ConfigGCE, []string, error) {
c := new(ConfigGCE)
c.ctx.Funcs = TemplateFuncs
err := config.Decode(c, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &c.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"run_command",
},
},
}, raws...)
if err != nil {
return nil, nil, err
}
var errs *packer.MultiError
// Set defaults.
if c.Network == "" && c.Subnetwork == "" {
c.Network = "default"
}
if c.NetworkProjectId == "" {
c.NetworkProjectId = c.ProjectId
}
if c.DiskSizeGb == 0 {
c.DiskSizeGb = 10
}
if c.DiskType == "" {
c.DiskType = "pd-standard"
}
if c.ImageDescription == "" {
c.ImageDescription = "Created by Packer"
}
if c.OnHostMaintenance == "MIGRATE" && c.Preemptible {
errs = packer.MultiErrorAppend(errs,
errors.New("on_host_maintenance must be TERMINATE when using preemptible instances."))
}
// Setting OnHostMaintenance Correct Defaults
// "MIGRATE" : Possible and default if Preemptible is false
// "TERMINATE": Required if Preemptible is true
if c.Preemptible {
c.OnHostMaintenance = "TERMINATE"
} else {
if c.OnHostMaintenance == "" {
c.OnHostMaintenance = "MIGRATE"
}
}
// Make sure user sets a valid value for on_host_maintenance option
if !(c.OnHostMaintenance == "MIGRATE" || c.OnHostMaintenance == "TERMINATE") {
errs = packer.MultiErrorAppend(errs,
errors.New("on_host_maintenance must be one of MIGRATE or TERMINATE."))
}
if c.ImageName == "" {
img, err := interpolate.Render("packer-{{timestamp}}", nil)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("Unable to parse image name: %s ", err))
} else {
c.ImageName = img
}
}
if len(c.ImageFamily) > 63 {
errs = packer.MultiErrorAppend(errs,
errors.New("Invalid image family: Must not be longer than 63 characters"))
}
if c.ImageFamily != "" {
if !reImageFamily.MatchString(c.ImageFamily) {
errs = packer.MultiErrorAppend(errs,
errors.New("Invalid image family: The first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash"))
}
}
if c.InstanceName == "" {
c.InstanceName = fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
}
if c.DiskName == "" {
c.DiskName = c.InstanceName
}
if c.MachineType == "" {
c.MachineType = "n1-standard-1"
}
if c.RawStateTimeout == "" {
c.RawStateTimeout = "5m"
}
if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
errs = packer.MultiErrorAppend(errs, es...)
}
// Process required parameters.
if c.ProjectId == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("a project_id must be specified"))
}
if c.Scopes == nil {
c.Scopes = []string{
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.full_control",
}
}
if c.SourceImage == "" && c.SourceImageFamily == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("a source_image or source_image_family must be specified"))
}
if c.Zone == "" {
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
}
err = c.CalcTimeout()
if err != nil {
errs = packer.MultiErrorAppend(errs, err)
}
if c.AccountFile != "" {
if err := ProcessAccountFile(&c.Account, c.AccountFile); err != nil {
errs = packer.MultiErrorAppend(errs, err)
}
}
if c.OmitExternalIP && c.Address != "" {
errs = packer.MultiErrorAppend(fmt.Errorf("you can not specify an external address when 'omit_external_ip' is true"))
}
if c.OmitExternalIP && !c.UseInternalIP {
errs = packer.MultiErrorAppend(fmt.Errorf("'use_internal_ip' must be true if 'omit_external_ip' is true"))
}
if c.AcceleratorCount > 0 && len(c.AcceleratorType) == 0 {
errs = packer.MultiErrorAppend(fmt.Errorf("'accelerator_type' must be set when 'accelerator_count' is more than 0"))
}
if c.AcceleratorCount > 0 && c.OnHostMaintenance != "TERMINATE" {
errs = packer.MultiErrorAppend(fmt.Errorf("'on_host_maintenance' must be set to 'TERMINATE' when 'accelerator_count' is more than 0"))
}
// If DisableDefaultServiceAccount is provided, don't allow a value for ServiceAccountEmail
if c.DisableDefaultServiceAccount && c.ServiceAccountEmail != "" {
errs = packer.MultiErrorAppend(fmt.Errorf("you may not specify a 'service_account_email' when 'disable_default_service_account' is true"))
}
if c.StartupScriptFile != "" {
if _, err := os.Stat(c.StartupScriptFile); err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("startup_script_file: %v", err))
}
}
// Check for any errors.
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
}
return c, nil, nil
}
func (c *ConfigGCE) CalcTimeout() error {
stateTimeout, err := time.ParseDuration(c.RawStateTimeout)
if err != nil {
return fmt.Errorf("Failed parsing state_timeout: %s", err)
}
c.stateTimeout = stateTimeout
return nil
}
func (c *ConfigGCE) GetImageDescription() string {
return c.ImageDescription
}
func (c *ConfigGCE) GetImageName() string {
return c.ImageName
}
func (c *ConfigGCE) GetImageFamily() string {
return c.ImageFamily
}
func (c *ConfigGCE) GetImageLabels() map[string]string {
return c.ImageLabels
}
func (c *ConfigGCE) GetImageLicenses() []string {
return c.ImageLicenses
}
func (c *ConfigGCE) GetDiskName() string {
return c.DiskName
}
func (c *ConfigGCE) GetZone() string {
return c.Zone
}
func (c *ConfigGCE) GetImageEncryptionKey() *compute.CustomerEncryptionKey {
return c.ImageEncryptionKey
}

View File

@ -362,16 +362,16 @@ func TestConfigPrepareStartupScriptFile(t *testing.T) {
func TestConfigDefaults(t *testing.T) {
cases := []struct {
Read func(c *ConfigGCE) interface{}
Read func(c *Config) interface{}
Value interface{}
}{
{
func(c *ConfigGCE) interface{} { return c.Comm.Type },
func(c *Config) interface{} { return c.Comm.Type },
"ssh",
},
{
func(c *ConfigGCE) interface{} { return c.Comm.SSHPort },
func(c *Config) interface{} { return c.Comm.SSHPort },
22,
},
}
@ -437,7 +437,7 @@ func testConfig(t *testing.T) (config map[string]interface{}, tempAccountFile st
return config, tempAccountFile
}
func testConfigStruct(t *testing.T) *ConfigGCE {
func testConfigStruct(t *testing.T) *Config {
raw, tempfile := testConfig(t)
defer os.Remove(tempfile)

View File

@ -3,6 +3,8 @@ package googlecompute
import (
"crypto/rsa"
"time"
compute "google.golang.org/api/compute/v1"
)
// Driver is the interface that has to be implemented to communicate
@ -11,7 +13,7 @@ import (
type Driver interface {
// CreateImage creates an image from the given disk in Google Compute
// Engine.
CreateImage(config Config) (<-chan *Image, <-chan error)
CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string, image_encryption_key *compute.CustomerEncryptionKey) (<-chan *Image, <-chan error)
// DeleteImage deletes the image with the given name.
DeleteImage(name string) <-chan error

View File

@ -104,17 +104,18 @@ func NewDriverGCE(ui packer.Ui, p string, a *AccountFile) (Driver, error) {
}, nil
}
func (d *driverGCE) CreateImage(config Config) (<-chan *Image, <-chan error) {
func (d *driverGCE) CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string, image_encryption_key *compute.CustomerEncryptionKey) (<-chan *Image, <-chan error) {
gce_image := &compute.Image{
Description: config.GetImageDescription(),
ImageEncryptionKey: config.GetImageEncryptionKey(),
Name: config.GetImageName(),
Family: config.GetImageFamily(),
Labels: config.GetImageLabels(),
Licenses: config.GetImageLicenses(),
SourceDisk: fmt.Sprintf("%s%s/zones/%s/disks/%s", d.service.BasePath, d.projectId, config.GetZone(), config.GetDiskName()),
Description: description,
Name: name,
Family: family,
Labels: image_labels,
Licenses: image_licenses,
ImageEncryptionKey: image_encryption_key,
SourceDisk: fmt.Sprintf("%s%s/zones/%s/disks/%s", d.service.BasePath, d.projectId, zone, disk),
SourceType: "RAW",
}
imageCh := make(chan *Image, 1)
errCh := make(chan error, 1)
op, err := d.service.Images.Insert(d.projectId, gce_image).Do()
@ -129,7 +130,7 @@ func (d *driverGCE) CreateImage(config Config) (<-chan *Image, <-chan error) {
return
}
var image *Image
image, err = d.GetImageFromProject(d.projectId, config.GetImageName(), false)
image, err = d.GetImageFromProject(d.projectId, name, false)
if err != nil {
close(imageCh)
errCh <- err

View File

@ -12,8 +12,8 @@ type DriverMock struct {
CreateImageName string
CreateImageDesc string
CreateImageFamily string
CreateImageLabels map[string]string
CreateImageEncryptionKey *compute.CustomerEncryptionKey
CreateImageLabels map[string]string
CreateImageLicenses []string
CreateImageZone string
CreateImageDisk string
@ -87,16 +87,15 @@ type DriverMock struct {
WaitForInstanceErrCh <-chan error
}
func (d *DriverMock) CreateImage(config Config) (<-chan *Image, <-chan error) {
d.CreateImageName = config.GetImageName()
d.CreateImageDesc = config.GetImageDescription()
d.CreateImageFamily = config.GetImageFamily()
d.CreateImageLabels = config.GetImageLabels()
d.CreateImageLicenses = config.GetImageLicenses()
d.CreateImageZone = config.GetZone()
d.CreateImageDisk = config.GetDiskName()
d.CreateImageEncryptionKey = config.GetImageEncryptionKey()
func (d *DriverMock) CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string, image_encryption_key *compute.CustomerEncryptionKey) (<-chan *Image, <-chan error) {
d.CreateImageName = name
d.CreateImageDesc = description
d.CreateImageFamily = family
d.CreateImageLabels = image_labels
d.CreateImageLicenses = image_licenses
d.CreateImageZone = zone
d.CreateImageDisk = disk
d.CreateImageEncryptionKey = image_encryption_key
if d.CreateImageResultProjectId == "" {
d.CreateImageResultProjectId = "test"
}
@ -115,7 +114,7 @@ func (d *DriverMock) CreateImage(config Config) (<-chan *Image, <-chan error) {
ch <- &Image{
Labels: d.CreateImageLabels,
Licenses: d.CreateImageLicenses,
Name: d.CreateImageName,
Name: name,
ProjectId: d.CreateImageResultProjectId,
SelfLink: d.CreateImageResultSelfLink,
SizeGb: d.CreateImageResultSizeGb,

View File

@ -14,7 +14,7 @@ type StepCheckExistingImage int
// Run executes the Packer build step that checks if the image already exists.
func (s *StepCheckExistingImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
d := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)

View File

@ -18,7 +18,7 @@ func TestStepCheckExistingImage(t *testing.T) {
state.Put("instance_name", "foo")
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(*DriverMock)
driver.ImageExistsResult = true

View File

@ -19,7 +19,7 @@ type StepCreateImage int
// The image is created from the persistent disk used by the instance. The
// instance must be deleted and the disk retained before doing this step.
func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)
@ -38,7 +38,9 @@ func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul
ui.Say("Creating image...")
imageCh, errCh := driver.CreateImage(config)
imageCh, errCh := driver.CreateImage(
config.ImageName, config.ImageDescription, config.ImageFamily, config.Zone,
config.DiskName, config.ImageLabels, config.ImageLicenses, config.ImageEncryptionKey)
var err error
select {
case err = <-errCh:

View File

@ -18,7 +18,7 @@ func TestStepCreateImage(t *testing.T) {
step := new(StepCreateImage)
defer step.Cleanup(state)
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
d := state.Get("driver").(*DriverMock)
// These are the values of the image the driver will return.

View File

@ -16,7 +16,7 @@ type StepCreateInstance struct {
Debug bool
}
func (c *ConfigGCE) createInstanceMetadata(sourceImage *Image, sshPublicKey string) (map[string]string, error) {
func (c *Config) createInstanceMetadata(sourceImage *Image, sshPublicKey string) (map[string]string, error) {
instanceMetadata := make(map[string]string)
var err error
@ -58,7 +58,7 @@ func (c *ConfigGCE) createInstanceMetadata(sourceImage *Image, sshPublicKey stri
return instanceMetadata, err
}
func getImage(c *ConfigGCE, d Driver) (*Image, error) {
func getImage(c *Config, d Driver) (*Image, error) {
name := c.SourceImageFamily
fromFamily := true
if c.SourceImage != "" {
@ -74,7 +74,7 @@ func getImage(c *ConfigGCE, d Driver) (*Image, error) {
// Run executes the Packer build step that creates a GCE instance.
func (s *StepCreateInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
d := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)
@ -167,7 +167,7 @@ func (s *StepCreateInstance) Cleanup(state multistep.StateBag) {
return
}
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)

View File

@ -22,7 +22,7 @@ func TestStepCreateInstance(t *testing.T) {
state.Put("ssh_public_key", "key")
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
d := state.Get("driver").(*DriverMock)
d.GetImageResult = StubImage("test-image", "test-project", []string{}, 100)
@ -61,7 +61,7 @@ func TestStepCreateInstance_fromFamily(t *testing.T) {
state.Put("ssh_public_key", "key")
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
c.SourceImage = tc.Name
c.SourceImageFamily = tc.Family
d := state.Get("driver").(*DriverMock)
@ -89,7 +89,7 @@ func TestStepCreateInstance_windowsNeedsPassword(t *testing.T) {
defer step.Cleanup(state)
state.Put("ssh_public_key", "key")
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
d := state.Get("driver").(*DriverMock)
d.GetImageResult = StubImage("test-image", "test-project", []string{"windows"}, 100)
c.Comm.Type = "winrm"
@ -136,7 +136,7 @@ func TestStepCreateInstance_windowsPasswordSet(t *testing.T) {
state.Put("ssh_public_key", "key")
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(*DriverMock)
driver.GetImageResult = StubImage("test-image", "test-project", []string{"windows"}, 100)
config.Comm.Type = "winrm"
@ -231,7 +231,7 @@ func TestStepCreateInstance_errorTimeout(t *testing.T) {
errCh := make(chan error, 1)
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
config.stateTimeout = 1 * time.Microsecond
d := state.Get("driver").(*DriverMock)
@ -255,7 +255,7 @@ func TestStepCreateInstance_noServiceAccount(t *testing.T) {
state.Put("ssh_public_key", "key")
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
c.DisableDefaultServiceAccount = true
c.ServiceAccountEmail = ""
d := state.Get("driver").(*DriverMock)
@ -279,7 +279,7 @@ func TestStepCreateInstance_customServiceAccount(t *testing.T) {
state.Put("ssh_public_key", "key")
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
c.DisableDefaultServiceAccount = true
c.ServiceAccountEmail = "custom-service-account"
d := state.Get("driver").(*DriverMock)
@ -298,7 +298,7 @@ func TestStepCreateInstance_customServiceAccount(t *testing.T) {
func TestCreateInstanceMetadata(t *testing.T) {
state := testState(t)
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
image := StubImage("test-image", "test-project", []string{}, 100)
key := "abcdefgh12345678"
@ -313,7 +313,7 @@ func TestCreateInstanceMetadata(t *testing.T) {
func TestCreateInstanceMetadata_noPublicKey(t *testing.T) {
state := testState(t)
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
image := StubImage("test-image", "test-project", []string{}, 100)
sshKeys := c.Metadata["sshKeys"]

View File

@ -24,7 +24,7 @@ type StepCreateSSHKey struct {
// The key pairs are added to the ssh config
func (s *StepCreateSSHKey) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
if config.Comm.SSHPrivateKeyFile != "" {
ui.Say("Using existing SSH private key")

View File

@ -17,7 +17,7 @@ func TestStepCreateSSHKey_impl(t *testing.T) {
func TestStepCreateSSHKey_privateKey(t *testing.T) {
state := testState(t)
step := new(StepCreateSSHKey)
cfg := state.Get("config").(*ConfigGCE)
cfg := state.Get("config").(*Config)
cfg.Comm.SSHPrivateKeyFile = "test-fixtures/fake-key"
defer step.Cleanup(state)
@ -35,7 +35,7 @@ func TestStepCreateSSHKey_privateKey(t *testing.T) {
func TestStepCreateSSHKey(t *testing.T) {
state := testState(t)
step := new(StepCreateSSHKey)
cfg := state.Get("config").(*ConfigGCE)
cfg := state.Get("config").(*Config)
defer step.Cleanup(state)
// run the step
@ -62,7 +62,7 @@ func TestStepCreateSSHKey_debug(t *testing.T) {
state := testState(t)
step := new(StepCreateSSHKey)
cfg := state.Get("config").(*ConfigGCE)
cfg := state.Get("config").(*Config)
step.Debug = true
step.DebugKeyPath = tf.Name()

View File

@ -28,7 +28,7 @@ type StepCreateWindowsPassword struct {
func (s *StepCreateWindowsPassword) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
d := state.Get("driver").(Driver)
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
name := state.Get("instance_name").(string)
if c.Comm.WinRMPassword != "" {

View File

@ -37,7 +37,7 @@ func TestStepCreateOrResetWindowsPassword_passwordSet(t *testing.T) {
// Step is run after the instance is created so we will have an instance name set
state.Put("instance_name", "mock_instance")
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
c.Comm.WinRMPassword = "password"

View File

@ -18,7 +18,7 @@ type StepInstanceInfo struct {
// Run executes the Packer build step that gathers GCE instance info.
// This adds "instance_ip" to the multistep state.
func (s *StepInstanceInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)

View File

@ -20,7 +20,7 @@ func TestStepInstanceInfo(t *testing.T) {
state.Put("instance_name", "foo")
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(*DriverMock)
driver.GetNatIPResult = "1.2.3.4"
@ -58,7 +58,7 @@ func TestStepInstanceInfo_InternalIP(t *testing.T) {
state.Put("instance_name", "foo")
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
config.UseInternalIP = true
driver := state.Get("driver").(*DriverMock)
driver.GetNatIPResult = "1.2.3.4"
@ -155,7 +155,7 @@ func TestStepInstanceInfo_errorTimeout(t *testing.T) {
state.Put("instance_name", "foo")
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
config.stateTimeout = 1 * time.Microsecond
driver := state.Get("driver").(*DriverMock)

View File

@ -18,7 +18,7 @@ type StepTeardownInstance struct {
// Run executes the Packer build step that tears down a GCE instance.
func (s *StepTeardownInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)
@ -55,7 +55,7 @@ func (s *StepTeardownInstance) Run(ctx context.Context, state multistep.StateBag
// Deleting the instance does not remove the boot disk. This cleanup removes
// the disk.
func (s *StepTeardownInstance) Cleanup(state multistep.StateBag) {
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)

View File

@ -16,7 +16,7 @@ func TestStepTeardownInstance(t *testing.T) {
step := new(StepTeardownInstance)
defer step.Cleanup(state)
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(*DriverMock)
// run the step

View File

@ -16,7 +16,7 @@ type StepWaitStartupScript int
// Run reads the instance metadata and looks for the log entry
// indicating the startup script finished.
func (s *StepWaitStartupScript) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)
instanceName := state.Get("instance_name").(string)

View File

@ -11,7 +11,7 @@ import (
func TestStepWaitStartupScript(t *testing.T) {
state := testState(t)
step := new(StepWaitStartupScript)
c := state.Get("config").(*ConfigGCE)
c := state.Get("config").(*Config)
d := state.Get("driver").(*DriverMock)
testZone := "test-zone"

View File

@ -7,7 +7,7 @@ import (
// winrmConfig returns the WinRM configuration.
func winrmConfig(state multistep.StateBag) (*communicator.WinRMConfig, error) {
config := state.Get("config").(*ConfigGCE)
config := state.Get("config").(*Config)
password := state.Get("winrm_password").(string)
return &communicator.WinRMConfig{

View File

@ -117,7 +117,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
"startup-script": StartupScript,
"zone": p.config.Zone,
}
exporterConfig := googlecompute.ConfigGCE{
exporterConfig := googlecompute.Config{
DiskName: exporterName,
DiskSizeGb: p.config.DiskSizeGb,
DiskType: p.config.DiskType,