diff --git a/builder/amazon/common/access_config.go b/builder/amazon/common/access_config.go index a9a60d7cf..559726c9f 100644 --- a/builder/amazon/common/access_config.go +++ b/builder/amazon/common/access_config.go @@ -2,10 +2,11 @@ package common import ( "fmt" - "github.com/mitchellh/goamz/aws" - "github.com/mitchellh/packer/packer" "strings" "unicode" + + "github.com/mitchellh/goamz/aws" + "github.com/mitchellh/packer/template/interpolate" ) // AccessConfig is for common configuration related to AWS access @@ -49,31 +50,8 @@ func (c *AccessConfig) Region() (aws.Region, error) { return aws.Regions[region], nil } -func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error { - if t == nil { - var err error - t, err = packer.NewConfigTemplate() - if err != nil { - return []error{err} - } - } - - templates := map[string]*string{ - "access_key": &c.AccessKey, - "secret_key": &c.SecretKey, - "region": &c.RawRegion, - } - - errs := make([]error, 0) - for n, ptr := range templates { - var err error - *ptr, err = t.Process(*ptr, nil) - if err != nil { - errs = append( - errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } - +func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { + var errs []error if c.RawRegion != "" { if _, ok := aws.Regions[c.RawRegion]; !ok { errs = append(errs, fmt.Errorf("Unknown region: %s", c.RawRegion)) diff --git a/builder/amazon/common/ami_config.go b/builder/amazon/common/ami_config.go index 91c2d12d0..aa515c3db 100644 --- a/builder/amazon/common/ami_config.go +++ b/builder/amazon/common/ami_config.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/mitchellh/goamz/aws" - "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) // AMIConfig is for common configuration related to creating AMIs. @@ -20,49 +20,8 @@ type AMIConfig struct { AMIEnhancedNetworking bool `mapstructure:"enhanced_networking"` } -func (c *AMIConfig) Prepare(t *packer.ConfigTemplate) []error { - if t == nil { - var err error - t, err = packer.NewConfigTemplate() - if err != nil { - return []error{err} - } - } - - templates := map[string]*string{ - "ami_name": &c.AMIName, - "ami_description": &c.AMIDescription, - "ami_virtualization_type": &c.AMIVirtType, - } - - errs := make([]error, 0) - for n, ptr := range templates { - var err error - *ptr, err = t.Process(*ptr, nil) - if err != nil { - errs = append( - errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } - - sliceTemplates := map[string][]string{ - "ami_users": c.AMIUsers, - "ami_groups": c.AMIGroups, - "ami_product_codes": c.AMIProductCodes, - "ami_regions": c.AMIRegions, - } - - for n, slice := range sliceTemplates { - for i, elem := range slice { - var err error - slice[i], err = t.Process(elem, nil) - if err != nil { - errs = append( - errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err)) - } - } - } - +func (c *AMIConfig) Prepare(ctx *interpolate.Context) []error { + var errs []error if c.AMIName == "" { errs = append(errs, fmt.Errorf("ami_name must be specified")) } @@ -92,27 +51,6 @@ func (c *AMIConfig) Prepare(t *packer.ConfigTemplate) []error { c.AMIRegions = regions } - newTags := make(map[string]string) - for k, v := range c.AMITags { - k, err := t.Process(k, nil) - if err != nil { - errs = append(errs, - fmt.Errorf("Error processing tag key %s: %s", k, err)) - continue - } - - v, err := t.Process(v, nil) - if err != nil { - errs = append(errs, - fmt.Errorf("Error processing tag value '%s': %s", v, err)) - continue - } - - newTags[k] = v - } - - c.AMITags = newTags - if len(errs) > 0 { return errs } diff --git a/builder/amazon/common/block_device.go b/builder/amazon/common/block_device.go index 9557cc579..a8402f2d7 100644 --- a/builder/amazon/common/block_device.go +++ b/builder/amazon/common/block_device.go @@ -1,10 +1,8 @@ package common import ( - "fmt" - "github.com/mitchellh/goamz/ec2" - "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) // BlockDevice @@ -44,48 +42,7 @@ func buildBlockDevices(b []BlockDevice) []ec2.BlockDeviceMapping { return blockDevices } -func (b *BlockDevices) Prepare(t *packer.ConfigTemplate) []error { - if t == nil { - var err error - t, err = packer.NewConfigTemplate() - if err != nil { - return []error{err} - } - } - - lists := map[string][]BlockDevice{ - "ami_block_device_mappings": b.AMIMappings, - "launch_block_device_mappings": b.LaunchMappings, - } - - var errs []error - for outer, bds := range lists { - for i := 0; i < len(bds); i++ { - templates := map[string]*string{ - "device_name": &bds[i].DeviceName, - "snapshot_id": &bds[i].SnapshotId, - "virtual_name": &bds[i].VirtualName, - "volume_type": &bds[i].VolumeType, - } - - errs := make([]error, 0) - for n, ptr := range templates { - var err error - *ptr, err = t.Process(*ptr, nil) - if err != nil { - errs = append( - errs, fmt.Errorf( - "Error processing %s[%d].%s: %s", - outer, i, n, err)) - } - } - } - } - - if len(errs) > 0 { - return errs - } - +func (b *BlockDevices) Prepare(ctx *interpolate.Context) []error { return nil } diff --git a/builder/amazon/common/run_config.go b/builder/amazon/common/run_config.go index a71387623..0afdeb07c 100644 --- a/builder/amazon/common/run_config.go +++ b/builder/amazon/common/run_config.go @@ -7,7 +7,7 @@ import ( "time" "github.com/mitchellh/packer/common/uuid" - "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) // RunConfig contains configuration for running an instance from a source @@ -38,43 +38,7 @@ type RunConfig struct { sshTimeout time.Duration } -func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { - if t == nil { - var err error - t, err = packer.NewConfigTemplate() - if err != nil { - return []error{err} - } - } - - templates := map[string]*string{ - "iam_instance_profile": &c.IamInstanceProfile, - "instance_type": &c.InstanceType, - "spot_price": &c.SpotPrice, - "spot_price_auto_product": &c.SpotPriceAutoProduct, - "ssh_timeout": &c.RawSSHTimeout, - "ssh_username": &c.SSHUsername, - "ssh_private_key_file": &c.SSHPrivateKeyFile, - "source_ami": &c.SourceAmi, - "subnet_id": &c.SubnetId, - "temporary_key_pair_name": &c.TemporaryKeyPairName, - "vpc_id": &c.VpcId, - "availability_zone": &c.AvailabilityZone, - "user_data": &c.UserData, - "user_data_file": &c.UserDataFile, - "security_group_id": &c.SecurityGroupId, - } - - errs := make([]error, 0) - for n, ptr := range templates { - var err error - *ptr, err = t.Process(*ptr, nil) - if err != nil { - errs = append( - errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } - +func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { // Defaults if c.SSHPort == 0 { c.SSHPort = 22 @@ -90,7 +54,7 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { } // Validation - var err error + var errs []error if c.SourceAmi == "" { errs = append(errs, errors.New("A source_ami must be specified")) } @@ -127,42 +91,7 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { } } - sliceTemplates := map[string][]string{ - "security_group_ids": c.SecurityGroupIds, - } - - for n, slice := range sliceTemplates { - for i, elem := range slice { - var err error - slice[i], err = t.Process(elem, nil) - if err != nil { - errs = append( - errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err)) - } - } - } - - newTags := make(map[string]string) - for k, v := range c.RunTags { - k, err := t.Process(k, nil) - if err != nil { - errs = append(errs, - fmt.Errorf("Error processing tag key %s: %s", k, err)) - continue - } - - v, err := t.Process(v, nil) - if err != nil { - errs = append(errs, - fmt.Errorf("Error processing tag value '%s': %s", v, err)) - continue - } - - newTags[k] = v - } - - c.RunTags = newTags - + var err error c.sshTimeout, err = time.ParseDuration(c.RawSSHTimeout) if err != nil { errs = append(errs, fmt.Errorf("Failed parsing ssh_timeout: %s", err)) diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 889cc7b60..cbf1709e0 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -13,13 +13,15 @@ import ( "github.com/mitchellh/multistep" awscommon "github.com/mitchellh/packer/builder/amazon/common" "github.com/mitchellh/packer/common" + "github.com/mitchellh/packer/helper/config" "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) // The unique ID for this builder const BuilderId = "mitchellh.amazonebs" -type config struct { +type Config struct { common.PackerConfig `mapstructure:",squash"` awscommon.AccessConfig `mapstructure:",squash"` awscommon.AMIConfig `mapstructure:",squash"` @@ -27,32 +29,30 @@ type config struct { awscommon.RunConfig `mapstructure:",squash"` tpl *packer.ConfigTemplate + ctx *interpolate.Context } type Builder struct { - config config + config Config runner multistep.Runner } func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { - md, err := common.DecodeConfig(&b.config, raws...) + b.config.ctx = &interpolate.Context{Funcs: awscommon.TemplateFuncs} + err := config.Decode(&b.config, &config.DecodeOpts{ + Interpolate: true, + InterpolateContext: b.config.ctx, + }, raws...) if err != nil { return nil, err } - b.config.tpl, err = packer.NewConfigTemplate() - if err != nil { - return nil, err - } - b.config.tpl.UserVars = b.config.PackerUserVars - b.config.tpl.Funcs(awscommon.TemplateFuncs) - // Accumulate any errors - errs := common.CheckUnusedConfig(md) - errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(b.config.tpl)...) - errs = packer.MultiErrorAppend(errs, b.config.BlockDevices.Prepare(b.config.tpl)...) - errs = packer.MultiErrorAppend(errs, b.config.AMIConfig.Prepare(b.config.tpl)...) - errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...) + var errs *packer.MultiError + errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(b.config.ctx)...) + errs = packer.MultiErrorAppend(errs, b.config.BlockDevices.Prepare(b.config.ctx)...) + errs = packer.MultiErrorAppend(errs, b.config.AMIConfig.Prepare(b.config.ctx)...) + errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.ctx)...) if errs != nil && len(errs.Errors) > 0 { return nil, errs diff --git a/builder/amazon/ebs/step_create_ami.go b/builder/amazon/ebs/step_create_ami.go index f380ea0b1..eb8ddea7c 100644 --- a/builder/amazon/ebs/step_create_ami.go +++ b/builder/amazon/ebs/step_create_ami.go @@ -13,7 +13,7 @@ type stepCreateAMI struct { } func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(config) + config := state.Get("config").(Config) ec2conn := state.Get("ec2").(*ec2.EC2) instance := state.Get("instance").(*ec2.Instance) ui := state.Get("ui").(packer.Ui) diff --git a/builder/amazon/ebs/step_modify_instance.go b/builder/amazon/ebs/step_modify_instance.go index 21c5e7de9..8b3f19b4d 100644 --- a/builder/amazon/ebs/step_modify_instance.go +++ b/builder/amazon/ebs/step_modify_instance.go @@ -11,7 +11,7 @@ import ( type stepModifyInstance struct{} func (s *stepModifyInstance) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(config) + config := state.Get("config").(Config) ec2conn := state.Get("ec2").(*ec2.EC2) instance := state.Get("instance").(*ec2.Instance) ui := state.Get("ui").(packer.Ui)