amazon/ebs: use new interpolation stuff

This commit is contained in:
Mitchell Hashimoto 2015-05-27 11:35:56 -07:00
parent bdb9bd7dc5
commit 50d7c598e9
7 changed files with 31 additions and 229 deletions

View File

@ -2,10 +2,11 @@ package common
import ( import (
"fmt" "fmt"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/packer/packer"
"strings" "strings"
"unicode" "unicode"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/packer/template/interpolate"
) )
// AccessConfig is for common configuration related to AWS access // 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 return aws.Regions[region], nil
} }
func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error { func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
if t == nil { var errs []error
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))
}
}
if c.RawRegion != "" { if c.RawRegion != "" {
if _, ok := aws.Regions[c.RawRegion]; !ok { if _, ok := aws.Regions[c.RawRegion]; !ok {
errs = append(errs, fmt.Errorf("Unknown region: %s", c.RawRegion)) errs = append(errs, fmt.Errorf("Unknown region: %s", c.RawRegion))

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"github.com/mitchellh/goamz/aws" "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. // AMIConfig is for common configuration related to creating AMIs.
@ -20,49 +20,8 @@ type AMIConfig struct {
AMIEnhancedNetworking bool `mapstructure:"enhanced_networking"` AMIEnhancedNetworking bool `mapstructure:"enhanced_networking"`
} }
func (c *AMIConfig) Prepare(t *packer.ConfigTemplate) []error { func (c *AMIConfig) Prepare(ctx *interpolate.Context) []error {
if t == nil { var errs []error
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))
}
}
}
if c.AMIName == "" { if c.AMIName == "" {
errs = append(errs, fmt.Errorf("ami_name must be specified")) 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 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 { if len(errs) > 0 {
return errs return errs
} }

View File

@ -1,10 +1,8 @@
package common package common
import ( import (
"fmt"
"github.com/mitchellh/goamz/ec2" "github.com/mitchellh/goamz/ec2"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/template/interpolate"
) )
// BlockDevice // BlockDevice
@ -44,48 +42,7 @@ func buildBlockDevices(b []BlockDevice) []ec2.BlockDeviceMapping {
return blockDevices return blockDevices
} }
func (b *BlockDevices) Prepare(t *packer.ConfigTemplate) []error { func (b *BlockDevices) Prepare(ctx *interpolate.Context) []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
}
return nil return nil
} }

View File

@ -7,7 +7,7 @@ import (
"time" "time"
"github.com/mitchellh/packer/common/uuid" "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 // RunConfig contains configuration for running an instance from a source
@ -38,43 +38,7 @@ type RunConfig struct {
sshTimeout time.Duration sshTimeout time.Duration
} }
func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { func (c *RunConfig) Prepare(ctx *interpolate.Context) []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))
}
}
// Defaults // Defaults
if c.SSHPort == 0 { if c.SSHPort == 0 {
c.SSHPort = 22 c.SSHPort = 22
@ -90,7 +54,7 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error {
} }
// Validation // Validation
var err error var errs []error
if c.SourceAmi == "" { if c.SourceAmi == "" {
errs = append(errs, errors.New("A source_ami must be specified")) 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{ var err error
"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
c.sshTimeout, err = time.ParseDuration(c.RawSSHTimeout) c.sshTimeout, err = time.ParseDuration(c.RawSSHTimeout)
if err != nil { if err != nil {
errs = append(errs, fmt.Errorf("Failed parsing ssh_timeout: %s", err)) errs = append(errs, fmt.Errorf("Failed parsing ssh_timeout: %s", err))

View File

@ -13,13 +13,15 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common" awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/common" "github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
) )
// The unique ID for this builder // The unique ID for this builder
const BuilderId = "mitchellh.amazonebs" const BuilderId = "mitchellh.amazonebs"
type config struct { type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
awscommon.AccessConfig `mapstructure:",squash"` awscommon.AccessConfig `mapstructure:",squash"`
awscommon.AMIConfig `mapstructure:",squash"` awscommon.AMIConfig `mapstructure:",squash"`
@ -27,32 +29,30 @@ type config struct {
awscommon.RunConfig `mapstructure:",squash"` awscommon.RunConfig `mapstructure:",squash"`
tpl *packer.ConfigTemplate tpl *packer.ConfigTemplate
ctx *interpolate.Context
} }
type Builder struct { type Builder struct {
config config config Config
runner multistep.Runner runner multistep.Runner
} }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { 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 { if err != nil {
return nil, err 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 // Accumulate any errors
errs := common.CheckUnusedConfig(md) var errs *packer.MultiError
errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.BlockDevices.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.BlockDevices.Prepare(b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.AMIConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.AMIConfig.Prepare(b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.ctx)...)
if errs != nil && len(errs.Errors) > 0 { if errs != nil && len(errs.Errors) > 0 {
return nil, errs return nil, errs

View File

@ -13,7 +13,7 @@ type stepCreateAMI struct {
} }
func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction { 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) ec2conn := state.Get("ec2").(*ec2.EC2)
instance := state.Get("instance").(*ec2.Instance) instance := state.Get("instance").(*ec2.Instance)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)

View File

@ -11,7 +11,7 @@ import (
type stepModifyInstance struct{} type stepModifyInstance struct{}
func (s *stepModifyInstance) Run(state multistep.StateBag) multistep.StepAction { 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) ec2conn := state.Get("ec2").(*ec2.EC2)
instance := state.Get("instance").(*ec2.Instance) instance := state.Get("instance").(*ec2.Instance)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)