diff --git a/builder/amazon/chroot/builder.go b/builder/amazon/chroot/builder.go index addf5c464..f5ba97f40 100644 --- a/builder/amazon/chroot/builder.go +++ b/builder/amazon/chroot/builder.go @@ -9,7 +9,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" @@ -124,17 +124,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) { ctx := *b.config.ctx diff --git a/builder/amazon/chroot/step_attach_volume.go b/builder/amazon/chroot/step_attach_volume.go index a7db44b91..b305046f1 100644 --- a/builder/amazon/chroot/step_attach_volume.go +++ b/builder/amazon/chroot/step_attach_volume.go @@ -6,7 +6,7 @@ import ( "strings" "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" @@ -34,7 +34,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) @@ -54,13 +58,13 @@ func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction { Refresh: func() (interface{}, string, error) { attempts := 0 for attempts < 30 { - resp, err := ec2conn.Volumes([]string{volumeId}, ec2.NewFilter()) + resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIDs: []*string{&volumeId}}) if err != nil { return nil, "", err } if len(resp.Volumes[0].Attachments) > 0 { a := resp.Volumes[0].Attachments[0] - return a, a.Status, nil + return a, *a.State, nil } // When Attachment on volume is not present sleep for 2s and retry attempts += 1 @@ -103,7 +107,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) } @@ -116,14 +120,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 } diff --git a/builder/amazon/chroot/step_check_root_device.go b/builder/amazon/chroot/step_check_root_device.go index da18599aa..49a83178a 100644 --- a/builder/amazon/chroot/step_check_root_device.go +++ b/builder/amazon/chroot/step_check_root_device.go @@ -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()) diff --git a/builder/amazon/chroot/step_create_volume.go b/builder/amazon/chroot/step_create_volume.go index 881857e71..d1d12d65b 100644 --- a/builder/amazon/chroot/step_create_volume.go +++ b/builder/amazon/chroot/step_create_volume.go @@ -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)) } diff --git a/builder/amazon/chroot/step_instance_info.go b/builder/amazon/chroot/step_instance_info.go index cb694cc07..23191c54d 100644 --- a/builder/amazon/chroot/step_instance_info.go +++ b/builder/amazon/chroot/step_instance_info.go @@ -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) diff --git a/builder/amazon/chroot/step_mount_device.go b/builder/amazon/chroot/step_mount_device.go index ef531ecc3..e1b42ec13 100644 --- a/builder/amazon/chroot/step_mount_device.go +++ b/builder/amazon/chroot/step_mount_device.go @@ -7,7 +7,7 @@ import ( "os" "path/filepath" - "github.com/mitchellh/goamz/ec2" + "github.com/awslabs/aws-sdk-go/service/ec2" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/template/interpolate" @@ -61,9 +61,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) diff --git a/builder/amazon/chroot/step_register_ami.go b/builder/amazon/chroot/step_register_ami.go index 62e6a3ff0..25b87592a 100644 --- a/builder/amazon/chroot/step_register_ami.go +++ b/builder/amazon/chroot/step_register_ami.go @@ -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,15 @@ 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 + if newDevice.EBS != nil { + newDevice.EBS.SnapshotID = &snapshotId + } else { + newDevice.EBS = &ec2.EBSBlockDevice{SnapshotID: &snapshotId} + } } blockDevices[i] = newDevice @@ -34,7 +39,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 +50,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 +76,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 diff --git a/builder/amazon/chroot/step_register_ami_test.go b/builder/amazon/chroot/step_register_ami_test.go index 393b95c8b..9d44ba684 100644 --- a/builder/amazon/chroot/step_register_ami_test.go +++ b/builder/amazon/chroot/step_register_ami_test.go @@ -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) } - } diff --git a/builder/amazon/chroot/step_snapshot.go b/builder/amazon/chroot/step_snapshot.go index cad4b782b..e798a3a3e 100644 --- a/builder/amazon/chroot/step_snapshot.go +++ b/builder/amazon/chroot/step_snapshot.go @@ -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)) } diff --git a/builder/amazon/common/access_config.go b/builder/amazon/common/access_config.go index 559726c9f..a5403a3fd 100644 --- a/builder/amazon/common/access_config.go +++ b/builder/amazon/common/access_config.go @@ -2,10 +2,12 @@ package common import ( "fmt" + "io/ioutil" + "net/http" "strings" "unicode" - "github.com/mitchellh/goamz/aws" + "github.com/awslabs/aws-sdk-go/aws" "github.com/mitchellh/packer/template/interpolate" ) @@ -17,43 +19,54 @@ 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(ctx *interpolate.Context) []error { var errs []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)) } } @@ -64,3 +77,24 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []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 +} diff --git a/builder/amazon/common/ami_config.go b/builder/amazon/common/ami_config.go index aa515c3db..14b880f4c 100644 --- a/builder/amazon/common/ami_config.go +++ b/builder/amazon/common/ami_config.go @@ -3,7 +3,6 @@ package common import ( "fmt" - "github.com/mitchellh/goamz/aws" "github.com/mitchellh/packer/template/interpolate" ) @@ -40,7 +39,7 @@ func (c *AMIConfig) Prepare(ctx *interpolate.Context) []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 } diff --git a/builder/amazon/common/artifact.go b/builder/amazon/common/artifact.go index 8d6265508..89f3d9fa2 100644 --- a/builder/amazon/common/artifact.go +++ b/builder/amazon/common/artifact.go @@ -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) } diff --git a/builder/amazon/common/block_device.go b/builder/amazon/common/block_device.go index a8402f2d7..f86feff1c 100644 --- a/builder/amazon/common/block_device.go +++ b/builder/amazon/common/block_device.go @@ -1,7 +1,10 @@ package common import ( - "github.com/mitchellh/goamz/ec2" + "fmt" + + "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/service/ec2" "github.com/mitchellh/packer/template/interpolate" ) @@ -23,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 } @@ -46,10 +57,10 @@ func (b *BlockDevices) Prepare(ctx *interpolate.Context) []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) } diff --git a/builder/amazon/common/block_device_test.go b/builder/amazon/common/block_device_test.go index 838b23aec..a4c1dbb79 100644 --- a/builder/amazon/common/block_device_test.go +++ b/builder/amazon/common/block_device_test.go @@ -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) } diff --git a/builder/amazon/common/regions.go b/builder/amazon/common/regions.go new file mode 100644 index 000000000..4d3762465 --- /dev/null +++ b/builder/amazon/common/regions.go @@ -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 +} diff --git a/builder/amazon/common/ssh.go b/builder/amazon/common/ssh.go index 38ea6cc40..811215572 100644 --- a/builder/amazon/common/ssh.go +++ b/builder/amazon/common/ssh.go @@ -1,12 +1,13 @@ package common import ( - "golang.org/x/crypto/ssh" "errors" "fmt" - "github.com/mitchellh/goamz/ec2" - "github.com/mitchellh/multistep" "time" + + "github.com/awslabs/aws-sdk-go/service/ec2" + "github.com/mitchellh/multistep" + "golang.org/x/crypto/ssh" ) // 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 != nil && *i.VPCID != "" { + if i.PublicIPAddress != nil && *i.PublicIPAddress != "" && !private { + host = *i.PublicIPAddress } else { - host = i.PrivateIpAddress + host = *i.PrivateIPAddress } - } else if i.DNSName != "" { - host = i.DNSName + } else if i.PublicDNSName != nil && *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]) diff --git a/builder/amazon/common/state.go b/builder/amazon/common/state.go index 62e861d74..00a58be08 100644 --- a/builder/amazon/common/state.go +++ b/builder/amazon/common/state.go @@ -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 } } diff --git a/builder/amazon/common/step_ami_region_copy.go b/builder/amazon/common/step_ami_region_copy.go index 898eacc08..88ed1884f 100644 --- a/builder/amazon/common/step_ami_region_copy.go +++ b/builder/amazon/common/step_ami_region_copy.go @@ -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 } diff --git a/builder/amazon/common/step_create_tags.go b/builder/amazon/common/step_create_tags.go index a204ca321..fc17458ee 100644 --- a/builder/amazon/common/step_create_tags.go +++ b/builder/amazon/common/step_create_tags.go @@ -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) diff --git a/builder/amazon/common/step_key_pair.go b/builder/amazon/common/step_key_pair.go index 3a7eb9f35..5082d7b26 100644 --- a/builder/amazon/common/step_key_pair.go +++ b/builder/amazon/common/step_key_pair.go @@ -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)) diff --git a/builder/amazon/common/step_modify_ami_attributes.go b/builder/amazon/common/step_modify_ami_attributes.go index 533d4cfd9..0628109b5 100644 --- a/builder/amazon/common/step_modify_ami_attributes.go +++ b/builder/amazon/common/step_modify_ami_attributes.go @@ -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) diff --git a/builder/amazon/common/step_run_source_instance.go b/builder/amazon/common/step_run_source_instance.go index 76baf9bde..500949733 100644 --- a/builder/amazon/common/step_run_source_instance.go +++ b/builder/amazon/common/step_run_source_instance.go @@ -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,54 +188,57 @@ 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, instanceErr := ec2conn.Instances([]string{instanceId}, nil) + instanceResp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{ + InstanceIDs: []*string{&instanceId}}) for i := 0; i < 10; i++ { - if instanceErr == nil { - err = instanceErr + if err == nil { break } time.Sleep(3 * time.Second) - 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", @@ -224,7 +247,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 @@ -232,29 +255,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 != nil && *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 != nil && *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 != nil && *s.instance.PrivateIPAddress != "" { + ui.Message(fmt.Sprintf("Private IP: %s", *s.instance.PrivateIPAddress)) } } @@ -271,13 +297,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", } @@ -289,7 +318,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 } diff --git a/builder/amazon/common/step_security_group.go b/builder/amazon/common/step_security_group.go index 1d95619fe..356c4a752 100644 --- a/builder/amazon/common/step_security_group.go +++ b/builder/amazon/common/step_security_group.go @@ -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 } diff --git a/builder/amazon/common/step_source_ami_info.go b/builder/amazon/common/step_source_ami_info.go index c9f72123d..b0c941fda 100644 --- a/builder/amazon/common/step_source_ami_info.go +++ b/builder/amazon/common/step_source_ami_info.go @@ -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()) diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index a41828e30..a2d393bd5 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -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" @@ -62,17 +62,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) diff --git a/builder/amazon/ebs/builder_test.go b/builder/amazon/ebs/builder_test.go index 6f777afa9..664c751fa 100644 --- a/builder/amazon/ebs/builder_test.go +++ b/builder/amazon/ebs/builder_test.go @@ -1,8 +1,9 @@ package ebs import ( - "github.com/mitchellh/packer/packer" "testing" + + "github.com/mitchellh/packer/packer" ) func testConfig() map[string]interface{} { diff --git a/builder/amazon/ebs/step_create_ami.go b/builder/amazon/ebs/step_create_ami.go index eb8ddea7c..4fa601dfd 100644 --- a/builder/amazon/ebs/step_create_ami.go +++ b/builder/amazon/ebs/step_create_ami.go @@ -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 } } diff --git a/builder/amazon/ebs/step_modify_instance.go b/builder/amazon/ebs/step_modify_instance.go index 8b3f19b4d..0fa766326 100644 --- a/builder/amazon/ebs/step_modify_instance.go +++ b/builder/amazon/ebs/step_modify_instance.go @@ -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 diff --git a/builder/amazon/ebs/step_stop_instance.go b/builder/amazon/ebs/step_stop_instance.go index 09c19bddb..c01de8fdc 100644 --- a/builder/amazon/ebs/step_stop_instance.go +++ b/builder/amazon/ebs/step_stop_instance.go @@ -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) diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 2845aa25d..66351aab0 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -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" @@ -141,17 +141,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) diff --git a/builder/amazon/instance/step_bundle_volume.go b/builder/amazon/instance/step_bundle_volume.go index 8fd320e4a..433c1ca6e 100644 --- a/builder/amazon/instance/step_bundle_volume.go +++ b/builder/amazon/instance/step_bundle_volume.go @@ -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" "github.com/mitchellh/packer/template/interpolate" @@ -35,7 +35,7 @@ func (s *StepBundleVolume) Run(state multistep.StateBag) multistep.StepAction { var err error config.ctx.Data = bundleCmdData{ AccountId: config.AccountId, - Architecture: instance.Architecture, + Architecture: *instance.Architecture, CertPath: x509RemoteCertPath, Destination: config.BundleDestination, KeyPath: x509RemoteKeyPath, diff --git a/builder/amazon/instance/step_register_ami.go b/builder/amazon/instance/step_register_ami.go index 07040f417..349c7f856 100644 --- a/builder/amazon/instance/step_register_ami.go +++ b/builder/amazon/instance/step_register_ami.go @@ -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, } diff --git a/builder/amazon/instance/step_upload_bundle.go b/builder/amazon/instance/step_upload_bundle.go index c30ec9415..2f6b328c6 100644 --- a/builder/amazon/instance/step_upload_bundle.go +++ b/builder/amazon/instance/step_upload_bundle.go @@ -41,7 +41,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, } config.BundleUploadCommand, err = interpolate.Render(config.BundleUploadCommand, config.ctx)