Migrate from mitchellh/goamz to awslabs/aws-sdk-go

This commit moves the Amazon builders of Packer away from the Hashicorp
fork of the goamz library to the official AWS SDK for Go, in order that
third party plugins may depend on the more complete official library
more easily.
This commit is contained in:
James Nugent 2015-04-05 17:58:48 -04:00
parent b49d74d999
commit e99cd56b6c
33 changed files with 508 additions and 360 deletions

View File

@ -10,7 +10,7 @@ import (
"log"
"runtime"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/common"
@ -153,17 +153,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
return nil, errors.New("The amazon-chroot builder only works on Linux environments.")
}
region, err := b.config.Region()
config, err := b.config.Config()
if err != nil {
return nil, err
}
auth, err := b.config.AccessConfig.Auth()
if err != nil {
return nil, err
}
ec2conn := ec2.New(auth, region)
ec2conn := ec2.New(config)
wrappedCommand := func(command string) (string, error) {
return b.config.tpl.Process(

View File

@ -3,11 +3,12 @@ package chroot
import (
"errors"
"fmt"
"github.com/mitchellh/goamz/ec2"
"strings"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
"strings"
)
// StepAttachVolume attaches the previously created volume to an
@ -32,7 +33,11 @@ func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction {
attachVolume := strings.Replace(device, "/xvd", "/sd", 1)
ui.Say(fmt.Sprintf("Attaching the root volume to %s", attachVolume))
_, err := ec2conn.AttachVolume(volumeId, instance.InstanceId, attachVolume)
_, err := ec2conn.AttachVolume(&ec2.AttachVolumeInput{
InstanceID: instance.InstanceID,
VolumeID: &volumeId,
Device: &attachVolume,
})
if err != nil {
err := fmt.Errorf("Error attaching volume: %s", err)
state.Put("error", err)
@ -50,7 +55,7 @@ func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction {
StepState: state,
Target: "attached",
Refresh: func() (interface{}, string, error) {
resp, err := ec2conn.Volumes([]string{volumeId}, ec2.NewFilter())
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIDs: []*string{&volumeId}})
if err != nil {
return nil, "", err
}
@ -60,7 +65,7 @@ func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction {
}
a := resp.Volumes[0].Attachments[0]
return a, a.Status, nil
return a, *a.State, nil
},
}
@ -92,7 +97,7 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
ui := state.Get("ui").(packer.Ui)
ui.Say("Detaching EBS volume...")
_, err := ec2conn.DetachVolume(s.volumeId)
_, err := ec2conn.DetachVolume(&ec2.DetachVolumeInput{VolumeID: &s.volumeId})
if err != nil {
return fmt.Errorf("Error detaching EBS volume: %s", err)
}
@ -105,14 +110,14 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
StepState: state,
Target: "detached",
Refresh: func() (interface{}, string, error) {
resp, err := ec2conn.Volumes([]string{s.volumeId}, ec2.NewFilter())
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIDs: []*string{&s.volumeId}})
if err != nil {
return nil, "", err
}
v := resp.Volumes[0]
if len(v.Attachments) > 0 {
return v, v.Attachments[0].Status, nil
return v, *v.Attachments[0].State, nil
} else {
return v, "detached", nil
}

View File

@ -3,7 +3,7 @@ package chroot
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
@ -18,7 +18,7 @@ func (s *StepCheckRootDevice) Run(state multistep.StateBag) multistep.StepAction
ui.Say("Checking the root device on source AMI...")
// It must be EBS-backed otherwise the build won't work
if image.RootDeviceType != "ebs" {
if *image.RootDeviceType != "ebs" {
err := fmt.Errorf("The root device of the source AMI must be EBS-backed.")
state.Put("error", err)
ui.Error(err.Error())

View File

@ -2,11 +2,12 @@ package chroot
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"log"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
"log"
)
// StepCreateVolume creates a new volume from the snapshot of the root
@ -25,11 +26,11 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
// Determine the root device snapshot
log.Printf("Searching for root device of the image (%s)", image.RootDeviceName)
log.Printf("Searching for root device of the image (%s)", *image.RootDeviceName)
var rootDevice *ec2.BlockDeviceMapping
for _, device := range image.BlockDevices {
for _, device := range image.BlockDeviceMappings {
if device.DeviceName == image.RootDeviceName {
rootDevice = &device
rootDevice = device
break
}
}
@ -42,12 +43,12 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
}
ui.Say("Creating the root volume...")
createVolume := &ec2.CreateVolume{
AvailZone: instance.AvailZone,
Size: rootDevice.VolumeSize,
SnapshotId: rootDevice.SnapshotId,
VolumeType: rootDevice.VolumeType,
IOPS: rootDevice.IOPS,
createVolume := &ec2.CreateVolumeInput{
AvailabilityZone: instance.Placement.AvailabilityZone,
Size: rootDevice.EBS.VolumeSize,
SnapshotID: rootDevice.EBS.SnapshotID,
VolumeType: rootDevice.EBS.VolumeType,
IOPS: rootDevice.EBS.IOPS,
}
log.Printf("Create args: %#v", createVolume)
@ -60,7 +61,7 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the volume ID so we remember to delete it later
s.volumeId = createVolumeResp.VolumeId
s.volumeId = *createVolumeResp.VolumeID
log.Printf("Volume ID: %s", s.volumeId)
// Wait for the volume to become ready
@ -69,13 +70,13 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
StepState: state,
Target: "available",
Refresh: func() (interface{}, string, error) {
resp, err := ec2conn.Volumes([]string{s.volumeId}, ec2.NewFilter())
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIDs: []*string{&s.volumeId}})
if err != nil {
return nil, "", err
}
v := resp.Volumes[0]
return v, v.Status, nil
return v, *v.State, nil
},
}
@ -100,7 +101,7 @@ func (s *StepCreateVolume) Cleanup(state multistep.StateBag) {
ui := state.Get("ui").(packer.Ui)
ui.Say("Deleting the created EBS volume...")
_, err := ec2conn.DeleteVolume(s.volumeId)
_, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeID: &s.volumeId})
if err != nil {
ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err))
}

View File

@ -2,11 +2,12 @@ package chroot
import (
"fmt"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
)
// StepInstanceInfo verifies that this builder is running on an EC2 instance.
@ -18,7 +19,7 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
// Get our own instance ID
ui.Say("Gathering information about this EC2 instance...")
instanceIdBytes, err := aws.GetMetaData("instance-id")
instanceIdBytes, err := common.GetInstanceMetaData("instance-id")
if err != nil {
log.Printf("Error: %s", err)
err := fmt.Errorf(
@ -33,7 +34,7 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
log.Printf("Instance ID: %s", instanceId)
// Query the entire instance metadata
instancesResp, err := ec2conn.Instances([]string{instanceId}, ec2.NewFilter())
instancesResp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{InstanceIDs: []*string{&instanceId}})
if err != nil {
err := fmt.Errorf("Error getting instance data: %s", err)
state.Put("error", err)

View File

@ -3,12 +3,13 @@ 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/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
type mountPathData struct {
@ -59,9 +60,9 @@ func (s *StepMountDevice) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
log.Printf("Source image virtualization type is: %s", image.VirtualizationType)
log.Printf("Source image virtualization type is: %s", *image.VirtualizationType)
deviceMount := device
if image.VirtualizationType == "hvm" {
if *image.VirtualizationType == "hvm" {
deviceMount = fmt.Sprintf("%s%d", device, 1)
}
state.Put("deviceMount", deviceMount)

View File

@ -3,7 +3,8 @@ package chroot
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
@ -20,11 +21,11 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
ui.Say("Registering the AMI...")
blockDevices := make([]ec2.BlockDeviceMapping, len(image.BlockDevices))
for i, device := range image.BlockDevices {
blockDevices := make([]*ec2.BlockDeviceMapping, len(image.BlockDeviceMappings))
for i, device := range image.BlockDeviceMappings {
newDevice := device
if newDevice.DeviceName == image.RootDeviceName {
newDevice.SnapshotId = snapshotId
newDevice.EBS.SnapshotID = &snapshotId
}
blockDevices[i] = newDevice
@ -34,7 +35,7 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
if config.AMIEnhancedNetworking {
registerOpts.SriovNetSupport = "simple"
registerOpts.SRIOVNetSupport = aws.String("simple")
}
registerResp, err := ec2conn.RegisterImage(registerOpts)
@ -45,16 +46,16 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the AMI ID in the state
ui.Say(fmt.Sprintf("AMI: %s", registerResp.ImageId))
ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageID))
amis := make(map[string]string)
amis[ec2conn.Region.Name] = registerResp.ImageId
amis[ec2conn.Config.Region] = *registerResp.ImageID
state.Put("amis", amis)
// Wait for the image to become ready
stateChange := awscommon.StateChangeConf{
Pending: []string{"pending"},
Target: "available",
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, registerResp.ImageId),
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageID),
StepState: state,
}
@ -71,18 +72,18 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {}
func buildRegisterOpts(config *Config, image *ec2.Image, blockDevices []ec2.BlockDeviceMapping) *ec2.RegisterImage {
registerOpts := &ec2.RegisterImage{
Name: config.AMIName,
Architecture: image.Architecture,
RootDeviceName: image.RootDeviceName,
BlockDevices: blockDevices,
VirtType: config.AMIVirtType,
func buildRegisterOpts(config *Config, image *ec2.Image, blockDevices []*ec2.BlockDeviceMapping) *ec2.RegisterImageInput {
registerOpts := &ec2.RegisterImageInput{
Name: &config.AMIName,
Architecture: image.Architecture,
RootDeviceName: image.RootDeviceName,
BlockDeviceMappings: blockDevices,
VirtualizationType: &config.AMIVirtType,
}
if config.AMIVirtType != "hvm" {
registerOpts.KernelId = image.KernelId
registerOpts.RamdiskId = image.RamdiskId
registerOpts.KernelID = image.KernelID
registerOpts.RAMDiskID = image.RAMDiskID
}
return registerOpts

View File

@ -1,16 +1,18 @@
package chroot
import (
"github.com/mitchellh/goamz/ec2"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
)
func testImage() ec2.Image {
return ec2.Image{
Id: "ami-abcd1234",
Name: "ami_test_name",
Architecture: "x86_64",
KernelId: "aki-abcd1234",
ImageID: aws.String("ami-abcd1234"),
Name: aws.String("ami_test_name"),
Architecture: aws.String("x86_64"),
KernelID: aws.String("aki-abcd1234"),
}
}
@ -22,23 +24,23 @@ func TestStepRegisterAmi_buildRegisterOpts_pv(t *testing.T) {
image := testImage()
blockDevices := []ec2.BlockDeviceMapping{}
blockDevices := []*ec2.BlockDeviceMapping{}
opts := buildRegisterOpts(&config, &image, blockDevices)
expected := config.AMIVirtType
if opts.VirtType != expected {
t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, opts.VirtType)
if *opts.VirtualizationType != expected {
t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, *opts.VirtualizationType)
}
expected = config.AMIName
if opts.Name != expected {
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, opts.Name)
if *opts.Name != expected {
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, *opts.Name)
}
expected = image.KernelId
if opts.KernelId != expected {
t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, opts.KernelId)
expected = *image.KernelID
if *opts.KernelID != expected {
t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, *opts.KernelID)
}
}
@ -51,23 +53,21 @@ func TestStepRegisterAmi_buildRegisterOpts_hvm(t *testing.T) {
image := testImage()
blockDevices := []ec2.BlockDeviceMapping{}
blockDevices := []*ec2.BlockDeviceMapping{}
opts := buildRegisterOpts(&config, &image, blockDevices)
expected := config.AMIVirtType
if opts.VirtType != expected {
t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, opts.VirtType)
if *opts.VirtualizationType != expected {
t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, *opts.VirtualizationType)
}
expected = config.AMIName
if opts.Name != expected {
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, opts.Name)
if *opts.Name != expected {
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, *opts.Name)
}
expected = ""
if opts.KernelId != expected {
t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, opts.KernelId)
if opts.KernelID != nil {
t.Fatalf("Unexpected KernelId value: expected nil got %s\n", *opts.KernelID)
}
}

View File

@ -5,7 +5,7 @@ import (
"fmt"
"time"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
@ -25,9 +25,12 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
volumeId := state.Get("volume_id").(string)
ui.Say("Creating snapshot...")
createSnapResp, err := ec2conn.CreateSnapshot(
volumeId,
fmt.Sprintf("Packer: %s", time.Now().String()))
description := fmt.Sprintf("Packer: %s", time.Now().String())
createSnapResp, err := ec2conn.CreateSnapshot(&ec2.CreateSnapshotInput{
VolumeID: &volumeId,
Description: &description,
})
if err != nil {
err := fmt.Errorf("Error creating snapshot: %s", err)
state.Put("error", err)
@ -36,7 +39,7 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the snapshot ID so we can delete it later
s.snapshotId = createSnapResp.Id
s.snapshotId = *createSnapResp.SnapshotID
ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId))
// Wait for the snapshot to be ready
@ -45,7 +48,7 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
StepState: state,
Target: "completed",
Refresh: func() (interface{}, string, error) {
resp, err := ec2conn.Snapshots([]string{s.snapshotId}, ec2.NewFilter())
resp, err := ec2conn.DescribeSnapshots(&ec2.DescribeSnapshotsInput{SnapshotIDs: []*string{&s.snapshotId}})
if err != nil {
return nil, "", err
}
@ -55,7 +58,7 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
}
s := resp.Snapshots[0]
return s, s.Status, nil
return s, *s.State, nil
},
}
@ -83,7 +86,7 @@ func (s *StepSnapshot) Cleanup(state multistep.StateBag) {
ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui)
ui.Say("Removing snapshot since we cancelled or halted...")
_, err := ec2conn.DeleteSnapshots([]string{s.snapshotId})
_, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{SnapshotID: &s.snapshotId})
if err != nil {
ui.Error(fmt.Sprintf("Error: %s", err))
}

View File

@ -2,10 +2,13 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/packer/packer"
"io/ioutil"
"net/http"
"strings"
"unicode"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/mitchellh/packer/packer"
)
// AccessConfig is for common configuration related to AWS access
@ -16,37 +19,48 @@ type AccessConfig struct {
Token string `mapstructure:"token"`
}
// Auth returns a valid aws.Auth object for access to AWS services, or
// an error if the authentication couldn't be resolved.
func (c *AccessConfig) Auth() (aws.Auth, error) {
auth, err := aws.GetAuth(c.AccessKey, c.SecretKey)
if err == nil {
// Store the accesskey and secret that we got...
c.AccessKey = auth.AccessKey
c.SecretKey = auth.SecretKey
c.Token = auth.Token
}
if c.Token != "" {
auth.Token = c.Token
// Config returns a valid aws.Config object for access to AWS services, or
// an error if the authentication and region couldn't be resolved
func (c *AccessConfig) Config() (*aws.Config, error) {
credsProvider := aws.DetectCreds(c.AccessKey, c.SecretKey, c.Token)
creds, err := credsProvider.Credentials()
if err != nil {
return nil, err
}
return auth, err
c.AccessKey = creds.AccessKeyID
c.SecretKey = creds.SecretAccessKey
c.Token = creds.SessionToken
region, err := c.Region()
if err != nil {
return nil, err
}
return &aws.Config{
Region: region,
Credentials: credsProvider,
}, nil
}
// Region returns the aws.Region object for access to AWS services, requesting
// the region from the instance metadata if possible.
func (c *AccessConfig) Region() (aws.Region, error) {
func (c *AccessConfig) Region() (string, error) {
if c.RawRegion != "" {
return aws.Regions[c.RawRegion], nil
if valid := ValidateRegion(c.RawRegion); valid == false {
return "", fmt.Errorf("Not a valid region: %s", c.RawRegion)
}
return c.RawRegion, nil
}
md, err := aws.GetMetaData("placement/availability-zone")
md, err := GetInstanceMetaData("placement/availability-zone")
if err != nil {
return aws.Region{}, err
return "", err
}
region := strings.TrimRightFunc(string(md), unicode.IsLetter)
return aws.Regions[region], nil
return region, nil
}
func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
@ -75,7 +89,7 @@ func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
}
if c.RawRegion != "" {
if _, ok := aws.Regions[c.RawRegion]; !ok {
if valid := ValidateRegion(c.RawRegion); valid == false {
errs = append(errs, fmt.Errorf("Unknown region: %s", c.RawRegion))
}
}
@ -86,3 +100,24 @@ func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
return nil
}
func GetInstanceMetaData(path string) (contents []byte, err error) {
url := "http://169.254.169.254/latest/meta-data/" + path
resp, err := http.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return []byte(body), err
}

View File

@ -3,7 +3,6 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/packer/packer"
)
@ -81,7 +80,7 @@ func (c *AMIConfig) Prepare(t *packer.ConfigTemplate) []error {
regionSet[region] = struct{}{}
// Verify the region is real
if _, ok := aws.Regions[region]; !ok {
if valid := ValidateRegion(region); valid == false {
errs = append(errs, fmt.Errorf("Unknown region: %s", region))
continue
}

View File

@ -6,8 +6,8 @@ import (
"sort"
"strings"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/packer/packer"
)
@ -67,8 +67,17 @@ func (a *Artifact) Destroy() error {
for region, imageId := range a.Amis {
log.Printf("Deregistering image ID (%s) from region (%s)", imageId, region)
regionconn := ec2.New(a.Conn.Auth, aws.Regions[region])
if _, err := regionconn.DeregisterImage(imageId); err != nil {
regionConfig := &aws.Config{
Credentials: a.Conn.Config.Credentials,
Region: region,
}
regionConn := ec2.New(regionConfig)
input := &ec2.DeregisterImageInput{
ImageID: &imageId,
}
if _, err := regionConn.DeregisterImage(input); err != nil {
errors = append(errors, err)
}

View File

@ -3,7 +3,8 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/packer/packer"
)
@ -25,21 +26,29 @@ type BlockDevices struct {
LaunchMappings []BlockDevice `mapstructure:"launch_block_device_mappings"`
}
func buildBlockDevices(b []BlockDevice) []ec2.BlockDeviceMapping {
var blockDevices []ec2.BlockDeviceMapping
func buildBlockDevices(b []BlockDevice) []*ec2.BlockDeviceMapping {
var blockDevices []*ec2.BlockDeviceMapping
for _, blockDevice := range b {
blockDevices = append(blockDevices, ec2.BlockDeviceMapping{
DeviceName: blockDevice.DeviceName,
VirtualName: blockDevice.VirtualName,
SnapshotId: blockDevice.SnapshotId,
VolumeType: blockDevice.VolumeType,
VolumeSize: blockDevice.VolumeSize,
DeleteOnTermination: blockDevice.DeleteOnTermination,
IOPS: blockDevice.IOPS,
NoDevice: blockDevice.NoDevice,
Encrypted: blockDevice.Encrypted,
})
ebsBlockDevice := &ec2.EBSBlockDevice{
SnapshotID: &blockDevice.SnapshotId,
Encrypted: &blockDevice.Encrypted,
IOPS: &blockDevice.IOPS,
VolumeType: &blockDevice.VolumeType,
VolumeSize: &blockDevice.VolumeSize,
DeleteOnTermination: &blockDevice.DeleteOnTermination,
}
mapping := &ec2.BlockDeviceMapping{
EBS: ebsBlockDevice,
DeviceName: &blockDevice.DeviceName,
VirtualName: &blockDevice.VirtualName,
}
if blockDevice.NoDevice {
mapping.NoDevice = aws.String("")
}
blockDevices = append(blockDevices, mapping)
}
return blockDevices
}
@ -89,10 +98,10 @@ func (b *BlockDevices) Prepare(t *packer.ConfigTemplate) []error {
return nil
}
func (b *BlockDevices) BuildAMIDevices() []ec2.BlockDeviceMapping {
func (b *BlockDevices) BuildAMIDevices() []*ec2.BlockDeviceMapping {
return buildBlockDevices(b.AMIMappings)
}
func (b *BlockDevices) BuildLaunchDevices() []ec2.BlockDeviceMapping {
func (b *BlockDevices) BuildLaunchDevices() []*ec2.BlockDeviceMapping {
return buildBlockDevices(b.LaunchMappings)
}

View File

@ -1,9 +1,11 @@
package common
import (
"github.com/mitchellh/goamz/ec2"
"reflect"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
)
func TestBlockDevice(t *testing.T) {
@ -23,13 +25,16 @@ func TestBlockDevice(t *testing.T) {
},
Result: &ec2.BlockDeviceMapping{
DeviceName: "/dev/sdb",
VirtualName: "ephemeral0",
SnapshotId: "snap-1234",
VolumeType: "standard",
VolumeSize: 8,
DeleteOnTermination: true,
IOPS: 1000,
DeviceName: aws.String("/dev/sdb"),
VirtualName: aws.String("ephemeral0"),
EBS: &ec2.EBSBlockDevice{
Encrypted: aws.Boolean(false),
SnapshotID: aws.String("snap-1234"),
VolumeType: aws.String("standard"),
VolumeSize: aws.Long(8),
DeleteOnTermination: aws.Boolean(true),
IOPS: aws.Long(1000),
},
},
},
}
@ -40,9 +45,9 @@ func TestBlockDevice(t *testing.T) {
LaunchMappings: []BlockDevice{*tc.Config},
}
expected := []ec2.BlockDeviceMapping{*tc.Result}
if !reflect.DeepEqual(expected, blockDevices.BuildAMIDevices()) {
expected := []*ec2.BlockDeviceMapping{tc.Result}
got := blockDevices.BuildAMIDevices()
if !reflect.DeepEqual(expected, got) {
t.Fatalf("bad: %#v", expected)
}

View File

@ -0,0 +1,16 @@
package common
// IsValidRegion returns true if the supplied region is a valid AWS
// region and false if it's not.
func ValidateRegion(region string) bool {
var regions = [11]string{"us-east-1", "us-west-2", "us-west-1", "eu-west-1",
"eu-central-1", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1",
"sa-east-1", "cn-north-1", "us-gov-west-1"}
for _, valid := range regions {
if region == valid {
return true
}
}
return false
}

View File

@ -1,12 +1,13 @@
package common
import (
"code.google.com/p/go.crypto/ssh"
"errors"
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/mitchellh/multistep"
"time"
"code.google.com/p/go.crypto/ssh"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
)
// SSHAddress returns a function that can be given to the SSH communicator
@ -16,27 +17,29 @@ func SSHAddress(e *ec2.EC2, port int, private bool) func(multistep.StateBag) (st
for j := 0; j < 2; j++ {
var host string
i := state.Get("instance").(*ec2.Instance)
if i.VpcId != "" {
if i.PublicIpAddress != "" && !private {
host = i.PublicIpAddress
if *i.VPCID != "" {
if *i.PublicIPAddress != "" && !private {
host = *i.PublicIPAddress
} else {
host = i.PrivateIpAddress
host = *i.PrivateIPAddress
}
} else if i.DNSName != "" {
host = i.DNSName
} else if *i.PublicDNSName != "" {
host = *i.PublicDNSName
}
if host != "" {
return fmt.Sprintf("%s:%d", host, port), nil
}
r, err := e.Instances([]string{i.InstanceId}, ec2.NewFilter())
r, err := e.DescribeInstances(&ec2.DescribeInstancesInput{
InstanceIDs: []*string{i.InstanceID},
})
if err != nil {
return "", err
}
if len(r.Reservations) == 0 || len(r.Reservations[0].Instances) == 0 {
return "", fmt.Errorf("instance not found: %s", i.InstanceId)
return "", fmt.Errorf("instance not found: %s", *i.InstanceID)
}
state.Put("instance", &r.Reservations[0].Instances[0])

View File

@ -3,13 +3,15 @@ package common
import (
"errors"
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/mitchellh/multistep"
"log"
"net"
"os"
"strconv"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
)
// StateRefreshFunc is a function type used for StateChangeConf that is
@ -36,9 +38,11 @@ type StateChangeConf struct {
// an AMI for state changes.
func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.Images([]string{imageId}, ec2.NewFilter())
resp, err := conn.DescribeImages(&ec2.DescribeImagesInput{
ImageIDs: []*string{&imageId},
})
if err != nil {
if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidAMIID.NotFound" {
if ec2err, ok := err.(*aws.APIError); ok && ec2err.Code == "InvalidAMIID.NotFound" {
// Set this to nil as if we didn't find anything.
resp = nil
} else if isTransientNetworkError(err) {
@ -57,7 +61,7 @@ func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
}
i := resp.Images[0]
return i, i.State, nil
return i, *i.State, nil
}
}
@ -65,9 +69,11 @@ func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
// an EC2 instance.
func InstanceStateRefreshFunc(conn *ec2.EC2, i *ec2.Instance) StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.Instances([]string{i.InstanceId}, ec2.NewFilter())
resp, err := conn.DescribeInstances(&ec2.DescribeInstancesInput{
InstanceIDs: []*string{i.InstanceID},
})
if err != nil {
if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" {
if ec2err, ok := err.(*aws.APIError); ok && ec2err.Code == "InvalidInstanceID.NotFound" {
// Set this to nil as if we didn't find anything.
resp = nil
} else if isTransientNetworkError(err) {
@ -85,8 +91,8 @@ func InstanceStateRefreshFunc(conn *ec2.EC2, i *ec2.Instance) StateRefreshFunc {
return nil, "", nil
}
i = &resp.Reservations[0].Instances[0]
return i, i.State.Name, nil
i = resp.Reservations[0].Instances[0]
return i, *i.State.Name, nil
}
}
@ -94,9 +100,12 @@ func InstanceStateRefreshFunc(conn *ec2.EC2, i *ec2.Instance) StateRefreshFunc {
// a spot request for state changes.
func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.DescribeSpotRequests([]string{spotRequestId}, ec2.NewFilter())
resp, err := conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{
SpotInstanceRequestIDs: []*string{&spotRequestId},
})
if err != nil {
if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidSpotInstanceRequestID.NotFound" {
if ec2err, ok := err.(*aws.APIError); ok && ec2err.Code == "InvalidSpotInstanceRequestID.NotFound" {
// Set this to nil as if we didn't find anything.
resp = nil
} else if isTransientNetworkError(err) {
@ -108,14 +117,14 @@ func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefre
}
}
if resp == nil || len(resp.SpotRequestResults) == 0 {
if resp == nil || len(resp.SpotInstanceRequests) == 0 {
// Sometimes AWS has consistency issues and doesn't see the
// SpotRequest. Return an empty state.
return nil, "", nil
}
i := resp.SpotRequestResults[0]
return i, i.State, nil
i := resp.SpotInstanceRequests[0]
return i, *i.State, nil
}
}

View File

@ -2,11 +2,14 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/ec2"
"sync"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"sync"
)
type StepAMIRegionCopy struct {
@ -17,7 +20,7 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui)
amis := state.Get("amis").(map[string]string)
ami := amis[ec2conn.Region.Name]
ami := amis[ec2conn.Config.Region]
if len(s.Regions) == 0 {
return multistep.ActionContinue
@ -34,8 +37,7 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction {
go func(region string) {
defer wg.Done()
id, err := amiRegionCopy(state, ec2conn.Auth, ami,
aws.Regions[region], ec2conn.Region)
id, err := amiRegionCopy(state, ec2conn.Config.Credentials, ami, region, ec2conn.Config.Region)
lock.Lock()
defer lock.Unlock()
@ -67,32 +69,36 @@ func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) {
// amiRegionCopy does a copy for the given AMI to the target region and
// returns the resulting ID or error.
func amiRegionCopy(state multistep.StateBag, auth aws.Auth, imageId string,
target aws.Region, source aws.Region) (string, error) {
func amiRegionCopy(state multistep.StateBag, auth aws.CredentialsProvider, imageId string,
target string, source string) (string, error) {
// Connect to the region where the AMI will be copied to
regionconn := ec2.New(auth, target)
resp, err := regionconn.CopyImage(&ec2.CopyImage{
SourceRegion: source.Name,
SourceImageId: imageId,
config := &aws.Config{
Credentials: auth,
Region: target,
}
regionconn := ec2.New(config)
resp, err := regionconn.CopyImage(&ec2.CopyImageInput{
SourceRegion: &source,
SourceImageID: &imageId,
})
if err != nil {
return "", fmt.Errorf("Error Copying AMI (%s) to region (%s): %s",
imageId, target.Name, err)
imageId, target, err)
}
stateChange := StateChangeConf{
Pending: []string{"pending"},
Target: "available",
Refresh: AMIStateRefreshFunc(regionconn, resp.ImageId),
Refresh: AMIStateRefreshFunc(regionconn, *resp.ImageID),
StepState: state,
}
if _, err := WaitForState(&stateChange); err != nil {
return "", fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s",
resp.ImageId, target.Name, err)
*resp.ImageID, target, err)
}
return resp.ImageId, nil
return *resp.ImageID, nil
}

View File

@ -2,8 +2,9 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
@ -21,14 +22,20 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction {
for region, ami := range amis {
ui.Say(fmt.Sprintf("Adding tags to AMI (%s)...", ami))
var ec2Tags []ec2.Tag
var ec2Tags []*ec2.Tag
for key, value := range s.Tags {
ui.Message(fmt.Sprintf("Adding tag: \"%s\": \"%s\"", key, value))
ec2Tags = append(ec2Tags, ec2.Tag{key, value})
ec2Tags = append(ec2Tags, &ec2.Tag{Key: &key, Value: &value})
}
regionconn := ec2.New(ec2conn.Auth, aws.Regions[region])
_, err := regionconn.CreateTags([]string{ami}, ec2Tags)
regionconn := ec2.New(&aws.Config{
Credentials: ec2conn.Config.Credentials,
Region: region,
})
_, err := regionconn.CreateTags(&ec2.CreateTagsInput{
Resources: []*string{&ami},
Tags: ec2Tags,
})
if err != nil {
err := fmt.Errorf("Error adding tags to AMI (%s): %s", ami, err)
state.Put("error", err)

View File

@ -2,12 +2,13 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"io/ioutil"
"os"
"runtime"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
type StepKeyPair struct {
@ -39,7 +40,7 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.KeyPairName))
keyResp, err := ec2conn.CreateKeyPair(s.KeyPairName)
keyResp, err := ec2conn.CreateKeyPair(&ec2.CreateKeyPairInput{KeyName: &s.KeyPairName})
if err != nil {
state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err))
return multistep.ActionHalt
@ -50,7 +51,7 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction {
// Set some state data for use in future steps
state.Put("keyPair", s.keyName)
state.Put("privateKey", keyResp.KeyMaterial)
state.Put("privateKey", *keyResp.KeyMaterial)
// If we're in debug mode, output the private key to the working
// directory.
@ -64,7 +65,7 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction {
defer f.Close()
// Write the key out
if _, err := f.Write([]byte(keyResp.KeyMaterial)); err != nil {
if _, err := f.Write([]byte(*keyResp.KeyMaterial)); err != nil {
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
return multistep.ActionHalt
}
@ -91,7 +92,7 @@ func (s *StepKeyPair) Cleanup(state multistep.StateBag) {
ui := state.Get("ui").(packer.Ui)
ui.Say("Deleting temporary keypair...")
_, err := ec2conn.DeleteKeyPair(s.keyName)
_, err := ec2conn.DeleteKeyPair(&ec2.DeleteKeyPairInput{KeyName: &s.keyName})
if err != nil {
ui.Error(fmt.Sprintf(
"Error cleaning up keypair. Please delete the key manually: %s", s.keyName))

View File

@ -2,8 +2,9 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
@ -34,37 +35,53 @@ func (s *StepModifyAMIAttributes) Run(state multistep.StateBag) multistep.StepAc
// Construct the modify image attribute requests we're going to make.
// We need to make each separately since the EC2 API only allows changing
// one type at a kind currently.
options := make(map[string]*ec2.ModifyImageAttribute)
options := make(map[string]*ec2.ModifyImageAttributeInput)
if s.Description != "" {
options["description"] = &ec2.ModifyImageAttribute{
Description: s.Description,
options["description"] = &ec2.ModifyImageAttributeInput{
Description: &ec2.AttributeValue{Value: &s.Description},
}
}
if len(s.Groups) > 0 {
options["groups"] = &ec2.ModifyImageAttribute{
AddGroups: s.Groups,
groups := make([]*string, len(s.Groups))
for i, g := range s.Groups {
groups[i] = &g
}
options["groups"] = &ec2.ModifyImageAttributeInput{
UserGroups: groups,
}
}
if len(s.Users) > 0 {
options["users"] = &ec2.ModifyImageAttribute{
AddUsers: s.Users,
users := make([]*string, len(s.Users))
for i, u := range s.Users {
users[i] = &u
}
options["users"] = &ec2.ModifyImageAttributeInput{
UserIDs: users,
}
}
if len(s.ProductCodes) > 0 {
options["product codes"] = &ec2.ModifyImageAttribute{
ProductCodes: s.ProductCodes,
codes := make([]*string, len(s.ProductCodes))
for i, c := range s.ProductCodes {
codes[i] = &c
}
options["product codes"] = &ec2.ModifyImageAttributeInput{
ProductCodes: codes,
}
}
for region, ami := range amis {
ui.Say(fmt.Sprintf("Modifying attributes on AMI (%s)...", ami))
regionconn := ec2.New(ec2conn.Auth, aws.Regions[region])
for name, opts := range options {
regionconn := ec2.New(&aws.Config{
Credentials: ec2conn.Config.Credentials,
Region: region,
})
for name, input := range options {
ui.Message(fmt.Sprintf("Modifying: %s", name))
_, err := regionconn.ModifyImageAttribute(ami, opts)
input.ImageID = &ami
_, err := regionconn.ModifyImageAttribute(input)
if err != nil {
err := fmt.Errorf("Error modify AMI attributes: %s", err)
state.Put("error", err)

View File

@ -7,7 +7,9 @@ import (
"strconv"
"time"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
@ -29,15 +31,20 @@ type StepRunSourceInstance struct {
UserDataFile string
instance *ec2.Instance
spotRequest *ec2.SpotRequestResult
spotRequest *ec2.SpotInstanceRequest
}
func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2)
keyName := state.Get("keyPair").(string)
securityGroupIds := state.Get("securityGroupIds").([]string)
tempSecurityGroupIds := state.Get("securityGroupIds").([]string)
ui := state.Get("ui").(packer.Ui)
securityGroupIds := make([]*string, len(tempSecurityGroupIds))
for i, sg := range tempSecurityGroupIds {
securityGroupIds[i] = &sg
}
userData := s.UserData
if s.UserDataFile != "" {
contents, err := ioutil.ReadFile(s.UserDataFile)
@ -49,13 +56,10 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
userData = string(contents)
}
securityGroups := make([]ec2.SecurityGroup, len(securityGroupIds))
for n, securityGroupId := range securityGroupIds {
securityGroups[n] = ec2.SecurityGroup{Id: securityGroupId}
}
ui.Say("Launching a source AWS instance...")
imageResp, err := ec2conn.Images([]string{s.SourceAMI}, ec2.NewFilter())
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
ImageIDs: []*string{&s.SourceAMI},
})
if err != nil {
state.Put("error", fmt.Errorf("There was a problem with the source AMI: %s", err))
return multistep.ActionHalt
@ -66,11 +70,11 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
return multistep.ActionHalt
}
if s.ExpectedRootDevice != "" && imageResp.Images[0].RootDeviceType != s.ExpectedRootDevice {
if s.ExpectedRootDevice != "" && *imageResp.Images[0].RootDeviceType != s.ExpectedRootDevice {
state.Put("error", fmt.Errorf(
"The provided source AMI has an invalid root device type.\n"+
"Expected '%s', got '%s'.",
s.ExpectedRootDevice, imageResp.Images[0].RootDeviceType))
s.ExpectedRootDevice, *imageResp.Images[0].RootDeviceType))
return multistep.ActionHalt
}
@ -82,11 +86,11 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
// Detect the spot price
startTime := time.Now().Add(-1 * time.Hour)
resp, err := ec2conn.DescribeSpotPriceHistory(&ec2.DescribeSpotPriceHistory{
InstanceType: []string{s.InstanceType},
ProductDescription: []string{s.SpotPriceProduct},
AvailabilityZone: s.AvailabilityZone,
StartTime: startTime,
resp, err := ec2conn.DescribeSpotPriceHistory(&ec2.DescribeSpotPriceHistoryInput{
InstanceTypes: []*string{&s.InstanceType},
ProductDescriptions: []*string{&s.SpotPriceProduct},
AvailabilityZone: &s.AvailabilityZone,
StartTime: &startTime,
})
if err != nil {
err := fmt.Errorf("Error finding spot price: %s", err)
@ -96,9 +100,9 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
}
var price float64
for _, history := range resp.History {
log.Printf("[INFO] Candidate spot price: %s", history.SpotPrice)
current, err := strconv.ParseFloat(history.SpotPrice, 64)
for _, history := range resp.SpotPriceHistory {
log.Printf("[INFO] Candidate spot price: %s", *history.SpotPrice)
current, err := strconv.ParseFloat(*history.SpotPrice, 64)
if err != nil {
log.Printf("[ERR] Error parsing spot price: %s", err)
continue
@ -120,20 +124,33 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
var instanceId string
if spotPrice == "" {
runOpts := &ec2.RunInstances{
KeyName: keyName,
ImageId: s.SourceAMI,
InstanceType: s.InstanceType,
UserData: []byte(userData),
MinCount: 0,
MaxCount: 0,
SecurityGroups: securityGroups,
IamInstanceProfile: s.IamInstanceProfile,
SubnetId: s.SubnetId,
AssociatePublicIpAddress: s.AssociatePublicIpAddress,
BlockDevices: s.BlockDevices.BuildLaunchDevices(),
AvailZone: s.AvailabilityZone,
runOpts := &ec2.RunInstancesInput{
KeyName: &keyName,
ImageID: &s.SourceAMI,
InstanceType: &s.InstanceType,
UserData: &userData,
MaxCount: aws.Long(1),
MinCount: aws.Long(1),
IAMInstanceProfile: &ec2.IAMInstanceProfileSpecification{Name: &s.IamInstanceProfile},
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
Placement: &ec2.Placement{AvailabilityZone: &s.AvailabilityZone},
}
if s.SubnetId != "" && s.AssociatePublicIpAddress {
runOpts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{
&ec2.InstanceNetworkInterfaceSpecification{
DeviceIndex: aws.Long(0),
AssociatePublicIPAddress: &s.AssociatePublicIpAddress,
SubnetID: &s.SubnetId,
Groups: securityGroupIds,
DeleteOnTermination: aws.Boolean(true),
},
}
} else {
runOpts.SubnetID = &s.SubnetId
runOpts.SecurityGroupIDs = securityGroupIds
}
runResp, err := ec2conn.RunInstances(runOpts)
if err != nil {
err := fmt.Errorf("Error launching source instance: %s", err)
@ -141,26 +158,29 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
ui.Error(err.Error())
return multistep.ActionHalt
}
instanceId = runResp.Instances[0].InstanceId
instanceId = *runResp.Instances[0].InstanceID
} else {
ui.Message(fmt.Sprintf(
"Requesting spot instance '%s' for: %s",
s.InstanceType, spotPrice))
runOpts := &ec2.RequestSpotInstances{
SpotPrice: spotPrice,
KeyName: keyName,
ImageId: s.SourceAMI,
InstanceType: s.InstanceType,
UserData: []byte(userData),
SecurityGroups: securityGroups,
IamInstanceProfile: s.IamInstanceProfile,
SubnetId: s.SubnetId,
AssociatePublicIpAddress: s.AssociatePublicIpAddress,
BlockDevices: s.BlockDevices.BuildLaunchDevices(),
AvailZone: s.AvailabilityZone,
}
runSpotResp, err := ec2conn.RequestSpotInstances(runOpts)
runSpotResp, err := ec2conn.RequestSpotInstances(&ec2.RequestSpotInstancesInput{
SpotPrice: &spotPrice,
LaunchSpecification: &ec2.RequestSpotLaunchSpecification{
KeyName: &keyName,
ImageID: &s.SourceAMI,
InstanceType: &s.InstanceType,
UserData: &userData,
SecurityGroupIDs: securityGroupIds,
IAMInstanceProfile: &ec2.IAMInstanceProfileSpecification{Name: &s.IamInstanceProfile},
SubnetID: &s.SubnetId,
NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{
&ec2.InstanceNetworkInterfaceSpecification{AssociatePublicIPAddress: &s.AssociatePublicIpAddress},
},
Placement: &ec2.SpotPlacement{AvailabilityZone: &s.AvailabilityZone},
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
},
})
if err != nil {
err := fmt.Errorf("Error launching source spot instance: %s", err)
state.Put("error", err)
@ -168,44 +188,47 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
return multistep.ActionHalt
}
s.spotRequest = &runSpotResp.SpotRequestResults[0]
s.spotRequest = runSpotResp.SpotInstanceRequests[0]
spotRequestId := s.spotRequest.SpotRequestId
ui.Message(fmt.Sprintf("Waiting for spot request (%s) to become active...", spotRequestId))
spotRequestId := s.spotRequest.SpotInstanceRequestID
ui.Message(fmt.Sprintf("Waiting for spot request (%s) to become active...", *spotRequestId))
stateChange := StateChangeConf{
Pending: []string{"open"},
Target: "active",
Refresh: SpotRequestStateRefreshFunc(ec2conn, spotRequestId),
Refresh: SpotRequestStateRefreshFunc(ec2conn, *spotRequestId),
StepState: state,
}
_, err = WaitForState(&stateChange)
if err != nil {
err := fmt.Errorf("Error waiting for spot request (%s) to become ready: %s", spotRequestId, err)
err := fmt.Errorf("Error waiting for spot request (%s) to become ready: %s", *spotRequestId, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
spotResp, err := ec2conn.DescribeSpotRequests([]string{spotRequestId}, nil)
spotResp, err := ec2conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{
SpotInstanceRequestIDs: []*string{spotRequestId},
})
if err != nil {
err := fmt.Errorf("Error finding spot request (%s): %s", spotRequestId, err)
err := fmt.Errorf("Error finding spot request (%s): %s", *spotRequestId, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
instanceId = spotResp.SpotRequestResults[0].InstanceId
instanceId = *spotResp.SpotInstanceRequests[0].InstanceID
}
instanceResp, err := ec2conn.Instances([]string{instanceId}, nil)
instanceResp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{InstanceIDs: []*string{&instanceId}})
if err != nil {
err := fmt.Errorf("Error finding source instance (%s): %s", instanceId, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
s.instance = &instanceResp.Reservations[0].Instances[0]
ui.Message(fmt.Sprintf("Instance ID: %s", s.instance.InstanceId))
s.instance = instanceResp.Reservations[0].Instances[0]
ui.Message(fmt.Sprintf("Instance ID: %s", *s.instance.InstanceID))
ui.Say(fmt.Sprintf("Waiting for instance (%s) to become ready...", s.instance.InstanceId))
ui.Say(fmt.Sprintf("Waiting for instance (%s) to become ready...", *s.instance.InstanceID))
stateChange := StateChangeConf{
Pending: []string{"pending"},
Target: "running",
@ -214,7 +237,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
}
latestInstance, err := WaitForState(&stateChange)
if err != nil {
err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", s.instance.InstanceId, err)
err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", *s.instance.InstanceID, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
@ -222,29 +245,32 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
s.instance = latestInstance.(*ec2.Instance)
ec2Tags := make([]ec2.Tag, 1, len(s.Tags)+1)
ec2Tags[0] = ec2.Tag{"Name", "Packer Builder"}
ec2Tags := make([]*ec2.Tag, 1, len(s.Tags)+1)
ec2Tags[0] = &ec2.Tag{Key: aws.String("Name"), Value: aws.String("Packer Builder")}
for k, v := range s.Tags {
ec2Tags = append(ec2Tags, ec2.Tag{k, v})
ec2Tags = append(ec2Tags, &ec2.Tag{Key: &k, Value: &v})
}
_, err = ec2conn.CreateTags([]string{s.instance.InstanceId}, ec2Tags)
_, err = ec2conn.CreateTags(&ec2.CreateTagsInput{
Tags: ec2Tags,
Resources: []*string{s.instance.InstanceID},
})
if err != nil {
ui.Message(
fmt.Sprintf("Failed to tag a Name on the builder instance: %s", err))
}
if s.Debug {
if s.instance.DNSName != "" {
ui.Message(fmt.Sprintf("Public DNS: %s", s.instance.DNSName))
if *s.instance.PublicDNSName != "" {
ui.Message(fmt.Sprintf("Public DNS: %s", *s.instance.PublicDNSName))
}
if s.instance.PublicIpAddress != "" {
ui.Message(fmt.Sprintf("Public IP: %s", s.instance.PublicIpAddress))
if *s.instance.PublicIPAddress != "" {
ui.Message(fmt.Sprintf("Public IP: %s", *s.instance.PublicIPAddress))
}
if s.instance.PrivateIpAddress != "" {
ui.Message(fmt.Sprintf("Private IP: %s", s.instance.PrivateIpAddress))
if *s.instance.PrivateIPAddress != "" {
ui.Message(fmt.Sprintf("Private IP: %s", *s.instance.PrivateIPAddress))
}
}
@ -261,13 +287,16 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
// Cancel the spot request if it exists
if s.spotRequest != nil {
ui.Say("Cancelling the spot request...")
if _, err := ec2conn.CancelSpotRequests([]string{s.spotRequest.SpotRequestId}); err != nil {
input := &ec2.CancelSpotInstanceRequestsInput{
SpotInstanceRequestIDs: []*string{s.spotRequest.InstanceID},
}
if _, err := ec2conn.CancelSpotInstanceRequests(input); err != nil {
ui.Error(fmt.Sprintf("Error cancelling the spot request, may still be around: %s", err))
return
}
stateChange := StateChangeConf{
Pending: []string{"active", "open"},
Refresh: SpotRequestStateRefreshFunc(ec2conn, s.spotRequest.SpotRequestId),
Refresh: SpotRequestStateRefreshFunc(ec2conn, *s.spotRequest.SpotInstanceRequestID),
Target: "cancelled",
}
@ -279,7 +308,7 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
if s.instance != nil {
ui.Say("Terminating the source AWS instance...")
if _, err := ec2conn.TerminateInstances([]string{s.instance.InstanceId}); err != nil {
if _, err := ec2conn.TerminateInstances(&ec2.TerminateInstancesInput{InstanceIDs: []*string{s.instance.InstanceID}}); err != nil {
ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err))
return
}

View File

@ -2,12 +2,14 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/common/uuid"
"github.com/mitchellh/packer/packer"
"log"
"time"
)
type StepSecurityGroup struct {
@ -36,10 +38,10 @@ func (s *StepSecurityGroup) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Creating temporary security group for this instance...")
groupName := fmt.Sprintf("packer %s", uuid.TimeOrderedUUID())
log.Printf("Temporary group name: %s", groupName)
group := ec2.SecurityGroup{
Name: groupName,
Description: "Temporary group for Packer",
VpcId: s.VpcId,
group := &ec2.CreateSecurityGroupInput{
GroupName: &groupName,
Description: aws.String("Temporary group for Packer"),
VPCID: &s.VpcId,
}
groupResp, err := ec2conn.CreateSecurityGroup(group)
if err != nil {
@ -48,16 +50,15 @@ func (s *StepSecurityGroup) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the group ID so we can delete it later
s.createdGroupId = groupResp.Id
s.createdGroupId = *groupResp.GroupID
// Authorize the SSH access
perms := []ec2.IPPerm{
ec2.IPPerm{
Protocol: "tcp",
FromPort: s.SSHPort,
ToPort: s.SSHPort,
SourceIPs: []string{"0.0.0.0/0"},
},
// Authorize the SSH access for the security group
req := &ec2.AuthorizeSecurityGroupIngressInput{
GroupID: groupResp.GroupID,
IPProtocol: aws.String("tcp"),
FromPort: aws.Long(int64(s.SSHPort)),
ToPort: aws.Long(int64(s.SSHPort)),
CIDRIP: aws.String("0.0.0.0/0"),
}
// We loop and retry this a few times because sometimes the security
@ -65,7 +66,7 @@ func (s *StepSecurityGroup) Run(state multistep.StateBag) multistep.StepAction {
// consistent.
ui.Say("Authorizing SSH access on the temporary security group...")
for i := 0; i < 5; i++ {
_, err = ec2conn.AuthorizeSecurityGroup(groupResp.SecurityGroup, perms)
_, err = ec2conn.AuthorizeSecurityGroupIngress(req)
if err == nil {
break
}
@ -99,7 +100,7 @@ func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) {
var err error
for i := 0; i < 5; i++ {
_, err = ec2conn.DeleteSecurityGroup(ec2.SecurityGroup{Id: s.createdGroupId})
_, err = ec2conn.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{GroupID: &s.createdGroupId})
if err == nil {
break
}

View File

@ -3,7 +3,7 @@ package common
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
@ -23,7 +23,7 @@ func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
ui.Say("Inspecting the source AMI...")
imageResp, err := ec2conn.Images([]string{s.SourceAmi}, ec2.NewFilter())
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIDs: []*string{&s.SourceAmi}})
if err != nil {
err := fmt.Errorf("Error querying AMI: %s", err)
state.Put("error", err)
@ -38,11 +38,11 @@ func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
image := &imageResp.Images[0]
image := imageResp.Images[0]
// Enhanced Networking (SriovNetSupport) can only be enabled on HVM AMIs.
// See http://goo.gl/icuXh5
if s.EnhancedNetworking && image.VirtualizationType != "hvm" {
if s.EnhancedNetworking && *image.VirtualizationType != "hvm" {
err := fmt.Errorf("Cannot enable enhanced networking, source AMI '%s' is not HVM", s.SourceAmi)
state.Put("error", err)
ui.Error(err.Error())

View File

@ -9,7 +9,7 @@ import (
"fmt"
"log"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/common"
@ -63,17 +63,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
region, err := b.config.Region()
config, err := b.config.Config()
if err != nil {
return nil, err
}
auth, err := b.config.AccessConfig.Auth()
if err != nil {
return nil, err
}
ec2conn := ec2.New(auth, region)
ec2conn := ec2.New(config)
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)

View File

@ -1,8 +1,9 @@
package ebs
import (
"github.com/mitchellh/packer/packer"
"testing"
"github.com/mitchellh/packer/packer"
)
func testConfig() map[string]interface{} {

View File

@ -2,7 +2,8 @@ package ebs
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
@ -20,10 +21,10 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
// Create the image
ui.Say(fmt.Sprintf("Creating the AMI: %s", config.AMIName))
createOpts := &ec2.CreateImage{
InstanceId: instance.InstanceId,
Name: config.AMIName,
BlockDevices: config.BlockDevices.BuildAMIDevices(),
createOpts := &ec2.CreateImageInput{
InstanceID: instance.InstanceID,
Name: &config.AMIName,
BlockDeviceMappings: config.BlockDevices.BuildAMIDevices(),
}
createResp, err := ec2conn.CreateImage(createOpts)
@ -35,16 +36,16 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the AMI ID in the state
ui.Message(fmt.Sprintf("AMI: %s", createResp.ImageId))
ui.Message(fmt.Sprintf("AMI: %s", *createResp.ImageID))
amis := make(map[string]string)
amis[ec2conn.Region.Name] = createResp.ImageId
amis[ec2conn.Config.Region] = *createResp.ImageID
state.Put("amis", amis)
// Wait for the image to become ready
stateChange := awscommon.StateChangeConf{
Pending: []string{"pending"},
Target: "available",
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, createResp.ImageId),
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *createResp.ImageID),
StepState: state,
}
@ -56,14 +57,14 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
imagesResp, err := ec2conn.Images([]string{createResp.ImageId}, nil)
imagesResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIDs: []*string{createResp.ImageID}})
if err != nil {
err := fmt.Errorf("Error searching for AMI: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
s.image = &imagesResp.Images[0]
s.image = imagesResp.Images[0]
return multistep.ActionContinue
}
@ -83,11 +84,9 @@ func (s *stepCreateAMI) Cleanup(state multistep.StateBag) {
ui := state.Get("ui").(packer.Ui)
ui.Say("Deregistering the AMI because cancelation or error...")
if resp, err := ec2conn.DeregisterImage(s.image.Id); err != nil {
deregisterOpts := &ec2.DeregisterImageInput{ImageID: s.image.ImageID}
if _, err := ec2conn.DeregisterImage(deregisterOpts); err != nil {
ui.Error(fmt.Sprintf("Error deregistering AMI, may still be around: %s", err))
return
} else if resp.Return == false {
ui.Error(fmt.Sprintf("Error deregistering AMI, may still be around: %t", resp.Return))
return
}
}

View File

@ -3,7 +3,7 @@ package ebs
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
@ -19,12 +19,13 @@ func (s *stepModifyInstance) Run(state multistep.StateBag) multistep.StepAction
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
if config.AMIEnhancedNetworking {
ui.Say("Enabling Enhanced Networking...")
_, err := ec2conn.ModifyInstance(
instance.InstanceId,
&ec2.ModifyInstance{SriovNetSupport: true},
)
simple := "simple"
_, err := ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{
InstanceID: instance.InstanceID,
SRIOVNetSupport: &ec2.AttributeValue{Value: &simple},
})
if err != nil {
err := fmt.Errorf("Error enabling Enhanced Networking on %s: %s", instance.InstanceId, err)
err := fmt.Errorf("Error enabling Enhanced Networking on %s: %s", *instance.InstanceID, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt

View File

@ -2,7 +2,8 @@ package ebs
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
@ -24,7 +25,9 @@ func (s *stepStopInstance) Run(state multistep.StateBag) multistep.StepAction {
// Stop the instance so we can create an AMI from it
ui.Say("Stopping the source instance...")
_, err := ec2conn.StopInstances(instance.InstanceId)
_, err := ec2conn.StopInstances(&ec2.StopInstancesInput{
InstanceIDs: []*string{instance.InstanceID},
})
if err != nil {
err := fmt.Errorf("Error stopping instance: %s", err)
state.Put("error", err)

View File

@ -9,7 +9,7 @@ import (
"os"
"strings"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/common"
@ -168,17 +168,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
region, err := b.config.Region()
config, err := b.config.Config()
if err != nil {
return nil, err
}
auth, err := b.config.AccessConfig.Auth()
if err != nil {
return nil, err
}
ec2conn := ec2.New(auth, region)
ec2conn := ec2.New(config)
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)

View File

@ -3,7 +3,7 @@ package instance
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
@ -34,7 +34,7 @@ func (s *StepBundleVolume) Run(state multistep.StateBag) multistep.StepAction {
var err error
config.BundleVolCommand, err = config.tpl.Process(config.BundleVolCommand, bundleCmdData{
AccountId: config.AccountId,
Architecture: instance.Architecture,
Architecture: *instance.Architecture,
CertPath: x509RemoteCertPath,
Destination: config.BundleDestination,
KeyPath: x509RemoteKeyPath,

View File

@ -3,7 +3,7 @@ package instance
import (
"fmt"
"github.com/mitchellh/goamz/ec2"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
awscommon "github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
@ -18,16 +18,17 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
ui.Say("Registering the AMI...")
registerOpts := &ec2.RegisterImage{
ImageLocation: manifestPath,
Name: config.AMIName,
BlockDevices: config.BlockDevices.BuildAMIDevices(),
VirtType: config.AMIVirtType,
registerOpts := &ec2.RegisterImageInput{
ImageLocation: &manifestPath,
Name: &config.AMIName,
BlockDeviceMappings: config.BlockDevices.BuildAMIDevices(),
VirtualizationType: &config.AMIVirtType,
}
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
if config.AMIEnhancedNetworking {
registerOpts.SriovNetSupport = "simple"
simple := "simple"
registerOpts.SRIOVNetSupport = &simple
}
registerResp, err := ec2conn.RegisterImage(registerOpts)
@ -38,16 +39,16 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the AMI ID in the state
ui.Say(fmt.Sprintf("AMI: %s", registerResp.ImageId))
ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageID))
amis := make(map[string]string)
amis[ec2conn.Region.Name] = registerResp.ImageId
amis[ec2conn.Config.Region] = *registerResp.ImageID
state.Put("amis", amis)
// Wait for the image to become ready
stateChange := awscommon.StateChangeConf{
Pending: []string{"pending"},
Target: "available",
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, registerResp.ImageId),
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageID),
StepState: state,
}

View File

@ -40,7 +40,7 @@ func (s *StepUploadBundle) Run(state multistep.StateBag) multistep.StepAction {
BucketName: config.S3Bucket,
BundleDirectory: config.BundleDestination,
ManifestPath: manifestPath,
Region: region.Name,
Region: region,
SecretKey: config.SecretKey,
})
if err != nil {