From 034e4e676ceb46bb70e98dc61ef227f3b2c61d1f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 27 May 2015 11:47:45 -0700 Subject: [PATCH] amazon/*: use new interpolation functions --- builder/amazon/chroot/builder.go | 72 ++++++------------- builder/amazon/chroot/step_mount_device.go | 14 ++-- builder/amazon/ebs/builder.go | 1 - builder/amazon/instance/builder.go | 65 +++++------------ builder/amazon/instance/step_bundle_volume.go | 6 +- builder/amazon/instance/step_upload_bundle.go | 6 +- template/interpolate/render.go | 21 +++++- 7 files changed, 75 insertions(+), 110 deletions(-) diff --git a/builder/amazon/chroot/builder.go b/builder/amazon/chroot/builder.go index 832a26022..addf5c464 100644 --- a/builder/amazon/chroot/builder.go +++ b/builder/amazon/chroot/builder.go @@ -6,7 +6,6 @@ package chroot import ( "errors" - "fmt" "log" "runtime" @@ -14,7 +13,9 @@ 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 @@ -34,7 +35,7 @@ type Config struct { MountPath string `mapstructure:"mount_path"` SourceAmi string `mapstructure:"source_ami"` - tpl *packer.ConfigTemplate + ctx *interpolate.Context } type wrappedCommandTemplate struct { @@ -47,18 +48,21 @@ type Builder struct { } 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, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{ + "command_wrapper", + "mount_path", + }, + }, + }, 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) - // Defaults if b.config.ChrootMounts == nil { b.config.ChrootMounts = make([][]string, 0) @@ -91,55 +95,22 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } // Accumulate any errors - errs := common.CheckUnusedConfig(md) - errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(b.config.tpl)...) - errs = packer.MultiErrorAppend(errs, b.config.AMIConfig.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.AMIConfig.Prepare(b.config.ctx)...) - for i, mounts := range b.config.ChrootMounts { + for _, mounts := range b.config.ChrootMounts { if len(mounts) != 3 { errs = packer.MultiErrorAppend( errs, errors.New("Each chroot_mounts entry should be three elements.")) break } - - for j, entry := range mounts { - b.config.ChrootMounts[i][j], err = b.config.tpl.Process(entry, nil) - if err != nil { - errs = packer.MultiErrorAppend(errs, - fmt.Errorf("Error processing chroot_mounts[%d][%d]: %s", - i, j, err)) - } - } - } - - for i, file := range b.config.CopyFiles { - var err error - b.config.CopyFiles[i], err = b.config.tpl.Process(file, nil) - if err != nil { - errs = packer.MultiErrorAppend(errs, - fmt.Errorf("Error processing copy_files[%d]: %s", - i, err)) - } } if b.config.SourceAmi == "" { errs = packer.MultiErrorAppend(errs, errors.New("source_ami is required.")) } - templates := map[string]*string{ - "device_path": &b.config.DevicePath, - "source_ami": &b.config.SourceAmi, - } - - for n, ptr := range templates { - var err error - *ptr, err = b.config.tpl.Process(*ptr, nil) - if err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } - if errs != nil && len(errs.Errors) > 0 { return nil, errs } @@ -166,10 +137,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe ec2conn := ec2.New(auth, region) wrappedCommand := func(command string) (string, error) { - return b.config.tpl.Process( - b.config.CommandWrapper, &wrappedCommandTemplate{ - Command: command, - }) + ctx := *b.config.ctx + ctx.Data = &wrappedCommandTemplate{Command: command} + return interpolate.Render(b.config.CommandWrapper, &ctx) } // Setup the state bag and initial state for the steps diff --git a/builder/amazon/chroot/step_mount_device.go b/builder/amazon/chroot/step_mount_device.go index 3c3d959c1..ef531ecc3 100644 --- a/builder/amazon/chroot/step_mount_device.go +++ b/builder/amazon/chroot/step_mount_device.go @@ -3,12 +3,14 @@ package chroot import ( "bytes" "fmt" - "github.com/mitchellh/goamz/ec2" - "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/packer" "log" "os" "path/filepath" + + "github.com/mitchellh/goamz/ec2" + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) type mountPathData struct { @@ -31,9 +33,9 @@ func (s *StepMountDevice) Run(state multistep.StateBag) multistep.StepAction { device := state.Get("device").(string) wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) - mountPath, err := config.tpl.Process(config.MountPath, &mountPathData{ - Device: filepath.Base(device), - }) + ctx := *config.ctx + ctx.Data = &mountPathData{Device: filepath.Base(device)} + mountPath, err := interpolate.Render(config.MountPath, &ctx) if err != nil { err := fmt.Errorf("Error preparing mount directory: %s", err) diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index cbf1709e0..a41828e30 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -28,7 +28,6 @@ type Config struct { awscommon.BlockDevices `mapstructure:",squash"` awscommon.RunConfig `mapstructure:",squash"` - tpl *packer.ConfigTemplate ctx *interpolate.Context } diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 63b8442ac..2845aa25d 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -13,7 +13,9 @@ 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 @@ -38,7 +40,7 @@ type Config struct { X509KeyPath string `mapstructure:"x509_key_path"` X509UploadPath string `mapstructure:"x509_upload_path"` - tpl *packer.ConfigTemplate + ctx *interpolate.Context } type Builder struct { @@ -47,18 +49,21 @@ type Builder struct { } 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, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{ + "bundle_upload_command", + "bundle_vol_command", + }, + }, + }, 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) - if b.config.BundleDestination == "" { b.config.BundleDestination = "/tmp" } @@ -97,43 +102,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } // 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)...) - - validates := map[string]*string{ - "bundle_upload_command": &b.config.BundleUploadCommand, - "bundle_vol_command": &b.config.BundleVolCommand, - } - - for n, ptr := range validates { - if err := b.config.tpl.Validate(*ptr); err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Error parsing %s: %s", n, err)) - } - } - - templates := map[string]*string{ - "account_id": &b.config.AccountId, - "ami_name": &b.config.AMIName, - "bundle_destination": &b.config.BundleDestination, - "bundle_prefix": &b.config.BundlePrefix, - "s3_bucket": &b.config.S3Bucket, - "x509_cert_path": &b.config.X509CertPath, - "x509_key_path": &b.config.X509KeyPath, - "x509_upload_path": &b.config.X509UploadPath, - } - - for n, ptr := range templates { - var err error - *ptr, err = b.config.tpl.Process(*ptr, nil) - if err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } + 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 b.config.AccountId == "" { errs = packer.MultiErrorAppend(errs, errors.New("account_id is required")) diff --git a/builder/amazon/instance/step_bundle_volume.go b/builder/amazon/instance/step_bundle_volume.go index 736e1adb2..8fd320e4a 100644 --- a/builder/amazon/instance/step_bundle_volume.go +++ b/builder/amazon/instance/step_bundle_volume.go @@ -6,6 +6,7 @@ import ( "github.com/mitchellh/goamz/ec2" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) type bundleCmdData struct { @@ -32,7 +33,7 @@ func (s *StepBundleVolume) Run(state multistep.StateBag) multistep.StepAction { // Bundle the volume var err error - config.BundleVolCommand, err = config.tpl.Process(config.BundleVolCommand, bundleCmdData{ + config.ctx.Data = bundleCmdData{ AccountId: config.AccountId, Architecture: instance.Architecture, CertPath: x509RemoteCertPath, @@ -40,7 +41,8 @@ func (s *StepBundleVolume) Run(state multistep.StateBag) multistep.StepAction { KeyPath: x509RemoteKeyPath, Prefix: config.BundlePrefix, PrivatePath: config.X509UploadPath, - }) + } + config.BundleVolCommand, err = interpolate.Render(config.BundleVolCommand, config.ctx) if err != nil { err := fmt.Errorf("Error processing bundle volume command: %s", err) state.Put("error", err) diff --git a/builder/amazon/instance/step_upload_bundle.go b/builder/amazon/instance/step_upload_bundle.go index dbf6a0c29..c30ec9415 100644 --- a/builder/amazon/instance/step_upload_bundle.go +++ b/builder/amazon/instance/step_upload_bundle.go @@ -5,6 +5,7 @@ import ( "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) type uploadCmdData struct { @@ -35,14 +36,15 @@ func (s *StepUploadBundle) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionHalt } - config.BundleUploadCommand, err = config.tpl.Process(config.BundleUploadCommand, uploadCmdData{ + config.ctx.Data = uploadCmdData{ AccessKey: config.AccessKey, BucketName: config.S3Bucket, BundleDirectory: config.BundleDestination, ManifestPath: manifestPath, Region: region.Name, SecretKey: config.SecretKey, - }) + } + config.BundleUploadCommand, err = interpolate.Render(config.BundleUploadCommand, config.ctx) if err != nil { err := fmt.Errorf("Error processing bundle upload command: %s", err) state.Put("error", err) diff --git a/template/interpolate/render.go b/template/interpolate/render.go index a16ae94e9..a4c33222d 100644 --- a/template/interpolate/render.go +++ b/template/interpolate/render.go @@ -14,8 +14,10 @@ import ( // doesn't within an interface. type RenderFilter struct { Include []string + Exclude []string once sync.Once + excludeSet map[string]struct{} includeSet map[string]struct{} } @@ -74,9 +76,19 @@ func (f *RenderFilter) include(k string) bool { return true } + k = strings.ToLower(k) + f.once.Do(f.init) - _, ok := f.includeSet[strings.ToLower(k)] - return ok + if len(f.includeSet) > 0 { + _, ok := f.includeSet[k] + return ok + } + if len(f.excludeSet) > 0 { + _, ok := f.excludeSet[k] + return !ok + } + + return true } func (f *RenderFilter) init() { @@ -84,6 +96,11 @@ func (f *RenderFilter) init() { for _, v := range f.Include { f.includeSet[strings.ToLower(v)] = struct{}{} } + + f.excludeSet = make(map[string]struct{}) + for _, v := range f.Exclude { + f.excludeSet[strings.ToLower(v)] = struct{}{} + } } // renderWalker implements interfaces for the reflectwalk package